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 |