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); |