summaryrefslogtreecommitdiff
path: root/target-ppc
diff options
context:
space:
mode:
authorj_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162>2007-09-30 01:11:48 +0000
committerj_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162>2007-09-30 01:11:48 +0000
commitd7e4b87e53923542c1a7220e08bcae2252f5a22e (patch)
tree0d29076ef6fd68674772fcefa0382a6921f0889c /target-ppc
parent477023a6038e8f457c604b138198f76d093b9a87 (diff)
Implement new floating-point instructions (fre, frin, friz, frip, frim)
as defined in the PowerPC 2.04 specification. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3281 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-ppc')
-rw-r--r--target-ppc/op.c31
-rw-r--r--target-ppc/op_helper.c56
-rw-r--r--target-ppc/op_helper.h5
-rw-r--r--target-ppc/translate.c14
4 files changed, 106 insertions, 0 deletions
diff --git a/target-ppc/op.c b/target-ppc/op.c
index 4622534c27..46843d790f 100644
--- a/target-ppc/op.c
+++ b/target-ppc/op.c
@@ -1701,6 +1701,13 @@ void OPPROTO op_fsqrt (void)
RETURN();
}
+/* fre - fre. */
+void OPPROTO op_fre (void)
+{
+ do_fre();
+ RETURN();
+}
+
/* fres - fres. */
void OPPROTO op_fres (void)
{
@@ -1806,6 +1813,30 @@ void OPPROTO op_fctidz (void)
}
#endif
+void OPPROTO op_frin (void)
+{
+ do_frin();
+ RETURN();
+}
+
+void OPPROTO op_friz (void)
+{
+ do_friz();
+ RETURN();
+}
+
+void OPPROTO op_frip (void)
+{
+ do_frip();
+ RETURN();
+}
+
+void OPPROTO op_frim (void)
+{
+ do_frim();
+ RETURN();
+}
+
/*** Floating-Point compare ***/
/* fcmpu */
void OPPROTO op_fcmpu (void)
diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c
index 9a79953f7d..08441caaec 100644
--- a/target-ppc/op_helper.c
+++ b/target-ppc/op_helper.c
@@ -700,6 +700,36 @@ void do_fctidz (void)
#endif
+static inline void do_fri (int rounding_mode)
+{
+ int curmode;
+
+ curmode = env->fp_status.float_rounding_mode;
+ set_float_rounding_mode(rounding_mode, &env->fp_status);
+ FT0 = float64_round_to_int(FT0, &env->fp_status);
+ set_float_rounding_mode(curmode, &env->fp_status);
+}
+
+void do_frin (void)
+{
+ do_fri(float_round_nearest_even);
+}
+
+void do_friz (void)
+{
+ do_fri(float_round_to_zero);
+}
+
+void do_frip (void)
+{
+ do_fri(float_round_up);
+}
+
+void do_frim (void)
+{
+ do_fri(float_round_down);
+}
+
#if USE_PRECISE_EMULATION
void do_fmadd (void)
{
@@ -789,6 +819,32 @@ void do_fsqrt (void)
FT0 = float64_sqrt(FT0, &env->fp_status);
}
+void do_fre (void)
+{
+ union {
+ double d;
+ uint64_t i;
+ } p;
+
+ if (likely(isnormal(FT0))) {
+ FT0 = float64_div(1.0, FT0, &env->fp_status);
+ } else {
+ p.d = FT0;
+ if (p.i == 0x8000000000000000ULL) {
+ p.i = 0xFFF0000000000000ULL;
+ } else if (p.i == 0x0000000000000000ULL) {
+ p.i = 0x7FF0000000000000ULL;
+ } else if (isnan(FT0)) {
+ p.i = 0x7FF8000000000000ULL;
+ } else if (FT0 < 0.0) {
+ p.i = 0x8000000000000000ULL;
+ } else {
+ p.i = 0x0000000000000000ULL;
+ }
+ FT0 = p.d;
+ }
+}
+
void do_fres (void)
{
union {
diff --git a/target-ppc/op_helper.h b/target-ppc/op_helper.h
index 4db8ac5308..6c0d2fbf92 100644
--- a/target-ppc/op_helper.h
+++ b/target-ppc/op_helper.h
@@ -94,6 +94,7 @@ void do_popcntb_64 (void);
/* Floating-point arithmetic helpers */
void do_fsqrt (void);
+void do_fre (void);
void do_fres (void);
void do_frsqrte (void);
void do_fsel (void);
@@ -110,6 +111,10 @@ void do_fcfid (void);
void do_fctid (void);
void do_fctidz (void);
#endif
+void do_frin (void);
+void do_friz (void);
+void do_frip (void);
+void do_frim (void);
void do_fcmpu (void);
void do_fcmpo (void);
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 7f84ed7d69..f4ff22e385 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -476,6 +476,8 @@ enum {
PPC_RFMCI = 0x0000020000000000ULL,
/* user-mode DCR access, implemented in PowerPC 460 */
PPC_DCRUX = 0x0000040000000000ULL,
+ /* New floating-point extensions (PowerPC 2.0x) */
+ PPC_FLOAT_EXT = 0x0000080000000000ULL,
};
/*****************************************************************************/
@@ -1660,6 +1662,9 @@ GEN_FLOAT_AB(div, 0x12, 0x000007C0);
/* fmul - fmuls */
GEN_FLOAT_AC(mul, 0x19, 0x0000F800);
+/* fre */
+GEN_FLOAT_BS(re, 0x3F, 0x18, PPC_FLOAT_EXT);
+
/* fres */
GEN_FLOAT_BS(res, 0x3B, 0x18, PPC_FLOAT_FRES);
@@ -1727,6 +1732,15 @@ GEN_FLOAT_B(ctid, 0x0E, 0x19, PPC_64B);
GEN_FLOAT_B(ctidz, 0x0F, 0x19, PPC_64B);
#endif
+/* frin */
+GEN_FLOAT_B(rin, 0x08, 0x0C, PPC_FLOAT_EXT);
+/* friz */
+GEN_FLOAT_B(riz, 0x08, 0x0D, PPC_FLOAT_EXT);
+/* frip */
+GEN_FLOAT_B(rip, 0x08, 0x0E, PPC_FLOAT_EXT);
+/* frim */
+GEN_FLOAT_B(rim, 0x08, 0x0F, PPC_FLOAT_EXT);
+
/*** Floating-Point compare ***/
/* fcmpo */
GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT)