| OLD | NEW |
| 1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 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 410 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 421 movl(dst, Immediate(x)); | 421 movl(dst, Immediate(x)); |
| 422 } else { | 422 } else { |
| 423 movq(kScratchRegister, x, RelocInfo::NONE); | 423 movq(kScratchRegister, x, RelocInfo::NONE); |
| 424 movq(dst, kScratchRegister); | 424 movq(dst, kScratchRegister); |
| 425 } | 425 } |
| 426 } | 426 } |
| 427 | 427 |
| 428 // ---------------------------------------------------------------------------- | 428 // ---------------------------------------------------------------------------- |
| 429 // Smi tagging, untagging and tag detection. | 429 // Smi tagging, untagging and tag detection. |
| 430 | 430 |
| 431 #ifdef V8_LONG_SMI | |
| 432 | |
| 433 static int kSmiShift = kSmiTagSize + kSmiShiftSize; | 431 static int kSmiShift = kSmiTagSize + kSmiShiftSize; |
| 434 | 432 |
| 435 void MacroAssembler::Integer32ToSmi(Register dst, Register src) { | 433 void MacroAssembler::Integer32ToSmi(Register dst, Register src) { |
| 436 ASSERT_EQ(0, kSmiTag); | 434 ASSERT_EQ(0, kSmiTag); |
| 437 if (!dst.is(src)) { | 435 if (!dst.is(src)) { |
| 438 movl(dst, src); | 436 movl(dst, src); |
| 439 } | 437 } |
| 440 shl(dst, Immediate(kSmiShift)); | 438 shl(dst, Immediate(kSmiShift)); |
| 441 } | 439 } |
| 442 | 440 |
| (...skipping 760 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1203 } | 1201 } |
| 1204 neg(dst); | 1202 neg(dst); |
| 1205 if (shift < kSmiShift) { | 1203 if (shift < kSmiShift) { |
| 1206 sar(dst, Immediate(kSmiShift - shift)); | 1204 sar(dst, Immediate(kSmiShift - shift)); |
| 1207 } else { | 1205 } else { |
| 1208 shl(dst, Immediate(shift - kSmiShift)); | 1206 shl(dst, Immediate(shift - kSmiShift)); |
| 1209 } | 1207 } |
| 1210 return SmiIndex(dst, times_1); | 1208 return SmiIndex(dst, times_1); |
| 1211 } | 1209 } |
| 1212 | 1210 |
| 1213 #else // ! V8_LONG_SMI | |
| 1214 // 31 bit smi operations | |
| 1215 | |
| 1216 // Extracts the low 32 bits of a Smi pointer, where the taqgged smi value | |
| 1217 // is stored. | |
| 1218 static int32_t SmiValue(Smi* smi) { | |
| 1219 return static_cast<int32_t>(reinterpret_cast<intptr_t>(smi)); | |
| 1220 } | |
| 1221 | |
| 1222 | |
| 1223 void MacroAssembler::Integer32ToSmi(Register dst, Register src) { | |
| 1224 ASSERT_EQ(1, kSmiTagSize); | |
| 1225 ASSERT_EQ(0, kSmiTag); | |
| 1226 #ifdef DEBUG | |
| 1227 if (allow_stub_calls()) { | |
| 1228 cmpl(src, Immediate(0xC0000000u)); | |
| 1229 Check(positive, "Smi conversion overflow"); | |
| 1230 } | |
| 1231 #endif | |
| 1232 if (dst.is(src)) { | |
| 1233 addl(dst, src); | |
| 1234 } else { | |
| 1235 lea(dst, Operand(src, src, times_1, 0)); | |
| 1236 } | |
| 1237 } | |
| 1238 | |
| 1239 | |
| 1240 void MacroAssembler::Integer32ToSmi(Register dst, | |
| 1241 Register src, | |
| 1242 Label* on_overflow) { | |
| 1243 ASSERT_EQ(1, kSmiTagSize); | |
| 1244 ASSERT_EQ(0, kSmiTag); | |
| 1245 if (!dst.is(src)) { | |
| 1246 movl(dst, src); | |
| 1247 } | |
| 1248 addl(dst, src); | |
| 1249 j(overflow, on_overflow); | |
| 1250 } | |
| 1251 | |
| 1252 | |
| 1253 void MacroAssembler::Integer64PlusConstantToSmi(Register dst, | |
| 1254 Register src, | |
| 1255 int constant) { | |
| 1256 #ifdef DEBUG | |
| 1257 if (allow_stub_calls()) { | |
| 1258 movl(kScratchRegister, src); | |
| 1259 addl(kScratchRegister, Immediate(constant)); | |
| 1260 Check(no_overflow, "Add-and-smi-convert overflow"); | |
| 1261 Condition valid = CheckInteger32ValidSmiValue(kScratchRegister); | |
| 1262 Check(valid, "Add-and-smi-convert overflow"); | |
| 1263 } | |
| 1264 #endif | |
| 1265 lea(dst, Operand(src, src, times_1, constant << kSmiTagSize)); | |
| 1266 } | |
| 1267 | |
| 1268 | |
| 1269 void MacroAssembler::SmiToInteger32(Register dst, Register src) { | |
| 1270 ASSERT_EQ(1, kSmiTagSize); | |
| 1271 ASSERT_EQ(0, kSmiTag); | |
| 1272 if (!dst.is(src)) { | |
| 1273 movl(dst, src); | |
| 1274 } | |
| 1275 sarl(dst, Immediate(kSmiTagSize)); | |
| 1276 } | |
| 1277 | |
| 1278 | |
| 1279 void MacroAssembler::SmiToInteger64(Register dst, Register src) { | |
| 1280 ASSERT_EQ(1, kSmiTagSize); | |
| 1281 ASSERT_EQ(0, kSmiTag); | |
| 1282 movsxlq(dst, src); | |
| 1283 sar(dst, Immediate(kSmiTagSize)); | |
| 1284 } | |
| 1285 | |
| 1286 | |
| 1287 void MacroAssembler::SmiTest(Register src) { | |
| 1288 testl(src, src); | |
| 1289 } | |
| 1290 | |
| 1291 | |
| 1292 void MacroAssembler::SmiCompare(Register dst, Register src) { | |
| 1293 cmpl(dst, src); | |
| 1294 } | |
| 1295 | |
| 1296 | |
| 1297 void MacroAssembler::SmiCompare(Register dst, Smi* src) { | |
| 1298 ASSERT(!dst.is(kScratchRegister)); | |
| 1299 if (src->value() == 0) { | |
| 1300 testl(dst, dst); | |
| 1301 } else { | |
| 1302 cmpl(dst, Immediate(SmiValue(src))); | |
| 1303 } | |
| 1304 } | |
| 1305 | |
| 1306 | |
| 1307 void MacroAssembler::SmiCompare(const Operand& dst, Register src) { | |
| 1308 cmpl(dst, src); | |
| 1309 } | |
| 1310 | |
| 1311 | |
| 1312 void MacroAssembler::SmiCompare(const Operand& dst, Smi* src) { | |
| 1313 if (src->value() == 0) { | |
| 1314 movl(kScratchRegister, dst); | |
| 1315 testl(kScratchRegister, kScratchRegister); | |
| 1316 } else { | |
| 1317 cmpl(dst, Immediate(SmiValue(src))); | |
| 1318 } | |
| 1319 } | |
| 1320 | |
| 1321 | |
| 1322 void MacroAssembler::PositiveSmiTimesPowerOfTwoToInteger64(Register dst, | |
| 1323 Register src, | |
| 1324 int power) { | |
| 1325 ASSERT(power >= 0); | |
| 1326 ASSERT(power < 64); | |
| 1327 if (power == 0) { | |
| 1328 SmiToInteger64(dst, src); | |
| 1329 return; | |
| 1330 } | |
| 1331 movsxlq(dst, src); | |
| 1332 shl(dst, Immediate(power - 1)); | |
| 1333 } | |
| 1334 | |
| 1335 Condition MacroAssembler::CheckSmi(Register src) { | |
| 1336 testb(src, Immediate(kSmiTagMask)); | |
| 1337 return zero; | |
| 1338 } | |
| 1339 | |
| 1340 Condition MacroAssembler::CheckPositiveSmi(Register src) { | |
| 1341 ASSERT_EQ(0, kSmiTag); | |
| 1342 testl(src, Immediate(static_cast<uint32_t>(0x80000000u | kSmiTagMask))); | |
| 1343 return zero; | |
| 1344 } | |
| 1345 | |
| 1346 Condition MacroAssembler::CheckBothSmi(Register first, Register second) { | |
| 1347 if (first.is(second)) { | |
| 1348 return CheckSmi(first); | |
| 1349 } | |
| 1350 movl(kScratchRegister, first); | |
| 1351 orl(kScratchRegister, second); | |
| 1352 return CheckSmi(kScratchRegister); | |
| 1353 } | |
| 1354 | |
| 1355 Condition MacroAssembler::CheckIsMinSmi(Register src) { | |
| 1356 ASSERT(kSmiTag == 0 && kSmiTagSize == 1); | |
| 1357 cmpl(src, Immediate(0x80000000u)); | |
| 1358 return equal; | |
| 1359 } | |
| 1360 | |
| 1361 Condition MacroAssembler::CheckInteger32ValidSmiValue(Register src) { | |
| 1362 // A 32-bit integer value can be converted to a smi if it is in the | |
| 1363 // range [-2^30 .. 2^30-1]. That is equivalent to having its 32-bit | |
| 1364 // representation have bits 30 and 31 be equal. | |
| 1365 cmpl(src, Immediate(0xC0000000u)); | |
| 1366 return positive; | |
| 1367 } | |
| 1368 | |
| 1369 | |
| 1370 void MacroAssembler::SmiNeg(Register dst, | |
| 1371 Register src, | |
| 1372 Label* on_smi_result) { | |
| 1373 if (!dst.is(src)) { | |
| 1374 movl(dst, src); | |
| 1375 } | |
| 1376 negl(dst); | |
| 1377 testl(dst, Immediate(0x7fffffff)); | |
| 1378 // If the result is zero or 0x80000000, negation failed to create a smi. | |
| 1379 j(not_equal, on_smi_result); | |
| 1380 } | |
| 1381 | |
| 1382 | |
| 1383 void MacroAssembler::SmiAdd(Register dst, | |
| 1384 Register src1, | |
| 1385 Register src2, | |
| 1386 Label* on_not_smi_result) { | |
| 1387 ASSERT(!dst.is(src2)); | |
| 1388 if (!dst.is(src1)) { | |
| 1389 movl(dst, src1); | |
| 1390 } | |
| 1391 addl(dst, src2); | |
| 1392 if (!dst.is(src1)) { | |
| 1393 j(overflow, on_not_smi_result); | |
| 1394 } else { | |
| 1395 Label smi_result; | |
| 1396 j(no_overflow, &smi_result); | |
| 1397 // Restore src1. | |
| 1398 subl(src1, src2); | |
| 1399 jmp(on_not_smi_result); | |
| 1400 bind(&smi_result); | |
| 1401 } | |
| 1402 } | |
| 1403 | |
| 1404 | |
| 1405 void MacroAssembler::SmiSub(Register dst, | |
| 1406 Register src1, | |
| 1407 Register src2, | |
| 1408 Label* on_not_smi_result) { | |
| 1409 ASSERT(!dst.is(src2)); | |
| 1410 if (!dst.is(src1)) { | |
| 1411 movl(dst, src1); | |
| 1412 } | |
| 1413 subl(dst, src2); | |
| 1414 if (!dst.is(src1)) { | |
| 1415 j(overflow, on_not_smi_result); | |
| 1416 } else { | |
| 1417 Label smi_result; | |
| 1418 j(no_overflow, &smi_result); | |
| 1419 // Restore src1. | |
| 1420 addl(src1, src2); | |
| 1421 jmp(on_not_smi_result); | |
| 1422 bind(&smi_result); | |
| 1423 } | |
| 1424 } | |
| 1425 | |
| 1426 | |
| 1427 void MacroAssembler::SmiMul(Register dst, | |
| 1428 Register src1, | |
| 1429 Register src2, | |
| 1430 Label* on_not_smi_result) { | |
| 1431 ASSERT(!dst.is(src2)); | |
| 1432 | |
| 1433 if (dst.is(src1)) { | |
| 1434 // Copy src1 before overwriting. | |
| 1435 movq(kScratchRegister, src1); | |
| 1436 } | |
| 1437 SmiToInteger32(dst, src1); | |
| 1438 | |
| 1439 imull(dst, src2); | |
| 1440 j(overflow, on_not_smi_result); | |
| 1441 | |
| 1442 // Check for negative zero result. If product is zero, and one | |
| 1443 // argument is negative, go to slow case. The frame is unchanged | |
| 1444 // in this block, so local control flow can use a Label rather | |
| 1445 // than a JumpTarget. | |
| 1446 Label non_zero_result; | |
| 1447 testl(dst, dst); | |
| 1448 j(not_zero, &non_zero_result); | |
| 1449 | |
| 1450 // Test whether either operand is negative (the other must be zero). | |
| 1451 if (!dst.is(src1)) { | |
| 1452 movl(kScratchRegister, src1); | |
| 1453 } | |
| 1454 orl(kScratchRegister, src2); | |
| 1455 j(negative, on_not_smi_result); | |
| 1456 | |
| 1457 bind(&non_zero_result); | |
| 1458 } | |
| 1459 | |
| 1460 | |
| 1461 void MacroAssembler::SmiTryAddConstant(Register dst, | |
| 1462 Register src, | |
| 1463 Smi* constant, | |
| 1464 Label* on_not_smi_result) { | |
| 1465 // Does not assume that src is a smi. | |
| 1466 ASSERT_EQ(static_cast<intptr_t>(1), kSmiTagMask); | |
| 1467 ASSERT_EQ(0, kSmiTag); | |
| 1468 | |
| 1469 Register tmp = (src.is(dst) ? kScratchRegister : dst); | |
| 1470 movl(tmp, src); | |
| 1471 addl(tmp, Immediate(SmiValue(constant))); | |
| 1472 if (tmp.is(kScratchRegister)) { | |
| 1473 j(overflow, on_not_smi_result); | |
| 1474 testl(tmp, Immediate(kSmiTagMask)); | |
| 1475 j(not_zero, on_not_smi_result); | |
| 1476 movl(dst, tmp); | |
| 1477 } else { | |
| 1478 movl(kScratchRegister, Immediate(kSmiTagMask)); | |
| 1479 cmovl(overflow, dst, kScratchRegister); | |
| 1480 testl(dst, kScratchRegister); | |
| 1481 j(not_zero, on_not_smi_result); | |
| 1482 } | |
| 1483 } | |
| 1484 | |
| 1485 | |
| 1486 void MacroAssembler::SmiAddConstant(Register dst, | |
| 1487 Register src, | |
| 1488 Smi* constant) { | |
| 1489 ASSERT_EQ(1, kSmiTagMask); | |
| 1490 ASSERT_EQ(0, kSmiTag); | |
| 1491 int32_t smi_value = SmiValue(constant); | |
| 1492 if (dst.is(src)) { | |
| 1493 addl(dst, Immediate(smi_value)); | |
| 1494 } else { | |
| 1495 lea(dst, Operand(src, smi_value)); | |
| 1496 } | |
| 1497 } | |
| 1498 | |
| 1499 | |
| 1500 void MacroAssembler::SmiAddConstant(Register dst, | |
| 1501 Register src, | |
| 1502 Smi* constant, | |
| 1503 Label* on_not_smi_result) { | |
| 1504 ASSERT_EQ(1, kSmiTagMask); | |
| 1505 ASSERT_EQ(0, kSmiTag); | |
| 1506 int32_t smi_value = SmiValue(constant); | |
| 1507 if (!dst.is(src)) { | |
| 1508 movl(dst, src); | |
| 1509 addl(dst, Immediate(smi_value)); | |
| 1510 j(overflow, on_not_smi_result); | |
| 1511 } else { | |
| 1512 addl(dst, Immediate(smi_value)); | |
| 1513 Label result_ok; | |
| 1514 j(no_overflow, &result_ok); | |
| 1515 subl(dst, Immediate(smi_value)); | |
| 1516 jmp(on_not_smi_result); | |
| 1517 bind(&result_ok); | |
| 1518 } | |
| 1519 } | |
| 1520 | |
| 1521 | |
| 1522 void MacroAssembler::SmiSubConstant(Register dst, | |
| 1523 Register src, | |
| 1524 Smi* constant) { | |
| 1525 ASSERT_EQ(1, kSmiTagMask); | |
| 1526 ASSERT_EQ(0, kSmiTag); | |
| 1527 if (!dst.is(src)) { | |
| 1528 movl(dst, src); | |
| 1529 } | |
| 1530 subl(dst, Immediate(SmiValue(constant))); | |
| 1531 } | |
| 1532 | |
| 1533 | |
| 1534 void MacroAssembler::SmiSubConstant(Register dst, | |
| 1535 Register src, | |
| 1536 Smi* constant, | |
| 1537 Label* on_not_smi_result) { | |
| 1538 ASSERT_EQ(1, kSmiTagMask); | |
| 1539 ASSERT_EQ(0, kSmiTag); | |
| 1540 int32_t smi_value = SmiValue(constant); | |
| 1541 if (dst.is(src)) { | |
| 1542 // Optimistic subtract - may change value of dst register, | |
| 1543 // if it has garbage bits in the higher half, but will not change | |
| 1544 // the value as a tagged smi. | |
| 1545 subl(dst, Immediate(smi_value)); | |
| 1546 Label add_success; | |
| 1547 j(no_overflow, &add_success); | |
| 1548 addl(dst, Immediate(smi_value)); | |
| 1549 jmp(on_not_smi_result); | |
| 1550 bind(&add_success); | |
| 1551 } else { | |
| 1552 movl(dst, src); | |
| 1553 subl(dst, Immediate(smi_value)); | |
| 1554 j(overflow, on_not_smi_result); | |
| 1555 } | |
| 1556 } | |
| 1557 | |
| 1558 | |
| 1559 void MacroAssembler::SmiDiv(Register dst, | |
| 1560 Register src1, | |
| 1561 Register src2, | |
| 1562 Label* on_not_smi_result) { | |
| 1563 ASSERT(!src2.is(rax)); | |
| 1564 ASSERT(!src2.is(rdx)); | |
| 1565 ASSERT(!src1.is(rdx)); | |
| 1566 | |
| 1567 // Check for 0 divisor (result is +/-Infinity). | |
| 1568 Label positive_divisor; | |
| 1569 testl(src2, src2); | |
| 1570 j(zero, on_not_smi_result); | |
| 1571 j(positive, &positive_divisor); | |
| 1572 // Check for negative zero result. If the dividend is zero, and the | |
| 1573 // divisor is negative, return a floating point negative zero. | |
| 1574 testl(src1, src1); | |
| 1575 j(zero, on_not_smi_result); | |
| 1576 bind(&positive_divisor); | |
| 1577 | |
| 1578 // Sign extend src1 into edx:eax. | |
| 1579 if (!src1.is(rax)) { | |
| 1580 movl(rax, src1); | |
| 1581 } | |
| 1582 cdq(); | |
| 1583 | |
| 1584 idivl(src2); | |
| 1585 // Check for the corner case of dividing the most negative smi by | |
| 1586 // -1. We cannot use the overflow flag, since it is not set by | |
| 1587 // idiv instruction. | |
| 1588 ASSERT(kSmiTag == 0 && kSmiTagSize == 1); | |
| 1589 cmpl(rax, Immediate(0x40000000)); | |
| 1590 j(equal, on_not_smi_result); | |
| 1591 // Check that the remainder is zero. | |
| 1592 testl(rdx, rdx); | |
| 1593 j(not_zero, on_not_smi_result); | |
| 1594 // Tag the result and store it in the destination register. | |
| 1595 Integer32ToSmi(dst, rax); | |
| 1596 } | |
| 1597 | |
| 1598 | |
| 1599 void MacroAssembler::SmiMod(Register dst, | |
| 1600 Register src1, | |
| 1601 Register src2, | |
| 1602 Label* on_not_smi_result) { | |
| 1603 ASSERT(!dst.is(kScratchRegister)); | |
| 1604 ASSERT(!src1.is(kScratchRegister)); | |
| 1605 ASSERT(!src2.is(kScratchRegister)); | |
| 1606 ASSERT(!src2.is(rax)); | |
| 1607 ASSERT(!src2.is(rdx)); | |
| 1608 ASSERT(!src1.is(rdx)); | |
| 1609 | |
| 1610 testl(src2, src2); | |
| 1611 j(zero, on_not_smi_result); | |
| 1612 | |
| 1613 if (src1.is(rax)) { | |
| 1614 // Mist remember the value to see if a zero result should | |
| 1615 // be a negative zero. | |
| 1616 movl(kScratchRegister, rax); | |
| 1617 } else { | |
| 1618 movl(rax, src1); | |
| 1619 } | |
| 1620 // Sign extend eax into edx:eax. | |
| 1621 cdq(); | |
| 1622 idivl(src2); | |
| 1623 // Check for a negative zero result. If the result is zero, and the | |
| 1624 // dividend is negative, return a floating point negative zero. | |
| 1625 Label non_zero_result; | |
| 1626 testl(rdx, rdx); | |
| 1627 j(not_zero, &non_zero_result); | |
| 1628 if (src1.is(rax)) { | |
| 1629 testl(kScratchRegister, kScratchRegister); | |
| 1630 } else { | |
| 1631 testl(src1, src1); | |
| 1632 } | |
| 1633 j(negative, on_not_smi_result); | |
| 1634 bind(&non_zero_result); | |
| 1635 if (!dst.is(rdx)) { | |
| 1636 movl(dst, rdx); | |
| 1637 } | |
| 1638 } | |
| 1639 | |
| 1640 | |
| 1641 void MacroAssembler::SmiNot(Register dst, Register src) { | |
| 1642 if (dst.is(src)) { | |
| 1643 not_(dst); | |
| 1644 // Remove inverted smi-tag. The mask is sign-extended to 64 bits. | |
| 1645 xor_(src, Immediate(kSmiTagMask)); | |
| 1646 } else { | |
| 1647 ASSERT_EQ(0, kSmiTag); | |
| 1648 lea(dst, Operand(src, kSmiTagMask)); | |
| 1649 not_(dst); | |
| 1650 } | |
| 1651 } | |
| 1652 | |
| 1653 | |
| 1654 void MacroAssembler::SmiAnd(Register dst, Register src1, Register src2) { | |
| 1655 if (!dst.is(src1)) { | |
| 1656 movl(dst, src1); | |
| 1657 } | |
| 1658 and_(dst, src2); | |
| 1659 } | |
| 1660 | |
| 1661 | |
| 1662 void MacroAssembler::SmiAndConstant(Register dst, Register src, Smi* constant) { | |
| 1663 if (!dst.is(src)) { | |
| 1664 movl(dst, src); | |
| 1665 } | |
| 1666 int32_t smi_value = SmiValue(constant); | |
| 1667 and_(dst, Immediate(smi_value)); | |
| 1668 } | |
| 1669 | |
| 1670 | |
| 1671 void MacroAssembler::SmiOr(Register dst, Register src1, Register src2) { | |
| 1672 if (!dst.is(src1)) { | |
| 1673 movl(dst, src1); | |
| 1674 } | |
| 1675 or_(dst, src2); | |
| 1676 } | |
| 1677 | |
| 1678 | |
| 1679 void MacroAssembler::SmiOrConstant(Register dst, Register src, Smi* constant) { | |
| 1680 if (!dst.is(src)) { | |
| 1681 movl(dst, src); | |
| 1682 } | |
| 1683 int32_t smi_value = SmiValue(constant); | |
| 1684 or_(dst, Immediate(smi_value)); | |
| 1685 } | |
| 1686 | |
| 1687 | |
| 1688 void MacroAssembler::SmiXor(Register dst, Register src1, Register src2) { | |
| 1689 if (!dst.is(src1)) { | |
| 1690 movl(dst, src1); | |
| 1691 } | |
| 1692 xor_(dst, src2); | |
| 1693 } | |
| 1694 | |
| 1695 | |
| 1696 void MacroAssembler::SmiXorConstant(Register dst, Register src, Smi* constant) { | |
| 1697 if (!dst.is(src)) { | |
| 1698 movl(dst, src); | |
| 1699 } | |
| 1700 int32_t smi_value = SmiValue(constant); | |
| 1701 xor_(dst, Immediate(smi_value)); | |
| 1702 } | |
| 1703 | |
| 1704 | |
| 1705 void MacroAssembler::SmiShiftArithmeticRightConstant(Register dst, | |
| 1706 Register src, | |
| 1707 int shift_value) { | |
| 1708 if (shift_value > 0) { | |
| 1709 if (dst.is(src)) { | |
| 1710 sarl(dst, Immediate(shift_value)); | |
| 1711 and_(dst, Immediate(~kSmiTagMask)); | |
| 1712 } else { | |
| 1713 UNIMPLEMENTED(); // Not used. | |
| 1714 } | |
| 1715 } | |
| 1716 } | |
| 1717 | |
| 1718 | |
| 1719 void MacroAssembler::SmiShiftLogicalRightConstant(Register dst, | |
| 1720 Register src, | |
| 1721 int shift_value, | |
| 1722 Label* on_not_smi_result) { | |
| 1723 // Logic right shift interprets its result as an *unsigned* number. | |
| 1724 if (dst.is(src)) { | |
| 1725 UNIMPLEMENTED(); // Not used. | |
| 1726 } else { | |
| 1727 movl(dst, src); | |
| 1728 // Untag the smi. | |
| 1729 sarl(dst, Immediate(kSmiTagSize)); | |
| 1730 if (shift_value < 2) { | |
| 1731 // A negative Smi shifted right two is in the positive Smi range, | |
| 1732 // but if shifted only by zero or one, it never is. | |
| 1733 j(negative, on_not_smi_result); | |
| 1734 } | |
| 1735 if (shift_value > 0) { | |
| 1736 // Do the right shift on the integer value. | |
| 1737 shrl(dst, Immediate(shift_value)); | |
| 1738 } | |
| 1739 // Re-tag the result. | |
| 1740 addl(dst, dst); | |
| 1741 } | |
| 1742 } | |
| 1743 | |
| 1744 | |
| 1745 void MacroAssembler::SmiShiftLeftConstant(Register dst, | |
| 1746 Register src, | |
| 1747 int shift_value, | |
| 1748 Label* on_not_smi_result) { | |
| 1749 if (dst.is(src)) { | |
| 1750 if (shift_value > 0) { | |
| 1751 movq(kScratchRegister, src); | |
| 1752 // Treat scratch as an untagged integer value equal to two times the | |
| 1753 // smi value of src, i.e., already shifted left by one. | |
| 1754 if (shift_value > 1) { | |
| 1755 shll(kScratchRegister, Immediate(shift_value - 1)); | |
| 1756 } | |
| 1757 JumpIfNotValidSmiValue(kScratchRegister, on_not_smi_result); | |
| 1758 // Convert int result to Smi, checking that it is in smi range. | |
| 1759 ASSERT(kSmiTagSize == 1); // adjust code if not the case | |
| 1760 Integer32ToSmi(dst, kScratchRegister); | |
| 1761 } | |
| 1762 } else { | |
| 1763 movl(dst, src); | |
| 1764 if (shift_value > 0) { | |
| 1765 // Treat dst as an untagged integer value equal to two times the | |
| 1766 // smi value of src, i.e., already shifted left by one. | |
| 1767 if (shift_value > 1) { | |
| 1768 shll(dst, Immediate(shift_value - 1)); | |
| 1769 } | |
| 1770 // Convert int result to Smi, checking that it is in smi range. | |
| 1771 ASSERT(kSmiTagSize == 1); // adjust code if not the case | |
| 1772 Integer32ToSmi(dst, dst, on_not_smi_result); | |
| 1773 } | |
| 1774 } | |
| 1775 } | |
| 1776 | |
| 1777 | |
| 1778 void MacroAssembler::SmiShiftLeft(Register dst, | |
| 1779 Register src1, | |
| 1780 Register src2, | |
| 1781 Label* on_not_smi_result) { | |
| 1782 ASSERT(!dst.is(rcx)); | |
| 1783 Label result_ok; | |
| 1784 // Untag both operands. | |
| 1785 if (dst.is(src1) || src1.is(rcx)) { | |
| 1786 movq(kScratchRegister, src1); | |
| 1787 } | |
| 1788 SmiToInteger32(dst, src1); | |
| 1789 SmiToInteger32(rcx, src2); | |
| 1790 shll(dst); | |
| 1791 // Check that the *signed* result fits in a smi. | |
| 1792 Condition is_valid = CheckInteger32ValidSmiValue(dst); | |
| 1793 j(is_valid, &result_ok); | |
| 1794 // Restore the relevant bits of the source registers | |
| 1795 // and call the slow version. | |
| 1796 if (dst.is(src1) || src1.is(rcx)) { | |
| 1797 movq(src1, kScratchRegister); | |
| 1798 } | |
| 1799 if (src2.is(rcx)) { | |
| 1800 Integer32ToSmi(rcx, rcx); | |
| 1801 } | |
| 1802 jmp(on_not_smi_result); | |
| 1803 bind(&result_ok); | |
| 1804 Integer32ToSmi(dst, dst); | |
| 1805 } | |
| 1806 | |
| 1807 | |
| 1808 void MacroAssembler::SmiShiftLogicalRight(Register dst, | |
| 1809 Register src1, | |
| 1810 Register src2, | |
| 1811 Label* on_not_smi_result) { | |
| 1812 ASSERT(!dst.is(kScratchRegister)); | |
| 1813 ASSERT(!src1.is(kScratchRegister)); | |
| 1814 ASSERT(!src2.is(kScratchRegister)); | |
| 1815 ASSERT(!dst.is(rcx)); | |
| 1816 Label result_ok; | |
| 1817 // Untag both operands. | |
| 1818 if (src1.is(rcx)) { | |
| 1819 movq(kScratchRegister, src1); | |
| 1820 } | |
| 1821 SmiToInteger32(dst, src1); | |
| 1822 SmiToInteger32(rcx, src2); | |
| 1823 | |
| 1824 shrl(dst); | |
| 1825 // Check that the *unsigned* result fits in a smi. | |
| 1826 // I.e., that it is a valid positive smi value. The positive smi | |
| 1827 // values are 0..0x3fffffff, i.e., neither of the top-most two | |
| 1828 // bits can be set. | |
| 1829 // | |
| 1830 // These two cases can only happen with shifts by 0 or 1 when | |
| 1831 // handed a valid smi. If the answer cannot be represented by a | |
| 1832 // smi, restore the left and right arguments, and jump to slow | |
| 1833 // case. The low bit of the left argument may be lost, but only | |
| 1834 // in a case where it is dropped anyway. | |
| 1835 testl(dst, Immediate(0xc0000000)); | |
| 1836 j(zero, &result_ok); | |
| 1837 if (dst.is(src1)) { | |
| 1838 shll(dst); | |
| 1839 Integer32ToSmi(dst, dst); | |
| 1840 } else if (src1.is(rcx)) { | |
| 1841 movq(rcx, kScratchRegister); | |
| 1842 } else if (src2.is(rcx)) { | |
| 1843 Integer32ToSmi(src2, src2); | |
| 1844 } | |
| 1845 jmp(on_not_smi_result); | |
| 1846 bind(&result_ok); | |
| 1847 // Smi-tag the result in answer. | |
| 1848 Integer32ToSmi(dst, dst); | |
| 1849 } | |
| 1850 | |
| 1851 | |
| 1852 void MacroAssembler::SmiShiftArithmeticRight(Register dst, | |
| 1853 Register src1, | |
| 1854 Register src2) { | |
| 1855 ASSERT(!dst.is(rcx)); | |
| 1856 // Untag both operands. | |
| 1857 SmiToInteger32(dst, src1); | |
| 1858 SmiToInteger32(rcx, src2); | |
| 1859 // Shift as integer. | |
| 1860 sarl(dst); | |
| 1861 // Retag result. | |
| 1862 Integer32ToSmi(dst, dst); | |
| 1863 } | |
| 1864 | |
| 1865 | |
| 1866 void MacroAssembler::SelectNonSmi(Register dst, | |
| 1867 Register src1, | |
| 1868 Register src2, | |
| 1869 Label* on_not_smis) { | |
| 1870 ASSERT(!dst.is(src1)); | |
| 1871 ASSERT(!dst.is(src2)); | |
| 1872 // Both operands must not be smis. | |
| 1873 #ifdef DEBUG | |
| 1874 if (allow_stub_calls()) { | |
| 1875 Condition not_both_smis = NegateCondition(CheckBothSmi(src1, src2)); | |
| 1876 Check(not_both_smis, "Both registers were smis."); | |
| 1877 } | |
| 1878 #endif | |
| 1879 ASSERT_EQ(0, kSmiTag); | |
| 1880 ASSERT_EQ(0, Smi::FromInt(0)); | |
| 1881 movq(kScratchRegister, Immediate(kSmiTagMask)); | |
| 1882 and_(kScratchRegister, src1); | |
| 1883 testl(kScratchRegister, src2); | |
| 1884 j(not_zero, on_not_smis); | |
| 1885 // One operand is a smi. | |
| 1886 | |
| 1887 ASSERT_EQ(1, static_cast<int>(kSmiTagMask)); | |
| 1888 // kScratchRegister still holds src1 & kSmiTag, which is either zero or one. | |
| 1889 subq(kScratchRegister, Immediate(1)); | |
| 1890 // If src1 is a smi, then scratch register all 1s, else it is all 0s. | |
| 1891 movq(dst, src1); | |
| 1892 xor_(dst, src2); | |
| 1893 and_(dst, kScratchRegister); | |
| 1894 // If src1 is a smi, dst holds src1 ^ src2, else it is zero. | |
| 1895 xor_(dst, src1); | |
| 1896 // If src1 is a smi, dst is src2, else it is src1, i.e., a non-smi. | |
| 1897 } | |
| 1898 | |
| 1899 | |
| 1900 SmiIndex MacroAssembler::SmiToIndex(Register dst, Register src, int shift) { | |
| 1901 ASSERT(is_uint6(shift)); | |
| 1902 if (shift == 0) { // times_1. | |
| 1903 SmiToInteger32(dst, src); | |
| 1904 return SmiIndex(dst, times_1); | |
| 1905 } | |
| 1906 if (shift <= 4) { // 2 - 16 times multiplier is handled using ScaleFactor. | |
| 1907 // We expect that all smis are actually zero-padded. If this holds after | |
| 1908 // checking, this line can be omitted. | |
| 1909 movl(dst, src); // Ensure that the smi is zero-padded. | |
| 1910 return SmiIndex(dst, static_cast<ScaleFactor>(shift - kSmiTagSize)); | |
| 1911 } | |
| 1912 // Shift by shift-kSmiTagSize. | |
| 1913 movl(dst, src); // Ensure that the smi is zero-padded. | |
| 1914 shl(dst, Immediate(shift - kSmiTagSize)); | |
| 1915 return SmiIndex(dst, times_1); | |
| 1916 } | |
| 1917 | |
| 1918 | 1211 |
| 1919 SmiIndex MacroAssembler::SmiToNegativeIndex(Register dst, | |
| 1920 Register src, | |
| 1921 int shift) { | |
| 1922 // Register src holds a positive smi. | |
| 1923 ASSERT(is_uint6(shift)); | |
| 1924 if (shift == 0) { // times_1. | |
| 1925 SmiToInteger32(dst, src); | |
| 1926 neg(dst); | |
| 1927 return SmiIndex(dst, times_1); | |
| 1928 } | |
| 1929 if (shift <= 4) { // 2 - 16 times multiplier is handled using ScaleFactor. | |
| 1930 movl(dst, src); | |
| 1931 neg(dst); | |
| 1932 return SmiIndex(dst, static_cast<ScaleFactor>(shift - kSmiTagSize)); | |
| 1933 } | |
| 1934 // Shift by shift-kSmiTagSize. | |
| 1935 movl(dst, src); | |
| 1936 neg(dst); | |
| 1937 shl(dst, Immediate(shift - kSmiTagSize)); | |
| 1938 return SmiIndex(dst, times_1); | |
| 1939 } | |
| 1940 | |
| 1941 #endif // V8_LONG_SMI | |
| 1942 | |
| 1943 | |
| 1944 void MacroAssembler::JumpIfSmi(Register src, Label* on_smi) { | 1212 void MacroAssembler::JumpIfSmi(Register src, Label* on_smi) { |
| 1945 ASSERT_EQ(0, kSmiTag); | 1213 ASSERT_EQ(0, kSmiTag); |
| 1946 Condition smi = CheckSmi(src); | 1214 Condition smi = CheckSmi(src); |
| 1947 j(smi, on_smi); | 1215 j(smi, on_smi); |
| 1948 } | 1216 } |
| 1949 | 1217 |
| 1950 | 1218 |
| 1951 void MacroAssembler::JumpIfNotSmi(Register src, Label* on_not_smi) { | 1219 void MacroAssembler::JumpIfNotSmi(Register src, Label* on_not_smi) { |
| 1952 Condition smi = CheckSmi(src); | 1220 Condition smi = CheckSmi(src); |
| 1953 j(NegateCondition(smi), on_not_smi); | 1221 j(NegateCondition(smi), on_not_smi); |
| (...skipping 1041 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2995 CodePatcher::~CodePatcher() { | 2263 CodePatcher::~CodePatcher() { |
| 2996 // Indicate that code has changed. | 2264 // Indicate that code has changed. |
| 2997 CPU::FlushICache(address_, size_); | 2265 CPU::FlushICache(address_, size_); |
| 2998 | 2266 |
| 2999 // Check that the code was patched as expected. | 2267 // Check that the code was patched as expected. |
| 3000 ASSERT(masm_.pc_ == address_ + size_); | 2268 ASSERT(masm_.pc_ == address_ + size_); |
| 3001 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); | 2269 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); |
| 3002 } | 2270 } |
| 3003 | 2271 |
| 3004 } } // namespace v8::internal | 2272 } } // namespace v8::internal |
| OLD | NEW |