OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. |
6 #if defined(TARGET_ARCH_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
7 | 7 |
8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
9 | 9 |
| 10 #include "vm/cpu.h" |
10 #include "vm/dart_entry.h" | 11 #include "vm/dart_entry.h" |
11 #include "vm/flow_graph_compiler.h" | 12 #include "vm/flow_graph_compiler.h" |
12 #include "vm/locations.h" | 13 #include "vm/locations.h" |
13 #include "vm/object_store.h" | 14 #include "vm/object_store.h" |
14 #include "vm/parser.h" | 15 #include "vm/parser.h" |
15 #include "vm/simulator.h" | 16 #include "vm/simulator.h" |
16 #include "vm/stack_frame.h" | 17 #include "vm/stack_frame.h" |
17 #include "vm/stub_code.h" | 18 #include "vm/stub_code.h" |
18 #include "vm/symbols.h" | 19 #include "vm/symbols.h" |
19 | 20 |
(...skipping 2860 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2880 summary->AddTemp(Location::RequiresFpuRegister()); | 2881 summary->AddTemp(Location::RequiresFpuRegister()); |
2881 summary->set_out(0, Location::RequiresRegister()); | 2882 summary->set_out(0, Location::RequiresRegister()); |
2882 return summary; | 2883 return summary; |
2883 } | 2884 } |
2884 summary->set_in(0, Location::RequiresRegister()); | 2885 summary->set_in(0, Location::RequiresRegister()); |
2885 summary->set_in(1, Location::RegisterOrSmiConstant(right())); | 2886 summary->set_in(1, Location::RegisterOrSmiConstant(right())); |
2886 if (((op_kind() == Token::kSHL) && !is_truncating()) || | 2887 if (((op_kind() == Token::kSHL) && !is_truncating()) || |
2887 (op_kind() == Token::kSHR)) { | 2888 (op_kind() == Token::kSHR)) { |
2888 summary->AddTemp(Location::RequiresRegister()); | 2889 summary->AddTemp(Location::RequiresRegister()); |
2889 } | 2890 } |
| 2891 if (op_kind() == Token::kMUL) { |
| 2892 if (TargetCPUFeatures::arm_version() != ARMv7) { |
| 2893 summary->AddTemp(Location::RequiresFpuRegister()); |
| 2894 } |
| 2895 } |
2890 // We make use of 3-operand instructions by not requiring result register | 2896 // We make use of 3-operand instructions by not requiring result register |
2891 // to be identical to first input register as on Intel. | 2897 // to be identical to first input register as on Intel. |
2892 summary->set_out(0, Location::RequiresRegister()); | 2898 summary->set_out(0, Location::RequiresRegister()); |
2893 return summary; | 2899 return summary; |
2894 } | 2900 } |
2895 | 2901 |
2896 | 2902 |
2897 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2903 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2898 if (op_kind() == Token::kSHL) { | 2904 if (op_kind() == Token::kSHL) { |
2899 EmitSmiShiftLeft(compiler, this); | 2905 EmitSmiShiftLeft(compiler, this); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2933 if (value == 2) { | 2939 if (value == 2) { |
2934 __ mov(result, ShifterOperand(left, LSL, 1)); | 2940 __ mov(result, ShifterOperand(left, LSL, 1)); |
2935 } else { | 2941 } else { |
2936 __ LoadImmediate(IP, value); | 2942 __ LoadImmediate(IP, value); |
2937 __ mul(result, left, IP); | 2943 __ mul(result, left, IP); |
2938 } | 2944 } |
2939 } else { | 2945 } else { |
2940 if (value == 2) { | 2946 if (value == 2) { |
2941 __ mov(IP, ShifterOperand(left, ASR, 31)); // IP = sign of left. | 2947 __ mov(IP, ShifterOperand(left, ASR, 31)); // IP = sign of left. |
2942 __ mov(result, ShifterOperand(left, LSL, 1)); | 2948 __ mov(result, ShifterOperand(left, LSL, 1)); |
| 2949 // IP: result bits 32..63. |
| 2950 __ cmp(IP, ShifterOperand(result, ASR, 31)); |
| 2951 __ b(deopt, NE); |
2943 } else { | 2952 } else { |
2944 __ LoadImmediate(IP, value); | 2953 if (TargetCPUFeatures::arm_version() == ARMv7) { |
2945 __ smull(result, IP, left, IP); | 2954 __ LoadImmediate(IP, value); |
| 2955 __ smull(result, IP, left, IP); |
| 2956 // IP: result bits 32..63. |
| 2957 __ cmp(IP, ShifterOperand(result, ASR, 31)); |
| 2958 __ b(deopt, NE); |
| 2959 } else { |
| 2960 const QRegister qtmp = locs()->temp(0).fpu_reg(); |
| 2961 const DRegister dtmp0 = EvenDRegisterOf(qtmp); |
| 2962 const DRegister dtmp1 = OddDRegisterOf(qtmp); |
| 2963 __ LoadImmediate(IP, value); |
| 2964 __ CheckMultSignedOverflow(left, IP, result, dtmp0, dtmp1, deopt); |
| 2965 __ mul(result, left, IP); |
| 2966 } |
2946 } | 2967 } |
2947 // IP: result bits 32..63. | |
2948 __ cmp(IP, ShifterOperand(result, ASR, 31)); | |
2949 __ b(deopt, NE); | |
2950 } | 2968 } |
2951 break; | 2969 break; |
2952 } | 2970 } |
2953 case Token::kTRUNCDIV: { | 2971 case Token::kTRUNCDIV: { |
2954 const intptr_t value = Smi::Cast(constant).Value(); | 2972 const intptr_t value = Smi::Cast(constant).Value(); |
2955 if (value == 1) { | 2973 if (value == 1) { |
2956 __ MoveRegister(result, left); | 2974 __ MoveRegister(result, left); |
2957 break; | 2975 break; |
2958 } else if (value == -1) { | 2976 } else if (value == -1) { |
2959 // Check the corner case of dividing the 'MIN_SMI' with -1, in which | 2977 // Check the corner case of dividing the 'MIN_SMI' with -1, in which |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3063 __ subs(result, left, ShifterOperand(right)); | 3081 __ subs(result, left, ShifterOperand(right)); |
3064 __ b(deopt, VS); | 3082 __ b(deopt, VS); |
3065 } | 3083 } |
3066 break; | 3084 break; |
3067 } | 3085 } |
3068 case Token::kMUL: { | 3086 case Token::kMUL: { |
3069 __ Asr(IP, left, kSmiTagSize); // SmiUntag left into IP. | 3087 __ Asr(IP, left, kSmiTagSize); // SmiUntag left into IP. |
3070 if (deopt == NULL) { | 3088 if (deopt == NULL) { |
3071 __ mul(result, IP, right); | 3089 __ mul(result, IP, right); |
3072 } else { | 3090 } else { |
3073 __ smull(result, IP, IP, right); | 3091 if (TargetCPUFeatures::arm_version() == ARMv7) { |
3074 // IP: result bits 32..63. | 3092 __ smull(result, IP, IP, right); |
3075 __ cmp(IP, ShifterOperand(result, ASR, 31)); | 3093 // IP: result bits 32..63. |
3076 __ b(deopt, NE); | 3094 __ cmp(IP, ShifterOperand(result, ASR, 31)); |
| 3095 __ b(deopt, NE); |
| 3096 } else { |
| 3097 const QRegister qtmp = locs()->temp(0).fpu_reg(); |
| 3098 const DRegister dtmp0 = EvenDRegisterOf(qtmp); |
| 3099 const DRegister dtmp1 = OddDRegisterOf(qtmp); |
| 3100 __ CheckMultSignedOverflow(IP, right, result, dtmp0, dtmp1, deopt); |
| 3101 __ mul(result, IP, right); |
| 3102 } |
3077 } | 3103 } |
3078 break; | 3104 break; |
3079 } | 3105 } |
3080 case Token::kBIT_AND: { | 3106 case Token::kBIT_AND: { |
3081 // No overflow check. | 3107 // No overflow check. |
3082 __ and_(result, left, ShifterOperand(right)); | 3108 __ and_(result, left, ShifterOperand(right)); |
3083 break; | 3109 break; |
3084 } | 3110 } |
3085 case Token::kBIT_OR: { | 3111 case Token::kBIT_OR: { |
3086 // No overflow check. | 3112 // No overflow check. |
(...skipping 2934 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6021 compiler->GenerateCall(token_pos(), | 6047 compiler->GenerateCall(token_pos(), |
6022 &label, | 6048 &label, |
6023 PcDescriptors::kOther, | 6049 PcDescriptors::kOther, |
6024 locs()); | 6050 locs()); |
6025 __ Drop(ArgumentCount()); // Discard arguments. | 6051 __ Drop(ArgumentCount()); // Discard arguments. |
6026 } | 6052 } |
6027 | 6053 |
6028 } // namespace dart | 6054 } // namespace dart |
6029 | 6055 |
6030 #endif // defined TARGET_ARCH_ARM | 6056 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |