OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
279 } | 279 } |
280 | 280 |
281 | 281 |
282 void MacroAssembler::Move(Register dst, Register src) { | 282 void MacroAssembler::Move(Register dst, Register src) { |
283 if (!dst.is(src)) { | 283 if (!dst.is(src)) { |
284 mov(dst, src); | 284 mov(dst, src); |
285 } | 285 } |
286 } | 286 } |
287 | 287 |
288 | 288 |
| 289 void MacroAssembler::Move(DoubleRegister dst, DoubleRegister src) { |
| 290 ASSERT(CpuFeatures::IsSupported(VFP3)); |
| 291 CpuFeatures::Scope scope(VFP3); |
| 292 if (!dst.is(src)) { |
| 293 vmov(dst, src); |
| 294 } |
| 295 } |
| 296 |
| 297 |
289 void MacroAssembler::And(Register dst, Register src1, const Operand& src2, | 298 void MacroAssembler::And(Register dst, Register src1, const Operand& src2, |
290 Condition cond) { | 299 Condition cond) { |
291 if (!src2.is_reg() && | 300 if (!src2.is_reg() && |
292 !src2.must_use_constant_pool() && | 301 !src2.must_use_constant_pool() && |
293 src2.immediate() == 0) { | 302 src2.immediate() == 0) { |
294 mov(dst, Operand(0, RelocInfo::NONE), LeaveCC, cond); | 303 mov(dst, Operand(0, RelocInfo::NONE), LeaveCC, cond); |
295 | 304 |
296 } else if (!src2.is_single_instruction() && | 305 } else if (!src2.is_single_instruction() && |
297 !src2.must_use_constant_pool() && | 306 !src2.must_use_constant_pool() && |
298 CpuFeatures::IsSupported(ARMv7) && | 307 CpuFeatures::IsSupported(ARMv7) && |
(...skipping 533 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
832 | 841 |
833 // Tear down the exit frame, pop the arguments, and return. | 842 // Tear down the exit frame, pop the arguments, and return. |
834 mov(sp, Operand(fp)); | 843 mov(sp, Operand(fp)); |
835 ldm(ia_w, sp, fp.bit() | lr.bit()); | 844 ldm(ia_w, sp, fp.bit() | lr.bit()); |
836 if (argument_count.is_valid()) { | 845 if (argument_count.is_valid()) { |
837 add(sp, sp, Operand(argument_count, LSL, kPointerSizeLog2)); | 846 add(sp, sp, Operand(argument_count, LSL, kPointerSizeLog2)); |
838 } | 847 } |
839 } | 848 } |
840 | 849 |
841 void MacroAssembler::GetCFunctionDoubleResult(const DoubleRegister dst) { | 850 void MacroAssembler::GetCFunctionDoubleResult(const DoubleRegister dst) { |
842 vmov(dst, r0, r1); | 851 if (FLAG_hardfloat) { |
| 852 Move(dst, d0); |
| 853 } else { |
| 854 vmov(dst, r0, r1); |
| 855 } |
843 } | 856 } |
844 | 857 |
845 | 858 |
846 void MacroAssembler::InvokePrologue(const ParameterCount& expected, | 859 void MacroAssembler::InvokePrologue(const ParameterCount& expected, |
847 const ParameterCount& actual, | 860 const ParameterCount& actual, |
848 Handle<Code> code_constant, | 861 Handle<Code> code_constant, |
849 Register code_reg, | 862 Register code_reg, |
850 Label* done, | 863 Label* done, |
851 InvokeFlag flag, | 864 InvokeFlag flag, |
852 CallWrapper* call_wrapper) { | 865 CallWrapper* call_wrapper) { |
(...skipping 1934 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2787 int kFlatAsciiStringMask = | 2800 int kFlatAsciiStringMask = |
2788 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask; | 2801 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask; |
2789 int kFlatAsciiStringTag = ASCII_STRING_TYPE; | 2802 int kFlatAsciiStringTag = ASCII_STRING_TYPE; |
2790 and_(scratch, type, Operand(kFlatAsciiStringMask)); | 2803 and_(scratch, type, Operand(kFlatAsciiStringMask)); |
2791 cmp(scratch, Operand(kFlatAsciiStringTag)); | 2804 cmp(scratch, Operand(kFlatAsciiStringTag)); |
2792 b(ne, failure); | 2805 b(ne, failure); |
2793 } | 2806 } |
2794 | 2807 |
2795 static const int kRegisterPassedArguments = 4; | 2808 static const int kRegisterPassedArguments = 4; |
2796 | 2809 |
2797 void MacroAssembler::PrepareCallCFunction(int num_arguments, Register scratch) { | 2810 |
| 2811 int MacroAssembler::CalculateStackPassedWords(int num_reg_arguments, |
| 2812 int num_double_arguments) { |
| 2813 int stack_passed_words = 0; |
| 2814 if (FLAG_hardfloat) { |
| 2815 // In the hard floating point calling convention, we can use |
| 2816 // all double registers to pass doubles. |
| 2817 if (num_double_arguments > DoubleRegister::kNumRegisters) { |
| 2818 stack_passed_words += |
| 2819 2 * (num_double_arguments - DoubleRegister::kNumRegisters); |
| 2820 } |
| 2821 } else { |
| 2822 // In the soft floating point calling convention, every double |
| 2823 // argument is passed using two registers. |
| 2824 num_reg_arguments += 2 * num_double_arguments; |
| 2825 } |
| 2826 // Up to four simple arguments are passed in registers r0..r3. |
| 2827 if (num_reg_arguments > kRegisterPassedArguments) { |
| 2828 stack_passed_words += num_reg_arguments - kRegisterPassedArguments; |
| 2829 } |
| 2830 return stack_passed_words; |
| 2831 } |
| 2832 |
| 2833 |
| 2834 void MacroAssembler::PrepareCallCFunction(int num_reg_arguments, |
| 2835 int num_double_arguments, |
| 2836 Register scratch) { |
2798 int frame_alignment = ActivationFrameAlignment(); | 2837 int frame_alignment = ActivationFrameAlignment(); |
2799 | 2838 int stack_passed_arguments = CalculateStackPassedWords( |
2800 // Up to four simple arguments are passed in registers r0..r3. | 2839 num_reg_arguments, num_double_arguments); |
2801 int stack_passed_arguments = (num_arguments <= kRegisterPassedArguments) ? | |
2802 0 : num_arguments - kRegisterPassedArguments; | |
2803 if (frame_alignment > kPointerSize) { | 2840 if (frame_alignment > kPointerSize) { |
2804 // Make stack end at alignment and make room for num_arguments - 4 words | 2841 // Make stack end at alignment and make room for num_arguments - 4 words |
2805 // and the original value of sp. | 2842 // and the original value of sp. |
2806 mov(scratch, sp); | 2843 mov(scratch, sp); |
2807 sub(sp, sp, Operand((stack_passed_arguments + 1) * kPointerSize)); | 2844 sub(sp, sp, Operand((stack_passed_arguments + 1) * kPointerSize)); |
2808 ASSERT(IsPowerOf2(frame_alignment)); | 2845 ASSERT(IsPowerOf2(frame_alignment)); |
2809 and_(sp, sp, Operand(-frame_alignment)); | 2846 and_(sp, sp, Operand(-frame_alignment)); |
2810 str(scratch, MemOperand(sp, stack_passed_arguments * kPointerSize)); | 2847 str(scratch, MemOperand(sp, stack_passed_arguments * kPointerSize)); |
2811 } else { | 2848 } else { |
2812 sub(sp, sp, Operand(stack_passed_arguments * kPointerSize)); | 2849 sub(sp, sp, Operand(stack_passed_arguments * kPointerSize)); |
2813 } | 2850 } |
2814 } | 2851 } |
2815 | 2852 |
2816 | 2853 |
| 2854 void MacroAssembler::PrepareCallCFunction(int num_reg_arguments, |
| 2855 Register scratch) { |
| 2856 PrepareCallCFunction(num_reg_arguments, 0, scratch); |
| 2857 } |
| 2858 |
| 2859 |
| 2860 void MacroAssembler::SetCallCDoubleArguments(DoubleRegister dreg) { |
| 2861 if (FLAG_hardfloat) { |
| 2862 Move(d0, dreg); |
| 2863 } else { |
| 2864 vmov(r0, r1, dreg); |
| 2865 } |
| 2866 } |
| 2867 |
| 2868 |
| 2869 void MacroAssembler::SetCallCDoubleArguments(DoubleRegister dreg1, |
| 2870 DoubleRegister dreg2) { |
| 2871 if (FLAG_hardfloat) { |
| 2872 if (dreg2.is(d0)) { |
| 2873 ASSERT(!dreg1.is(d1)); |
| 2874 Move(d1, dreg2); |
| 2875 Move(d0, dreg1); |
| 2876 } else { |
| 2877 Move(d0, dreg1); |
| 2878 Move(d1, dreg2); |
| 2879 } |
| 2880 } else { |
| 2881 vmov(r0, r1, dreg1); |
| 2882 vmov(r2, r3, dreg2); |
| 2883 } |
| 2884 } |
| 2885 |
| 2886 |
| 2887 void MacroAssembler::SetCallCDoubleArguments(DoubleRegister dreg, |
| 2888 Register reg) { |
| 2889 if (FLAG_hardfloat) { |
| 2890 Move(d0, dreg); |
| 2891 Move(r0, reg); |
| 2892 } else { |
| 2893 Move(r2, reg); |
| 2894 vmov(r0, r1, dreg); |
| 2895 } |
| 2896 } |
| 2897 |
| 2898 |
| 2899 void MacroAssembler::CallCFunction(ExternalReference function, |
| 2900 int num_reg_arguments, |
| 2901 int num_double_arguments) { |
| 2902 CallCFunctionHelper(no_reg, |
| 2903 function, |
| 2904 ip, |
| 2905 num_reg_arguments, |
| 2906 num_double_arguments); |
| 2907 } |
| 2908 |
| 2909 |
| 2910 void MacroAssembler::CallCFunction(Register function, |
| 2911 Register scratch, |
| 2912 int num_reg_arguments, |
| 2913 int num_double_arguments) { |
| 2914 CallCFunctionHelper(function, |
| 2915 ExternalReference::the_hole_value_location(isolate()), |
| 2916 scratch, |
| 2917 num_reg_arguments, |
| 2918 num_double_arguments); |
| 2919 } |
| 2920 |
| 2921 |
2817 void MacroAssembler::CallCFunction(ExternalReference function, | 2922 void MacroAssembler::CallCFunction(ExternalReference function, |
2818 int num_arguments) { | 2923 int num_arguments) { |
2819 CallCFunctionHelper(no_reg, function, ip, num_arguments); | 2924 CallCFunction(function, num_arguments, 0); |
2820 } | 2925 } |
2821 | 2926 |
| 2927 |
2822 void MacroAssembler::CallCFunction(Register function, | 2928 void MacroAssembler::CallCFunction(Register function, |
2823 Register scratch, | 2929 Register scratch, |
2824 int num_arguments) { | 2930 int num_arguments) { |
2825 CallCFunctionHelper(function, | 2931 CallCFunction(function, scratch, num_arguments, 0); |
2826 ExternalReference::the_hole_value_location(isolate()), | |
2827 scratch, | |
2828 num_arguments); | |
2829 } | 2932 } |
2830 | 2933 |
2831 | 2934 |
2832 void MacroAssembler::CallCFunctionHelper(Register function, | 2935 void MacroAssembler::CallCFunctionHelper(Register function, |
2833 ExternalReference function_reference, | 2936 ExternalReference function_reference, |
2834 Register scratch, | 2937 Register scratch, |
2835 int num_arguments) { | 2938 int num_reg_arguments, |
| 2939 int num_double_arguments) { |
2836 // Make sure that the stack is aligned before calling a C function unless | 2940 // Make sure that the stack is aligned before calling a C function unless |
2837 // running in the simulator. The simulator has its own alignment check which | 2941 // running in the simulator. The simulator has its own alignment check which |
2838 // provides more information. | 2942 // provides more information. |
2839 #if defined(V8_HOST_ARCH_ARM) | 2943 #if defined(V8_HOST_ARCH_ARM) |
2840 if (emit_debug_code()) { | 2944 if (emit_debug_code()) { |
2841 int frame_alignment = OS::ActivationFrameAlignment(); | 2945 int frame_alignment = OS::ActivationFrameAlignment(); |
2842 int frame_alignment_mask = frame_alignment - 1; | 2946 int frame_alignment_mask = frame_alignment - 1; |
2843 if (frame_alignment > kPointerSize) { | 2947 if (frame_alignment > kPointerSize) { |
2844 ASSERT(IsPowerOf2(frame_alignment)); | 2948 ASSERT(IsPowerOf2(frame_alignment)); |
2845 Label alignment_as_expected; | 2949 Label alignment_as_expected; |
2846 tst(sp, Operand(frame_alignment_mask)); | 2950 tst(sp, Operand(frame_alignment_mask)); |
2847 b(eq, &alignment_as_expected); | 2951 b(eq, &alignment_as_expected); |
2848 // Don't use Check here, as it will call Runtime_Abort possibly | 2952 // Don't use Check here, as it will call Runtime_Abort possibly |
2849 // re-entering here. | 2953 // re-entering here. |
2850 stop("Unexpected alignment"); | 2954 stop("Unexpected alignment"); |
2851 bind(&alignment_as_expected); | 2955 bind(&alignment_as_expected); |
2852 } | 2956 } |
2853 } | 2957 } |
2854 #endif | 2958 #endif |
2855 | 2959 |
2856 // Just call directly. The function called cannot cause a GC, or | 2960 // Just call directly. The function called cannot cause a GC, or |
2857 // allow preemption, so the return address in the link register | 2961 // allow preemption, so the return address in the link register |
2858 // stays correct. | 2962 // stays correct. |
2859 if (function.is(no_reg)) { | 2963 if (function.is(no_reg)) { |
2860 mov(scratch, Operand(function_reference)); | 2964 mov(scratch, Operand(function_reference)); |
2861 function = scratch; | 2965 function = scratch; |
2862 } | 2966 } |
2863 Call(function); | 2967 Call(function); |
2864 int stack_passed_arguments = (num_arguments <= kRegisterPassedArguments) ? | 2968 int stack_passed_arguments = CalculateStackPassedWords( |
2865 0 : num_arguments - kRegisterPassedArguments; | 2969 num_reg_arguments, num_double_arguments); |
2866 if (ActivationFrameAlignment() > kPointerSize) { | 2970 if (ActivationFrameAlignment() > kPointerSize) { |
2867 ldr(sp, MemOperand(sp, stack_passed_arguments * kPointerSize)); | 2971 ldr(sp, MemOperand(sp, stack_passed_arguments * kPointerSize)); |
2868 } else { | 2972 } else { |
2869 add(sp, sp, Operand(stack_passed_arguments * sizeof(kPointerSize))); | 2973 add(sp, sp, Operand(stack_passed_arguments * sizeof(kPointerSize))); |
2870 } | 2974 } |
2871 } | 2975 } |
2872 | 2976 |
2873 | 2977 |
2874 void MacroAssembler::GetRelocatedValueLocation(Register ldr_location, | 2978 void MacroAssembler::GetRelocatedValueLocation(Register ldr_location, |
2875 Register result) { | 2979 Register result) { |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2926 void CodePatcher::EmitCondition(Condition cond) { | 3030 void CodePatcher::EmitCondition(Condition cond) { |
2927 Instr instr = Assembler::instr_at(masm_.pc_); | 3031 Instr instr = Assembler::instr_at(masm_.pc_); |
2928 instr = (instr & ~kCondMask) | cond; | 3032 instr = (instr & ~kCondMask) | cond; |
2929 masm_.emit(instr); | 3033 masm_.emit(instr); |
2930 } | 3034 } |
2931 | 3035 |
2932 | 3036 |
2933 } } // namespace v8::internal | 3037 } } // namespace v8::internal |
2934 | 3038 |
2935 #endif // V8_TARGET_ARCH_ARM | 3039 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |