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
This commit is contained in:
j_mayer 2007-09-30 01:11:48 +00:00
parent 477023a603
commit d7e4b87e53
4 changed files with 106 additions and 0 deletions

View File

@ -1701,6 +1701,13 @@ void OPPROTO op_fsqrt (void)
RETURN(); RETURN();
} }
/* fre - fre. */
void OPPROTO op_fre (void)
{
do_fre();
RETURN();
}
/* fres - fres. */ /* fres - fres. */
void OPPROTO op_fres (void) void OPPROTO op_fres (void)
{ {
@ -1806,6 +1813,30 @@ void OPPROTO op_fctidz (void)
} }
#endif #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 ***/ /*** Floating-Point compare ***/
/* fcmpu */ /* fcmpu */
void OPPROTO op_fcmpu (void) void OPPROTO op_fcmpu (void)

View File

@ -700,6 +700,36 @@ void do_fctidz (void)
#endif #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 #if USE_PRECISE_EMULATION
void do_fmadd (void) void do_fmadd (void)
{ {
@ -789,6 +819,32 @@ void do_fsqrt (void)
FT0 = float64_sqrt(FT0, &env->fp_status); 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) void do_fres (void)
{ {
union { union {

View File

@ -94,6 +94,7 @@ void do_popcntb_64 (void);
/* Floating-point arithmetic helpers */ /* Floating-point arithmetic helpers */
void do_fsqrt (void); void do_fsqrt (void);
void do_fre (void);
void do_fres (void); void do_fres (void);
void do_frsqrte (void); void do_frsqrte (void);
void do_fsel (void); void do_fsel (void);
@ -110,6 +111,10 @@ void do_fcfid (void);
void do_fctid (void); void do_fctid (void);
void do_fctidz (void); void do_fctidz (void);
#endif #endif
void do_frin (void);
void do_friz (void);
void do_frip (void);
void do_frim (void);
void do_fcmpu (void); void do_fcmpu (void);
void do_fcmpo (void); void do_fcmpo (void);

View File

@ -476,6 +476,8 @@ enum {
PPC_RFMCI = 0x0000020000000000ULL, PPC_RFMCI = 0x0000020000000000ULL,
/* user-mode DCR access, implemented in PowerPC 460 */ /* user-mode DCR access, implemented in PowerPC 460 */
PPC_DCRUX = 0x0000040000000000ULL, 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 */ /* fmul - fmuls */
GEN_FLOAT_AC(mul, 0x19, 0x0000F800); GEN_FLOAT_AC(mul, 0x19, 0x0000F800);
/* fre */
GEN_FLOAT_BS(re, 0x3F, 0x18, PPC_FLOAT_EXT);
/* fres */ /* fres */
GEN_FLOAT_BS(res, 0x3B, 0x18, PPC_FLOAT_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); GEN_FLOAT_B(ctidz, 0x0F, 0x19, PPC_64B);
#endif #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 ***/ /*** Floating-Point compare ***/
/* fcmpo */ /* fcmpo */
GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT) GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT)