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 2555 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2566 *encoding |= (hi >> 12) & 0x80000; // Top bit of the high nybble. | 2566 *encoding |= (hi >> 12) & 0x80000; // Top bit of the high nybble. |
2567 | 2567 |
2568 return true; | 2568 return true; |
2569 } | 2569 } |
2570 | 2570 |
2571 | 2571 |
2572 void Assembler::vmov(const DwVfpRegister dst, | 2572 void Assembler::vmov(const DwVfpRegister dst, |
2573 double imm, | 2573 double imm, |
2574 const Register scratch) { | 2574 const Register scratch) { |
2575 uint32_t enc; | 2575 uint32_t enc; |
| 2576 // If the embedded constant pool is disabled, we can use the normal, inline |
| 2577 // constant pool. If the embedded constant pool is enabled (via |
| 2578 // FLAG_enable_embedded_constant_pool), we can only use it where the pool |
| 2579 // pointer (pp) is valid. |
| 2580 bool can_use_pool = |
| 2581 !FLAG_enable_embedded_constant_pool || is_constant_pool_available(); |
2576 if (CpuFeatures::IsSupported(VFP3) && FitsVMOVDoubleImmediate(imm, &enc)) { | 2582 if (CpuFeatures::IsSupported(VFP3) && FitsVMOVDoubleImmediate(imm, &enc)) { |
2577 // The double can be encoded in the instruction. | 2583 // The double can be encoded in the instruction. |
2578 // | 2584 // |
2579 // Dd = immediate | 2585 // Dd = immediate |
2580 // Instruction details available in ARM DDI 0406C.b, A8-936. | 2586 // Instruction details available in ARM DDI 0406C.b, A8-936. |
2581 // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | imm4H(19-16) | | 2587 // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | imm4H(19-16) | |
2582 // Vd(15-12) | 101(11-9) | sz=1(8) | imm4L(3-0) | 2588 // Vd(15-12) | 101(11-9) | sz=1(8) | imm4L(3-0) |
2583 int vd, d; | 2589 int vd, d; |
2584 dst.split_code(&vd, &d); | 2590 dst.split_code(&vd, &d); |
2585 emit(al | 0x1D*B23 | d*B22 | 0x3*B20 | vd*B12 | 0x5*B9 | B8 | enc); | 2591 emit(al | 0x1D*B23 | d*B22 | 0x3*B20 | vd*B12 | 0x5*B9 | B8 | enc); |
2586 } else if (FLAG_enable_vldr_imm && is_constant_pool_available()) { | 2592 } else if (FLAG_enable_vldr_imm && can_use_pool) { |
2587 // TODO(jfb) Temporarily turned off until we have constant blinding or | 2593 // TODO(jfb) Temporarily turned off until we have constant blinding or |
2588 // some equivalent mitigation: an attacker can otherwise control | 2594 // some equivalent mitigation: an attacker can otherwise control |
2589 // generated data which also happens to be executable, a Very Bad | 2595 // generated data which also happens to be executable, a Very Bad |
2590 // Thing indeed. | 2596 // Thing indeed. |
2591 // Blinding gets tricky because we don't have xor, we probably | 2597 // Blinding gets tricky because we don't have xor, we probably |
2592 // need to add/subtract without losing precision, which requires a | 2598 // need to add/subtract without losing precision, which requires a |
2593 // cookie value that Lithium is probably better positioned to | 2599 // cookie value that Lithium is probably better positioned to |
2594 // choose. | 2600 // choose. |
2595 // We could also add a few peepholes here like detecting 0.0 and | 2601 // We could also add a few peepholes here like detecting 0.0 and |
2596 // -0.0 and doing a vmov from the sequestered d14, forcing denorms | 2602 // -0.0 and doing a vmov from the sequestered d14, forcing denorms |
(...skipping 984 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3581 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta, | 3587 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta, |
3582 reloc_info_writer.last_pc() + pc_delta); | 3588 reloc_info_writer.last_pc() + pc_delta); |
3583 | 3589 |
3584 // None of our relocation types are pc relative pointing outside the code | 3590 // None of our relocation types are pc relative pointing outside the code |
3585 // buffer nor pc absolute pointing inside the code buffer, so there is no need | 3591 // buffer nor pc absolute pointing inside the code buffer, so there is no need |
3586 // to relocate any emitted relocation entries. | 3592 // to relocate any emitted relocation entries. |
3587 } | 3593 } |
3588 | 3594 |
3589 | 3595 |
3590 void Assembler::db(uint8_t data) { | 3596 void Assembler::db(uint8_t data) { |
3591 // No relocation info should be pending while using db. db is used | 3597 // db is used to write raw data. The constant pool should be emitted or |
3592 // to write pure data with no pointers and the constant pool should | 3598 // blocked before using db. |
3593 // be emitted before using db. | 3599 DCHECK(is_const_pool_blocked() || (num_pending_32_bit_constants_ == 0)); |
3594 DCHECK(num_pending_32_bit_constants_ == 0); | 3600 DCHECK(is_const_pool_blocked() || (num_pending_64_bit_constants_ == 0)); |
3595 DCHECK(num_pending_64_bit_constants_ == 0); | |
3596 CheckBuffer(); | 3601 CheckBuffer(); |
3597 *reinterpret_cast<uint8_t*>(pc_) = data; | 3602 *reinterpret_cast<uint8_t*>(pc_) = data; |
3598 pc_ += sizeof(uint8_t); | 3603 pc_ += sizeof(uint8_t); |
3599 } | 3604 } |
3600 | 3605 |
3601 | 3606 |
3602 void Assembler::dd(uint32_t data) { | 3607 void Assembler::dd(uint32_t data) { |
3603 // No relocation info should be pending while using dd. dd is used | 3608 // dd is used to write raw data. The constant pool should be emitted or |
3604 // to write pure data with no pointers and the constant pool should | 3609 // blocked before using dd. |
3605 // be emitted before using dd. | 3610 DCHECK(is_const_pool_blocked() || (num_pending_32_bit_constants_ == 0)); |
3606 DCHECK(num_pending_32_bit_constants_ == 0); | 3611 DCHECK(is_const_pool_blocked() || (num_pending_64_bit_constants_ == 0)); |
3607 DCHECK(num_pending_64_bit_constants_ == 0); | |
3608 CheckBuffer(); | 3612 CheckBuffer(); |
3609 *reinterpret_cast<uint32_t*>(pc_) = data; | 3613 *reinterpret_cast<uint32_t*>(pc_) = data; |
3610 pc_ += sizeof(uint32_t); | 3614 pc_ += sizeof(uint32_t); |
3611 } | 3615 } |
3612 | 3616 |
3613 | 3617 |
3614 void Assembler::dq(uint64_t value) { | 3618 void Assembler::dq(uint64_t value) { |
3615 // No relocation info should be pending while using dq. dq is used | 3619 // dq is used to write raw data. The constant pool should be emitted or |
3616 // to write pure data with no pointers and the constant pool should | 3620 // blocked before using dq. |
3617 // be emitted before using dd. | 3621 DCHECK(is_const_pool_blocked() || (num_pending_32_bit_constants_ == 0)); |
3618 DCHECK(num_pending_32_bit_constants_ == 0); | 3622 DCHECK(is_const_pool_blocked() || (num_pending_64_bit_constants_ == 0)); |
3619 DCHECK(num_pending_64_bit_constants_ == 0); | |
3620 CheckBuffer(); | 3623 CheckBuffer(); |
3621 *reinterpret_cast<uint64_t*>(pc_) = value; | 3624 *reinterpret_cast<uint64_t*>(pc_) = value; |
3622 pc_ += sizeof(uint64_t); | 3625 pc_ += sizeof(uint64_t); |
3623 } | 3626 } |
3624 | 3627 |
3625 | 3628 |
3626 void Assembler::emit_code_stub_address(Code* stub) { | 3629 void Assembler::emit_code_stub_address(Code* stub) { |
3627 CheckBuffer(); | 3630 CheckBuffer(); |
3628 *reinterpret_cast<uint32_t*>(pc_) = | 3631 *reinterpret_cast<uint32_t*>(pc_) = |
3629 reinterpret_cast<uint32_t>(stub->instruction_start()); | 3632 reinterpret_cast<uint32_t>(stub->instruction_start()); |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3748 return; | 3751 return; |
3749 } | 3752 } |
3750 | 3753 |
3751 // Check that the code buffer is large enough before emitting the constant | 3754 // Check that the code buffer is large enough before emitting the constant |
3752 // pool (include the jump over the pool and the constant pool marker and | 3755 // pool (include the jump over the pool and the constant pool marker and |
3753 // the gap to the relocation information). | 3756 // the gap to the relocation information). |
3754 int jump_instr = require_jump ? kInstrSize : 0; | 3757 int jump_instr = require_jump ? kInstrSize : 0; |
3755 int size_up_to_marker = jump_instr + kInstrSize; | 3758 int size_up_to_marker = jump_instr + kInstrSize; |
3756 int estimated_size_after_marker = | 3759 int estimated_size_after_marker = |
3757 num_pending_32_bit_constants_ * kPointerSize; | 3760 num_pending_32_bit_constants_ * kPointerSize; |
| 3761 bool has_int_values = (num_pending_32_bit_constants_ > 0); |
3758 bool has_fp_values = (num_pending_64_bit_constants_ > 0); | 3762 bool has_fp_values = (num_pending_64_bit_constants_ > 0); |
3759 bool require_64_bit_align = false; | 3763 bool require_64_bit_align = false; |
3760 if (has_fp_values) { | 3764 if (has_fp_values) { |
3761 require_64_bit_align = IsAligned( | 3765 require_64_bit_align = |
3762 reinterpret_cast<intptr_t>(pc_ + size_up_to_marker), kDoubleAlignment); | 3766 !IsAligned(reinterpret_cast<intptr_t>(pc_ + size_up_to_marker), |
| 3767 kDoubleAlignment); |
3763 if (require_64_bit_align) { | 3768 if (require_64_bit_align) { |
3764 estimated_size_after_marker += kInstrSize; | 3769 estimated_size_after_marker += kInstrSize; |
3765 } | 3770 } |
3766 estimated_size_after_marker += num_pending_64_bit_constants_ * kDoubleSize; | 3771 estimated_size_after_marker += num_pending_64_bit_constants_ * kDoubleSize; |
3767 } | 3772 } |
3768 int estimated_size = size_up_to_marker + estimated_size_after_marker; | 3773 int estimated_size = size_up_to_marker + estimated_size_after_marker; |
3769 | 3774 |
3770 // We emit a constant pool when: | 3775 // We emit a constant pool when: |
3771 // * requested to do so by parameter force_emit (e.g. after each function). | 3776 // * requested to do so by parameter force_emit (e.g. after each function). |
3772 // * the distance from the first instruction accessing the constant pool to | 3777 // * the distance from the first instruction accessing the constant pool to |
3773 // any of the constant pool entries will exceed its limit the next | 3778 // any of the constant pool entries will exceed its limit the next |
3774 // time the pool is checked. This is overly restrictive, but we don't emit | 3779 // time the pool is checked. This is overly restrictive, but we don't emit |
3775 // constant pool entries in-order so it's conservatively correct. | 3780 // constant pool entries in-order so it's conservatively correct. |
3776 // * the instruction doesn't require a jump after itself to jump over the | 3781 // * the instruction doesn't require a jump after itself to jump over the |
3777 // constant pool, and we're getting close to running out of range. | 3782 // constant pool, and we're getting close to running out of range. |
3778 if (!force_emit) { | 3783 if (!force_emit) { |
3779 DCHECK((first_const_pool_32_use_ >= 0) || (first_const_pool_64_use_ >= 0)); | 3784 DCHECK(has_fp_values || has_int_values); |
3780 bool need_emit = false; | 3785 bool need_emit = false; |
3781 if (has_fp_values) { | 3786 if (has_fp_values) { |
| 3787 // The 64-bit constants are always emitted before the 32-bit constants, so |
| 3788 // we can ignore the effect of the 32-bit constants on estimated_size. |
3782 int dist64 = pc_offset() + estimated_size - | 3789 int dist64 = pc_offset() + estimated_size - |
3783 num_pending_32_bit_constants_ * kPointerSize - | 3790 num_pending_32_bit_constants_ * kPointerSize - |
3784 first_const_pool_64_use_; | 3791 first_const_pool_64_use_; |
3785 if ((dist64 >= kMaxDistToFPPool - kCheckPoolInterval) || | 3792 if ((dist64 >= kMaxDistToFPPool - kCheckPoolInterval) || |
3786 (!require_jump && (dist64 >= kMaxDistToFPPool / 2))) { | 3793 (!require_jump && (dist64 >= kMaxDistToFPPool / 2))) { |
3787 need_emit = true; | 3794 need_emit = true; |
3788 } | 3795 } |
3789 } | 3796 } |
3790 int dist32 = pc_offset() + estimated_size - first_const_pool_32_use_; | 3797 if (has_int_values) { |
3791 if ((dist32 >= kMaxDistToIntPool - kCheckPoolInterval) || | 3798 int dist32 = pc_offset() + estimated_size - first_const_pool_32_use_; |
3792 (!require_jump && (dist32 >= kMaxDistToIntPool / 2))) { | 3799 if ((dist32 >= kMaxDistToIntPool - kCheckPoolInterval) || |
3793 need_emit = true; | 3800 (!require_jump && (dist32 >= kMaxDistToIntPool / 2))) { |
| 3801 need_emit = true; |
| 3802 } |
3794 } | 3803 } |
3795 if (!need_emit) return; | 3804 if (!need_emit) return; |
3796 } | 3805 } |
3797 | 3806 |
3798 // Deduplicate constants. | 3807 // Deduplicate constants. |
3799 int size_after_marker = estimated_size_after_marker; | 3808 int size_after_marker = estimated_size_after_marker; |
3800 for (int i = 0; i < num_pending_64_bit_constants_; i++) { | 3809 for (int i = 0; i < num_pending_64_bit_constants_; i++) { |
3801 ConstantPoolEntry& entry = pending_64_bit_constants_[i]; | 3810 ConstantPoolEntry& entry = pending_64_bit_constants_[i]; |
3802 DCHECK(!entry.is_merged()); | 3811 DCHECK(!entry.is_merged()); |
3803 for (int j = 0; j < i; j++) { | 3812 for (int j = 0; j < i; j++) { |
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3989 DCHECK(is_uint12(offset)); | 3998 DCHECK(is_uint12(offset)); |
3990 instr_at_put(pc, SetLdrRegisterImmediateOffset(instr, offset)); | 3999 instr_at_put(pc, SetLdrRegisterImmediateOffset(instr, offset)); |
3991 } | 4000 } |
3992 } | 4001 } |
3993 | 4002 |
3994 | 4003 |
3995 } // namespace internal | 4004 } // namespace internal |
3996 } // namespace v8 | 4005 } // namespace v8 |
3997 | 4006 |
3998 #endif // V8_TARGET_ARCH_ARM | 4007 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |