OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 2037 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2048 if (can_overflow) { | 2048 if (can_overflow) { |
2049 DeoptimizeIf(vs, instr->environment()); | 2049 DeoptimizeIf(vs, instr->environment()); |
2050 } | 2050 } |
2051 } | 2051 } |
2052 | 2052 |
2053 | 2053 |
2054 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { | 2054 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { |
2055 LOperand* left = instr->left(); | 2055 LOperand* left = instr->left(); |
2056 LOperand* right = instr->right(); | 2056 LOperand* right = instr->right(); |
2057 HMathMinMax::Operation operation = instr->hydrogen()->operation(); | 2057 HMathMinMax::Operation operation = instr->hydrogen()->operation(); |
2058 Condition condition = (operation == HMathMinMax::kMathMin) ? le : ge; | |
2059 if (instr->hydrogen()->representation().IsInteger32()) { | 2058 if (instr->hydrogen()->representation().IsInteger32()) { |
2059 Condition condition = (operation == HMathMinMax::kMathMin) ? le : ge; | |
2060 Register left_reg = ToRegister(left); | 2060 Register left_reg = ToRegister(left); |
2061 Operand right_op = (right->IsRegister() || right->IsConstantOperand()) | 2061 Operand right_op = (right->IsRegister() || right->IsConstantOperand()) |
2062 ? ToOperand(right) | 2062 ? ToOperand(right) |
2063 : Operand(EmitLoadRegister(right, ip)); | 2063 : Operand(EmitLoadRegister(right, ip)); |
2064 Register result_reg = ToRegister(instr->result()); | 2064 Register result_reg = ToRegister(instr->result()); |
2065 __ cmp(left_reg, right_op); | 2065 __ cmp(left_reg, right_op); |
2066 if (!result_reg.is(left_reg)) { | 2066 __ Move(result_reg, left_reg, condition); |
2067 __ mov(result_reg, left_reg, LeaveCC, condition); | |
2068 } | |
2069 __ mov(result_reg, right_op, LeaveCC, NegateCondition(condition)); | 2067 __ mov(result_reg, right_op, LeaveCC, NegateCondition(condition)); |
2070 } else { | 2068 } else { |
2071 ASSERT(instr->hydrogen()->representation().IsDouble()); | 2069 ASSERT(instr->hydrogen()->representation().IsDouble()); |
2072 DwVfpRegister left_reg = ToDoubleRegister(left); | 2070 DwVfpRegister left_reg = ToDoubleRegister(left); |
2073 DwVfpRegister right_reg = ToDoubleRegister(right); | 2071 DwVfpRegister right_reg = ToDoubleRegister(right); |
2074 DwVfpRegister result_reg = ToDoubleRegister(instr->result()); | 2072 DwVfpRegister result_reg = ToDoubleRegister(instr->result()); |
2075 Label check_nan_left, check_zero, return_left, return_right, done; | 2073 Label result_is_nan, return_left, return_right, check_zero, done; |
2076 __ VFPCompareAndSetFlags(left_reg, right_reg); | 2074 __ VFPCompareAndSetFlags(left_reg, right_reg); |
2077 __ b(vs, &check_nan_left); | 2075 if (operation == HMathMinMax::kMathMin) { |
2078 __ b(eq, &check_zero); | 2076 __ b(mi, &return_left); |
2079 __ b(condition, &return_left); | 2077 __ b(gt, &return_right); |
2080 __ b(al, &return_right); | 2078 } else { |
2081 | 2079 __ b(mi, &return_right); |
2082 __ bind(&check_zero); | 2080 __ b(gt, &return_left); |
2081 } | |
2082 __ b(vs, &result_is_nan); | |
2083 // Left equals right => check for -0. | |
2083 __ VFPCompareAndSetFlags(left_reg, 0.0); | 2084 __ VFPCompareAndSetFlags(left_reg, 0.0); |
2084 __ b(ne, &return_left); // left == right != 0. | 2085 if (left_reg.is(result_reg) || right_reg.is(result_reg)) { |
2086 __ b(ne, &done); // left == right != 0. | |
2087 } else { | |
2088 __ b(ne, &return_left); // left == right != 0. | |
2089 } | |
2085 // At this point, both left and right are either 0 or -0. | 2090 // At this point, both left and right are either 0 or -0. |
2086 if (operation == HMathMinMax::kMathMin) { | 2091 if (operation == HMathMinMax::kMathMin) { |
2087 // We could use a single 'vorr' instruction here if we had NEON support. | 2092 // We could use a single 'vorr' instruction here if we had NEON support. |
2088 __ vneg(left_reg, left_reg); | 2093 __ vneg(left_reg, left_reg); |
2089 __ vsub(result_reg, left_reg, right_reg); | 2094 __ vsub(result_reg, left_reg, right_reg); |
2090 __ vneg(result_reg, result_reg); | 2095 __ vneg(result_reg, result_reg); |
2091 } else { | 2096 } else { |
2092 // Since we operate on +0 and/or -0, vadd and vand have the same effect; | 2097 // Since we operate on +0 and/or -0, vadd and vand have the same effect; |
2093 // the decision for vadd is easy because vand is a NEON instruction. | 2098 // the decision for vadd is easy because vand is a NEON instruction. |
2094 __ vadd(result_reg, left_reg, right_reg); | 2099 __ vadd(result_reg, left_reg, right_reg); |
2095 } | 2100 } |
2096 __ b(al, &done); | 2101 __ b(&done); |
2097 | 2102 |
2098 __ bind(&check_nan_left); | 2103 __ bind(&result_is_nan); |
2099 __ VFPCompareAndSetFlags(left_reg, left_reg); | 2104 __ vadd(result_reg, left_reg, right_reg); |
2100 __ b(vs, &return_left); // left == NaN. | 2105 __ b(&done); |
2106 | |
2101 __ bind(&return_right); | 2107 __ bind(&return_right); |
2102 if (!right_reg.is(result_reg)) { | 2108 __ Move(result_reg, right_reg); |
2103 __ vmov(result_reg, right_reg); | 2109 if (!left_reg.is(result_reg)) { |
ulan
2013/04/17 14:30:41
Why do we need this "if" here?
| |
2110 __ b(&done); | |
2104 } | 2111 } |
2105 __ b(al, &done); | |
2106 | 2112 |
2107 __ bind(&return_left); | 2113 __ bind(&return_left); |
2108 if (!left_reg.is(result_reg)) { | 2114 __ Move(result_reg, left_reg); |
2109 __ vmov(result_reg, left_reg); | 2115 |
2110 } | |
2111 __ bind(&done); | 2116 __ bind(&done); |
2112 } | 2117 } |
2113 } | 2118 } |
2114 | 2119 |
2115 | 2120 |
2116 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { | 2121 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { |
2117 DwVfpRegister left = ToDoubleRegister(instr->left()); | 2122 DwVfpRegister left = ToDoubleRegister(instr->left()); |
2118 DwVfpRegister right = ToDoubleRegister(instr->right()); | 2123 DwVfpRegister right = ToDoubleRegister(instr->right()); |
2119 DwVfpRegister result = ToDoubleRegister(instr->result()); | 2124 DwVfpRegister result = ToDoubleRegister(instr->result()); |
2120 switch (instr->op()) { | 2125 switch (instr->op()) { |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2198 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2203 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
2199 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2204 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
2200 | 2205 |
2201 Representation r = instr->hydrogen()->value()->representation(); | 2206 Representation r = instr->hydrogen()->value()->representation(); |
2202 if (r.IsInteger32()) { | 2207 if (r.IsInteger32()) { |
2203 Register reg = ToRegister(instr->value()); | 2208 Register reg = ToRegister(instr->value()); |
2204 __ cmp(reg, Operand::Zero()); | 2209 __ cmp(reg, Operand::Zero()); |
2205 EmitBranch(true_block, false_block, ne); | 2210 EmitBranch(true_block, false_block, ne); |
2206 } else if (r.IsDouble()) { | 2211 } else if (r.IsDouble()) { |
2207 DwVfpRegister reg = ToDoubleRegister(instr->value()); | 2212 DwVfpRegister reg = ToDoubleRegister(instr->value()); |
2208 Register scratch = scratch0(); | |
2209 | |
2210 // Test the double value. Zero and NaN are false. | 2213 // Test the double value. Zero and NaN are false. |
2211 __ VFPCompareAndLoadFlags(reg, 0.0, scratch); | 2214 __ VFPCompareAndSetFlags(reg, 0.0); |
2212 __ tst(scratch, Operand(kVFPZConditionFlagBit | kVFPVConditionFlagBit)); | 2215 __ cmp(r0, r0, vs); // If NaN, set the Z flag. |
2213 EmitBranch(true_block, false_block, eq); | 2216 EmitBranch(true_block, false_block, ne); |
2214 } else { | 2217 } else { |
2215 ASSERT(r.IsTagged()); | 2218 ASSERT(r.IsTagged()); |
2216 Register reg = ToRegister(instr->value()); | 2219 Register reg = ToRegister(instr->value()); |
2217 HType type = instr->hydrogen()->value()->type(); | 2220 HType type = instr->hydrogen()->value()->type(); |
2218 if (type.IsBoolean()) { | 2221 if (type.IsBoolean()) { |
2219 __ CompareRoot(reg, Heap::kTrueValueRootIndex); | 2222 __ CompareRoot(reg, Heap::kTrueValueRootIndex); |
2220 EmitBranch(true_block, false_block, eq); | 2223 EmitBranch(true_block, false_block, eq); |
2221 } else if (type.IsSmi()) { | 2224 } else if (type.IsSmi()) { |
2222 __ cmp(reg, Operand::Zero()); | 2225 __ cmp(reg, Operand::Zero()); |
2223 EmitBranch(true_block, false_block, ne); | 2226 EmitBranch(true_block, false_block, ne); |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2295 } | 2298 } |
2296 | 2299 |
2297 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) { | 2300 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) { |
2298 // heap number -> false iff +0, -0, or NaN. | 2301 // heap number -> false iff +0, -0, or NaN. |
2299 DwVfpRegister dbl_scratch = double_scratch0(); | 2302 DwVfpRegister dbl_scratch = double_scratch0(); |
2300 Label not_heap_number; | 2303 Label not_heap_number; |
2301 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex); | 2304 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex); |
2302 __ b(ne, ¬_heap_number); | 2305 __ b(ne, ¬_heap_number); |
2303 __ vldr(dbl_scratch, FieldMemOperand(reg, HeapNumber::kValueOffset)); | 2306 __ vldr(dbl_scratch, FieldMemOperand(reg, HeapNumber::kValueOffset)); |
2304 __ VFPCompareAndSetFlags(dbl_scratch, 0.0); | 2307 __ VFPCompareAndSetFlags(dbl_scratch, 0.0); |
2305 __ b(vs, false_label); // NaN -> false. | 2308 __ cmp(r0, r0, vs); // NaN -> false. |
2306 __ b(eq, false_label); // +0, -0 -> false. | 2309 __ b(eq, false_label); // +0, -0 -> false. |
2307 __ b(true_label); | 2310 __ b(true_label); |
2308 __ bind(¬_heap_number); | 2311 __ bind(¬_heap_number); |
2309 } | 2312 } |
2310 | 2313 |
2311 // We've seen something for the first time -> deopt. | 2314 // We've seen something for the first time -> deopt. |
2312 DeoptimizeIf(al, instr->environment()); | 2315 DeoptimizeIf(al, instr->environment()); |
2313 } | 2316 } |
2314 } | 2317 } |
2315 } | 2318 } |
(...skipping 3696 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6012 __ sub(scratch, result, Operand(index, LSL, kPointerSizeLog2 - kSmiTagSize)); | 6015 __ sub(scratch, result, Operand(index, LSL, kPointerSizeLog2 - kSmiTagSize)); |
6013 __ ldr(result, FieldMemOperand(scratch, | 6016 __ ldr(result, FieldMemOperand(scratch, |
6014 FixedArray::kHeaderSize - kPointerSize)); | 6017 FixedArray::kHeaderSize - kPointerSize)); |
6015 __ bind(&done); | 6018 __ bind(&done); |
6016 } | 6019 } |
6017 | 6020 |
6018 | 6021 |
6019 #undef __ | 6022 #undef __ |
6020 | 6023 |
6021 } } // namespace v8::internal | 6024 } } // namespace v8::internal |
OLD | NEW |