Commit 417454b0322ab1eed03615fe563d770fa7e4c9f9

Authored by blueswir1
1 parent c185970a

Full implementation of IEEE exceptions (Aurelien Jarno)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2625 c046a42c-6fe2-441c-8c8c-71466251a162
target-sparc/exec.h
@@ -61,6 +61,8 @@ void do_fsqrts(void); @@ -61,6 +61,8 @@ void do_fsqrts(void);
61 void do_fsqrtd(void); 61 void do_fsqrtd(void);
62 void do_fcmps(void); 62 void do_fcmps(void);
63 void do_fcmpd(void); 63 void do_fcmpd(void);
  64 +void do_fcmpes(void);
  65 +void do_fcmped(void);
64 #ifdef TARGET_SPARC64 66 #ifdef TARGET_SPARC64
65 void do_fabsd(void); 67 void do_fabsd(void);
66 void do_fcmps_fcc1(void); 68 void do_fcmps_fcc1(void);
@@ -69,6 +71,12 @@ void do_fcmps_fcc2(void); @@ -69,6 +71,12 @@ void do_fcmps_fcc2(void);
69 void do_fcmpd_fcc2(void); 71 void do_fcmpd_fcc2(void);
70 void do_fcmps_fcc3(void); 72 void do_fcmps_fcc3(void);
71 void do_fcmpd_fcc3(void); 73 void do_fcmpd_fcc3(void);
  74 +void do_fcmpes_fcc1(void);
  75 +void do_fcmped_fcc1(void);
  76 +void do_fcmpes_fcc2(void);
  77 +void do_fcmped_fcc2(void);
  78 +void do_fcmpes_fcc3(void);
  79 +void do_fcmped_fcc3(void);
72 void do_popc(); 80 void do_popc();
73 void do_wrpstate(); 81 void do_wrpstate();
74 void do_done(); 82 void do_done();
@@ -79,6 +87,7 @@ void do_ldd_user(target_ulong addr); @@ -79,6 +87,7 @@ void do_ldd_user(target_ulong addr);
79 void do_ldd_raw(target_ulong addr); 87 void do_ldd_raw(target_ulong addr);
80 void do_interrupt(int intno); 88 void do_interrupt(int intno);
81 void raise_exception(int tt); 89 void raise_exception(int tt);
  90 +void check_ieee_exceptions();
82 void memcpy32(target_ulong *dst, const target_ulong *src); 91 void memcpy32(target_ulong *dst, const target_ulong *src);
83 target_ulong mmu_probe(CPUState *env, target_ulong address, int mmulev); 92 target_ulong mmu_probe(CPUState *env, target_ulong address, int mmulev);
84 void dump_mmu(CPUState *env); 93 void dump_mmu(CPUState *env);
target-sparc/op.c
@@ -1534,16 +1534,25 @@ void OPPROTO op_flush_T0(void) @@ -1534,16 +1534,25 @@ void OPPROTO op_flush_T0(void)
1534 helper_flush(T0); 1534 helper_flush(T0);
1535 } 1535 }
1536 1536
  1537 +void OPPROTO op_clear_ieee_excp_and_FTT(void)
  1538 +{
  1539 + env->fsr &= ~(FSR_FTT_MASK | FSR_CEXC_MASK);;
  1540 +}
  1541 +
1537 #define F_OP(name, p) void OPPROTO op_f##name##p(void) 1542 #define F_OP(name, p) void OPPROTO op_f##name##p(void)
1538 1543
1539 #define F_BINOP(name) \ 1544 #define F_BINOP(name) \
1540 F_OP(name, s) \ 1545 F_OP(name, s) \
1541 { \ 1546 { \
  1547 + set_float_exception_flags(0, &env->fp_status); \
1542 FT0 = float32_ ## name (FT0, FT1, &env->fp_status); \ 1548 FT0 = float32_ ## name (FT0, FT1, &env->fp_status); \
  1549 + check_ieee_exceptions(); \
1543 } \ 1550 } \
1544 F_OP(name, d) \ 1551 F_OP(name, d) \
1545 { \ 1552 { \
  1553 + set_float_exception_flags(0, &env->fp_status); \
1546 DT0 = float64_ ## name (DT0, DT1, &env->fp_status); \ 1554 DT0 = float64_ ## name (DT0, DT1, &env->fp_status); \
  1555 + check_ieee_exceptions(); \
1547 } 1556 }
1548 1557
1549 F_BINOP(add); 1558 F_BINOP(add);
@@ -1554,9 +1563,11 @@ F_BINOP(div); @@ -1554,9 +1563,11 @@ F_BINOP(div);
1554 1563
1555 void OPPROTO op_fsmuld(void) 1564 void OPPROTO op_fsmuld(void)
1556 { 1565 {
  1566 + set_float_exception_flags(0, &env->fp_status);
1557 DT0 = float64_mul(float32_to_float64(FT0, &env->fp_status), 1567 DT0 = float64_mul(float32_to_float64(FT0, &env->fp_status),
1558 float32_to_float64(FT1, &env->fp_status), 1568 float32_to_float64(FT1, &env->fp_status),
1559 &env->fp_status); 1569 &env->fp_status);
  1570 + check_ieee_exceptions();
1560 } 1571 }
1561 1572
1562 #define F_HELPER(name) \ 1573 #define F_HELPER(name) \
@@ -1582,6 +1593,7 @@ F_OP(abs, s) @@ -1582,6 +1593,7 @@ F_OP(abs, s)
1582 } 1593 }
1583 1594
1584 F_HELPER(cmp); 1595 F_HELPER(cmp);
  1596 +F_HELPER(cmpe);
1585 1597
1586 #ifdef TARGET_SPARC64 1598 #ifdef TARGET_SPARC64
1587 F_OP(neg, d) 1599 F_OP(neg, d)
@@ -1623,6 +1635,37 @@ void OPPROTO op_fcmpd_fcc3(void) @@ -1623,6 +1635,37 @@ void OPPROTO op_fcmpd_fcc3(void)
1623 { 1635 {
1624 do_fcmpd_fcc3(); 1636 do_fcmpd_fcc3();
1625 } 1637 }
  1638 +
  1639 +void OPPROTO op_fcmpes_fcc1(void)
  1640 +{
  1641 + do_fcmpes_fcc1();
  1642 +}
  1643 +
  1644 +void OPPROTO op_fcmped_fcc1(void)
  1645 +{
  1646 + do_fcmped_fcc1();
  1647 +}
  1648 +
  1649 +void OPPROTO op_fcmpes_fcc2(void)
  1650 +{
  1651 + do_fcmpes_fcc2();
  1652 +}
  1653 +
  1654 +void OPPROTO op_fcmped_fcc2(void)
  1655 +{
  1656 + do_fcmped_fcc2();
  1657 +}
  1658 +
  1659 +void OPPROTO op_fcmpes_fcc3(void)
  1660 +{
  1661 + do_fcmpes_fcc3();
  1662 +}
  1663 +
  1664 +void OPPROTO op_fcmped_fcc3(void)
  1665 +{
  1666 + do_fcmped_fcc3();
  1667 +}
  1668 +
1626 #endif 1669 #endif
1627 1670
1628 /* Integer to float conversion. */ 1671 /* Integer to float conversion. */
@@ -1631,23 +1674,31 @@ F_HELPER(ito); @@ -1631,23 +1674,31 @@ F_HELPER(ito);
1631 #else 1674 #else
1632 F_OP(ito, s) 1675 F_OP(ito, s)
1633 { 1676 {
  1677 + set_float_exception_flags(0, &env->fp_status);
1634 FT0 = int32_to_float32(*((int32_t *)&FT1), &env->fp_status); 1678 FT0 = int32_to_float32(*((int32_t *)&FT1), &env->fp_status);
  1679 + check_ieee_exceptions();
1635 } 1680 }
1636 1681
1637 F_OP(ito, d) 1682 F_OP(ito, d)
1638 { 1683 {
  1684 + set_float_exception_flags(0, &env->fp_status);
1639 DT0 = int32_to_float64(*((int32_t *)&FT1), &env->fp_status); 1685 DT0 = int32_to_float64(*((int32_t *)&FT1), &env->fp_status);
  1686 + check_ieee_exceptions();
1640 } 1687 }
1641 1688
1642 #ifdef TARGET_SPARC64 1689 #ifdef TARGET_SPARC64
1643 F_OP(xto, s) 1690 F_OP(xto, s)
1644 { 1691 {
  1692 + set_float_exception_flags(0, &env->fp_status);
1645 FT0 = int64_to_float32(*((int64_t *)&DT1), &env->fp_status); 1693 FT0 = int64_to_float32(*((int64_t *)&DT1), &env->fp_status);
  1694 + check_ieee_exceptions();
1646 } 1695 }
1647 1696
1648 F_OP(xto, d) 1697 F_OP(xto, d)
1649 { 1698 {
  1699 + set_float_exception_flags(0, &env->fp_status);
1650 DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status); 1700 DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status);
  1701 + check_ieee_exceptions();
1651 } 1702 }
1652 #endif 1703 #endif
1653 #endif 1704 #endif
@@ -1656,34 +1707,46 @@ F_OP(xto, d) @@ -1656,34 +1707,46 @@ F_OP(xto, d)
1656 /* floating point conversion */ 1707 /* floating point conversion */
1657 void OPPROTO op_fdtos(void) 1708 void OPPROTO op_fdtos(void)
1658 { 1709 {
  1710 + set_float_exception_flags(0, &env->fp_status);
1659 FT0 = float64_to_float32(DT1, &env->fp_status); 1711 FT0 = float64_to_float32(DT1, &env->fp_status);
  1712 + check_ieee_exceptions();
1660 } 1713 }
1661 1714
1662 void OPPROTO op_fstod(void) 1715 void OPPROTO op_fstod(void)
1663 { 1716 {
  1717 + set_float_exception_flags(0, &env->fp_status);
1664 DT0 = float32_to_float64(FT1, &env->fp_status); 1718 DT0 = float32_to_float64(FT1, &env->fp_status);
  1719 + check_ieee_exceptions();
1665 } 1720 }
1666 1721
1667 /* Float to integer conversion. */ 1722 /* Float to integer conversion. */
1668 void OPPROTO op_fstoi(void) 1723 void OPPROTO op_fstoi(void)
1669 { 1724 {
  1725 + set_float_exception_flags(0, &env->fp_status);
1670 *((int32_t *)&FT0) = float32_to_int32_round_to_zero(FT1, &env->fp_status); 1726 *((int32_t *)&FT0) = float32_to_int32_round_to_zero(FT1, &env->fp_status);
  1727 + check_ieee_exceptions();
1671 } 1728 }
1672 1729
1673 void OPPROTO op_fdtoi(void) 1730 void OPPROTO op_fdtoi(void)
1674 { 1731 {
  1732 + set_float_exception_flags(0, &env->fp_status);
1675 *((int32_t *)&FT0) = float64_to_int32_round_to_zero(DT1, &env->fp_status); 1733 *((int32_t *)&FT0) = float64_to_int32_round_to_zero(DT1, &env->fp_status);
  1734 + check_ieee_exceptions();
1676 } 1735 }
1677 1736
1678 #ifdef TARGET_SPARC64 1737 #ifdef TARGET_SPARC64
1679 void OPPROTO op_fstox(void) 1738 void OPPROTO op_fstox(void)
1680 { 1739 {
  1740 + set_float_exception_flags(0, &env->fp_status);
1681 *((int64_t *)&DT0) = float32_to_int64_round_to_zero(FT1, &env->fp_status); 1741 *((int64_t *)&DT0) = float32_to_int64_round_to_zero(FT1, &env->fp_status);
  1742 + check_ieee_exceptions();
1682 } 1743 }
1683 1744
1684 void OPPROTO op_fdtox(void) 1745 void OPPROTO op_fdtox(void)
1685 { 1746 {
  1747 + set_float_exception_flags(0, &env->fp_status);
1686 *((int64_t *)&DT0) = float64_to_int64_round_to_zero(DT1, &env->fp_status); 1748 *((int64_t *)&DT0) = float64_to_int64_round_to_zero(DT1, &env->fp_status);
  1749 + check_ieee_exceptions();
1687 } 1750 }
1688 1751
1689 void OPPROTO op_fmovs_cc(void) 1752 void OPPROTO op_fmovs_cc(void)
target-sparc/op_helper.c
@@ -9,10 +9,43 @@ void raise_exception(int tt) @@ -9,10 +9,43 @@ void raise_exception(int tt)
9 cpu_loop_exit(); 9 cpu_loop_exit();
10 } 10 }
11 11
  12 +void check_ieee_exceptions()
  13 +{
  14 + T0 = get_float_exception_flags(&env->fp_status);
  15 + if (T0)
  16 + {
  17 + /* Copy IEEE 754 flags into FSR */
  18 + if (T0 & float_flag_invalid)
  19 + env->fsr |= FSR_NVC;
  20 + if (T0 & float_flag_overflow)
  21 + env->fsr |= FSR_OFC;
  22 + if (T0 & float_flag_underflow)
  23 + env->fsr |= FSR_UFC;
  24 + if (T0 & float_flag_divbyzero)
  25 + env->fsr |= FSR_DZC;
  26 + if (T0 & float_flag_inexact)
  27 + env->fsr |= FSR_NXC;
  28 +
  29 + if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23))
  30 + {
  31 + /* Unmasked exception, generate a trap */
  32 + env->fsr |= FSR_FTT_IEEE_EXCP;
  33 + raise_exception(TT_FP_EXCP);
  34 + }
  35 + else
  36 + {
  37 + /* Accumulate exceptions */
  38 + env->fsr |= (env->fsr & FSR_CEXC_MASK) << 5;
  39 + }
  40 + }
  41 +}
  42 +
12 #ifdef USE_INT_TO_FLOAT_HELPERS 43 #ifdef USE_INT_TO_FLOAT_HELPERS
13 void do_fitos(void) 44 void do_fitos(void)
14 { 45 {
  46 + set_float_exception_flags(0, &env->fp_status);
15 FT0 = int32_to_float32(*((int32_t *)&FT1), &env->fp_status); 47 FT0 = int32_to_float32(*((int32_t *)&FT1), &env->fp_status);
  48 + check_ieee_exceptions();
16 } 49 }
17 50
18 void do_fitod(void) 51 void do_fitod(void)
@@ -35,23 +68,29 @@ void do_fabsd(void) @@ -35,23 +68,29 @@ void do_fabsd(void)
35 68
36 void do_fsqrts(void) 69 void do_fsqrts(void)
37 { 70 {
  71 + set_float_exception_flags(0, &env->fp_status);
38 FT0 = float32_sqrt(FT1, &env->fp_status); 72 FT0 = float32_sqrt(FT1, &env->fp_status);
  73 + check_ieee_exceptions();
39 } 74 }
40 75
41 void do_fsqrtd(void) 76 void do_fsqrtd(void)
42 { 77 {
  78 + set_float_exception_flags(0, &env->fp_status);
43 DT0 = float64_sqrt(DT1, &env->fp_status); 79 DT0 = float64_sqrt(DT1, &env->fp_status);
  80 + check_ieee_exceptions();
44 } 81 }
45 82
46 -#define GEN_FCMP(name, size, reg1, reg2, FS) \ 83 +#define GEN_FCMP(name, size, reg1, reg2, FS, TRAP) \
47 void glue(do_, name) (void) \ 84 void glue(do_, name) (void) \
48 { \ 85 { \
49 env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \ 86 env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
50 switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) { \ 87 switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) { \
51 case float_relation_unordered: \ 88 case float_relation_unordered: \
52 T0 = (FSR_FCC1 | FSR_FCC0) << FS; \ 89 T0 = (FSR_FCC1 | FSR_FCC0) << FS; \
53 - if (env->fsr & FSR_NVM) { \ 90 + if ((env->fsr & FSR_NVM) || TRAP) { \
54 env->fsr |= T0; \ 91 env->fsr |= T0; \
  92 + env->fsr |= FSR_NVC; \
  93 + env->fsr |= FSR_FTT_IEEE_EXCP; \
55 raise_exception(TT_FP_EXCP); \ 94 raise_exception(TT_FP_EXCP); \
56 } else { \ 95 } else { \
57 env->fsr |= FSR_NVA; \ 96 env->fsr |= FSR_NVA; \
@@ -70,18 +109,30 @@ void do_fsqrtd(void) @@ -70,18 +109,30 @@ void do_fsqrtd(void)
70 env->fsr |= T0; \ 109 env->fsr |= T0; \
71 } 110 }
72 111
73 -GEN_FCMP(fcmps, float32, FT0, FT1, 0);  
74 -GEN_FCMP(fcmpd, float64, DT0, DT1, 0); 112 +GEN_FCMP(fcmps, float32, FT0, FT1, 0, 0);
  113 +GEN_FCMP(fcmpd, float64, DT0, DT1, 0, 0);
  114 +
  115 +GEN_FCMP(fcmpes, float32, FT0, FT1, 0, 1);
  116 +GEN_FCMP(fcmped, float64, DT0, DT1, 0, 1);
75 117
76 #ifdef TARGET_SPARC64 118 #ifdef TARGET_SPARC64
77 -GEN_FCMP(fcmps_fcc1, float32, FT0, FT1, 22);  
78 -GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22); 119 +GEN_FCMP(fcmps_fcc1, float32, FT0, FT1, 22, 0);
  120 +GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0);
  121 +
  122 +GEN_FCMP(fcmps_fcc2, float32, FT0, FT1, 24, 0);
  123 +GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24, 0);
  124 +
  125 +GEN_FCMP(fcmps_fcc3, float32, FT0, FT1, 26, 0);
  126 +GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26, 0);
  127 +
  128 +GEN_FCMP(fcmpes_fcc1, float32, FT0, FT1, 22, 1);
  129 +GEN_FCMP(fcmped_fcc1, float64, DT0, DT1, 22, 1);
79 130
80 -GEN_FCMP(fcmps_fcc2, float32, FT0, FT1, 24);  
81 -GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24); 131 +GEN_FCMP(fcmpes_fcc2, float32, FT0, FT1, 24, 1);
  132 +GEN_FCMP(fcmped_fcc2, float64, DT0, DT1, 24, 1);
82 133
83 -GEN_FCMP(fcmps_fcc3, float32, FT0, FT1, 26);  
84 -GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26); 134 +GEN_FCMP(fcmpes_fcc3, float32, FT0, FT1, 26, 1);
  135 +GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1);
85 #endif 136 #endif
86 137
87 #if defined(CONFIG_USER_ONLY) 138 #if defined(CONFIG_USER_ONLY)
target-sparc/translate.c
@@ -943,6 +943,21 @@ static GenOpFunc * const gen_fcmpd[4] = { @@ -943,6 +943,21 @@ static GenOpFunc * const gen_fcmpd[4] = {
943 gen_op_fcmpd_fcc2, 943 gen_op_fcmpd_fcc2,
944 gen_op_fcmpd_fcc3, 944 gen_op_fcmpd_fcc3,
945 }; 945 };
  946 +
  947 +static GenOpFunc * const gen_fcmpes[4] = {
  948 + gen_op_fcmpes,
  949 + gen_op_fcmpes_fcc1,
  950 + gen_op_fcmpes_fcc2,
  951 + gen_op_fcmpes_fcc3,
  952 +};
  953 +
  954 +static GenOpFunc * const gen_fcmped[4] = {
  955 + gen_op_fcmped,
  956 + gen_op_fcmped_fcc1,
  957 + gen_op_fcmped_fcc2,
  958 + gen_op_fcmped_fcc3,
  959 +};
  960 +
946 #endif 961 #endif
947 962
948 static int gen_trap_ifnofpu(DisasContext * dc) 963 static int gen_trap_ifnofpu(DisasContext * dc)
@@ -1289,6 +1304,7 @@ static void disas_sparc_insn(DisasContext * dc) @@ -1289,6 +1304,7 @@ static void disas_sparc_insn(DisasContext * dc)
1289 } else if (xop == 0x34) { /* FPU Operations */ 1304 } else if (xop == 0x34) { /* FPU Operations */
1290 if (gen_trap_ifnofpu(dc)) 1305 if (gen_trap_ifnofpu(dc))
1291 goto jmp_insn; 1306 goto jmp_insn;
  1307 + gen_op_clear_ieee_excp_and_FTT();
1292 rs1 = GET_FIELD(insn, 13, 17); 1308 rs1 = GET_FIELD(insn, 13, 17);
1293 rs2 = GET_FIELD(insn, 27, 31); 1309 rs2 = GET_FIELD(insn, 27, 31);
1294 xop = GET_FIELD(insn, 18, 26); 1310 xop = GET_FIELD(insn, 18, 26);
@@ -1476,6 +1492,7 @@ static void disas_sparc_insn(DisasContext * dc) @@ -1476,6 +1492,7 @@ static void disas_sparc_insn(DisasContext * dc)
1476 #endif 1492 #endif
1477 if (gen_trap_ifnofpu(dc)) 1493 if (gen_trap_ifnofpu(dc))
1478 goto jmp_insn; 1494 goto jmp_insn;
  1495 + gen_op_clear_ieee_excp_and_FTT();
1479 rs1 = GET_FIELD(insn, 13, 17); 1496 rs1 = GET_FIELD(insn, 13, 17);
1480 rs2 = GET_FIELD(insn, 27, 31); 1497 rs2 = GET_FIELD(insn, 27, 31);
1481 xop = GET_FIELD(insn, 18, 26); 1498 xop = GET_FIELD(insn, 18, 26);
@@ -1653,18 +1670,18 @@ static void disas_sparc_insn(DisasContext * dc) @@ -1653,18 +1670,18 @@ static void disas_sparc_insn(DisasContext * dc)
1653 gen_op_load_fpr_FT0(rs1); 1670 gen_op_load_fpr_FT0(rs1);
1654 gen_op_load_fpr_FT1(rs2); 1671 gen_op_load_fpr_FT1(rs2);
1655 #ifdef TARGET_SPARC64 1672 #ifdef TARGET_SPARC64
1656 - gen_fcmps[rd & 3](); 1673 + gen_fcmpes[rd & 3]();
1657 #else 1674 #else
1658 - gen_op_fcmps(); /* XXX should trap if qNaN or sNaN */ 1675 + gen_op_fcmpes();
1659 #endif 1676 #endif
1660 break; 1677 break;
1661 case 0x56: /* fcmped, V9 %fcc */ 1678 case 0x56: /* fcmped, V9 %fcc */
1662 gen_op_load_fpr_DT0(DFPREG(rs1)); 1679 gen_op_load_fpr_DT0(DFPREG(rs1));
1663 gen_op_load_fpr_DT1(DFPREG(rs2)); 1680 gen_op_load_fpr_DT1(DFPREG(rs2));
1664 #ifdef TARGET_SPARC64 1681 #ifdef TARGET_SPARC64
1665 - gen_fcmpd[rd & 3](); 1682 + gen_fcmped[rd & 3]();
1666 #else 1683 #else
1667 - gen_op_fcmpd(); /* XXX should trap if qNaN or sNaN */ 1684 + gen_op_fcmped();
1668 #endif 1685 #endif
1669 break; 1686 break;
1670 case 0x57: /* fcmpeq */ 1687 case 0x57: /* fcmpeq */