Revision 6c01bf6c
b/target-ppc/op_helper.c | ||
---|---|---|
563 | 563 |
return ((u.ll >> 52) & 0x7FF) == 0; |
564 | 564 |
} |
565 | 565 |
|
566 |
#ifdef CONFIG_SOFTFLOAT |
|
567 |
static always_inline int isnormal (float64 d) |
|
568 |
{ |
|
569 |
CPU_DoubleU u; |
|
570 |
|
|
571 |
u.d = d; |
|
572 |
|
|
573 |
uint32_t exp = (u.ll >> 52) & 0x7FF; |
|
574 |
return ((0 < exp) && (exp < 0x7FF)); |
|
575 |
} |
|
576 |
#endif |
|
577 |
|
|
578 | 566 |
uint32_t helper_compute_fprf (uint64_t arg, uint32_t set_fprf) |
579 | 567 |
{ |
580 | 568 |
CPU_DoubleU farg; |
... | ... | |
1528 | 1516 |
} else if (unlikely(float64_is_zero(farg.d))) { |
1529 | 1517 |
/* Zero reciprocal */ |
1530 | 1518 |
farg.ll = float_zero_divide_excp(fone.d, farg.d); |
1531 |
} else if (likely(isnormal(farg.d))) { |
|
1532 |
farg.d = float64_div(fone.d, farg.d, &env->fp_status); |
|
1533 | 1519 |
} else { |
1534 |
if (farg.ll == 0x8000000000000000ULL) { |
|
1535 |
farg.ll = 0xFFF0000000000000ULL; |
|
1536 |
} else if (farg.ll == 0x0000000000000000ULL) { |
|
1537 |
farg.ll = 0x7FF0000000000000ULL; |
|
1538 |
} else if (float64_is_nan(farg.d)) { |
|
1539 |
farg.ll = 0x7FF8000000000000ULL; |
|
1540 |
} else if (float64_is_neg(farg.d)) { |
|
1541 |
farg.ll = 0x8000000000000000ULL; |
|
1542 |
} else { |
|
1543 |
farg.ll = 0x0000000000000000ULL; |
|
1544 |
} |
|
1520 |
farg.d = float64_div(fone.d, farg.d, &env->fp_status); |
|
1545 | 1521 |
} |
1546 | 1522 |
return farg.d; |
1547 | 1523 |
} |
... | ... | |
1550 | 1526 |
uint64_t helper_fres (uint64_t arg) |
1551 | 1527 |
{ |
1552 | 1528 |
CPU_DoubleU fone, farg; |
1529 |
float32 f32; |
|
1553 | 1530 |
fone.ll = 0x3FF0000000000000ULL; /* 1.0 */ |
1554 | 1531 |
farg.ll = arg; |
1555 | 1532 |
|
... | ... | |
1559 | 1536 |
} else if (unlikely(float64_is_zero(farg.d))) { |
1560 | 1537 |
/* Zero reciprocal */ |
1561 | 1538 |
farg.ll = float_zero_divide_excp(fone.d, farg.d); |
1562 |
} else if (likely(isnormal(farg.d))) { |
|
1563 |
#if USE_PRECISE_EMULATION |
|
1564 |
farg.d = float64_div(fone.d, farg.d, &env->fp_status); |
|
1565 |
farg.d = float64_to_float32(farg.d, &env->fp_status); |
|
1566 |
#else |
|
1567 |
farg.d = float32_div(fone.d, farg.d, &env->fp_status); |
|
1568 |
#endif |
|
1569 | 1539 |
} else { |
1570 |
if (farg.ll == 0x8000000000000000ULL) { |
|
1571 |
farg.ll = 0xFFF0000000000000ULL; |
|
1572 |
} else if (farg.ll == 0x0000000000000000ULL) { |
|
1573 |
farg.ll = 0x7FF0000000000000ULL; |
|
1574 |
} else if (float64_is_nan(farg.d)) { |
|
1575 |
farg.ll = 0x7FF8000000000000ULL; |
|
1576 |
} else if (float64_is_neg(farg.d)) { |
|
1577 |
farg.ll = 0x8000000000000000ULL; |
|
1578 |
} else { |
|
1579 |
farg.ll = 0x0000000000000000ULL; |
|
1580 |
} |
|
1540 |
farg.d = float64_div(fone.d, farg.d, &env->fp_status); |
|
1541 |
f32 = float64_to_float32(farg.d, &env->fp_status); |
|
1542 |
farg.d = float32_to_float64(f32, &env->fp_status); |
|
1581 | 1543 |
} |
1582 | 1544 |
return farg.ll; |
1583 | 1545 |
} |
... | ... | |
1586 | 1548 |
uint64_t helper_frsqrte (uint64_t arg) |
1587 | 1549 |
{ |
1588 | 1550 |
CPU_DoubleU fone, farg; |
1551 |
float32 f32; |
|
1589 | 1552 |
fone.ll = 0x3FF0000000000000ULL; /* 1.0 */ |
1590 | 1553 |
farg.ll = arg; |
1591 | 1554 |
|
... | ... | |
1595 | 1558 |
} else if (unlikely(float64_is_neg(farg.d) && !float64_is_zero(farg.d))) { |
1596 | 1559 |
/* Reciprocal square root of a negative nonzero number */ |
1597 | 1560 |
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSQRT); |
1598 |
} else if (likely(isnormal(farg.d))) { |
|
1599 |
farg.d = float64_sqrt(farg.d, &env->fp_status); |
|
1600 |
farg.d = float32_div(fone.d, farg.d, &env->fp_status); |
|
1601 | 1561 |
} else { |
1602 |
if (farg.ll == 0x8000000000000000ULL) { |
|
1603 |
farg.ll = 0xFFF0000000000000ULL; |
|
1604 |
} else if (farg.ll == 0x0000000000000000ULL) { |
|
1605 |
farg.ll = 0x7FF0000000000000ULL; |
|
1606 |
} else if (float64_is_nan(farg.d)) { |
|
1607 |
farg.ll |= 0x000FFFFFFFFFFFFFULL; |
|
1608 |
} else if (float64_is_neg(farg.d)) { |
|
1609 |
farg.ll = 0x7FF8000000000000ULL; |
|
1610 |
} else { |
|
1611 |
farg.ll = 0x0000000000000000ULL; |
|
1612 |
} |
|
1562 |
farg.d = float64_sqrt(farg.d, &env->fp_status); |
|
1563 |
farg.d = float64_div(fone.d, farg.d, &env->fp_status); |
|
1564 |
f32 = float64_to_float32(farg.d, &env->fp_status); |
|
1565 |
farg.d = float32_to_float64(f32, &env->fp_status); |
|
1613 | 1566 |
} |
1614 | 1567 |
return farg.ll; |
1615 | 1568 |
} |
Also available in: Unified diff