| 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 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 282 const Instr kLdrStrOffsetMask = 0x00000fff; | 282 const Instr kLdrStrOffsetMask = 0x00000fff; |
| 283 | 283 |
| 284 | 284 |
| 285 // Spare buffer. | 285 // Spare buffer. |
| 286 static const int kMinimalBufferSize = 4*KB; | 286 static const int kMinimalBufferSize = 4*KB; |
| 287 | 287 |
| 288 | 288 |
| 289 Assembler::Assembler(Isolate* arg_isolate, void* buffer, int buffer_size) | 289 Assembler::Assembler(Isolate* arg_isolate, void* buffer, int buffer_size) |
| 290 : AssemblerBase(arg_isolate), | 290 : AssemblerBase(arg_isolate), |
| 291 positions_recorder_(this), | 291 positions_recorder_(this), |
| 292 allow_peephole_optimization_(false), | |
| 293 emit_debug_code_(FLAG_debug_code) { | 292 emit_debug_code_(FLAG_debug_code) { |
| 294 allow_peephole_optimization_ = FLAG_peephole_optimization; | |
| 295 if (buffer == NULL) { | 293 if (buffer == NULL) { |
| 296 // Do our own buffer management. | 294 // Do our own buffer management. |
| 297 if (buffer_size <= kMinimalBufferSize) { | 295 if (buffer_size <= kMinimalBufferSize) { |
| 298 buffer_size = kMinimalBufferSize; | 296 buffer_size = kMinimalBufferSize; |
| 299 | 297 |
| 300 if (isolate()->assembler_spare_buffer() != NULL) { | 298 if (isolate()->assembler_spare_buffer() != NULL) { |
| 301 buffer = isolate()->assembler_spare_buffer(); | 299 buffer = isolate()->assembler_spare_buffer(); |
| 302 isolate()->set_assembler_spare_buffer(NULL); | 300 isolate()->set_assembler_spare_buffer(NULL); |
| 303 } | 301 } |
| 304 } | 302 } |
| (...skipping 784 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1089 | 1087 |
| 1090 void Assembler::rsb(Register dst, Register src1, const Operand& src2, | 1088 void Assembler::rsb(Register dst, Register src1, const Operand& src2, |
| 1091 SBit s, Condition cond) { | 1089 SBit s, Condition cond) { |
| 1092 addrmod1(cond | RSB | s, src1, dst, src2); | 1090 addrmod1(cond | RSB | s, src1, dst, src2); |
| 1093 } | 1091 } |
| 1094 | 1092 |
| 1095 | 1093 |
| 1096 void Assembler::add(Register dst, Register src1, const Operand& src2, | 1094 void Assembler::add(Register dst, Register src1, const Operand& src2, |
| 1097 SBit s, Condition cond) { | 1095 SBit s, Condition cond) { |
| 1098 addrmod1(cond | ADD | s, src1, dst, src2); | 1096 addrmod1(cond | ADD | s, src1, dst, src2); |
| 1099 | |
| 1100 // Eliminate pattern: push(r), pop() | |
| 1101 // str(src, MemOperand(sp, 4, NegPreIndex), al); | |
| 1102 // add(sp, sp, Operand(kPointerSize)); | |
| 1103 // Both instructions can be eliminated. | |
| 1104 if (can_peephole_optimize(2) && | |
| 1105 // Pattern. | |
| 1106 instr_at(pc_ - 1 * kInstrSize) == kPopInstruction && | |
| 1107 (instr_at(pc_ - 2 * kInstrSize) & ~kRdMask) == kPushRegPattern) { | |
| 1108 pc_ -= 2 * kInstrSize; | |
| 1109 if (FLAG_print_peephole_optimization) { | |
| 1110 PrintF("%x push(reg)/pop() eliminated\n", pc_offset()); | |
| 1111 } | |
| 1112 } | |
| 1113 } | 1097 } |
| 1114 | 1098 |
| 1115 | 1099 |
| 1116 void Assembler::adc(Register dst, Register src1, const Operand& src2, | 1100 void Assembler::adc(Register dst, Register src1, const Operand& src2, |
| 1117 SBit s, Condition cond) { | 1101 SBit s, Condition cond) { |
| 1118 addrmod1(cond | ADC | s, src1, dst, src2); | 1102 addrmod1(cond | ADC | s, src1, dst, src2); |
| 1119 } | 1103 } |
| 1120 | 1104 |
| 1121 | 1105 |
| 1122 void Assembler::sbc(Register dst, Register src1, const Operand& src2, | 1106 void Assembler::sbc(Register dst, Register src1, const Operand& src2, |
| (...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1407 emit(cond | instr | B24 | B21 | fields | 15*B12); | 1391 emit(cond | instr | B24 | B21 | fields | 15*B12); |
| 1408 } | 1392 } |
| 1409 | 1393 |
| 1410 | 1394 |
| 1411 // Load/Store instructions. | 1395 // Load/Store instructions. |
| 1412 void Assembler::ldr(Register dst, const MemOperand& src, Condition cond) { | 1396 void Assembler::ldr(Register dst, const MemOperand& src, Condition cond) { |
| 1413 if (dst.is(pc)) { | 1397 if (dst.is(pc)) { |
| 1414 positions_recorder()->WriteRecordedPositions(); | 1398 positions_recorder()->WriteRecordedPositions(); |
| 1415 } | 1399 } |
| 1416 addrmod2(cond | B26 | L, dst, src); | 1400 addrmod2(cond | B26 | L, dst, src); |
| 1417 | |
| 1418 // Eliminate pattern: push(ry), pop(rx) | |
| 1419 // str(ry, MemOperand(sp, 4, NegPreIndex), al) | |
| 1420 // ldr(rx, MemOperand(sp, 4, PostIndex), al) | |
| 1421 // Both instructions can be eliminated if ry = rx. | |
| 1422 // If ry != rx, a register copy from ry to rx is inserted | |
| 1423 // after eliminating the push and the pop instructions. | |
| 1424 if (can_peephole_optimize(2)) { | |
| 1425 Instr push_instr = instr_at(pc_ - 2 * kInstrSize); | |
| 1426 Instr pop_instr = instr_at(pc_ - 1 * kInstrSize); | |
| 1427 | |
| 1428 if (IsPush(push_instr) && IsPop(pop_instr)) { | |
| 1429 if (Instruction::RdValue(pop_instr) != Instruction::RdValue(push_instr)) { | |
| 1430 // For consecutive push and pop on different registers, | |
| 1431 // we delete both the push & pop and insert a register move. | |
| 1432 // push ry, pop rx --> mov rx, ry | |
| 1433 Register reg_pushed, reg_popped; | |
| 1434 reg_pushed = GetRd(push_instr); | |
| 1435 reg_popped = GetRd(pop_instr); | |
| 1436 pc_ -= 2 * kInstrSize; | |
| 1437 // Insert a mov instruction, which is better than a pair of push & pop | |
| 1438 mov(reg_popped, reg_pushed); | |
| 1439 if (FLAG_print_peephole_optimization) { | |
| 1440 PrintF("%x push/pop (diff reg) replaced by a reg move\n", | |
| 1441 pc_offset()); | |
| 1442 } | |
| 1443 } else { | |
| 1444 // For consecutive push and pop on the same register, | |
| 1445 // both the push and the pop can be deleted. | |
| 1446 pc_ -= 2 * kInstrSize; | |
| 1447 if (FLAG_print_peephole_optimization) { | |
| 1448 PrintF("%x push/pop (same reg) eliminated\n", pc_offset()); | |
| 1449 } | |
| 1450 } | |
| 1451 } | |
| 1452 } | |
| 1453 | |
| 1454 if (can_peephole_optimize(2)) { | |
| 1455 Instr str_instr = instr_at(pc_ - 2 * kInstrSize); | |
| 1456 Instr ldr_instr = instr_at(pc_ - 1 * kInstrSize); | |
| 1457 | |
| 1458 if ((IsStrRegFpOffset(str_instr) && | |
| 1459 IsLdrRegFpOffset(ldr_instr)) || | |
| 1460 (IsStrRegFpNegOffset(str_instr) && | |
| 1461 IsLdrRegFpNegOffset(ldr_instr))) { | |
| 1462 if ((ldr_instr & kLdrStrInstrArgumentMask) == | |
| 1463 (str_instr & kLdrStrInstrArgumentMask)) { | |
| 1464 // Pattern: Ldr/str same fp+offset, same register. | |
| 1465 // | |
| 1466 // The following: | |
| 1467 // str rx, [fp, #-12] | |
| 1468 // ldr rx, [fp, #-12] | |
| 1469 // | |
| 1470 // Becomes: | |
| 1471 // str rx, [fp, #-12] | |
| 1472 | |
| 1473 pc_ -= 1 * kInstrSize; | |
| 1474 if (FLAG_print_peephole_optimization) { | |
| 1475 PrintF("%x str/ldr (fp + same offset), same reg\n", pc_offset()); | |
| 1476 } | |
| 1477 } else if ((ldr_instr & kLdrStrOffsetMask) == | |
| 1478 (str_instr & kLdrStrOffsetMask)) { | |
| 1479 // Pattern: Ldr/str same fp+offset, different register. | |
| 1480 // | |
| 1481 // The following: | |
| 1482 // str rx, [fp, #-12] | |
| 1483 // ldr ry, [fp, #-12] | |
| 1484 // | |
| 1485 // Becomes: | |
| 1486 // str rx, [fp, #-12] | |
| 1487 // mov ry, rx | |
| 1488 | |
| 1489 Register reg_stored, reg_loaded; | |
| 1490 reg_stored = GetRd(str_instr); | |
| 1491 reg_loaded = GetRd(ldr_instr); | |
| 1492 pc_ -= 1 * kInstrSize; | |
| 1493 // Insert a mov instruction, which is better than ldr. | |
| 1494 mov(reg_loaded, reg_stored); | |
| 1495 if (FLAG_print_peephole_optimization) { | |
| 1496 PrintF("%x str/ldr (fp + same offset), diff reg \n", pc_offset()); | |
| 1497 } | |
| 1498 } | |
| 1499 } | |
| 1500 } | |
| 1501 | |
| 1502 if (can_peephole_optimize(3)) { | |
| 1503 Instr mem_write_instr = instr_at(pc_ - 3 * kInstrSize); | |
| 1504 Instr ldr_instr = instr_at(pc_ - 2 * kInstrSize); | |
| 1505 Instr mem_read_instr = instr_at(pc_ - 1 * kInstrSize); | |
| 1506 if (IsPush(mem_write_instr) && | |
| 1507 IsPop(mem_read_instr)) { | |
| 1508 if ((IsLdrRegFpOffset(ldr_instr) || | |
| 1509 IsLdrRegFpNegOffset(ldr_instr))) { | |
| 1510 if (Instruction::RdValue(mem_write_instr) == | |
| 1511 Instruction::RdValue(mem_read_instr)) { | |
| 1512 // Pattern: push & pop from/to same register, | |
| 1513 // with a fp+offset ldr in between | |
| 1514 // | |
| 1515 // The following: | |
| 1516 // str rx, [sp, #-4]! | |
| 1517 // ldr rz, [fp, #-24] | |
| 1518 // ldr rx, [sp], #+4 | |
| 1519 // | |
| 1520 // Becomes: | |
| 1521 // if(rx == rz) | |
| 1522 // delete all | |
| 1523 // else | |
| 1524 // ldr rz, [fp, #-24] | |
| 1525 | |
| 1526 if (Instruction::RdValue(mem_write_instr) == | |
| 1527 Instruction::RdValue(ldr_instr)) { | |
| 1528 pc_ -= 3 * kInstrSize; | |
| 1529 } else { | |
| 1530 pc_ -= 3 * kInstrSize; | |
| 1531 // Reinsert back the ldr rz. | |
| 1532 emit(ldr_instr); | |
| 1533 } | |
| 1534 if (FLAG_print_peephole_optimization) { | |
| 1535 PrintF("%x push/pop -dead ldr fp+offset in middle\n", pc_offset()); | |
| 1536 } | |
| 1537 } else { | |
| 1538 // Pattern: push & pop from/to different registers | |
| 1539 // with a fp+offset ldr in between | |
| 1540 // | |
| 1541 // The following: | |
| 1542 // str rx, [sp, #-4]! | |
| 1543 // ldr rz, [fp, #-24] | |
| 1544 // ldr ry, [sp], #+4 | |
| 1545 // | |
| 1546 // Becomes: | |
| 1547 // if(ry == rz) | |
| 1548 // mov ry, rx; | |
| 1549 // else if(rx != rz) | |
| 1550 // ldr rz, [fp, #-24] | |
| 1551 // mov ry, rx | |
| 1552 // else if((ry != rz) || (rx == rz)) becomes: | |
| 1553 // mov ry, rx | |
| 1554 // ldr rz, [fp, #-24] | |
| 1555 | |
| 1556 Register reg_pushed, reg_popped; | |
| 1557 if (Instruction::RdValue(mem_read_instr) == | |
| 1558 Instruction::RdValue(ldr_instr)) { | |
| 1559 reg_pushed = GetRd(mem_write_instr); | |
| 1560 reg_popped = GetRd(mem_read_instr); | |
| 1561 pc_ -= 3 * kInstrSize; | |
| 1562 mov(reg_popped, reg_pushed); | |
| 1563 } else if (Instruction::RdValue(mem_write_instr) != | |
| 1564 Instruction::RdValue(ldr_instr)) { | |
| 1565 reg_pushed = GetRd(mem_write_instr); | |
| 1566 reg_popped = GetRd(mem_read_instr); | |
| 1567 pc_ -= 3 * kInstrSize; | |
| 1568 emit(ldr_instr); | |
| 1569 mov(reg_popped, reg_pushed); | |
| 1570 } else if ((Instruction::RdValue(mem_read_instr) != | |
| 1571 Instruction::RdValue(ldr_instr)) || | |
| 1572 (Instruction::RdValue(mem_write_instr) == | |
| 1573 Instruction::RdValue(ldr_instr))) { | |
| 1574 reg_pushed = GetRd(mem_write_instr); | |
| 1575 reg_popped = GetRd(mem_read_instr); | |
| 1576 pc_ -= 3 * kInstrSize; | |
| 1577 mov(reg_popped, reg_pushed); | |
| 1578 emit(ldr_instr); | |
| 1579 } | |
| 1580 if (FLAG_print_peephole_optimization) { | |
| 1581 PrintF("%x push/pop (ldr fp+off in middle)\n", pc_offset()); | |
| 1582 } | |
| 1583 } | |
| 1584 } | |
| 1585 } | |
| 1586 } | |
| 1587 } | 1401 } |
| 1588 | 1402 |
| 1589 | 1403 |
| 1590 void Assembler::str(Register src, const MemOperand& dst, Condition cond) { | 1404 void Assembler::str(Register src, const MemOperand& dst, Condition cond) { |
| 1591 addrmod2(cond | B26, src, dst); | 1405 addrmod2(cond | B26, src, dst); |
| 1592 | |
| 1593 // Eliminate pattern: pop(), push(r) | |
| 1594 // add sp, sp, #4 LeaveCC, al; str r, [sp, #-4], al | |
| 1595 // -> str r, [sp, 0], al | |
| 1596 if (can_peephole_optimize(2) && | |
| 1597 // Pattern. | |
| 1598 instr_at(pc_ - 1 * kInstrSize) == (kPushRegPattern | src.code() * B12) && | |
| 1599 instr_at(pc_ - 2 * kInstrSize) == kPopInstruction) { | |
| 1600 pc_ -= 2 * kInstrSize; | |
| 1601 emit(al | B26 | 0 | Offset | sp.code() * B16 | src.code() * B12); | |
| 1602 if (FLAG_print_peephole_optimization) { | |
| 1603 PrintF("%x pop()/push(reg) eliminated\n", pc_offset()); | |
| 1604 } | |
| 1605 } | |
| 1606 } | 1406 } |
| 1607 | 1407 |
| 1608 | 1408 |
| 1609 void Assembler::ldrb(Register dst, const MemOperand& src, Condition cond) { | 1409 void Assembler::ldrb(Register dst, const MemOperand& src, Condition cond) { |
| 1610 addrmod2(cond | B26 | B | L, dst, src); | 1410 addrmod2(cond | B26 | B | L, dst, src); |
| 1611 } | 1411 } |
| 1612 | 1412 |
| 1613 | 1413 |
| 1614 void Assembler::strb(Register src, const MemOperand& dst, Condition cond) { | 1414 void Assembler::strb(Register src, const MemOperand& dst, Condition cond) { |
| 1615 addrmod2(cond | B26 | B, src, dst); | 1415 addrmod2(cond | B26 | B, src, dst); |
| (...skipping 1236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2852 | 2652 |
| 2853 // Since a constant pool was just emitted, move the check offset forward by | 2653 // Since a constant pool was just emitted, move the check offset forward by |
| 2854 // the standard interval. | 2654 // the standard interval. |
| 2855 next_buffer_check_ = pc_offset() + kCheckConstInterval; | 2655 next_buffer_check_ = pc_offset() + kCheckConstInterval; |
| 2856 } | 2656 } |
| 2857 | 2657 |
| 2858 | 2658 |
| 2859 } } // namespace v8::internal | 2659 } } // namespace v8::internal |
| 2860 | 2660 |
| 2861 #endif // V8_TARGET_ARCH_ARM | 2661 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |