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/cpu.h" |
(...skipping 6125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6136 } | 6136 } |
6137 if (FLAG_throw_on_javascript_int_overflow) { | 6137 if (FLAG_throw_on_javascript_int_overflow) { |
6138 EmitJavascriptIntOverflowCheck(compiler, deopt, out_lo, out_hi); | 6138 EmitJavascriptIntOverflowCheck(compiler, deopt, out_lo, out_hi); |
6139 } | 6139 } |
6140 } | 6140 } |
6141 | 6141 |
6142 | 6142 |
6143 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Isolate* isolate, | 6143 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Isolate* isolate, |
6144 bool opt) const { | 6144 bool opt) const { |
6145 const intptr_t kNumInputs = 2; | 6145 const intptr_t kNumInputs = 2; |
6146 const intptr_t kNumTemps = 1; | 6146 const intptr_t kNumTemps = 0; |
6147 LocationSummary* summary = new(isolate) LocationSummary( | 6147 LocationSummary* summary = new(isolate) LocationSummary( |
6148 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6148 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
6149 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | 6149 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
6150 Location::RequiresRegister())); | 6150 Location::RequiresRegister())); |
6151 summary->set_in(1, Location::WritableRegister()); | 6151 summary->set_in(1, Location::WritableRegisterOrSmiConstant(right())); |
6152 summary->set_temp(0, Location::RequiresRegister()); | |
6153 summary->set_out(0, Location::Pair(Location::RequiresRegister(), | 6152 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
6154 Location::RequiresRegister())); | 6153 Location::RequiresRegister())); |
6155 return summary; | 6154 return summary; |
6156 } | 6155 } |
6157 | 6156 |
6158 | 6157 |
6159 static const intptr_t kMintShiftCountLimit = 63; | 6158 static const intptr_t kMintShiftCountLimit = 63; |
6160 | 6159 |
6161 bool ShiftMintOpInstr::has_shift_count_check() const { | 6160 bool ShiftMintOpInstr::has_shift_count_check() const { |
6162 return (right()->definition()->range() == NULL) | 6161 return (right()->definition()->range() == NULL) |
6163 || !right()->definition()->range()->IsWithin(0, kMintShiftCountLimit); | 6162 || !right()->definition()->range()->IsWithin(0, kMintShiftCountLimit); |
6164 } | 6163 } |
6165 | 6164 |
6166 | 6165 |
6167 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6166 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6168 PairLocation* left_pair = locs()->in(0).AsPairLocation(); | 6167 PairLocation* left_pair = locs()->in(0).AsPairLocation(); |
6169 Register left_lo = left_pair->At(0).reg(); | 6168 Register left_lo = left_pair->At(0).reg(); |
6170 Register left_hi = left_pair->At(1).reg(); | 6169 Register left_hi = left_pair->At(1).reg(); |
6171 Register shift = locs()->in(1).reg(); | |
6172 PairLocation* out_pair = locs()->out(0).AsPairLocation(); | 6170 PairLocation* out_pair = locs()->out(0).AsPairLocation(); |
6173 Register out_lo = out_pair->At(0).reg(); | 6171 Register out_lo = out_pair->At(0).reg(); |
6174 Register out_hi = out_pair->At(1).reg(); | 6172 Register out_hi = out_pair->At(1).reg(); |
6175 Register temp = locs()->temp(0).reg(); | |
6176 | 6173 |
6177 Label* deopt = NULL; | 6174 Label* deopt = NULL; |
6178 if (CanDeoptimize()) { | 6175 if (CanDeoptimize()) { |
6179 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp); | 6176 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp); |
6180 } | 6177 } |
6181 __ mov(out_lo, Operand(left_lo)); | 6178 if (locs()->in(1).IsConstant()) { |
6182 __ mov(out_hi, Operand(left_hi)); | 6179 // Code for a constant shift amount. |
| 6180 ASSERT(locs()->in(1).constant().IsSmi()); |
| 6181 const int32_t shift = |
| 6182 reinterpret_cast<int32_t>(locs()->in(1).constant().raw()) >> 1; |
| 6183 if ((shift < 0) || (shift > kMintShiftCountLimit)) { |
| 6184 __ b(deopt); |
| 6185 return; |
| 6186 } else if (shift == 0) { |
| 6187 // Nothing to do for zero shift amount. |
| 6188 __ mov(out_lo, Operand(left_lo)); |
| 6189 __ mov(out_hi, Operand(left_hi)); |
| 6190 return; |
| 6191 } |
| 6192 switch (op_kind()) { |
| 6193 case Token::kSHR: { |
| 6194 if (shift < 32) { |
| 6195 __ Lsl(out_lo, left_hi, 32 - shift); |
| 6196 __ orr(out_lo, out_lo, Operand(left_lo, LSR, shift)); |
| 6197 __ Asr(out_hi, left_hi, shift); |
| 6198 } else { |
| 6199 if (shift == 32) { |
| 6200 __ mov(out_lo, Operand(left_hi)); |
| 6201 } else { |
| 6202 __ Asr(out_lo, left_hi, shift - 32); |
| 6203 } |
| 6204 __ Asr(out_hi, left_hi, 31); |
| 6205 } |
| 6206 break; |
| 6207 } |
| 6208 case Token::kSHL: { |
| 6209 if (shift < 32) { |
| 6210 __ Lsr(out_hi, left_lo, 32 - shift); |
| 6211 __ orr(out_hi, out_hi, Operand(left_hi, LSL, shift)); |
| 6212 __ Lsl(out_lo, left_lo, shift); |
| 6213 } else { |
| 6214 if (shift == 32) { |
| 6215 __ mov(out_hi, Operand(left_lo)); |
| 6216 } else { |
| 6217 __ Lsl(out_hi, left_lo, shift - 32); |
| 6218 } |
| 6219 __ mov(out_lo, Operand(0)); |
| 6220 } |
| 6221 // Check for overflow. |
| 6222 if (can_overflow()) { |
| 6223 // Compare high word from input with shifted high word from output. |
| 6224 if (shift > 31) { |
| 6225 __ cmp(left_hi, Operand(out_hi)); |
| 6226 } else { |
| 6227 __ cmp(left_hi, Operand(out_hi, ASR, shift)); |
| 6228 } |
| 6229 // Overflow if they aren't equal. |
| 6230 __ b(deopt, NE); |
| 6231 } |
| 6232 break; |
| 6233 } |
| 6234 default: |
| 6235 UNREACHABLE(); |
| 6236 } |
| 6237 } else { |
| 6238 // Code for a variable shift amount. |
| 6239 Register shift = locs()->in(1).reg(); |
6183 | 6240 |
6184 // Untag shift count. | 6241 // Untag shift count. |
6185 __ SmiUntag(shift); | 6242 __ SmiUntag(shift); |
6186 | 6243 |
6187 // Deopt if shift is larger than 63 or less than 0. | 6244 // Deopt if shift is larger than 63 or less than 0. |
6188 if (has_shift_count_check()) { | 6245 if (has_shift_count_check()) { |
6189 __ CompareImmediate(shift, kMintShiftCountLimit); | 6246 __ CompareImmediate(shift, kMintShiftCountLimit); |
6190 __ b(deopt, HI); | 6247 __ b(deopt, HI); |
6191 } | 6248 } |
6192 | 6249 |
6193 switch (op_kind()) { | 6250 __ mov(out_lo, Operand(left_lo)); |
6194 case Token::kSHR: { | 6251 __ mov(out_hi, Operand(left_hi)); |
6195 __ cmp(shift, Operand(32)); | |
6196 | 6252 |
6197 __ mov(out_lo, Operand(out_hi), HI); | 6253 switch (op_kind()) { |
6198 __ Asr(out_hi, out_hi, 31, HI); | 6254 case Token::kSHR: { |
6199 __ sub(shift, shift, Operand(32), HI); | 6255 __ cmp(shift, Operand(32)); |
6200 | 6256 |
6201 __ rsb(temp, shift, Operand(32)); | 6257 __ mov(out_lo, Operand(out_hi), HI); |
6202 __ mov(temp, Operand(out_hi, LSL, temp)); | 6258 __ Asr(out_hi, out_hi, 31, HI); |
6203 __ orr(out_lo, temp, Operand(out_lo, LSR, shift)); | 6259 __ sub(shift, shift, Operand(32), HI); |
6204 __ Asr(out_hi, out_hi, shift); | 6260 |
6205 break; | 6261 __ rsb(IP, shift, Operand(32)); |
| 6262 __ mov(IP, Operand(out_hi, LSL, IP)); |
| 6263 __ orr(out_lo, IP, Operand(out_lo, LSR, shift)); |
| 6264 __ Asr(out_hi, out_hi, shift); |
| 6265 break; |
| 6266 } |
| 6267 case Token::kSHL: { |
| 6268 __ rsbs(IP, shift, Operand(32)); |
| 6269 __ sub(IP, shift, Operand(32), MI); |
| 6270 __ mov(out_hi, Operand(out_lo, LSL, IP), MI); |
| 6271 __ mov(out_hi, Operand(out_hi, LSL, shift), PL); |
| 6272 __ orr(out_hi, out_hi, Operand(out_lo, LSR, IP), PL); |
| 6273 __ mov(out_lo, Operand(out_lo, LSL, shift)); |
| 6274 |
| 6275 // Check for overflow. |
| 6276 if (can_overflow()) { |
| 6277 // Compare high word from input with shifted high word from output. |
| 6278 __ cmp(left_hi, Operand(out_hi, ASR, shift)); |
| 6279 // Overflow if they aren't equal. |
| 6280 __ b(deopt, NE); |
| 6281 } |
| 6282 break; |
| 6283 } |
| 6284 default: |
| 6285 UNREACHABLE(); |
6206 } | 6286 } |
6207 case Token::kSHL: { | |
6208 __ rsbs(temp, shift, Operand(32)); | |
6209 __ sub(temp, shift, Operand(32), MI); | |
6210 __ mov(out_hi, Operand(out_lo, LSL, temp), MI); | |
6211 __ mov(out_hi, Operand(out_hi, LSL, shift), PL); | |
6212 __ orr(out_hi, out_hi, Operand(out_lo, LSR, temp), PL); | |
6213 __ mov(out_lo, Operand(out_lo, LSL, shift)); | |
6214 | |
6215 // Check for overflow. | |
6216 if (can_overflow()) { | |
6217 // Copy high word from output. | |
6218 __ mov(temp, Operand(out_hi)); | |
6219 // Shift copy right. | |
6220 __ Asr(temp, temp, shift); | |
6221 // Compare with high word from input. | |
6222 __ cmp(temp, Operand(left_hi)); | |
6223 // Overflow if they aren't equal. | |
6224 __ b(deopt, NE); | |
6225 } | |
6226 break; | |
6227 } | |
6228 default: | |
6229 UNREACHABLE(); | |
6230 break; | |
6231 } | 6287 } |
6232 | 6288 |
6233 if (FLAG_throw_on_javascript_int_overflow) { | 6289 if (FLAG_throw_on_javascript_int_overflow) { |
6234 EmitJavascriptIntOverflowCheck(compiler, deopt, out_lo, out_hi); | 6290 EmitJavascriptIntOverflowCheck(compiler, deopt, out_lo, out_hi); |
6235 } | 6291 } |
6236 } | 6292 } |
6237 | 6293 |
6238 | 6294 |
6239 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(Isolate* isolate, | 6295 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(Isolate* isolate, |
6240 bool opt) const { | 6296 bool opt) const { |
(...skipping 575 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6816 compiler->GenerateCall(token_pos(), &label, stub_kind_, locs()); | 6872 compiler->GenerateCall(token_pos(), &label, stub_kind_, locs()); |
6817 #if defined(DEBUG) | 6873 #if defined(DEBUG) |
6818 __ LoadImmediate(R4, kInvalidObjectPointer); | 6874 __ LoadImmediate(R4, kInvalidObjectPointer); |
6819 __ LoadImmediate(R5, kInvalidObjectPointer); | 6875 __ LoadImmediate(R5, kInvalidObjectPointer); |
6820 #endif | 6876 #endif |
6821 } | 6877 } |
6822 | 6878 |
6823 } // namespace dart | 6879 } // namespace dart |
6824 | 6880 |
6825 #endif // defined TARGET_ARCH_ARM | 6881 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |