OLD | NEW |
1 // Copyright (c) 1994-2006 Sun Microsystems Inc. | 1 // Copyright (c) 1994-2006 Sun Microsystems Inc. |
2 // All Rights Reserved. | 2 // All Rights Reserved. |
3 // | 3 // |
4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
5 // modification, are permitted provided that the following conditions | 5 // modification, are permitted provided that the following conditions |
6 // are met: | 6 // are met: |
7 // | 7 // |
8 // - Redistributions of source code must retain the above copyright notice, | 8 // - Redistributions of source code must retain the above copyright notice, |
9 // this list of conditions and the following disclaimer. | 9 // this list of conditions and the following disclaimer. |
10 // | 10 // |
(...skipping 492 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
503 const Instr kStrRegFpOffsetPattern = | 503 const Instr kStrRegFpOffsetPattern = |
504 al | B26 | Offset | kRegister_fp_Code * B16; | 504 al | B26 | Offset | kRegister_fp_Code * B16; |
505 const Instr kLdrRegFpNegOffsetPattern = | 505 const Instr kLdrRegFpNegOffsetPattern = |
506 al | B26 | L | NegOffset | kRegister_fp_Code * B16; | 506 al | B26 | L | NegOffset | kRegister_fp_Code * B16; |
507 const Instr kStrRegFpNegOffsetPattern = | 507 const Instr kStrRegFpNegOffsetPattern = |
508 al | B26 | NegOffset | kRegister_fp_Code * B16; | 508 al | B26 | NegOffset | kRegister_fp_Code * B16; |
509 const Instr kLdrStrInstrTypeMask = 0xffff0000; | 509 const Instr kLdrStrInstrTypeMask = 0xffff0000; |
510 const Instr kLdrStrInstrArgumentMask = 0x0000ffff; | 510 const Instr kLdrStrInstrArgumentMask = 0x0000ffff; |
511 const Instr kLdrStrOffsetMask = 0x00000fff; | 511 const Instr kLdrStrOffsetMask = 0x00000fff; |
512 | 512 |
| 513 const Instr kThumbLdrPCMask = BH15 | 7 * BH12 | 15 * BH8 | 7 * BH4 | 15 * BH0; |
| 514 const Instr kThumbLdrPCPattern = BH15 | 7 * BH12 | BH11 | BH6 | BH4 | 15 * BH0; |
513 | 515 |
514 Assembler::Assembler(Isolate* isolate, void* buffer, int buffer_size) | 516 Assembler::Assembler(Isolate* isolate, void* buffer, int buffer_size) |
515 : AssemblerBase(isolate, buffer, buffer_size), | 517 : AssemblerBase(isolate, buffer, buffer_size), |
516 recorded_ast_id_(TypeFeedbackId::None()), | 518 recorded_ast_id_(TypeFeedbackId::None()), |
517 positions_recorder_(this) { | 519 positions_recorder_(this), |
| 520 thumb_mode_(false) { |
518 reloc_info_writer.Reposition(buffer_ + buffer_size_, pc_); | 521 reloc_info_writer.Reposition(buffer_ + buffer_size_, pc_); |
519 num_pending_reloc_info_ = 0; | 522 num_pending_reloc_info_ = 0; |
520 num_pending_64_bit_reloc_info_ = 0; | 523 num_pending_64_bit_reloc_info_ = 0; |
521 next_buffer_check_ = 0; | 524 next_buffer_check_ = 0; |
522 const_pool_blocked_nesting_ = 0; | 525 const_pool_blocked_nesting_ = 0; |
523 no_const_pool_before_ = 0; | 526 no_const_pool_before_ = 0; |
524 first_const_pool_use_ = -1; | 527 first_const_pool_use_ = -1; |
525 last_bound_pos_ = 0; | 528 last_bound_pos_ = 0; |
526 ClearRecordedAstId(); | 529 ClearRecordedAstId(); |
527 } | 530 } |
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
768 // | 771 // |
769 // The linked labels form a link chain by making the branch offset | 772 // The linked labels form a link chain by making the branch offset |
770 // in the instruction steam to point to the previous branch | 773 // in the instruction steam to point to the previous branch |
771 // instruction using the same label. | 774 // instruction using the same label. |
772 // | 775 // |
773 // The link chain is terminated by a branch offset pointing to the | 776 // The link chain is terminated by a branch offset pointing to the |
774 // same position. | 777 // same position. |
775 | 778 |
776 | 779 |
777 int Assembler::target_at(int pos) { | 780 int Assembler::target_at(int pos) { |
| 781 if (is_thumb_mode()) { |
| 782 return target_at_thumb(pos); |
| 783 } |
| 784 |
778 Instr instr = instr_at(pos); | 785 Instr instr = instr_at(pos); |
779 if (is_uint24(instr)) { | 786 if (is_uint24(instr)) { |
780 // Emitted link to a label, not part of a branch. | 787 // Emitted link to a label, not part of a branch. |
781 return instr; | 788 return instr; |
782 } | 789 } |
783 ASSERT((instr & 7*B25) == 5*B25); // b, bl, or blx imm24 | 790 ASSERT((instr & 7*B25) == 5*B25); // b, bl, or blx imm24 |
784 int imm26 = ((instr & kImm24Mask) << 8) >> 6; | 791 int imm26 = ((instr & kImm24Mask) << 8) >> 6; |
785 if ((Instruction::ConditionField(instr) == kSpecialCondition) && | 792 if ((Instruction::ConditionField(instr) == kSpecialCondition) && |
786 ((instr & B24) != 0)) { | 793 ((instr & B24) != 0)) { |
787 // blx uses bit 24 to encode bit 2 of imm26 | 794 // blx uses bit 24 to encode bit 2 of imm26 |
788 imm26 += 2; | 795 imm26 += 2; |
789 } | 796 } |
790 return pos + kPcLoadDelta + imm26; | 797 return pos + kPcLoadDelta + imm26; |
791 } | 798 } |
792 | 799 |
793 | 800 |
794 void Assembler::target_at_put(int pos, int target_pos) { | 801 void Assembler::target_at_put(int pos, int target_pos) { |
| 802 if (is_thumb_mode()) { |
| 803 target_at_put_thumb(pos, target_pos); |
| 804 return; |
| 805 } |
| 806 |
795 Instr instr = instr_at(pos); | 807 Instr instr = instr_at(pos); |
796 if (is_uint24(instr)) { | 808 if (is_uint24(instr)) { |
797 ASSERT(target_pos == pos || target_pos >= 0); | 809 ASSERT(target_pos == pos || target_pos >= 0); |
798 // Emitted link to a label, not part of a branch. | 810 // Emitted link to a label, not part of a branch. |
799 // Load the position of the label relative to the generated code object | 811 // Load the position of the label relative to the generated code object |
800 // pointer in a register. | 812 // pointer in a register. |
801 | 813 |
802 // Here are the instructions we need to emit: | 814 // Here are the instructions we need to emit: |
803 // For ARMv7: target24 => target16_1:target16_0 | 815 // For ARMv7: target24 => target16_1:target16_0 |
804 // movw dst, #target16_0 | 816 // movw dst, #target16_0 |
(...skipping 501 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1306 } else { | 1318 } else { |
1307 // First entry of the link chain points to itself. | 1319 // First entry of the link chain points to itself. |
1308 target_pos = pc_offset(); | 1320 target_pos = pc_offset(); |
1309 } | 1321 } |
1310 L->link_to(pc_offset()); | 1322 L->link_to(pc_offset()); |
1311 } | 1323 } |
1312 | 1324 |
1313 // Block the emission of the constant pool, since the branch instruction must | 1325 // Block the emission of the constant pool, since the branch instruction must |
1314 // be emitted at the pc offset recorded by the label. | 1326 // be emitted at the pc offset recorded by the label. |
1315 BlockConstPoolFor(1); | 1327 BlockConstPoolFor(1); |
| 1328 if (is_thumb_mode()) { |
| 1329 return target_pos - (pc_offset() + kThumbPcLoadDelta); |
| 1330 } |
1316 return target_pos - (pc_offset() + kPcLoadDelta); | 1331 return target_pos - (pc_offset() + kPcLoadDelta); |
1317 } | 1332 } |
1318 | 1333 |
1319 | 1334 |
1320 // Branch instructions. | 1335 // Branch instructions. |
1321 void Assembler::b(int branch_offset, Condition cond) { | 1336 void Assembler::b(int branch_offset, Condition cond) { |
| 1337 if (is_thumb_mode()) { |
| 1338 ASSERT((branch_offset & 1) == 0); |
| 1339 b_thumb(branch_offset, cond); |
| 1340 return; |
| 1341 } |
1322 ASSERT((branch_offset & 3) == 0); | 1342 ASSERT((branch_offset & 3) == 0); |
1323 int imm24 = branch_offset >> 2; | 1343 int imm24 = branch_offset >> 2; |
1324 ASSERT(is_int24(imm24)); | 1344 ASSERT(is_int24(imm24)); |
1325 emit(cond | B27 | B25 | (imm24 & kImm24Mask)); | 1345 emit(cond | B27 | B25 | (imm24 & kImm24Mask)); |
1326 | 1346 |
1327 if (cond == al) { | 1347 if (cond == al) { |
1328 // Dead code is a good location to emit the constant pool. | 1348 // Dead code is a good location to emit the constant pool. |
1329 CheckConstPool(false, false); | 1349 CheckConstPool(false, false); |
1330 } | 1350 } |
1331 } | 1351 } |
1332 | 1352 |
1333 | 1353 |
1334 void Assembler::bl(int branch_offset, Condition cond) { | 1354 void Assembler::bl(int branch_offset, Condition cond) { |
1335 positions_recorder()->WriteRecordedPositions(); | 1355 positions_recorder()->WriteRecordedPositions(); |
| 1356 if (is_thumb_mode()) { |
| 1357 ASSERT(cond == al); |
| 1358 ASSERT((branch_offset & 1) == 0); |
| 1359 int imm = branch_offset >> 1; |
| 1360 emit32(thumb32_mode4(BL_32_IMM) | thumb32_sign_extend_imm24(imm)); |
| 1361 return; |
| 1362 } |
1336 ASSERT((branch_offset & 3) == 0); | 1363 ASSERT((branch_offset & 3) == 0); |
1337 int imm24 = branch_offset >> 2; | 1364 int imm24 = branch_offset >> 2; |
1338 ASSERT(is_int24(imm24)); | 1365 ASSERT(is_int24(imm24)); |
1339 emit(cond | B27 | B25 | B24 | (imm24 & kImm24Mask)); | 1366 emit(cond | B27 | B25 | B24 | (imm24 & kImm24Mask)); |
1340 } | 1367 } |
1341 | 1368 |
1342 | 1369 |
1343 void Assembler::blx(int branch_offset) { // v5 and above | 1370 void Assembler::blx(int branch_offset) { // v5 and above |
1344 positions_recorder()->WriteRecordedPositions(); | 1371 positions_recorder()->WriteRecordedPositions(); |
| 1372 if (is_thumb_mode()) { |
| 1373 ASSERT((branch_offset & 3) == 0); |
| 1374 int imm = branch_offset >> 1; |
| 1375 emit32(thumb32_mode4(BLX_32_IMM) | thumb32_sign_extend_imm24(imm)); |
| 1376 return; |
| 1377 } |
1345 ASSERT((branch_offset & 1) == 0); | 1378 ASSERT((branch_offset & 1) == 0); |
1346 int h = ((branch_offset & 2) >> 1)*B24; | 1379 int h = ((branch_offset & 2) >> 1)*B24; |
1347 int imm24 = branch_offset >> 2; | 1380 int imm24 = branch_offset >> 2; |
1348 ASSERT(is_int24(imm24)); | 1381 ASSERT(is_int24(imm24)); |
1349 emit(kSpecialCondition | B27 | B25 | h | (imm24 & kImm24Mask)); | 1382 emit(kSpecialCondition | B27 | B25 | h | (imm24 & kImm24Mask)); |
1350 } | 1383 } |
1351 | 1384 |
1352 | 1385 |
1353 void Assembler::blx(Register target, Condition cond) { // v5 and above | 1386 void Assembler::blx(Register target, Condition cond) { // v5 and above |
1354 positions_recorder()->WriteRecordedPositions(); | 1387 positions_recorder()->WriteRecordedPositions(); |
1355 ASSERT(!target.is(pc)); | 1388 ASSERT(!target.is(pc)); |
| 1389 if (is_thumb_mode()) { |
| 1390 ASSERT(cond == al); |
| 1391 emit16(thumb16_mode3(BLX_REG) | thumb16_anyreg_encoding(target)); |
| 1392 return; |
| 1393 } |
1356 emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | BLX | target.code()); | 1394 emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | BLX | target.code()); |
1357 } | 1395 } |
1358 | 1396 |
1359 | 1397 |
1360 void Assembler::bx(Register target, Condition cond) { // v5 and above, plus v4t | 1398 void Assembler::bx(Register target, Condition cond) { // v5 and above, plus v4t |
1361 positions_recorder()->WriteRecordedPositions(); | 1399 positions_recorder()->WriteRecordedPositions(); |
1362 ASSERT(!target.is(pc)); // use of pc is actually allowed, but discouraged | 1400 ASSERT(!target.is(pc)); // use of pc is actually allowed, but discouraged |
| 1401 if (is_thumb_mode()) { |
| 1402 ASSERT(cond == al); |
| 1403 emit16(thumb16_mode3(BX_REG) | thumb16_anyreg_encoding(target)); |
| 1404 return; |
| 1405 } |
1363 emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | BX | target.code()); | 1406 emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | BX | target.code()); |
1364 } | 1407 } |
1365 | 1408 |
1366 | 1409 |
1367 // Data-processing instructions. | 1410 // Data-processing instructions. |
1368 | 1411 |
1369 void Assembler::and_(Register dst, Register src1, const Operand& src2, | 1412 void Assembler::and_(Register dst, Register src1, const Operand& src2, |
1370 SBit s, Condition cond) { | 1413 SBit s, Condition cond) { |
| 1414 if (is_thumb_mode()) { |
| 1415 and_thumb(dst, src1, src2, s, cond); |
| 1416 return; |
| 1417 } |
1371 addrmod1(cond | AND | s, src1, dst, src2); | 1418 addrmod1(cond | AND | s, src1, dst, src2); |
1372 } | 1419 } |
1373 | 1420 |
1374 | 1421 |
1375 void Assembler::eor(Register dst, Register src1, const Operand& src2, | 1422 void Assembler::eor(Register dst, Register src1, const Operand& src2, |
1376 SBit s, Condition cond) { | 1423 SBit s, Condition cond) { |
| 1424 if (is_thumb_mode()) { |
| 1425 eor_thumb(dst, src1, src2, s, cond); |
| 1426 return; |
| 1427 } |
1377 addrmod1(cond | EOR | s, src1, dst, src2); | 1428 addrmod1(cond | EOR | s, src1, dst, src2); |
1378 } | 1429 } |
1379 | 1430 |
1380 | 1431 |
1381 void Assembler::sub(Register dst, Register src1, const Operand& src2, | 1432 void Assembler::sub(Register dst, Register src1, const Operand& src2, |
1382 SBit s, Condition cond) { | 1433 SBit s, Condition cond) { |
| 1434 if (is_thumb_mode()) { |
| 1435 sub_thumb(dst, src1, src2, s, cond); |
| 1436 return; |
| 1437 } |
1383 addrmod1(cond | SUB | s, src1, dst, src2); | 1438 addrmod1(cond | SUB | s, src1, dst, src2); |
1384 } | 1439 } |
1385 | 1440 |
1386 | 1441 |
1387 void Assembler::rsb(Register dst, Register src1, const Operand& src2, | 1442 void Assembler::rsb(Register dst, Register src1, const Operand& src2, |
1388 SBit s, Condition cond) { | 1443 SBit s, Condition cond) { |
| 1444 if (is_thumb_mode()) { |
| 1445 rsb_thumb(dst, src1, src2, s, cond); |
| 1446 return; |
| 1447 } |
1389 addrmod1(cond | RSB | s, src1, dst, src2); | 1448 addrmod1(cond | RSB | s, src1, dst, src2); |
1390 } | 1449 } |
1391 | 1450 |
1392 | 1451 |
1393 void Assembler::add(Register dst, Register src1, const Operand& src2, | 1452 void Assembler::add(Register dst, Register src1, const Operand& src2, |
1394 SBit s, Condition cond) { | 1453 SBit s, Condition cond) { |
| 1454 if (is_thumb_mode()) { |
| 1455 add_thumb(dst, src1, src2, s, cond); |
| 1456 return; |
| 1457 } |
1395 addrmod1(cond | ADD | s, src1, dst, src2); | 1458 addrmod1(cond | ADD | s, src1, dst, src2); |
1396 } | 1459 } |
1397 | 1460 |
1398 | 1461 |
1399 void Assembler::adc(Register dst, Register src1, const Operand& src2, | 1462 void Assembler::adc(Register dst, Register src1, const Operand& src2, |
1400 SBit s, Condition cond) { | 1463 SBit s, Condition cond) { |
| 1464 if (is_thumb_mode()) { |
| 1465 adc_thumb(dst, src1, src2, s, cond); |
| 1466 return; |
| 1467 } |
1401 addrmod1(cond | ADC | s, src1, dst, src2); | 1468 addrmod1(cond | ADC | s, src1, dst, src2); |
1402 } | 1469 } |
1403 | 1470 |
1404 | 1471 |
1405 void Assembler::sbc(Register dst, Register src1, const Operand& src2, | 1472 void Assembler::sbc(Register dst, Register src1, const Operand& src2, |
1406 SBit s, Condition cond) { | 1473 SBit s, Condition cond) { |
| 1474 if (is_thumb_mode()) { |
| 1475 sbc_thumb(dst, src1, src2, s, cond); |
| 1476 return; |
| 1477 } |
1407 addrmod1(cond | SBC | s, src1, dst, src2); | 1478 addrmod1(cond | SBC | s, src1, dst, src2); |
1408 } | 1479 } |
1409 | 1480 |
1410 | 1481 |
1411 void Assembler::rsc(Register dst, Register src1, const Operand& src2, | 1482 void Assembler::rsc(Register dst, Register src1, const Operand& src2, |
1412 SBit s, Condition cond) { | 1483 SBit s, Condition cond) { |
1413 addrmod1(cond | RSC | s, src1, dst, src2); | 1484 addrmod1(cond | RSC | s, src1, dst, src2); |
1414 } | 1485 } |
1415 | 1486 |
1416 | 1487 |
1417 void Assembler::tst(Register src1, const Operand& src2, Condition cond) { | 1488 void Assembler::tst(Register src1, const Operand& src2, Condition cond) { |
| 1489 if (is_thumb_mode()) { |
| 1490 tst_thumb(src1, src2, cond); |
| 1491 return; |
| 1492 } |
1418 addrmod1(cond | TST | S, src1, r0, src2); | 1493 addrmod1(cond | TST | S, src1, r0, src2); |
1419 } | 1494 } |
1420 | 1495 |
1421 | 1496 |
1422 void Assembler::teq(Register src1, const Operand& src2, Condition cond) { | 1497 void Assembler::teq(Register src1, const Operand& src2, Condition cond) { |
| 1498 if (is_thumb_mode()) { |
| 1499 teq_thumb(src1, src2, cond); |
| 1500 return; |
| 1501 } |
1423 addrmod1(cond | TEQ | S, src1, r0, src2); | 1502 addrmod1(cond | TEQ | S, src1, r0, src2); |
1424 } | 1503 } |
1425 | 1504 |
1426 | 1505 |
1427 void Assembler::cmp(Register src1, const Operand& src2, Condition cond) { | 1506 void Assembler::cmp(Register src1, const Operand& src2, Condition cond) { |
| 1507 if (is_thumb_mode()) { |
| 1508 cmp_thumb(src1, src2, cond); |
| 1509 return; |
| 1510 } |
1428 addrmod1(cond | CMP | S, src1, r0, src2); | 1511 addrmod1(cond | CMP | S, src1, r0, src2); |
1429 } | 1512 } |
1430 | 1513 |
1431 | 1514 |
1432 void Assembler::cmp_raw_immediate( | 1515 void Assembler::cmp_raw_immediate( |
1433 Register src, int raw_immediate, Condition cond) { | 1516 Register src, int raw_immediate, Condition cond) { |
1434 ASSERT(is_uint12(raw_immediate)); | 1517 ASSERT(is_uint12(raw_immediate)); |
1435 emit(cond | I | CMP | S | src.code() << 16 | raw_immediate); | 1518 emit(cond | I | CMP | S | src.code() << 16 | raw_immediate); |
1436 } | 1519 } |
1437 | 1520 |
1438 | 1521 |
1439 void Assembler::cmn(Register src1, const Operand& src2, Condition cond) { | 1522 void Assembler::cmn(Register src1, const Operand& src2, Condition cond) { |
| 1523 if (is_thumb_mode()) { |
| 1524 cmn_thumb(src1, src2, cond); |
| 1525 return; |
| 1526 } |
1440 addrmod1(cond | CMN | S, src1, r0, src2); | 1527 addrmod1(cond | CMN | S, src1, r0, src2); |
1441 } | 1528 } |
1442 | 1529 |
1443 | 1530 |
1444 void Assembler::orr(Register dst, Register src1, const Operand& src2, | 1531 void Assembler::orr(Register dst, Register src1, const Operand& src2, |
1445 SBit s, Condition cond) { | 1532 SBit s, Condition cond) { |
| 1533 if (is_thumb_mode()) { |
| 1534 orr_thumb(dst, src1, src2, s, cond); |
| 1535 return; |
| 1536 } |
1446 addrmod1(cond | ORR | s, src1, dst, src2); | 1537 addrmod1(cond | ORR | s, src1, dst, src2); |
1447 } | 1538 } |
1448 | 1539 |
1449 | 1540 |
1450 void Assembler::mov(Register dst, const Operand& src, SBit s, Condition cond) { | 1541 void Assembler::mov(Register dst, const Operand& src, SBit s, Condition cond) { |
1451 if (dst.is(pc)) { | 1542 if (dst.is(pc)) { |
1452 positions_recorder()->WriteRecordedPositions(); | 1543 positions_recorder()->WriteRecordedPositions(); |
1453 } | 1544 } |
1454 // Don't allow nop instructions in the form mov rn, rn to be generated using | 1545 // Don't allow nop instructions in the form mov rn, rn to be generated using |
1455 // the mov instruction. They must be generated using nop(int/NopMarkerTypes) | 1546 // the mov instruction. They must be generated using nop(int/NopMarkerTypes) |
1456 // or MarkCode(int/NopMarkerTypes) pseudo instructions. | 1547 // or MarkCode(int/NopMarkerTypes) pseudo instructions. |
1457 ASSERT(!(src.is_reg() && src.rm().is(dst) && s == LeaveCC && cond == al)); | 1548 ASSERT(!(src.is_reg() && src.rm().is(dst) && s == LeaveCC && cond == al)); |
| 1549 if (is_thumb_mode()) { |
| 1550 mov_thumb(dst, src, s, cond); |
| 1551 return; |
| 1552 } |
1458 addrmod1(cond | MOV | s, r0, dst, src); | 1553 addrmod1(cond | MOV | s, r0, dst, src); |
1459 } | 1554 } |
1460 | 1555 |
1461 | 1556 |
1462 void Assembler::mov_label_offset(Register dst, Label* label) { | 1557 void Assembler::mov_label_offset(Register dst, Label* label) { |
1463 if (label->is_bound()) { | 1558 if (label->is_bound()) { |
1464 mov(dst, Operand(label->pos() + (Code::kHeaderSize - kHeapObjectTag))); | 1559 mov(dst, Operand(label->pos() + (Code::kHeaderSize - kHeapObjectTag))); |
1465 } else { | 1560 } else { |
1466 // Emit the link to the label in the code stream followed by extra nop | 1561 // Emit the link to the label in the code stream followed by extra nop |
1467 // instructions. | 1562 // instructions. |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1501 void Assembler::movw(Register reg, uint32_t immediate, Condition cond) { | 1596 void Assembler::movw(Register reg, uint32_t immediate, Condition cond) { |
1502 ASSERT(immediate < 0x10000); | 1597 ASSERT(immediate < 0x10000); |
1503 // May use movw if supported, but on unsupported platforms will try to use | 1598 // May use movw if supported, but on unsupported platforms will try to use |
1504 // equivalent rotated immed_8 value and other tricks before falling back to a | 1599 // equivalent rotated immed_8 value and other tricks before falling back to a |
1505 // constant pool load. | 1600 // constant pool load. |
1506 mov(reg, Operand(immediate), LeaveCC, cond); | 1601 mov(reg, Operand(immediate), LeaveCC, cond); |
1507 } | 1602 } |
1508 | 1603 |
1509 | 1604 |
1510 void Assembler::movt(Register reg, uint32_t immediate, Condition cond) { | 1605 void Assembler::movt(Register reg, uint32_t immediate, Condition cond) { |
| 1606 if (is_thumb_mode()) { |
| 1607 movt_thumb(reg, immediate, cond); |
| 1608 return; |
| 1609 } |
1511 emit(cond | 0x34*B20 | reg.code()*B12 | EncodeMovwImmediate(immediate)); | 1610 emit(cond | 0x34*B20 | reg.code()*B12 | EncodeMovwImmediate(immediate)); |
1512 } | 1611 } |
1513 | 1612 |
1514 | 1613 |
1515 void Assembler::bic(Register dst, Register src1, const Operand& src2, | 1614 void Assembler::bic(Register dst, Register src1, const Operand& src2, |
1516 SBit s, Condition cond) { | 1615 SBit s, Condition cond) { |
| 1616 if (is_thumb_mode()) { |
| 1617 bic_thumb(dst, src1, src2, s, cond); |
| 1618 return; |
| 1619 } |
1517 addrmod1(cond | BIC | s, src1, dst, src2); | 1620 addrmod1(cond | BIC | s, src1, dst, src2); |
1518 } | 1621 } |
1519 | 1622 |
1520 | 1623 |
1521 void Assembler::mvn(Register dst, const Operand& src, SBit s, Condition cond) { | 1624 void Assembler::mvn(Register dst, const Operand& src, SBit s, Condition cond) { |
| 1625 if (is_thumb_mode()) { |
| 1626 mvn_thumb(dst, src, s, cond); |
| 1627 return; |
| 1628 } |
1522 addrmod1(cond | MVN | s, r0, dst, src); | 1629 addrmod1(cond | MVN | s, r0, dst, src); |
1523 } | 1630 } |
1524 | 1631 |
1525 | 1632 |
1526 // Multiply instructions. | 1633 // Multiply instructions. |
1527 void Assembler::mla(Register dst, Register src1, Register src2, Register srcA, | 1634 void Assembler::mla(Register dst, Register src1, Register src2, Register srcA, |
1528 SBit s, Condition cond) { | 1635 SBit s, Condition cond) { |
| 1636 if (is_thumb_mode()) { |
| 1637 mla_thumb(dst, src1, src2, srcA, s, cond); |
| 1638 return; |
| 1639 } |
1529 ASSERT(!dst.is(pc) && !src1.is(pc) && !src2.is(pc) && !srcA.is(pc)); | 1640 ASSERT(!dst.is(pc) && !src1.is(pc) && !src2.is(pc) && !srcA.is(pc)); |
1530 emit(cond | A | s | dst.code()*B16 | srcA.code()*B12 | | 1641 emit(cond | A | s | dst.code()*B16 | srcA.code()*B12 | |
1531 src2.code()*B8 | B7 | B4 | src1.code()); | 1642 src2.code()*B8 | B7 | B4 | src1.code()); |
1532 } | 1643 } |
1533 | 1644 |
1534 | 1645 |
1535 void Assembler::mls(Register dst, Register src1, Register src2, Register srcA, | 1646 void Assembler::mls(Register dst, Register src1, Register src2, Register srcA, |
1536 Condition cond) { | 1647 Condition cond) { |
| 1648 if (is_thumb_mode()) { |
| 1649 mls_thumb(dst, src1, src2, srcA, cond); |
| 1650 return; |
| 1651 } |
1537 ASSERT(!dst.is(pc) && !src1.is(pc) && !src2.is(pc) && !srcA.is(pc)); | 1652 ASSERT(!dst.is(pc) && !src1.is(pc) && !src2.is(pc) && !srcA.is(pc)); |
1538 emit(cond | B22 | B21 | dst.code()*B16 | srcA.code()*B12 | | 1653 emit(cond | B22 | B21 | dst.code()*B16 | srcA.code()*B12 | |
1539 src2.code()*B8 | B7 | B4 | src1.code()); | 1654 src2.code()*B8 | B7 | B4 | src1.code()); |
1540 } | 1655 } |
1541 | 1656 |
1542 | 1657 |
1543 void Assembler::sdiv(Register dst, Register src1, Register src2, | 1658 void Assembler::sdiv(Register dst, Register src1, Register src2, |
1544 Condition cond) { | 1659 Condition cond) { |
| 1660 if (is_thumb_mode()) { |
| 1661 sdiv_thumb(dst, src1, src2, cond); |
| 1662 return; |
| 1663 } |
1545 ASSERT(!dst.is(pc) && !src1.is(pc) && !src2.is(pc)); | 1664 ASSERT(!dst.is(pc) && !src1.is(pc) && !src2.is(pc)); |
1546 ASSERT(IsEnabled(SUDIV)); | 1665 ASSERT(IsEnabled(SUDIV)); |
1547 emit(cond | B26 | B25| B24 | B20 | dst.code()*B16 | 0xf * B12 | | 1666 emit(cond | B26 | B25| B24 | B20 | dst.code()*B16 | 0xf * B12 | |
1548 src2.code()*B8 | B4 | src1.code()); | 1667 src2.code()*B8 | B4 | src1.code()); |
1549 } | 1668 } |
1550 | 1669 |
1551 | 1670 |
1552 void Assembler::mul(Register dst, Register src1, Register src2, | 1671 void Assembler::mul(Register dst, Register src1, Register src2, |
1553 SBit s, Condition cond) { | 1672 SBit s, Condition cond) { |
1554 ASSERT(!dst.is(pc) && !src1.is(pc) && !src2.is(pc)); | 1673 ASSERT(!dst.is(pc) && !src1.is(pc) && !src2.is(pc)); |
| 1674 if (is_thumb_mode()) { |
| 1675 mul_thumb(dst, src1, src2, s, cond); |
| 1676 return; |
| 1677 } |
1555 // dst goes in bits 16-19 for this instruction! | 1678 // dst goes in bits 16-19 for this instruction! |
1556 emit(cond | s | dst.code()*B16 | src2.code()*B8 | B7 | B4 | src1.code()); | 1679 emit(cond | s | dst.code()*B16 | src2.code()*B8 | B7 | B4 | src1.code()); |
1557 } | 1680 } |
1558 | 1681 |
1559 | 1682 |
1560 void Assembler::smlal(Register dstL, | 1683 void Assembler::smlal(Register dstL, |
1561 Register dstH, | 1684 Register dstH, |
1562 Register src1, | 1685 Register src1, |
1563 Register src2, | 1686 Register src2, |
1564 SBit s, | 1687 SBit s, |
1565 Condition cond) { | 1688 Condition cond) { |
| 1689 if (is_thumb_mode()) { |
| 1690 smlal_thumb(dstL, dstH, src1, src2, s, cond); |
| 1691 return; |
| 1692 } |
1566 ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc)); | 1693 ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc)); |
1567 ASSERT(!dstL.is(dstH)); | 1694 ASSERT(!dstL.is(dstH)); |
1568 emit(cond | B23 | B22 | A | s | dstH.code()*B16 | dstL.code()*B12 | | 1695 emit(cond | B23 | B22 | A | s | dstH.code()*B16 | dstL.code()*B12 | |
1569 src2.code()*B8 | B7 | B4 | src1.code()); | 1696 src2.code()*B8 | B7 | B4 | src1.code()); |
1570 } | 1697 } |
1571 | 1698 |
1572 | 1699 |
1573 void Assembler::smull(Register dstL, | 1700 void Assembler::smull(Register dstL, |
1574 Register dstH, | 1701 Register dstH, |
1575 Register src1, | 1702 Register src1, |
1576 Register src2, | 1703 Register src2, |
1577 SBit s, | 1704 SBit s, |
1578 Condition cond) { | 1705 Condition cond) { |
| 1706 if (is_thumb_mode()) { |
| 1707 smull_thumb(dstL, dstH, src1, src2, s, cond); |
| 1708 return; |
| 1709 } |
1579 ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc)); | 1710 ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc)); |
1580 ASSERT(!dstL.is(dstH)); | 1711 ASSERT(!dstL.is(dstH)); |
1581 emit(cond | B23 | B22 | s | dstH.code()*B16 | dstL.code()*B12 | | 1712 emit(cond | B23 | B22 | s | dstH.code()*B16 | dstL.code()*B12 | |
1582 src2.code()*B8 | B7 | B4 | src1.code()); | 1713 src2.code()*B8 | B7 | B4 | src1.code()); |
1583 } | 1714 } |
1584 | 1715 |
1585 | 1716 |
1586 void Assembler::umlal(Register dstL, | 1717 void Assembler::umlal(Register dstL, |
1587 Register dstH, | 1718 Register dstH, |
1588 Register src1, | 1719 Register src1, |
1589 Register src2, | 1720 Register src2, |
1590 SBit s, | 1721 SBit s, |
1591 Condition cond) { | 1722 Condition cond) { |
| 1723 if (is_thumb_mode()) { |
| 1724 umlal_thumb(dstL, dstH, src1, src2, s, cond); |
| 1725 return; |
| 1726 } |
1592 ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc)); | 1727 ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc)); |
1593 ASSERT(!dstL.is(dstH)); | 1728 ASSERT(!dstL.is(dstH)); |
1594 emit(cond | B23 | A | s | dstH.code()*B16 | dstL.code()*B12 | | 1729 emit(cond | B23 | A | s | dstH.code()*B16 | dstL.code()*B12 | |
1595 src2.code()*B8 | B7 | B4 | src1.code()); | 1730 src2.code()*B8 | B7 | B4 | src1.code()); |
1596 } | 1731 } |
1597 | 1732 |
1598 | 1733 |
1599 void Assembler::umull(Register dstL, | 1734 void Assembler::umull(Register dstL, |
1600 Register dstH, | 1735 Register dstH, |
1601 Register src1, | 1736 Register src1, |
1602 Register src2, | 1737 Register src2, |
1603 SBit s, | 1738 SBit s, |
1604 Condition cond) { | 1739 Condition cond) { |
| 1740 if (is_thumb_mode()) { |
| 1741 umull_thumb(dstL, dstH, src1, src2, s, cond); |
| 1742 return; |
| 1743 } |
1605 ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc)); | 1744 ASSERT(!dstL.is(pc) && !dstH.is(pc) && !src1.is(pc) && !src2.is(pc)); |
1606 ASSERT(!dstL.is(dstH)); | 1745 ASSERT(!dstL.is(dstH)); |
1607 emit(cond | B23 | s | dstH.code()*B16 | dstL.code()*B12 | | 1746 emit(cond | B23 | s | dstH.code()*B16 | dstL.code()*B12 | |
1608 src2.code()*B8 | B7 | B4 | src1.code()); | 1747 src2.code()*B8 | B7 | B4 | src1.code()); |
1609 } | 1748 } |
1610 | 1749 |
1611 | 1750 |
1612 // Miscellaneous arithmetic instructions. | 1751 // Miscellaneous arithmetic instructions. |
1613 void Assembler::clz(Register dst, Register src, Condition cond) { | 1752 void Assembler::clz(Register dst, Register src, Condition cond) { |
1614 // v5 and above. | 1753 // v5 and above. |
1615 ASSERT(!dst.is(pc) && !src.is(pc)); | 1754 ASSERT(!dst.is(pc) && !src.is(pc)); |
| 1755 |
| 1756 if (is_thumb_mode()) { |
| 1757 ASSERT(cond == al); |
| 1758 emit32(BH15 | BH14 | BH13 | BH12 | BH11 | BH9 | BH7 | src.code()*BH0 | |
| 1759 B15 | B14 | B13 | B12 | dst.code()*B8 | B7 | src.code()); |
| 1760 return; |
| 1761 } |
| 1762 |
1616 emit(cond | B24 | B22 | B21 | 15*B16 | dst.code()*B12 | | 1763 emit(cond | B24 | B22 | B21 | 15*B16 | dst.code()*B12 | |
1617 15*B8 | CLZ | src.code()); | 1764 15*B8 | CLZ | src.code()); |
1618 } | 1765 } |
1619 | 1766 |
1620 | 1767 |
1621 // Saturating instructions. | 1768 // Saturating instructions. |
1622 | 1769 |
1623 // Unsigned saturate. | 1770 // Unsigned saturate. |
1624 void Assembler::usat(Register dst, | 1771 void Assembler::usat(Register dst, |
1625 int satpos, | 1772 int satpos, |
1626 const Operand& src, | 1773 const Operand& src, |
1627 Condition cond) { | 1774 Condition cond) { |
1628 // v6 and above. | 1775 // v6 and above. |
1629 ASSERT(CpuFeatures::IsSupported(ARMv7)); | 1776 ASSERT(CpuFeatures::IsSupported(ARMv7)); |
1630 ASSERT(!dst.is(pc) && !src.rm_.is(pc)); | 1777 ASSERT(!dst.is(pc) && !src.rm_.is(pc)); |
1631 ASSERT((satpos >= 0) && (satpos <= 31)); | 1778 ASSERT((satpos >= 0) && (satpos <= 31)); |
1632 ASSERT((src.shift_op_ == ASR) || (src.shift_op_ == LSL)); | 1779 ASSERT((src.shift_op_ == ASR) || (src.shift_op_ == LSL)); |
1633 ASSERT(src.rs_.is(no_reg)); | 1780 ASSERT(src.rs_.is(no_reg)); |
1634 | 1781 |
1635 int sh = 0; | 1782 int sh = 0; |
1636 if (src.shift_op_ == ASR) { | 1783 if (src.shift_op_ == ASR) { |
1637 sh = 1; | 1784 sh = 1; |
1638 } | 1785 } |
1639 | 1786 |
| 1787 if (is_thumb_mode()) { |
| 1788 ASSERT(cond == al); |
| 1789 emit32(thumb32_mode3(USAT_32_IMM) | sh*BH5 | |
| 1790 thumb32_bit_field(src.rm_, dst, src.shift_imm_, satpos)); |
| 1791 return; |
| 1792 } |
| 1793 |
1640 emit(cond | 0x6*B24 | 0xe*B20 | satpos*B16 | dst.code()*B12 | | 1794 emit(cond | 0x6*B24 | 0xe*B20 | satpos*B16 | dst.code()*B12 | |
1641 src.shift_imm_*B7 | sh*B6 | 0x1*B4 | src.rm_.code()); | 1795 src.shift_imm_*B7 | sh*B6 | 0x1*B4 | src.rm_.code()); |
1642 } | 1796 } |
1643 | 1797 |
1644 | 1798 |
1645 // Bitfield manipulation instructions. | 1799 // Bitfield manipulation instructions. |
1646 | 1800 |
1647 // Unsigned bit field extract. | 1801 // Unsigned bit field extract. |
1648 // Extracts #width adjacent bits from position #lsb in a register, and | 1802 // Extracts #width adjacent bits from position #lsb in a register, and |
1649 // writes them to the low bits of a destination register. | 1803 // writes them to the low bits of a destination register. |
1650 // ubfx dst, src, #lsb, #width | 1804 // ubfx dst, src, #lsb, #width |
1651 void Assembler::ubfx(Register dst, | 1805 void Assembler::ubfx(Register dst, |
1652 Register src, | 1806 Register src, |
1653 int lsb, | 1807 int lsb, |
1654 int width, | 1808 int width, |
1655 Condition cond) { | 1809 Condition cond) { |
1656 // v7 and above. | 1810 // v7 and above. |
1657 ASSERT(CpuFeatures::IsSupported(ARMv7)); | 1811 ASSERT(CpuFeatures::IsSupported(ARMv7)); |
1658 ASSERT(!dst.is(pc) && !src.is(pc)); | 1812 ASSERT(!dst.is(pc) && !src.is(pc)); |
1659 ASSERT((lsb >= 0) && (lsb <= 31)); | 1813 ASSERT((lsb >= 0) && (lsb <= 31)); |
1660 ASSERT((width >= 1) && (width <= (32 - lsb))); | 1814 ASSERT((width >= 1) && (width <= (32 - lsb))); |
| 1815 |
| 1816 if (is_thumb_mode()) { |
| 1817 ASSERT(cond == al); |
| 1818 emit32(thumb32_mode3(UBFX_32_IMM) | |
| 1819 thumb32_bit_field(src, dst, lsb, width - 1)); |
| 1820 return; |
| 1821 } |
| 1822 |
1661 emit(cond | 0xf*B23 | B22 | B21 | (width - 1)*B16 | dst.code()*B12 | | 1823 emit(cond | 0xf*B23 | B22 | B21 | (width - 1)*B16 | dst.code()*B12 | |
1662 lsb*B7 | B6 | B4 | src.code()); | 1824 lsb*B7 | B6 | B4 | src.code()); |
1663 } | 1825 } |
1664 | 1826 |
1665 | 1827 |
1666 // Signed bit field extract. | 1828 // Signed bit field extract. |
1667 // Extracts #width adjacent bits from position #lsb in a register, and | 1829 // Extracts #width adjacent bits from position #lsb in a register, and |
1668 // writes them to the low bits of a destination register. The extracted | 1830 // writes them to the low bits of a destination register. The extracted |
1669 // value is sign extended to fill the destination register. | 1831 // value is sign extended to fill the destination register. |
1670 // sbfx dst, src, #lsb, #width | 1832 // sbfx dst, src, #lsb, #width |
1671 void Assembler::sbfx(Register dst, | 1833 void Assembler::sbfx(Register dst, |
1672 Register src, | 1834 Register src, |
1673 int lsb, | 1835 int lsb, |
1674 int width, | 1836 int width, |
1675 Condition cond) { | 1837 Condition cond) { |
1676 // v7 and above. | 1838 // v7 and above. |
1677 ASSERT(CpuFeatures::IsSupported(ARMv7)); | 1839 ASSERT(CpuFeatures::IsSupported(ARMv7)); |
1678 ASSERT(!dst.is(pc) && !src.is(pc)); | 1840 ASSERT(!dst.is(pc) && !src.is(pc)); |
1679 ASSERT((lsb >= 0) && (lsb <= 31)); | 1841 ASSERT((lsb >= 0) && (lsb <= 31)); |
1680 ASSERT((width >= 1) && (width <= (32 - lsb))); | 1842 ASSERT((width >= 1) && (width <= (32 - lsb))); |
| 1843 |
| 1844 if (is_thumb_mode()) { |
| 1845 ASSERT(cond == al); |
| 1846 emit32(thumb32_mode3(SBFX_32_IMM) | |
| 1847 thumb32_bit_field(src, dst, lsb, width - 1)); |
| 1848 return; |
| 1849 } |
| 1850 |
1681 emit(cond | 0xf*B23 | B21 | (width - 1)*B16 | dst.code()*B12 | | 1851 emit(cond | 0xf*B23 | B21 | (width - 1)*B16 | dst.code()*B12 | |
1682 lsb*B7 | B6 | B4 | src.code()); | 1852 lsb*B7 | B6 | B4 | src.code()); |
1683 } | 1853 } |
1684 | 1854 |
1685 | 1855 |
1686 // Bit field clear. | 1856 // Bit field clear. |
1687 // Sets #width adjacent bits at position #lsb in the destination register | 1857 // Sets #width adjacent bits at position #lsb in the destination register |
1688 // to zero, preserving the value of the other bits. | 1858 // to zero, preserving the value of the other bits. |
1689 // bfc dst, #lsb, #width | 1859 // bfc dst, #lsb, #width |
1690 void Assembler::bfc(Register dst, int lsb, int width, Condition cond) { | 1860 void Assembler::bfc(Register dst, int lsb, int width, Condition cond) { |
1691 // v7 and above. | 1861 // v7 and above. |
1692 ASSERT(CpuFeatures::IsSupported(ARMv7)); | 1862 ASSERT(CpuFeatures::IsSupported(ARMv7)); |
1693 ASSERT(!dst.is(pc)); | 1863 ASSERT(!dst.is(pc)); |
1694 ASSERT((lsb >= 0) && (lsb <= 31)); | 1864 ASSERT((lsb >= 0) && (lsb <= 31)); |
1695 ASSERT((width >= 1) && (width <= (32 - lsb))); | 1865 ASSERT((width >= 1) && (width <= (32 - lsb))); |
1696 int msb = lsb + width - 1; | 1866 int msb = lsb + width - 1; |
| 1867 |
| 1868 if (is_thumb_mode()) { |
| 1869 ASSERT(cond == al); |
| 1870 emit32(thumb32_mode3(BFC_32_IMM) | thumb32_bit_field(pc, dst, lsb, msb)); |
| 1871 return; |
| 1872 } |
| 1873 |
1697 emit(cond | 0x1f*B22 | msb*B16 | dst.code()*B12 | lsb*B7 | B4 | 0xf); | 1874 emit(cond | 0x1f*B22 | msb*B16 | dst.code()*B12 | lsb*B7 | B4 | 0xf); |
1698 } | 1875 } |
1699 | 1876 |
1700 | 1877 |
1701 // Bit field insert. | 1878 // Bit field insert. |
1702 // Inserts #width adjacent bits from the low bits of the source register | 1879 // Inserts #width adjacent bits from the low bits of the source register |
1703 // into position #lsb of the destination register. | 1880 // into position #lsb of the destination register. |
1704 // bfi dst, src, #lsb, #width | 1881 // bfi dst, src, #lsb, #width |
1705 void Assembler::bfi(Register dst, | 1882 void Assembler::bfi(Register dst, |
1706 Register src, | 1883 Register src, |
1707 int lsb, | 1884 int lsb, |
1708 int width, | 1885 int width, |
1709 Condition cond) { | 1886 Condition cond) { |
1710 // v7 and above. | 1887 // v7 and above. |
1711 ASSERT(CpuFeatures::IsSupported(ARMv7)); | 1888 ASSERT(CpuFeatures::IsSupported(ARMv7)); |
1712 ASSERT(!dst.is(pc) && !src.is(pc)); | 1889 ASSERT(!dst.is(pc) && !src.is(pc)); |
1713 ASSERT((lsb >= 0) && (lsb <= 31)); | 1890 ASSERT((lsb >= 0) && (lsb <= 31)); |
1714 ASSERT((width >= 1) && (width <= (32 - lsb))); | 1891 ASSERT((width >= 1) && (width <= (32 - lsb))); |
1715 int msb = lsb + width - 1; | 1892 int msb = lsb + width - 1; |
| 1893 |
| 1894 if (is_thumb_mode()) { |
| 1895 ASSERT(cond == al); |
| 1896 emit32(thumb32_mode3(BFI_32_IMM) | thumb32_bit_field(src, dst, lsb, msb)); |
| 1897 return; |
| 1898 } |
| 1899 |
1716 emit(cond | 0x1f*B22 | msb*B16 | dst.code()*B12 | lsb*B7 | B4 | | 1900 emit(cond | 0x1f*B22 | msb*B16 | dst.code()*B12 | lsb*B7 | B4 | |
1717 src.code()); | 1901 src.code()); |
1718 } | 1902 } |
1719 | 1903 |
1720 | 1904 |
1721 void Assembler::pkhbt(Register dst, | 1905 void Assembler::pkhbt(Register dst, |
1722 Register src1, | 1906 Register src1, |
1723 const Operand& src2, | 1907 const Operand& src2, |
1724 Condition cond ) { | 1908 Condition cond ) { |
1725 // Instruction details available in ARM DDI 0406C.b, A8.8.125. | 1909 // Instruction details available in ARM DDI 0406C.b, A8.8.125. |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1849 } | 2033 } |
1850 emit(cond | instr | B24 | B21 | fields | 15*B12); | 2034 emit(cond | instr | B24 | B21 | fields | 15*B12); |
1851 } | 2035 } |
1852 | 2036 |
1853 | 2037 |
1854 // Load/Store instructions. | 2038 // Load/Store instructions. |
1855 void Assembler::ldr(Register dst, const MemOperand& src, Condition cond) { | 2039 void Assembler::ldr(Register dst, const MemOperand& src, Condition cond) { |
1856 if (dst.is(pc)) { | 2040 if (dst.is(pc)) { |
1857 positions_recorder()->WriteRecordedPositions(); | 2041 positions_recorder()->WriteRecordedPositions(); |
1858 } | 2042 } |
| 2043 |
| 2044 if (is_thumb_mode()) { |
| 2045 ldr_thumb(dst, src); |
| 2046 return; |
| 2047 } |
| 2048 |
1859 addrmod2(cond | B26 | L, dst, src); | 2049 addrmod2(cond | B26 | L, dst, src); |
1860 } | 2050 } |
1861 | 2051 |
1862 | 2052 |
1863 void Assembler::str(Register src, const MemOperand& dst, Condition cond) { | 2053 void Assembler::str(Register src, const MemOperand& dst, Condition cond) { |
| 2054 if (is_thumb_mode()) { |
| 2055 ASSERT(cond == al); |
| 2056 str_thumb(src, dst); |
| 2057 return; |
| 2058 } |
1864 addrmod2(cond | B26, src, dst); | 2059 addrmod2(cond | B26, src, dst); |
1865 } | 2060 } |
1866 | 2061 |
1867 | 2062 |
1868 void Assembler::ldrb(Register dst, const MemOperand& src, Condition cond) { | 2063 void Assembler::ldrb(Register dst, const MemOperand& src, Condition cond) { |
| 2064 if (is_thumb_mode()) { |
| 2065 ASSERT(cond == al); |
| 2066 ldrb_thumb(dst, src); |
| 2067 return; |
| 2068 } |
1869 addrmod2(cond | B26 | B | L, dst, src); | 2069 addrmod2(cond | B26 | B | L, dst, src); |
1870 } | 2070 } |
1871 | 2071 |
1872 | 2072 |
1873 void Assembler::strb(Register src, const MemOperand& dst, Condition cond) { | 2073 void Assembler::strb(Register src, const MemOperand& dst, Condition cond) { |
| 2074 if (is_thumb_mode()) { |
| 2075 ASSERT(cond == al); |
| 2076 strb_thumb(src, dst); |
| 2077 return; |
| 2078 } |
1874 addrmod2(cond | B26 | B, src, dst); | 2079 addrmod2(cond | B26 | B, src, dst); |
1875 } | 2080 } |
1876 | 2081 |
1877 | 2082 |
1878 void Assembler::ldrh(Register dst, const MemOperand& src, Condition cond) { | 2083 void Assembler::ldrh(Register dst, const MemOperand& src, Condition cond) { |
| 2084 if (is_thumb_mode()) { |
| 2085 ASSERT(cond == al); |
| 2086 ldrh_thumb(dst, src); |
| 2087 return; |
| 2088 } |
1879 addrmod3(cond | L | B7 | H | B4, dst, src); | 2089 addrmod3(cond | L | B7 | H | B4, dst, src); |
1880 } | 2090 } |
1881 | 2091 |
1882 | 2092 |
1883 void Assembler::strh(Register src, const MemOperand& dst, Condition cond) { | 2093 void Assembler::strh(Register src, const MemOperand& dst, Condition cond) { |
| 2094 if (is_thumb_mode()) { |
| 2095 ASSERT(cond == al); |
| 2096 strh_thumb(src, dst); |
| 2097 return; |
| 2098 } |
1884 addrmod3(cond | B7 | H | B4, src, dst); | 2099 addrmod3(cond | B7 | H | B4, src, dst); |
1885 } | 2100 } |
1886 | 2101 |
1887 | 2102 |
1888 void Assembler::ldrsb(Register dst, const MemOperand& src, Condition cond) { | 2103 void Assembler::ldrsb(Register dst, const MemOperand& src, Condition cond) { |
| 2104 if (is_thumb_mode()) { |
| 2105 ASSERT(cond == al); |
| 2106 ldrsb_thumb(dst, src); |
| 2107 return; |
| 2108 } |
1889 addrmod3(cond | L | B7 | S6 | B4, dst, src); | 2109 addrmod3(cond | L | B7 | S6 | B4, dst, src); |
1890 } | 2110 } |
1891 | 2111 |
1892 | 2112 |
1893 void Assembler::ldrsh(Register dst, const MemOperand& src, Condition cond) { | 2113 void Assembler::ldrsh(Register dst, const MemOperand& src, Condition cond) { |
| 2114 if (is_thumb_mode()) { |
| 2115 ASSERT(cond == al); |
| 2116 ldrsh_thumb(dst, src); |
| 2117 return; |
| 2118 } |
1894 addrmod3(cond | L | B7 | S6 | H | B4, dst, src); | 2119 addrmod3(cond | L | B7 | S6 | H | B4, dst, src); |
1895 } | 2120 } |
1896 | 2121 |
1897 | 2122 |
1898 void Assembler::ldrd(Register dst1, Register dst2, | 2123 void Assembler::ldrd(Register dst1, Register dst2, |
1899 const MemOperand& src, Condition cond) { | 2124 const MemOperand& src, Condition cond) { |
1900 ASSERT(IsEnabled(ARMv7)); | 2125 ASSERT(IsEnabled(ARMv7)); |
1901 ASSERT(src.rm().is(no_reg)); | 2126 ASSERT(src.rm().is(no_reg)); |
1902 ASSERT(!dst1.is(lr)); // r14. | 2127 ASSERT(!dst1.is(lr)); // r14. |
1903 ASSERT_EQ(0, dst1.code() % 2); | 2128 ASSERT_EQ(0, dst1.code() % 2); |
| 2129 if (is_thumb_mode()) { |
| 2130 ASSERT(cond == al); |
| 2131 ASSERT(!src.rm_.is_valid()); // Immediate. |
| 2132 ldrd_imm_t1(dst1, dst2, src); |
| 2133 return; |
| 2134 } |
1904 ASSERT_EQ(dst1.code() + 1, dst2.code()); | 2135 ASSERT_EQ(dst1.code() + 1, dst2.code()); |
1905 addrmod3(cond | B7 | B6 | B4, dst1, src); | 2136 addrmod3(cond | B7 | B6 | B4, dst1, src); |
1906 } | 2137 } |
1907 | 2138 |
1908 | 2139 |
1909 void Assembler::strd(Register src1, Register src2, | 2140 void Assembler::strd(Register src1, Register src2, |
1910 const MemOperand& dst, Condition cond) { | 2141 const MemOperand& dst, Condition cond) { |
1911 ASSERT(dst.rm().is(no_reg)); | 2142 ASSERT(dst.rm().is(no_reg)); |
1912 ASSERT(!src1.is(lr)); // r14. | 2143 ASSERT(!src1.is(lr)); // r14. |
1913 ASSERT_EQ(0, src1.code() % 2); | 2144 ASSERT_EQ(0, src1.code() % 2); |
| 2145 ASSERT(IsEnabled(ARMv7)); |
| 2146 if (is_thumb_mode()) { |
| 2147 ASSERT(cond == al); |
| 2148 ASSERT(!dst.rm_.is_valid()); // Immediate. |
| 2149 strd_imm_t1(src1, src2, dst); |
| 2150 return; |
| 2151 } |
1914 ASSERT_EQ(src1.code() + 1, src2.code()); | 2152 ASSERT_EQ(src1.code() + 1, src2.code()); |
1915 ASSERT(IsEnabled(ARMv7)); | |
1916 addrmod3(cond | B7 | B6 | B5 | B4, src1, dst); | 2153 addrmod3(cond | B7 | B6 | B5 | B4, src1, dst); |
1917 } | 2154 } |
1918 | 2155 |
1919 | 2156 |
1920 // Preload instructions. | 2157 // Preload instructions. |
1921 void Assembler::pld(const MemOperand& address) { | 2158 void Assembler::pld(const MemOperand& address) { |
1922 // Instruction details available in ARM DDI 0406C.b, A8.8.128. | 2159 // Instruction details available in ARM DDI 0406C.b, A8.8.128. |
1923 // 1111(31-28) | 0111(27-24) | U(23) | R(22) | 01(21-20) | Rn(19-16) | | 2160 // 1111(31-28) | 0111(27-24) | U(23) | R(22) | 01(21-20) | Rn(19-16) | |
1924 // 1111(15-12) | imm5(11-07) | type(6-5) | 0(4)| Rm(3-0) | | 2161 // 1111(15-12) | imm5(11-07) | type(6-5) | 0(4)| Rm(3-0) | |
1925 ASSERT(address.rm().is(no_reg)); | 2162 ASSERT(address.rm().is(no_reg)); |
(...skipping 10 matching lines...) Expand all Loading... |
1936 } | 2173 } |
1937 | 2174 |
1938 | 2175 |
1939 // Load/Store multiple instructions. | 2176 // Load/Store multiple instructions. |
1940 void Assembler::ldm(BlockAddrMode am, | 2177 void Assembler::ldm(BlockAddrMode am, |
1941 Register base, | 2178 Register base, |
1942 RegList dst, | 2179 RegList dst, |
1943 Condition cond) { | 2180 Condition cond) { |
1944 // ABI stack constraint: ldmxx base, {..sp..} base != sp is not restartable. | 2181 // ABI stack constraint: ldmxx base, {..sp..} base != sp is not restartable. |
1945 ASSERT(base.is(sp) || (dst & sp.bit()) == 0); | 2182 ASSERT(base.is(sp) || (dst & sp.bit()) == 0); |
1946 | 2183 if (is_thumb_mode()) { |
| 2184 ldm_thumb(am, base, dst, cond); |
| 2185 return; |
| 2186 } |
1947 addrmod4(cond | B27 | am | L, base, dst); | 2187 addrmod4(cond | B27 | am | L, base, dst); |
1948 | 2188 |
1949 // Emit the constant pool after a function return implemented by ldm ..{..pc}. | 2189 // Emit the constant pool after a function return implemented by ldm ..{..pc}. |
1950 if (cond == al && (dst & pc.bit()) != 0) { | 2190 if (cond == al && (dst & pc.bit()) != 0) { |
1951 // There is a slight chance that the ldm instruction was actually a call, | 2191 // There is a slight chance that the ldm instruction was actually a call, |
1952 // in which case it would be wrong to return into the constant pool; we | 2192 // in which case it would be wrong to return into the constant pool; we |
1953 // recognize this case by checking if the emission of the pool was blocked | 2193 // recognize this case by checking if the emission of the pool was blocked |
1954 // at the pc of the ldm instruction by a mov lr, pc instruction; if this is | 2194 // at the pc of the ldm instruction by a mov lr, pc instruction; if this is |
1955 // the case, we emit a jump over the pool. | 2195 // the case, we emit a jump over the pool. |
1956 CheckConstPool(true, no_const_pool_before_ == pc_offset() - kInstrSize); | 2196 CheckConstPool(true, no_const_pool_before_ == pc_offset() - kInstrSize); |
1957 } | 2197 } |
1958 } | 2198 } |
1959 | 2199 |
1960 | 2200 |
1961 void Assembler::stm(BlockAddrMode am, | 2201 void Assembler::stm(BlockAddrMode am, |
1962 Register base, | 2202 Register base, |
1963 RegList src, | 2203 RegList src, |
1964 Condition cond) { | 2204 Condition cond) { |
| 2205 if (is_thumb_mode()) { |
| 2206 stm_thumb(am, base, src, cond); |
| 2207 return; |
| 2208 } |
1965 addrmod4(cond | B27 | am, base, src); | 2209 addrmod4(cond | B27 | am, base, src); |
1966 } | 2210 } |
1967 | 2211 |
1968 | 2212 |
1969 // Exception-generating instructions and debugging support. | 2213 // Exception-generating instructions and debugging support. |
1970 // Stops with a non-negative code less than kNumOfWatchedStops support | 2214 // Stops with a non-negative code less than kNumOfWatchedStops support |
1971 // enabling/disabling and a counter feature. See simulator-arm.h . | 2215 // enabling/disabling and a counter feature. See simulator-arm.h . |
1972 void Assembler::stop(const char* msg, Condition cond, int32_t code) { | 2216 void Assembler::stop(const char* msg, Condition cond, int32_t code) { |
1973 #ifndef __arm__ | 2217 #ifndef __arm__ |
1974 ASSERT(code >= kDefaultStopCode); | 2218 ASSERT(code >= kDefaultStopCode); |
(...skipping 15 matching lines...) Expand all Loading... |
1990 bkpt(0); | 2234 bkpt(0); |
1991 bind(&skip); | 2235 bind(&skip); |
1992 } else { | 2236 } else { |
1993 bkpt(0); | 2237 bkpt(0); |
1994 } | 2238 } |
1995 #endif // def __arm__ | 2239 #endif // def __arm__ |
1996 } | 2240 } |
1997 | 2241 |
1998 | 2242 |
1999 void Assembler::bkpt(uint32_t imm16) { // v5 and above | 2243 void Assembler::bkpt(uint32_t imm16) { // v5 and above |
| 2244 if (is_thumb_mode()) { |
| 2245 ASSERT(is_uint8(imm16)); |
| 2246 emit16(B15 | B13 | B12 | B11 | B10 | B9 | (imm16 & 0xFF)); |
| 2247 return; |
| 2248 } |
2000 ASSERT(is_uint16(imm16)); | 2249 ASSERT(is_uint16(imm16)); |
2001 emit(al | B24 | B21 | (imm16 >> 4)*B8 | BKPT | (imm16 & 0xf)); | 2250 emit(al | B24 | B21 | (imm16 >> 4)*B8 | BKPT | (imm16 & 0xf)); |
2002 } | 2251 } |
2003 | 2252 |
2004 | 2253 |
2005 void Assembler::svc(uint32_t imm24, Condition cond) { | 2254 void Assembler::svc(uint32_t imm24, Condition cond) { |
2006 ASSERT(is_uint24(imm24)); | 2255 ASSERT(is_uint24(imm24)); |
2007 emit(cond | 15*B24 | imm24); | 2256 emit(cond | 15*B24 | imm24); |
2008 } | 2257 } |
2009 | 2258 |
(...skipping 522 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2532 const VmovIndex index, | 2781 const VmovIndex index, |
2533 const Register src, | 2782 const Register src, |
2534 const Condition cond) { | 2783 const Condition cond) { |
2535 // Dd[index] = Rt | 2784 // Dd[index] = Rt |
2536 // Instruction details available in ARM DDI 0406C.b, A8-940. | 2785 // Instruction details available in ARM DDI 0406C.b, A8-940. |
2537 // cond(31-28) | 1110(27-24) | 0(23) | opc1=0index(22-21) | 0(20) | | 2786 // cond(31-28) | 1110(27-24) | 0(23) | opc1=0index(22-21) | 0(20) | |
2538 // Vd(19-16) | Rt(15-12) | 1011(11-8) | D(7) | opc2=00(6-5) | 1(4) | 0000(3-0) | 2787 // Vd(19-16) | Rt(15-12) | 1011(11-8) | D(7) | opc2=00(6-5) | 1(4) | 0000(3-0) |
2539 ASSERT(index.index == 0 || index.index == 1); | 2788 ASSERT(index.index == 0 || index.index == 1); |
2540 int vd, d; | 2789 int vd, d; |
2541 dst.split_code(&vd, &d); | 2790 dst.split_code(&vd, &d); |
| 2791 if (is_thumb_mode() && cond != al) { |
| 2792 it_thumb(cond, 1); |
| 2793 emit(al | 0xE*B24 | index.index*B21 | vd*B16 | src.code()*B12 | 0xB*B8 | |
| 2794 d*B7 | B4); |
| 2795 return; |
| 2796 } |
2542 emit(cond | 0xE*B24 | index.index*B21 | vd*B16 | src.code()*B12 | 0xB*B8 | | 2797 emit(cond | 0xE*B24 | index.index*B21 | vd*B16 | src.code()*B12 | 0xB*B8 | |
2543 d*B7 | B4); | 2798 d*B7 | B4); |
2544 } | 2799 } |
2545 | 2800 |
2546 | 2801 |
2547 void Assembler::vmov(const Register dst, | 2802 void Assembler::vmov(const Register dst, |
2548 const VmovIndex index, | 2803 const VmovIndex index, |
2549 const DwVfpRegister src, | 2804 const DwVfpRegister src, |
2550 const Condition cond) { | 2805 const Condition cond) { |
2551 // Dd[index] = Rt | 2806 // Dd[index] = Rt |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2809 void Assembler::vneg(const DwVfpRegister dst, | 3064 void Assembler::vneg(const DwVfpRegister dst, |
2810 const DwVfpRegister src, | 3065 const DwVfpRegister src, |
2811 const Condition cond) { | 3066 const Condition cond) { |
2812 // Instruction details available in ARM DDI 0406C.b, A8-968. | 3067 // Instruction details available in ARM DDI 0406C.b, A8-968. |
2813 // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0001(19-16) | Vd(15-12) | | 3068 // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0001(19-16) | Vd(15-12) | |
2814 // 101(11-9) | sz=1(8) | 0(7) | 1(6) | M(5) | 0(4) | Vm(3-0) | 3069 // 101(11-9) | sz=1(8) | 0(7) | 1(6) | M(5) | 0(4) | Vm(3-0) |
2815 int vd, d; | 3070 int vd, d; |
2816 dst.split_code(&vd, &d); | 3071 dst.split_code(&vd, &d); |
2817 int vm, m; | 3072 int vm, m; |
2818 src.split_code(&vm, &m); | 3073 src.split_code(&vm, &m); |
2819 | 3074 if (is_thumb_mode() && cond != al) { |
| 3075 it_thumb(cond, 1); |
| 3076 emit(al | 0x1D*B23 | d*B22 | 0x3*B20 | B16 | vd*B12 | 0x5*B9 | B8 | B6 | |
| 3077 m*B5 | vm); |
| 3078 return; |
| 3079 } |
2820 emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | B16 | vd*B12 | 0x5*B9 | B8 | B6 | | 3080 emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | B16 | vd*B12 | 0x5*B9 | B8 | B6 | |
2821 m*B5 | vm); | 3081 m*B5 | vm); |
2822 } | 3082 } |
2823 | 3083 |
2824 | 3084 |
2825 void Assembler::vabs(const DwVfpRegister dst, | 3085 void Assembler::vabs(const DwVfpRegister dst, |
2826 const DwVfpRegister src, | 3086 const DwVfpRegister src, |
2827 const Condition cond) { | 3087 const Condition cond) { |
2828 // Instruction details available in ARM DDI 0406C.b, A8-524. | 3088 // Instruction details available in ARM DDI 0406C.b, A8-524. |
2829 // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0000(19-16) | Vd(15-12) | | 3089 // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0000(19-16) | Vd(15-12) | |
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3061 | 3321 |
3062 | 3322 |
3063 // Pseudo instructions. | 3323 // Pseudo instructions. |
3064 void Assembler::nop(int type) { | 3324 void Assembler::nop(int type) { |
3065 // ARMv6{K/T2} and v7 have an actual NOP instruction but it serializes | 3325 // ARMv6{K/T2} and v7 have an actual NOP instruction but it serializes |
3066 // some of the CPU's pipeline and has to issue. Older ARM chips simply used | 3326 // some of the CPU's pipeline and has to issue. Older ARM chips simply used |
3067 // MOV Rx, Rx as NOP and it performs better even in newer CPUs. | 3327 // MOV Rx, Rx as NOP and it performs better even in newer CPUs. |
3068 // We therefore use MOV Rx, Rx, even on newer CPUs, and use Rx to encode | 3328 // We therefore use MOV Rx, Rx, even on newer CPUs, and use Rx to encode |
3069 // a type. | 3329 // a type. |
3070 ASSERT(0 <= type && type <= 14); // mov pc, pc isn't a nop. | 3330 ASSERT(0 <= type && type <= 14); // mov pc, pc isn't a nop. |
| 3331 if (is_thumb_mode()) { |
| 3332 uint16_t d = type >> 3; |
| 3333 emit16(4*B12 | 6*B8 | d*B7 | type*B3 | (type & 7)); |
| 3334 return; |
| 3335 } |
3071 emit(al | 13*B21 | type*B12 | type); | 3336 emit(al | 13*B21 | type*B12 | type); |
3072 } | 3337 } |
3073 | 3338 |
3074 | 3339 |
3075 bool Assembler::IsMovT(Instr instr) { | 3340 bool Assembler::IsMovT(Instr instr) { |
3076 instr &= ~(((kNumberOfConditions - 1) << 28) | // Mask off conditions | 3341 instr &= ~(((kNumberOfConditions - 1) << 28) | // Mask off conditions |
3077 ((kNumRegisters-1)*B12) | // mask out register | 3342 ((kNumRegisters-1)*B12) | // mask out register |
3078 EncodeMovwImmediate(0xFFFF)); // mask out immediate value | 3343 EncodeMovwImmediate(0xFFFF)); // mask out immediate value |
3079 return instr == 0x34*B20; | 3344 return instr == 0x34*B20; |
3080 } | 3345 } |
3081 | 3346 |
3082 | 3347 |
3083 bool Assembler::IsMovW(Instr instr) { | 3348 bool Assembler::IsMovW(Instr instr) { |
3084 instr &= ~(((kNumberOfConditions - 1) << 28) | // Mask off conditions | 3349 instr &= ~(((kNumberOfConditions - 1) << 28) | // Mask off conditions |
3085 ((kNumRegisters-1)*B12) | // mask out destination | 3350 ((kNumRegisters-1)*B12) | // mask out destination |
3086 EncodeMovwImmediate(0xFFFF)); // mask out immediate value | 3351 EncodeMovwImmediate(0xFFFF)); // mask out immediate value |
3087 return instr == 0x30*B20; | 3352 return instr == 0x30*B20; |
3088 } | 3353 } |
3089 | 3354 |
3090 | 3355 |
| 3356 bool Assembler::IsMovTThumb(Instr instr) { |
| 3357 return ((instr & ~MOVW_THUMB_IMM_MASK) == (MOVW_THUMB_MASK | BH7)); |
| 3358 } |
| 3359 |
| 3360 |
| 3361 bool Assembler::IsMovWThumb(Instr instr) { |
| 3362 return ((instr & ~MOVW_THUMB_IMM_MASK) == MOVW_THUMB_MASK); |
| 3363 } |
| 3364 |
| 3365 |
3091 bool Assembler::IsNop(Instr instr, int type) { | 3366 bool Assembler::IsNop(Instr instr, int type) { |
3092 ASSERT(0 <= type && type <= 14); // mov pc, pc isn't a nop. | 3367 ASSERT(0 <= type && type <= 14); // mov pc, pc isn't a nop. |
3093 // Check for mov rx, rx where x = type. | 3368 // Check for mov rx, rx where x = type. |
3094 return instr == (al | 13*B21 | type*B12 | type); | 3369 return instr == (al | 13*B21 | type*B12 | type); |
3095 } | 3370 } |
3096 | 3371 |
3097 | 3372 |
3098 bool Assembler::ImmediateFitsAddrMode1Instruction(int32_t imm32) { | 3373 bool Assembler::ImmediateFitsAddrMode1Instruction(int32_t imm32) { |
3099 uint32_t dummy1; | 3374 uint32_t dummy1; |
3100 uint32_t dummy2; | 3375 uint32_t dummy2; |
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3372 RecordConstPool(size); | 3647 RecordConstPool(size); |
3373 | 3648 |
3374 // Emit jump over constant pool if necessary. | 3649 // Emit jump over constant pool if necessary. |
3375 Label after_pool; | 3650 Label after_pool; |
3376 if (require_jump) { | 3651 if (require_jump) { |
3377 b(&after_pool); | 3652 b(&after_pool); |
3378 } | 3653 } |
3379 | 3654 |
3380 // Put down constant pool marker "Undefined instruction". | 3655 // Put down constant pool marker "Undefined instruction". |
3381 // The data size helps disassembly know what to print. | 3656 // The data size helps disassembly know what to print. |
3382 emit(kConstantPoolMarker | | 3657 if (is_thumb_mode()) { |
3383 EncodeConstantPoolLength(size_after_marker / kPointerSize)); | 3658 emit32(kConstantPoolMarker | |
| 3659 EncodeConstantPoolLength(size_after_marker / kPointerSize)); |
| 3660 } else { |
| 3661 emit(kConstantPoolMarker | |
| 3662 EncodeConstantPoolLength(size_after_marker / kPointerSize)); |
| 3663 } |
3384 | 3664 |
3385 if (require_64_bit_align) { | 3665 if (require_64_bit_align) { |
3386 emit(kConstantPoolMarker); | 3666 emit(kConstantPoolMarker); |
3387 } | 3667 } |
3388 | 3668 |
3389 // Emit 64-bit constant pool entries first: their range is smaller than | 3669 // Emit 64-bit constant pool entries first: their range is smaller than |
3390 // 32-bit entries. | 3670 // 32-bit entries. |
3391 for (int i = 0; i < num_pending_reloc_info_; i++) { | 3671 for (int i = 0; i < num_pending_reloc_info_; i++) { |
3392 RelocInfo& rinfo = pending_reloc_info_[i]; | 3672 RelocInfo& rinfo = pending_reloc_info_[i]; |
3393 | 3673 |
(...skipping 27 matching lines...) Expand all Loading... |
3421 ASSERT(rinfo.rmode() != RelocInfo::COMMENT && | 3701 ASSERT(rinfo.rmode() != RelocInfo::COMMENT && |
3422 rinfo.rmode() != RelocInfo::POSITION && | 3702 rinfo.rmode() != RelocInfo::POSITION && |
3423 rinfo.rmode() != RelocInfo::STATEMENT_POSITION && | 3703 rinfo.rmode() != RelocInfo::STATEMENT_POSITION && |
3424 rinfo.rmode() != RelocInfo::CONST_POOL); | 3704 rinfo.rmode() != RelocInfo::CONST_POOL); |
3425 | 3705 |
3426 if (rinfo.rmode() == RelocInfo::NONE64) { | 3706 if (rinfo.rmode() == RelocInfo::NONE64) { |
3427 // 64-bit values emitted earlier. | 3707 // 64-bit values emitted earlier. |
3428 continue; | 3708 continue; |
3429 } | 3709 } |
3430 | 3710 |
| 3711 if (is_thumb_mode()) { |
| 3712 Instr instr = thumb32_instr_at(rinfo.pc()); |
| 3713 int thumb_ldr_delta = 2; |
| 3714 if ((reinterpret_cast<int>(rinfo.pc()) & 3) == 0) { |
| 3715 thumb_ldr_delta = 4; |
| 3716 } |
| 3717 int delta = pc_ - rinfo.pc() - thumb_ldr_delta; |
| 3718 ASSERT(is_uint12(delta)); |
| 3719 instr &= ~kOff12Mask; |
| 3720 instr |= delta; |
| 3721 thumb32_instr_at_put(rinfo.pc(), instr); |
| 3722 set_arm_mode(); |
| 3723 emit(rinfo.data()); |
| 3724 set_thumb_mode(); |
| 3725 continue; |
| 3726 } |
| 3727 |
3431 Instr instr = instr_at(rinfo.pc()); | 3728 Instr instr = instr_at(rinfo.pc()); |
3432 | 3729 |
3433 // 64-bit loads shouldn't get here. | 3730 // 64-bit loads shouldn't get here. |
3434 ASSERT(!IsVldrDPcImmediateOffset(instr)); | 3731 ASSERT(!IsVldrDPcImmediateOffset(instr)); |
3435 | 3732 |
3436 int delta = pc_ - rinfo.pc() - kPcLoadDelta; | 3733 int delta = pc_ - rinfo.pc() - kPcLoadDelta; |
3437 // 0 is the smallest delta: | 3734 // 0 is the smallest delta: |
3438 // ldr rd, [pc, #0] | 3735 // ldr rd, [pc, #0] |
3439 // constant pool marker | 3736 // constant pool marker |
3440 // data | 3737 // data |
(...skipping 22 matching lines...) Expand all Loading... |
3463 | 3760 |
3464 // Since a constant pool was just emitted, move the check offset forward by | 3761 // Since a constant pool was just emitted, move the check offset forward by |
3465 // the standard interval. | 3762 // the standard interval. |
3466 next_buffer_check_ = pc_offset() + kCheckPoolInterval; | 3763 next_buffer_check_ = pc_offset() + kCheckPoolInterval; |
3467 } | 3764 } |
3468 | 3765 |
3469 | 3766 |
3470 } } // namespace v8::internal | 3767 } } // namespace v8::internal |
3471 | 3768 |
3472 #endif // V8_TARGET_ARCH_ARM | 3769 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |