| 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 1126 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1137     } | 1137     } | 
| 1138     __ b(&done); | 1138     __ b(&done); | 
| 1139   } | 1139   } | 
| 1140 | 1140 | 
| 1141   __ bind(÷nd_is_not_negative); | 1141   __ bind(÷nd_is_not_negative); | 
| 1142   __ and_(dividend, dividend, Operand(mask)); | 1142   __ and_(dividend, dividend, Operand(mask)); | 
| 1143   __ bind(&done); | 1143   __ bind(&done); | 
| 1144 } | 1144 } | 
| 1145 | 1145 | 
| 1146 | 1146 | 
|  | 1147 void LCodeGen::DoModByConstI(LModByConstI* instr) { | 
|  | 1148   Register dividend = ToRegister(instr->dividend()); | 
|  | 1149   int32_t divisor = instr->divisor(); | 
|  | 1150   Register result = ToRegister(instr->result()); | 
|  | 1151   ASSERT(!dividend.is(result)); | 
|  | 1152 | 
|  | 1153   if (divisor == 0) { | 
|  | 1154     DeoptimizeIf(al, instr->environment()); | 
|  | 1155     return; | 
|  | 1156   } | 
|  | 1157 | 
|  | 1158   __ FlooringDiv(result, dividend, Abs(divisor)); | 
|  | 1159   __ mov(ip, Operand(Abs(divisor))); | 
|  | 1160   __ smull(result, ip, result, ip); | 
|  | 1161   __ sub(result, dividend, result, SetCC); | 
|  | 1162 | 
|  | 1163   // Check for negative zero. | 
|  | 1164   HMod* hmod = instr->hydrogen(); | 
|  | 1165   if (hmod->CheckFlag(HValue::kBailoutOnMinusZero) && | 
|  | 1166       hmod->left()->CanBeNegative()) { | 
|  | 1167     Label remainder_not_zero; | 
|  | 1168     __ b(ne, &remainder_not_zero); | 
|  | 1169     __ cmp(dividend, Operand::Zero()); | 
|  | 1170     DeoptimizeIf(lt, instr->environment()); | 
|  | 1171     __ bind(&remainder_not_zero); | 
|  | 1172   } | 
|  | 1173 } | 
|  | 1174 | 
|  | 1175 | 
| 1147 void LCodeGen::DoModI(LModI* instr) { | 1176 void LCodeGen::DoModI(LModI* instr) { | 
| 1148   HMod* hmod = instr->hydrogen(); | 1177   HMod* hmod = instr->hydrogen(); | 
| 1149   HValue* left = hmod->left(); | 1178   HValue* left = hmod->left(); | 
| 1150   HValue* right = hmod->right(); | 1179   HValue* right = hmod->right(); | 
| 1151   if (CpuFeatures::IsSupported(SUDIV)) { | 1180   if (CpuFeatures::IsSupported(SUDIV)) { | 
| 1152     CpuFeatureScope scope(masm(), SUDIV); | 1181     CpuFeatureScope scope(masm(), SUDIV); | 
| 1153 | 1182 | 
| 1154     Register left_reg = ToRegister(instr->left()); | 1183     Register left_reg = ToRegister(instr->left()); | 
| 1155     Register right_reg = ToRegister(instr->right()); | 1184     Register right_reg = ToRegister(instr->right()); | 
| 1156     Register result_reg = ToRegister(instr->result()); | 1185     Register result_reg = ToRegister(instr->result()); | 
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1251         hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1280         hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | 
| 1252       __ b(ne, &done); | 1281       __ b(ne, &done); | 
| 1253       __ cmp(left_reg, Operand::Zero()); | 1282       __ cmp(left_reg, Operand::Zero()); | 
| 1254       DeoptimizeIf(mi, instr->environment()); | 1283       DeoptimizeIf(mi, instr->environment()); | 
| 1255     } | 1284     } | 
| 1256     __ bind(&done); | 1285     __ bind(&done); | 
| 1257   } | 1286   } | 
| 1258 } | 1287 } | 
| 1259 | 1288 | 
| 1260 | 1289 | 
| 1261 void LCodeGen::EmitSignedIntegerDivisionByConstant( |  | 
| 1262     Register result, |  | 
| 1263     Register dividend, |  | 
| 1264     int32_t divisor, |  | 
| 1265     Register remainder, |  | 
| 1266     Register scratch, |  | 
| 1267     LEnvironment* environment) { |  | 
| 1268   ASSERT(!AreAliased(dividend, scratch, ip)); |  | 
| 1269   ASSERT(LChunkBuilder::HasMagicNumberForDivisor(divisor)); |  | 
| 1270 |  | 
| 1271   uint32_t divisor_abs = abs(divisor); |  | 
| 1272 |  | 
| 1273   int32_t power_of_2_factor = |  | 
| 1274     CompilerIntrinsics::CountTrailingZeros(divisor_abs); |  | 
| 1275 |  | 
| 1276   switch (divisor_abs) { |  | 
| 1277     case 0: |  | 
| 1278       DeoptimizeIf(al, environment); |  | 
| 1279       return; |  | 
| 1280 |  | 
| 1281     case 1: |  | 
| 1282       if (divisor > 0) { |  | 
| 1283         __ Move(result, dividend); |  | 
| 1284       } else { |  | 
| 1285         __ rsb(result, dividend, Operand::Zero(), SetCC); |  | 
| 1286         DeoptimizeIf(vs, environment); |  | 
| 1287       } |  | 
| 1288       // Compute the remainder. |  | 
| 1289       __ mov(remainder, Operand::Zero()); |  | 
| 1290       return; |  | 
| 1291 |  | 
| 1292     default: |  | 
| 1293       if (IsPowerOf2(divisor_abs)) { |  | 
| 1294         // Branch and condition free code for integer division by a power |  | 
| 1295         // of two. |  | 
| 1296         int32_t power = WhichPowerOf2(divisor_abs); |  | 
| 1297         if (power > 1) { |  | 
| 1298           __ mov(scratch, Operand(dividend, ASR, power - 1)); |  | 
| 1299         } |  | 
| 1300         __ add(scratch, dividend, Operand(scratch, LSR, 32 - power)); |  | 
| 1301         __ mov(result, Operand(scratch, ASR, power)); |  | 
| 1302         // Negate if necessary. |  | 
| 1303         // We don't need to check for overflow because the case '-1' is |  | 
| 1304         // handled separately. |  | 
| 1305         if (divisor < 0) { |  | 
| 1306           ASSERT(divisor != -1); |  | 
| 1307           __ rsb(result, result, Operand::Zero()); |  | 
| 1308         } |  | 
| 1309         // Compute the remainder. |  | 
| 1310         if (divisor > 0) { |  | 
| 1311           __ sub(remainder, dividend, Operand(result, LSL, power)); |  | 
| 1312         } else { |  | 
| 1313           __ add(remainder, dividend, Operand(result, LSL, power)); |  | 
| 1314         } |  | 
| 1315         return; |  | 
| 1316       } else { |  | 
| 1317         // Use magic numbers for a few specific divisors. |  | 
| 1318         // Details and proofs can be found in: |  | 
| 1319         // - Hacker's Delight, Henry S. Warren, Jr. |  | 
| 1320         // - The PowerPC Compiler Writer’s Guide |  | 
| 1321         // and probably many others. |  | 
| 1322         // |  | 
| 1323         // We handle |  | 
| 1324         //   <divisor with magic numbers> * <power of 2> |  | 
| 1325         // but not |  | 
| 1326         //   <divisor with magic numbers> * <other divisor with magic numbers> |  | 
| 1327         DivMagicNumbers magic_numbers = |  | 
| 1328           DivMagicNumberFor(divisor_abs >> power_of_2_factor); |  | 
| 1329         // Branch and condition free code for integer division by a power |  | 
| 1330         // of two. |  | 
| 1331         const int32_t M = magic_numbers.M; |  | 
| 1332         const int32_t s = magic_numbers.s + power_of_2_factor; |  | 
| 1333 |  | 
| 1334         __ mov(ip, Operand(M)); |  | 
| 1335         __ smull(ip, scratch, dividend, ip); |  | 
| 1336         if (M < 0) { |  | 
| 1337           __ add(scratch, scratch, Operand(dividend)); |  | 
| 1338         } |  | 
| 1339         if (s > 0) { |  | 
| 1340           __ mov(scratch, Operand(scratch, ASR, s)); |  | 
| 1341         } |  | 
| 1342         __ add(result, scratch, Operand(dividend, LSR, 31)); |  | 
| 1343         if (divisor < 0) __ rsb(result, result, Operand::Zero()); |  | 
| 1344         // Compute the remainder. |  | 
| 1345         __ mov(ip, Operand(divisor)); |  | 
| 1346         // This sequence could be replaced with 'mls' when |  | 
| 1347         // it gets implemented. |  | 
| 1348         __ mul(scratch, result, ip); |  | 
| 1349         __ sub(remainder, dividend, scratch); |  | 
| 1350       } |  | 
| 1351   } |  | 
| 1352 } |  | 
| 1353 |  | 
| 1354 |  | 
| 1355 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) { | 1290 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) { | 
| 1356   Register dividend = ToRegister(instr->dividend()); | 1291   Register dividend = ToRegister(instr->dividend()); | 
| 1357   int32_t divisor = instr->divisor(); | 1292   int32_t divisor = instr->divisor(); | 
| 1358   Register result = ToRegister(instr->result()); | 1293   Register result = ToRegister(instr->result()); | 
| 1359   ASSERT(divisor == kMinInt || (divisor != 0 && IsPowerOf2(Abs(divisor)))); | 1294   ASSERT(divisor == kMinInt || (divisor != 0 && IsPowerOf2(Abs(divisor)))); | 
| 1360   ASSERT(!result.is(dividend)); | 1295   ASSERT(!result.is(dividend)); | 
| 1361 | 1296 | 
| 1362   // Check for (0 / -x) that will produce negative zero. | 1297   // Check for (0 / -x) that will produce negative zero. | 
| 1363   HDiv* hdiv = instr->hydrogen(); | 1298   HDiv* hdiv = instr->hydrogen(); | 
| 1364   if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && | 1299   if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && | 
| (...skipping 26 matching lines...) Expand all  Loading... | 
| 1391     __ add(result, dividend, Operand(dividend, LSR, 31)); | 1326     __ add(result, dividend, Operand(dividend, LSR, 31)); | 
| 1392   } else { | 1327   } else { | 
| 1393     __ mov(result, Operand(dividend, ASR, 31)); | 1328     __ mov(result, Operand(dividend, ASR, 31)); | 
| 1394     __ add(result, dividend, Operand(result, LSR, 32 - shift)); | 1329     __ add(result, dividend, Operand(result, LSR, 32 - shift)); | 
| 1395   } | 1330   } | 
| 1396   if (shift > 0) __ mov(result, Operand(result, ASR, shift)); | 1331   if (shift > 0) __ mov(result, Operand(result, ASR, shift)); | 
| 1397   if (divisor < 0) __ rsb(result, result, Operand(0)); | 1332   if (divisor < 0) __ rsb(result, result, Operand(0)); | 
| 1398 } | 1333 } | 
| 1399 | 1334 | 
| 1400 | 1335 | 
|  | 1336 void LCodeGen::DoDivByConstI(LDivByConstI* instr) { | 
|  | 1337   Register dividend = ToRegister(instr->dividend()); | 
|  | 1338   int32_t divisor = instr->divisor(); | 
|  | 1339   Register result = ToRegister(instr->result()); | 
|  | 1340   ASSERT(!dividend.is(result)); | 
|  | 1341 | 
|  | 1342   if (divisor == 0) { | 
|  | 1343     DeoptimizeIf(al, instr->environment()); | 
|  | 1344     return; | 
|  | 1345   } | 
|  | 1346 | 
|  | 1347   // Check for (0 / -x) that will produce negative zero. | 
|  | 1348   HDiv* hdiv = instr->hydrogen(); | 
|  | 1349   if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && | 
|  | 1350       hdiv->left()->RangeCanInclude(0) && divisor < 0) { | 
|  | 1351     __ cmp(dividend, Operand::Zero()); | 
|  | 1352     DeoptimizeIf(eq, instr->environment()); | 
|  | 1353   } | 
|  | 1354 | 
|  | 1355   __ FlooringDiv(result, dividend, Abs(divisor)); | 
|  | 1356   if (divisor < 0) __ rsb(result, result, Operand::Zero()); | 
|  | 1357 | 
|  | 1358   if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { | 
|  | 1359     __ mov(ip, Operand(divisor)); | 
|  | 1360     __ smull(scratch0(), ip, result, ip); | 
|  | 1361     __ sub(scratch0(), scratch0(), dividend, SetCC); | 
|  | 1362     DeoptimizeIf(ne, instr->environment()); | 
|  | 1363   } | 
|  | 1364 } | 
|  | 1365 | 
|  | 1366 | 
| 1401 void LCodeGen::DoDivI(LDivI* instr) { | 1367 void LCodeGen::DoDivI(LDivI* instr) { | 
| 1402   const Register left = ToRegister(instr->left()); | 1368   const Register left = ToRegister(instr->left()); | 
| 1403   const Register right = ToRegister(instr->right()); | 1369   const Register right = ToRegister(instr->right()); | 
| 1404   const Register result = ToRegister(instr->result()); | 1370   const Register result = ToRegister(instr->result()); | 
| 1405 | 1371 | 
| 1406   // Check for x / 0. | 1372   // Check for x / 0. | 
| 1407   if (instr->hydrogen_value()->CheckFlag(HValue::kCanBeDivByZero)) { | 1373   if (instr->hydrogen_value()->CheckFlag(HValue::kCanBeDivByZero)) { | 
| 1408     __ cmp(right, Operand::Zero()); | 1374     __ cmp(right, Operand::Zero()); | 
| 1409     DeoptimizeIf(eq, instr->environment()); | 1375     DeoptimizeIf(eq, instr->environment()); | 
| 1410   } | 1376   } | 
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1524       __ b(&done); | 1490       __ b(&done); | 
| 1525     } | 1491     } | 
| 1526   } | 1492   } | 
| 1527   __ bind(¬_kmin_int); | 1493   __ bind(¬_kmin_int); | 
| 1528   __ mov(dividend, Operand(dividend, ASR, shift)); | 1494   __ mov(dividend, Operand(dividend, ASR, shift)); | 
| 1529   __ bind(&done); | 1495   __ bind(&done); | 
| 1530 } | 1496 } | 
| 1531 | 1497 | 
| 1532 | 1498 | 
| 1533 void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) { | 1499 void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) { | 
| 1534   Register left = ToRegister(instr->dividend()); | 1500   Register dividend = ToRegister(instr->dividend()); | 
| 1535   Register remainder = ToRegister(instr->temp()); | 1501   int32_t divisor = instr->divisor(); | 
| 1536   Register scratch = scratch0(); |  | 
| 1537   Register result = ToRegister(instr->result()); | 1502   Register result = ToRegister(instr->result()); | 
|  | 1503   ASSERT(!dividend.is(result)); | 
| 1538 | 1504 | 
| 1539   if (!CpuFeatures::IsSupported(SUDIV)) { | 1505   if (divisor == 0) { | 
| 1540     // If the CPU doesn't support sdiv instruction, we only optimize when we | 1506     DeoptimizeIf(al, instr->environment()); | 
| 1541     // have magic numbers for the divisor. The standard integer division routine | 1507     return; | 
| 1542     // is usually slower than transitionning to VFP. | 1508   } | 
| 1543     ASSERT(instr->divisor()->IsConstantOperand()); |  | 
| 1544     int32_t divisor = ToInteger32(LConstantOperand::cast(instr->divisor())); |  | 
| 1545     ASSERT(LChunkBuilder::HasMagicNumberForDivisor(divisor)); |  | 
| 1546     if (divisor < 0) { |  | 
| 1547       __ cmp(left, Operand::Zero()); |  | 
| 1548       DeoptimizeIf(eq, instr->environment()); |  | 
| 1549     } |  | 
| 1550     EmitSignedIntegerDivisionByConstant(result, |  | 
| 1551                                         left, |  | 
| 1552                                         divisor, |  | 
| 1553                                         remainder, |  | 
| 1554                                         scratch, |  | 
| 1555                                         instr->environment()); |  | 
| 1556     // We performed a truncating division. Correct the result if necessary. |  | 
| 1557     __ cmp(remainder, Operand::Zero()); |  | 
| 1558     __ teq(remainder, Operand(divisor), ne); |  | 
| 1559     __ sub(result, result, Operand(1), LeaveCC, mi); |  | 
| 1560   } else { |  | 
| 1561     CpuFeatureScope scope(masm(), SUDIV); |  | 
| 1562     // TODO(svenpanne) We *statically* know the divisor, use that fact! |  | 
| 1563     Register right = ToRegister(instr->divisor()); |  | 
| 1564 | 1509 | 
| 1565     // Check for x / 0. | 1510   // Check for (0 / -x) that will produce negative zero. | 
| 1566     __ cmp(right, Operand::Zero()); | 1511   HMathFloorOfDiv* hdiv = instr->hydrogen(); | 
|  | 1512   if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && | 
|  | 1513       hdiv->left()->RangeCanInclude(0) && divisor < 0) { | 
|  | 1514     __ cmp(dividend, Operand::Zero()); | 
| 1567     DeoptimizeIf(eq, instr->environment()); | 1515     DeoptimizeIf(eq, instr->environment()); | 
|  | 1516   } | 
| 1568 | 1517 | 
| 1569     // Check for (kMinInt / -1). | 1518   __ FlooringDiv(result, dividend, divisor); | 
| 1570     if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |  | 
| 1571       __ cmp(left, Operand(kMinInt)); |  | 
| 1572       __ cmp(right, Operand(-1), eq); |  | 
| 1573       DeoptimizeIf(eq, instr->environment()); |  | 
| 1574     } |  | 
| 1575 |  | 
| 1576     // Check for (0 / -x) that will produce negative zero. |  | 
| 1577     if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |  | 
| 1578       __ cmp(right, Operand::Zero()); |  | 
| 1579       __ cmp(left, Operand::Zero(), mi); |  | 
| 1580       // "right" can't be null because the code would have already been |  | 
| 1581       // deoptimized. The Z flag is set only if (right < 0) and (left == 0). |  | 
| 1582       // In this case we need to deoptimize to produce a -0. |  | 
| 1583       DeoptimizeIf(eq, instr->environment()); |  | 
| 1584     } |  | 
| 1585 |  | 
| 1586     Label done; |  | 
| 1587     __ sdiv(result, left, right); |  | 
| 1588     // If both operands have the same sign then we are done. |  | 
| 1589     __ eor(remainder, left, Operand(right), SetCC); |  | 
| 1590     __ b(pl, &done); |  | 
| 1591 |  | 
| 1592     // Check if the result needs to be corrected. |  | 
| 1593     __ mls(remainder, result, right, left); |  | 
| 1594     __ cmp(remainder, Operand::Zero()); |  | 
| 1595     __ sub(result, result, Operand(1), LeaveCC, ne); |  | 
| 1596 |  | 
| 1597     __ bind(&done); |  | 
| 1598   } |  | 
| 1599 } | 1519 } | 
| 1600 | 1520 | 
| 1601 | 1521 | 
| 1602 void LCodeGen::DoMulI(LMulI* instr) { | 1522 void LCodeGen::DoMulI(LMulI* instr) { | 
| 1603   Register result = ToRegister(instr->result()); | 1523   Register result = ToRegister(instr->result()); | 
| 1604   // Note that result may alias left. | 1524   // Note that result may alias left. | 
| 1605   Register left = ToRegister(instr->left()); | 1525   Register left = ToRegister(instr->left()); | 
| 1606   LOperand* right_op = instr->right(); | 1526   LOperand* right_op = instr->right(); | 
| 1607 | 1527 | 
| 1608   bool bailout_on_minus_zero = | 1528   bool bailout_on_minus_zero = | 
| (...skipping 4193 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 5802   __ sub(scratch, result, Operand::PointerOffsetFromSmiKey(index)); | 5722   __ sub(scratch, result, Operand::PointerOffsetFromSmiKey(index)); | 
| 5803   __ ldr(result, FieldMemOperand(scratch, | 5723   __ ldr(result, FieldMemOperand(scratch, | 
| 5804                                  FixedArray::kHeaderSize - kPointerSize)); | 5724                                  FixedArray::kHeaderSize - kPointerSize)); | 
| 5805   __ bind(&done); | 5725   __ bind(&done); | 
| 5806 } | 5726 } | 
| 5807 | 5727 | 
| 5808 | 5728 | 
| 5809 #undef __ | 5729 #undef __ | 
| 5810 | 5730 | 
| 5811 } }  // namespace v8::internal | 5731 } }  // namespace v8::internal | 
| OLD | NEW | 
|---|