< prev index next >

src/cpu/ppc/vm/macroAssembler_ppc.cpp

Print this page




1387     return ds+(address)uc->uc_mcontext.regs->gpr[ra];
1388   } else if (is_stdux(instruction) && rs == 1) {
1389     int rb = inv_rb_field(instruction);
1390     address sp = (address)uc->uc_mcontext.regs->gpr[1];
1391     long rb_val = (long)uc->uc_mcontext.regs->gpr[rb];
1392     return ra != 1 || rb_val >= 0 ? NULL         // not a stack bang
1393                                   : sp + rb_val; // banged address
1394   }
1395   return NULL; // not a stack bang
1396 #else
1397   // workaround not needed on !LINUX :-)
1398   ShouldNotCallThis();
1399   return NULL;
1400 #endif
1401 }
1402 
1403 // CmpxchgX sets condition register to cmpX(current, compare).
1404 void MacroAssembler::cmpxchgw(ConditionRegister flag, Register dest_current_value,
1405                               Register compare_value, Register exchange_value,
1406                               Register addr_base, int semantics, bool cmpxchgx_hint,
1407                               Register int_flag_success, bool contention_hint) {
1408   Label retry;
1409   Label failed;
1410   Label done;
1411 
1412   // Save one branch if result is returned via register and
1413   // result register is different from the other ones.
1414   bool use_result_reg    = (int_flag_success != noreg);
1415   bool preset_result_reg = (int_flag_success != dest_current_value && int_flag_success != compare_value &&
1416                             int_flag_success != exchange_value && int_flag_success != addr_base);

1417 
1418   if (use_result_reg && preset_result_reg) {
1419     li(int_flag_success, 0); // preset (assume cas failed)
1420   }
1421 
1422   // Add simple guard in order to reduce risk of starving under high contention (recommended by IBM).
1423   if (contention_hint) { // Don't try to reserve if cmp fails.
1424     lwz(dest_current_value, 0, addr_base);
1425     cmpw(flag, dest_current_value, compare_value);
1426     bne(flag, failed);
1427   }
1428 
1429   // release/fence semantics
1430   if (semantics & MemBarRel) {
1431     release();
1432   }
1433 
1434   // atomic emulation loop
1435   bind(retry);
1436 
1437   lwarx(dest_current_value, addr_base, cmpxchgx_hint);
1438   cmpw(flag, dest_current_value, compare_value);
1439   if (UseStaticBranchPredictionInCompareAndSwapPPC64) {
1440     bne_predict_not_taken(flag, failed);
1441   } else {
1442     bne(                  flag, failed);
1443   }
1444   // branch to done  => (flag == ne), (dest_current_value != compare_value)
1445   // fall through    => (flag == eq), (dest_current_value == compare_value)
1446 
1447   stwcx_(exchange_value, addr_base);

1448   if (UseStaticBranchPredictionInCompareAndSwapPPC64) {
1449     bne_predict_not_taken(CCR0, retry); // StXcx_ sets CCR0.
1450   } else {
1451     bne(                  CCR0, retry); // StXcx_ sets CCR0.

1452   }
1453   // fall through    => (flag == eq), (dest_current_value == compare_value), (swapped)
1454 
1455   // Result in register (must do this at the end because int_flag_success can be the
1456   // same register as one above).
1457   if (use_result_reg) {
1458     li(int_flag_success, 1);
1459   }
1460 
1461   if (semantics & MemBarFenceAfter) {
1462     fence();
1463   } else if (semantics & MemBarAcq) {
1464     isync();
1465   }
1466 
1467   if (use_result_reg && !preset_result_reg) {
1468     b(done);
1469   }
1470 
1471   bind(failed);


1481 // Preforms atomic compare exchange:
1482 //   if (compare_value == *addr_base)
1483 //     *addr_base = exchange_value
1484 //     int_flag_success = 1;
1485 //   else
1486 //     int_flag_success = 0;
1487 //
1488 // ConditionRegister flag       = cmp(compare_value, *addr_base)
1489 // Register dest_current_value  = *addr_base
1490 // Register compare_value       Used to compare with value in memory
1491 // Register exchange_value      Written to memory if compare_value == *addr_base
1492 // Register addr_base           The memory location to compareXChange
1493 // Register int_flag_success    Set to 1 if exchange_value was written to *addr_base
1494 //
1495 // To avoid the costly compare exchange the value is tested beforehand.
1496 // Several special cases exist to avoid that unnecessary information is generated.
1497 //
1498 void MacroAssembler::cmpxchgd(ConditionRegister flag,
1499                               Register dest_current_value, RegisterOrConstant compare_value, Register exchange_value,
1500                               Register addr_base, int semantics, bool cmpxchgx_hint,
1501                               Register int_flag_success, Label* failed_ext, bool contention_hint) {
1502   Label retry;
1503   Label failed_int;
1504   Label& failed = (failed_ext != NULL) ? *failed_ext : failed_int;
1505   Label done;
1506 
1507   // Save one branch if result is returned via register and result register is different from the other ones.
1508   bool use_result_reg    = (int_flag_success!=noreg);
1509   bool preset_result_reg = (int_flag_success!=dest_current_value && int_flag_success!=compare_value.register_or_noreg() &&
1510                             int_flag_success!=exchange_value && int_flag_success!=addr_base);

1511   assert(int_flag_success == noreg || failed_ext == NULL, "cannot have both");
1512 
1513   if (use_result_reg && preset_result_reg) {
1514     li(int_flag_success, 0); // preset (assume cas failed)
1515   }
1516 
1517   // Add simple guard in order to reduce risk of starving under high contention (recommended by IBM).
1518   if (contention_hint) { // Don't try to reserve if cmp fails.
1519     ld(dest_current_value, 0, addr_base);
1520     cmpd(flag, compare_value, dest_current_value);
1521     bne(flag, failed);
1522   }
1523 
1524   // release/fence semantics
1525   if (semantics & MemBarRel) {
1526     release();
1527   }
1528 
1529   // atomic emulation loop
1530   bind(retry);
1531 
1532   ldarx(dest_current_value, addr_base, cmpxchgx_hint);
1533   cmpd(flag, compare_value, dest_current_value);
1534   if (UseStaticBranchPredictionInCompareAndSwapPPC64) {
1535     bne_predict_not_taken(flag, failed);
1536   } else {
1537     bne(                  flag, failed);
1538   }
1539 
1540   stdcx_(exchange_value, addr_base);

1541   if (UseStaticBranchPredictionInCompareAndSwapPPC64) {
1542     bne_predict_not_taken(CCR0, retry); // stXcx_ sets CCR0
1543   } else {
1544     bne(                  CCR0, retry); // stXcx_ sets CCR0

1545   }
1546 
1547   // result in register (must do this at the end because int_flag_success can be the same register as one above)
1548   if (use_result_reg) {
1549     li(int_flag_success, 1);
1550   }
1551 
1552   if (semantics & MemBarFenceAfter) {
1553     fence();
1554   } else if (semantics & MemBarAcq) {
1555     isync();
1556   }
1557 
1558   if (use_result_reg && !preset_result_reg) {
1559     b(done);
1560   }
1561 
1562   bind(failed_int);
1563   if (use_result_reg && !preset_result_reg) {
1564     li(int_flag_success, 0);




1387     return ds+(address)uc->uc_mcontext.regs->gpr[ra];
1388   } else if (is_stdux(instruction) && rs == 1) {
1389     int rb = inv_rb_field(instruction);
1390     address sp = (address)uc->uc_mcontext.regs->gpr[1];
1391     long rb_val = (long)uc->uc_mcontext.regs->gpr[rb];
1392     return ra != 1 || rb_val >= 0 ? NULL         // not a stack bang
1393                                   : sp + rb_val; // banged address
1394   }
1395   return NULL; // not a stack bang
1396 #else
1397   // workaround not needed on !LINUX :-)
1398   ShouldNotCallThis();
1399   return NULL;
1400 #endif
1401 }
1402 
1403 // CmpxchgX sets condition register to cmpX(current, compare).
1404 void MacroAssembler::cmpxchgw(ConditionRegister flag, Register dest_current_value,
1405                               Register compare_value, Register exchange_value,
1406                               Register addr_base, int semantics, bool cmpxchgx_hint,
1407                               Register int_flag_success, bool contention_hint, bool weak) {
1408   Label retry;
1409   Label failed;
1410   Label done;
1411 
1412   // Save one branch if result is returned via register and
1413   // result register is different from the other ones.
1414   bool use_result_reg    = (int_flag_success != noreg);
1415   bool preset_result_reg = (int_flag_success != dest_current_value && int_flag_success != compare_value &&
1416                             int_flag_success != exchange_value && int_flag_success != addr_base);
1417   assert(!weak || flag == CCR0, "weak only supported with CCR0");
1418 
1419   if (use_result_reg && preset_result_reg) {
1420     li(int_flag_success, 0); // preset (assume cas failed)
1421   }
1422 
1423   // Add simple guard in order to reduce risk of starving under high contention (recommended by IBM).
1424   if (contention_hint) { // Don't try to reserve if cmp fails.
1425     lwz(dest_current_value, 0, addr_base);
1426     cmpw(flag, dest_current_value, compare_value);
1427     bne(flag, failed);
1428   }
1429 
1430   // release/fence semantics
1431   if (semantics & MemBarRel) {
1432     release();
1433   }
1434 
1435   // atomic emulation loop
1436   bind(retry);
1437 
1438   lwarx(dest_current_value, addr_base, cmpxchgx_hint);
1439   cmpw(flag, dest_current_value, compare_value);
1440   if (UseStaticBranchPredictionInCompareAndSwapPPC64) {
1441     bne_predict_not_taken(flag, failed);
1442   } else {
1443     bne(                  flag, failed);
1444   }
1445   // branch to done  => (flag == ne), (dest_current_value != compare_value)
1446   // fall through    => (flag == eq), (dest_current_value == compare_value)
1447 
1448   stwcx_(exchange_value, addr_base);
1449   if (!weak || use_result_reg) {
1450     if (UseStaticBranchPredictionInCompareAndSwapPPC64) {
1451       bne_predict_not_taken(CCR0, weak ? failed : retry); // StXcx_ sets CCR0.
1452     } else {
1453       bne(                  CCR0, weak ? failed : retry); // StXcx_ sets CCR0.
1454     }
1455   }
1456   // fall through    => (flag == eq), (dest_current_value == compare_value), (swapped)
1457 
1458   // Result in register (must do this at the end because int_flag_success can be the
1459   // same register as one above).
1460   if (use_result_reg) {
1461     li(int_flag_success, 1);
1462   }
1463 
1464   if (semantics & MemBarFenceAfter) {
1465     fence();
1466   } else if (semantics & MemBarAcq) {
1467     isync();
1468   }
1469 
1470   if (use_result_reg && !preset_result_reg) {
1471     b(done);
1472   }
1473 
1474   bind(failed);


1484 // Preforms atomic compare exchange:
1485 //   if (compare_value == *addr_base)
1486 //     *addr_base = exchange_value
1487 //     int_flag_success = 1;
1488 //   else
1489 //     int_flag_success = 0;
1490 //
1491 // ConditionRegister flag       = cmp(compare_value, *addr_base)
1492 // Register dest_current_value  = *addr_base
1493 // Register compare_value       Used to compare with value in memory
1494 // Register exchange_value      Written to memory if compare_value == *addr_base
1495 // Register addr_base           The memory location to compareXChange
1496 // Register int_flag_success    Set to 1 if exchange_value was written to *addr_base
1497 //
1498 // To avoid the costly compare exchange the value is tested beforehand.
1499 // Several special cases exist to avoid that unnecessary information is generated.
1500 //
1501 void MacroAssembler::cmpxchgd(ConditionRegister flag,
1502                               Register dest_current_value, RegisterOrConstant compare_value, Register exchange_value,
1503                               Register addr_base, int semantics, bool cmpxchgx_hint,
1504                               Register int_flag_success, Label* failed_ext, bool contention_hint, bool weak) {
1505   Label retry;
1506   Label failed_int;
1507   Label& failed = (failed_ext != NULL) ? *failed_ext : failed_int;
1508   Label done;
1509 
1510   // Save one branch if result is returned via register and result register is different from the other ones.
1511   bool use_result_reg    = (int_flag_success!=noreg);
1512   bool preset_result_reg = (int_flag_success!=dest_current_value && int_flag_success!=compare_value.register_or_noreg() &&
1513                             int_flag_success!=exchange_value && int_flag_success!=addr_base);
1514   assert(!weak || flag == CCR0, "weak only supported with CCR0");
1515   assert(int_flag_success == noreg || failed_ext == NULL, "cannot have both");
1516 
1517   if (use_result_reg && preset_result_reg) {
1518     li(int_flag_success, 0); // preset (assume cas failed)
1519   }
1520 
1521   // Add simple guard in order to reduce risk of starving under high contention (recommended by IBM).
1522   if (contention_hint) { // Don't try to reserve if cmp fails.
1523     ld(dest_current_value, 0, addr_base);
1524     cmpd(flag, compare_value, dest_current_value);
1525     bne(flag, failed);
1526   }
1527 
1528   // release/fence semantics
1529   if (semantics & MemBarRel) {
1530     release();
1531   }
1532 
1533   // atomic emulation loop
1534   bind(retry);
1535 
1536   ldarx(dest_current_value, addr_base, cmpxchgx_hint);
1537   cmpd(flag, compare_value, dest_current_value);
1538   if (UseStaticBranchPredictionInCompareAndSwapPPC64) {
1539     bne_predict_not_taken(flag, failed);
1540   } else {
1541     bne(                  flag, failed);
1542   }
1543 
1544   stdcx_(exchange_value, addr_base);
1545   if (!weak || use_result_reg || failed_ext) {
1546     if (UseStaticBranchPredictionInCompareAndSwapPPC64) {
1547       bne_predict_not_taken(CCR0, weak ? failed : retry); // stXcx_ sets CCR0
1548     } else {
1549       bne(                  CCR0, weak ? failed : retry); // stXcx_ sets CCR0
1550     }
1551   }
1552 
1553   // result in register (must do this at the end because int_flag_success can be the same register as one above)
1554   if (use_result_reg) {
1555     li(int_flag_success, 1);
1556   }
1557 
1558   if (semantics & MemBarFenceAfter) {
1559     fence();
1560   } else if (semantics & MemBarAcq) {
1561     isync();
1562   }
1563 
1564   if (use_result_reg && !preset_result_reg) {
1565     b(done);
1566   }
1567 
1568   bind(failed_int);
1569   if (use_result_reg && !preset_result_reg) {
1570     li(int_flag_success, 0);


< prev index next >