| 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 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 295 | 295 |
| 296 | 296 |
| 297 // Spare buffer. | 297 // Spare buffer. |
| 298 static const int kMinimalBufferSize = 4*KB; | 298 static const int kMinimalBufferSize = 4*KB; |
| 299 | 299 |
| 300 | 300 |
| 301 Assembler::Assembler(Isolate* arg_isolate, void* buffer, int buffer_size) | 301 Assembler::Assembler(Isolate* arg_isolate, void* buffer, int buffer_size) |
| 302 : AssemblerBase(arg_isolate), | 302 : AssemblerBase(arg_isolate), |
| 303 recorded_ast_id_(TypeFeedbackId::None()), | 303 recorded_ast_id_(TypeFeedbackId::None()), |
| 304 positions_recorder_(this), | 304 positions_recorder_(this), |
| 305 emit_debug_code_(FLAG_debug_code) { | 305 emit_debug_code_(FLAG_debug_code), |
| 306 predictable_code_size_(false) { |
| 306 if (buffer == NULL) { | 307 if (buffer == NULL) { |
| 307 // Do our own buffer management. | 308 // Do our own buffer management. |
| 308 if (buffer_size <= kMinimalBufferSize) { | 309 if (buffer_size <= kMinimalBufferSize) { |
| 309 buffer_size = kMinimalBufferSize; | 310 buffer_size = kMinimalBufferSize; |
| 310 | 311 |
| 311 if (isolate()->assembler_spare_buffer() != NULL) { | 312 if (isolate()->assembler_spare_buffer() != NULL) { |
| 312 buffer = isolate()->assembler_spare_buffer(); | 313 buffer = isolate()->assembler_spare_buffer(); |
| 313 isolate()->set_assembler_spare_buffer(NULL); | 314 isolate()->set_assembler_spare_buffer(NULL); |
| 314 } | 315 } |
| 315 } | 316 } |
| (...skipping 461 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 777 } | 778 } |
| 778 } | 779 } |
| 779 return false; | 780 return false; |
| 780 } | 781 } |
| 781 | 782 |
| 782 | 783 |
| 783 // We have to use the temporary register for things that can be relocated even | 784 // We have to use the temporary register for things that can be relocated even |
| 784 // if they can be encoded in the ARM's 12 bits of immediate-offset instruction | 785 // if they can be encoded in the ARM's 12 bits of immediate-offset instruction |
| 785 // space. There is no guarantee that the relocated location can be similarly | 786 // space. There is no guarantee that the relocated location can be similarly |
| 786 // encoded. | 787 // encoded. |
| 787 bool Operand::must_use_constant_pool() const { | 788 bool Operand::must_use_constant_pool(const Assembler* assembler) const { |
| 788 if (rmode_ == RelocInfo::EXTERNAL_REFERENCE) { | 789 if (rmode_ == RelocInfo::EXTERNAL_REFERENCE) { |
| 789 #ifdef DEBUG | 790 #ifdef DEBUG |
| 790 if (!Serializer::enabled()) { | 791 if (!Serializer::enabled()) { |
| 791 Serializer::TooLateToEnableNow(); | 792 Serializer::TooLateToEnableNow(); |
| 792 } | 793 } |
| 793 #endif // def DEBUG | 794 #endif // def DEBUG |
| 795 if (assembler != NULL && assembler->predictable_code_size()) return true; |
| 794 return Serializer::enabled(); | 796 return Serializer::enabled(); |
| 795 } else if (rmode_ == RelocInfo::NONE) { | 797 } else if (rmode_ == RelocInfo::NONE) { |
| 796 return false; | 798 return false; |
| 797 } | 799 } |
| 798 return true; | 800 return true; |
| 799 } | 801 } |
| 800 | 802 |
| 801 | 803 |
| 802 bool Operand::is_single_instruction(Instr instr) const { | 804 bool Operand::is_single_instruction(const Assembler* assembler, |
| 805 Instr instr) const { |
| 803 if (rm_.is_valid()) return true; | 806 if (rm_.is_valid()) return true; |
| 804 uint32_t dummy1, dummy2; | 807 uint32_t dummy1, dummy2; |
| 805 if (must_use_constant_pool() || | 808 if (must_use_constant_pool(assembler) || |
| 806 !fits_shifter(imm32_, &dummy1, &dummy2, &instr)) { | 809 !fits_shifter(imm32_, &dummy1, &dummy2, &instr)) { |
| 807 // The immediate operand cannot be encoded as a shifter operand, or use of | 810 // The immediate operand cannot be encoded as a shifter operand, or use of |
| 808 // constant pool is required. For a mov instruction not setting the | 811 // constant pool is required. For a mov instruction not setting the |
| 809 // condition code additional instruction conventions can be used. | 812 // condition code additional instruction conventions can be used. |
| 810 if ((instr & ~kCondMask) == 13*B21) { // mov, S not set | 813 if ((instr & ~kCondMask) == 13*B21) { // mov, S not set |
| 811 if (must_use_constant_pool() || | 814 if (must_use_constant_pool(assembler) || |
| 812 !CpuFeatures::IsSupported(ARMv7)) { | 815 !CpuFeatures::IsSupported(ARMv7)) { |
| 813 // mov instruction will be an ldr from constant pool (one instruction). | 816 // mov instruction will be an ldr from constant pool (one instruction). |
| 814 return true; | 817 return true; |
| 815 } else { | 818 } else { |
| 816 // mov instruction will be a mov or movw followed by movt (two | 819 // mov instruction will be a mov or movw followed by movt (two |
| 817 // instructions). | 820 // instructions). |
| 818 return false; | 821 return false; |
| 819 } | 822 } |
| 820 } else { | 823 } else { |
| 821 // If this is not a mov or mvn instruction there will always an additional | 824 // If this is not a mov or mvn instruction there will always an additional |
| (...skipping 13 matching lines...) Expand all Loading... |
| 835 void Assembler::addrmod1(Instr instr, | 838 void Assembler::addrmod1(Instr instr, |
| 836 Register rn, | 839 Register rn, |
| 837 Register rd, | 840 Register rd, |
| 838 const Operand& x) { | 841 const Operand& x) { |
| 839 CheckBuffer(); | 842 CheckBuffer(); |
| 840 ASSERT((instr & ~(kCondMask | kOpCodeMask | S)) == 0); | 843 ASSERT((instr & ~(kCondMask | kOpCodeMask | S)) == 0); |
| 841 if (!x.rm_.is_valid()) { | 844 if (!x.rm_.is_valid()) { |
| 842 // Immediate. | 845 // Immediate. |
| 843 uint32_t rotate_imm; | 846 uint32_t rotate_imm; |
| 844 uint32_t immed_8; | 847 uint32_t immed_8; |
| 845 if (x.must_use_constant_pool() || | 848 if (x.must_use_constant_pool(this) || |
| 846 !fits_shifter(x.imm32_, &rotate_imm, &immed_8, &instr)) { | 849 !fits_shifter(x.imm32_, &rotate_imm, &immed_8, &instr)) { |
| 847 // The immediate operand cannot be encoded as a shifter operand, so load | 850 // The immediate operand cannot be encoded as a shifter operand, so load |
| 848 // it first to register ip and change the original instruction to use ip. | 851 // it first to register ip and change the original instruction to use ip. |
| 849 // However, if the original instruction is a 'mov rd, x' (not setting the | 852 // However, if the original instruction is a 'mov rd, x' (not setting the |
| 850 // condition code), then replace it with a 'ldr rd, [pc]'. | 853 // condition code), then replace it with a 'ldr rd, [pc]'. |
| 851 CHECK(!rn.is(ip)); // rn should never be ip, or will be trashed | 854 CHECK(!rn.is(ip)); // rn should never be ip, or will be trashed |
| 852 Condition cond = Instruction::ConditionField(instr); | 855 Condition cond = Instruction::ConditionField(instr); |
| 853 if ((instr & ~kCondMask) == 13*B21) { // mov, S not set | 856 if ((instr & ~kCondMask) == 13*B21) { // mov, S not set |
| 854 if (x.must_use_constant_pool() || | 857 if (x.must_use_constant_pool(this) || |
| 855 !CpuFeatures::IsSupported(ARMv7)) { | 858 !CpuFeatures::IsSupported(ARMv7)) { |
| 856 RecordRelocInfo(x.rmode_, x.imm32_); | 859 RecordRelocInfo(x.rmode_, x.imm32_); |
| 857 ldr(rd, MemOperand(pc, 0), cond); | 860 ldr(rd, MemOperand(pc, 0), cond); |
| 858 } else { | 861 } else { |
| 859 // Will probably use movw, will certainly not use constant pool. | 862 // Will probably use movw, will certainly not use constant pool. |
| 860 mov(rd, Operand(x.imm32_ & 0xffff), LeaveCC, cond); | 863 mov(rd, Operand(x.imm32_ & 0xffff), LeaveCC, cond); |
| 861 movt(rd, static_cast<uint32_t>(x.imm32_) >> 16, cond); | 864 movt(rd, static_cast<uint32_t>(x.imm32_) >> 16, cond); |
| 862 } | 865 } |
| 863 } else { | 866 } else { |
| 864 // If this is not a mov or mvn instruction we may still be able to avoid | 867 // If this is not a mov or mvn instruction we may still be able to avoid |
| 865 // a constant pool entry by using mvn or movw. | 868 // a constant pool entry by using mvn or movw. |
| 866 if (!x.must_use_constant_pool() && | 869 if (!x.must_use_constant_pool(this) && |
| 867 (instr & kMovMvnMask) != kMovMvnPattern) { | 870 (instr & kMovMvnMask) != kMovMvnPattern) { |
| 868 mov(ip, x, LeaveCC, cond); | 871 mov(ip, x, LeaveCC, cond); |
| 869 } else { | 872 } else { |
| 870 RecordRelocInfo(x.rmode_, x.imm32_); | 873 RecordRelocInfo(x.rmode_, x.imm32_); |
| 871 ldr(ip, MemOperand(pc, 0), cond); | 874 ldr(ip, MemOperand(pc, 0), cond); |
| 872 } | 875 } |
| 873 addrmod1(instr, rn, rd, Operand(ip)); | 876 addrmod1(instr, rn, rd, Operand(ip)); |
| 874 } | 877 } |
| 875 return; | 878 return; |
| 876 } | 879 } |
| (...skipping 504 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1381 | 1384 |
| 1382 | 1385 |
| 1383 void Assembler::msr(SRegisterFieldMask fields, const Operand& src, | 1386 void Assembler::msr(SRegisterFieldMask fields, const Operand& src, |
| 1384 Condition cond) { | 1387 Condition cond) { |
| 1385 ASSERT(fields >= B16 && fields < B20); // at least one field set | 1388 ASSERT(fields >= B16 && fields < B20); // at least one field set |
| 1386 Instr instr; | 1389 Instr instr; |
| 1387 if (!src.rm_.is_valid()) { | 1390 if (!src.rm_.is_valid()) { |
| 1388 // Immediate. | 1391 // Immediate. |
| 1389 uint32_t rotate_imm; | 1392 uint32_t rotate_imm; |
| 1390 uint32_t immed_8; | 1393 uint32_t immed_8; |
| 1391 if (src.must_use_constant_pool() || | 1394 if (src.must_use_constant_pool(this) || |
| 1392 !fits_shifter(src.imm32_, &rotate_imm, &immed_8, NULL)) { | 1395 !fits_shifter(src.imm32_, &rotate_imm, &immed_8, NULL)) { |
| 1393 // Immediate operand cannot be encoded, load it first to register ip. | 1396 // Immediate operand cannot be encoded, load it first to register ip. |
| 1394 RecordRelocInfo(src.rmode_, src.imm32_); | 1397 RecordRelocInfo(src.rmode_, src.imm32_); |
| 1395 ldr(ip, MemOperand(pc, 0), cond); | 1398 ldr(ip, MemOperand(pc, 0), cond); |
| 1396 msr(fields, Operand(ip), cond); | 1399 msr(fields, Operand(ip), cond); |
| 1397 return; | 1400 return; |
| 1398 } | 1401 } |
| 1399 instr = I | rotate_imm*B8 | immed_8; | 1402 instr = I | rotate_imm*B8 | immed_8; |
| 1400 } else { | 1403 } else { |
| 1401 ASSERT(!src.rs_.is_valid() && src.shift_imm_ == 0); // only rm allowed | 1404 ASSERT(!src.rs_.is_valid() && src.shift_imm_ == 0); // only rm allowed |
| (...skipping 1283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2685 | 2688 |
| 2686 // Since a constant pool was just emitted, move the check offset forward by | 2689 // Since a constant pool was just emitted, move the check offset forward by |
| 2687 // the standard interval. | 2690 // the standard interval. |
| 2688 next_buffer_check_ = pc_offset() + kCheckPoolInterval; | 2691 next_buffer_check_ = pc_offset() + kCheckPoolInterval; |
| 2689 } | 2692 } |
| 2690 | 2693 |
| 2691 | 2694 |
| 2692 } } // namespace v8::internal | 2695 } } // namespace v8::internal |
| 2693 | 2696 |
| 2694 #endif // V8_TARGET_ARCH_ARM | 2697 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |