mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-28 04:21:50 -06:00
Implement recip1/recip2/rsqrt1/rsqrt2.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3026 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
d79acba420
commit
8dfdb87c8d
2 changed files with 143 additions and 93 deletions
|
@ -597,6 +597,13 @@ void tlb_fill (target_ulong addr, int is_write, int is_user, void *retaddr)
|
||||||
|
|
||||||
/* Complex FPU operations which may need stack space. */
|
/* Complex FPU operations which may need stack space. */
|
||||||
|
|
||||||
|
#define FLOAT_SIGN32 (1 << 31)
|
||||||
|
#define FLOAT_SIGN64 (1ULL << 63)
|
||||||
|
#define FLOAT_ONE32 (0x3f8 << 20)
|
||||||
|
#define FLOAT_ONE64 (0x3ffULL << 52)
|
||||||
|
#define FLOAT_TWO32 (1 << 30)
|
||||||
|
#define FLOAT_TWO64 (1ULL << 62)
|
||||||
|
|
||||||
/* convert MIPS rounding mode in FCR31 to IEEE library */
|
/* convert MIPS rounding mode in FCR31 to IEEE library */
|
||||||
unsigned int ieee_rm[] = {
|
unsigned int ieee_rm[] = {
|
||||||
float_round_nearest_even,
|
float_round_nearest_even,
|
||||||
|
@ -912,58 +919,78 @@ FLOAT_OP(floorw, s)
|
||||||
WT2 = 0x7fffffff;
|
WT2 = 0x7fffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* unary operations, MIPS specific, s and d */
|
/* MIPS specific unary operations */
|
||||||
#define FLOAT_UNOP(name) \
|
FLOAT_OP(recip, d)
|
||||||
FLOAT_OP(name, d) \
|
{
|
||||||
{ \
|
set_float_exception_flags(0, &env->fp_status);
|
||||||
set_float_exception_flags(0, &env->fp_status); \
|
FDT2 = float64_div(FLOAT_ONE64, FDT0, &env->fp_status);
|
||||||
/* XXX: not implemented */ \
|
update_fcr31();
|
||||||
/* FDT2 = float64_ ## name (FDT0, &env->fp_status);*/ \
|
}
|
||||||
do_raise_exception(EXCP_RI); \
|
FLOAT_OP(recip, s)
|
||||||
update_fcr31(); \
|
{
|
||||||
} \
|
set_float_exception_flags(0, &env->fp_status);
|
||||||
FLOAT_OP(name, s) \
|
FST2 = float32_div(FLOAT_ONE32, FST0, &env->fp_status);
|
||||||
{ \
|
update_fcr31();
|
||||||
set_float_exception_flags(0, &env->fp_status); \
|
|
||||||
/* XXX: not implemented */ \
|
|
||||||
/* FST2 = float32_ ## name (FST0, &env->fp_status);*/ \
|
|
||||||
do_raise_exception(EXCP_RI); \
|
|
||||||
update_fcr31(); \
|
|
||||||
}
|
}
|
||||||
FLOAT_UNOP(rsqrt)
|
|
||||||
FLOAT_UNOP(recip)
|
|
||||||
#undef FLOAT_UNOP
|
|
||||||
|
|
||||||
/* unary operations, MIPS specific, s, d and ps */
|
FLOAT_OP(rsqrt, d)
|
||||||
#define FLOAT_UNOP(name) \
|
{
|
||||||
FLOAT_OP(name, d) \
|
set_float_exception_flags(0, &env->fp_status);
|
||||||
{ \
|
FDT2 = float64_sqrt(FDT0, &env->fp_status);
|
||||||
set_float_exception_flags(0, &env->fp_status); \
|
FDT2 = float64_div(FLOAT_ONE64, FDT2, &env->fp_status);
|
||||||
/* XXX: not implemented */ \
|
update_fcr31();
|
||||||
/* FDT2 = float64_ ## name (FDT0, &env->fp_status);*/ \
|
}
|
||||||
do_raise_exception(EXCP_RI); \
|
FLOAT_OP(rsqrt, s)
|
||||||
update_fcr31(); \
|
{
|
||||||
} \
|
set_float_exception_flags(0, &env->fp_status);
|
||||||
FLOAT_OP(name, s) \
|
FST2 = float32_sqrt(FST0, &env->fp_status);
|
||||||
{ \
|
FST2 = float32_div(FLOAT_ONE32, FST2, &env->fp_status);
|
||||||
set_float_exception_flags(0, &env->fp_status); \
|
update_fcr31();
|
||||||
/* XXX: not implemented */ \
|
}
|
||||||
/* FST2 = float32_ ## name (FST0, &env->fp_status);*/ \
|
|
||||||
do_raise_exception(EXCP_RI); \
|
FLOAT_OP(recip1, d)
|
||||||
update_fcr31(); \
|
{
|
||||||
} \
|
set_float_exception_flags(0, &env->fp_status);
|
||||||
FLOAT_OP(name, ps) \
|
FDT2 = float64_div(FLOAT_ONE64, FDT0, &env->fp_status);
|
||||||
{ \
|
update_fcr31();
|
||||||
set_float_exception_flags(0, &env->fp_status); \
|
}
|
||||||
/* XXX: not implemented */ \
|
FLOAT_OP(recip1, s)
|
||||||
/* FST2 = float32_ ## name (FST0, &env->fp_status);*/ \
|
{
|
||||||
/* FSTH2 = float32_ ## name (FSTH0, &env->fp_status);*/ \
|
set_float_exception_flags(0, &env->fp_status);
|
||||||
do_raise_exception(EXCP_RI); \
|
FST2 = float32_div(FLOAT_ONE32, FST0, &env->fp_status);
|
||||||
update_fcr31(); \
|
update_fcr31();
|
||||||
|
}
|
||||||
|
FLOAT_OP(recip1, ps)
|
||||||
|
{
|
||||||
|
set_float_exception_flags(0, &env->fp_status);
|
||||||
|
FST2 = float32_div(FLOAT_ONE32, FST0, &env->fp_status);
|
||||||
|
FSTH2 = float32_div(FLOAT_ONE32, FSTH0, &env->fp_status);
|
||||||
|
update_fcr31();
|
||||||
|
}
|
||||||
|
|
||||||
|
FLOAT_OP(rsqrt1, d)
|
||||||
|
{
|
||||||
|
set_float_exception_flags(0, &env->fp_status);
|
||||||
|
FDT2 = float64_sqrt(FDT0, &env->fp_status);
|
||||||
|
FDT2 = float64_div(FLOAT_ONE64, FDT2, &env->fp_status);
|
||||||
|
update_fcr31();
|
||||||
|
}
|
||||||
|
FLOAT_OP(rsqrt1, s)
|
||||||
|
{
|
||||||
|
set_float_exception_flags(0, &env->fp_status);
|
||||||
|
FST2 = float32_sqrt(FST0, &env->fp_status);
|
||||||
|
FST2 = float32_div(FLOAT_ONE32, FST2, &env->fp_status);
|
||||||
|
update_fcr31();
|
||||||
|
}
|
||||||
|
FLOAT_OP(rsqrt1, ps)
|
||||||
|
{
|
||||||
|
set_float_exception_flags(0, &env->fp_status);
|
||||||
|
FST2 = float32_sqrt(FST0, &env->fp_status);
|
||||||
|
FSTH2 = float32_sqrt(FSTH0, &env->fp_status);
|
||||||
|
FST2 = float32_div(FLOAT_ONE32, FST2, &env->fp_status);
|
||||||
|
FSTH2 = float32_div(FLOAT_ONE32, FSTH2, &env->fp_status);
|
||||||
|
update_fcr31();
|
||||||
}
|
}
|
||||||
FLOAT_UNOP(rsqrt1)
|
|
||||||
FLOAT_UNOP(recip1)
|
|
||||||
#undef FLOAT_UNOP
|
|
||||||
|
|
||||||
/* binary operations */
|
/* binary operations */
|
||||||
#define FLOAT_BINOP(name) \
|
#define FLOAT_BINOP(name) \
|
||||||
|
@ -976,7 +1003,7 @@ FLOAT_OP(name, d) \
|
||||||
FDT2 = 0x7ff7ffffffffffffULL; \
|
FDT2 = 0x7ff7ffffffffffffULL; \
|
||||||
else if (GET_FP_CAUSE(env->fcr31) & FP_UNDERFLOW) { \
|
else if (GET_FP_CAUSE(env->fcr31) & FP_UNDERFLOW) { \
|
||||||
if ((env->fcr31 & 0x3) == 0) \
|
if ((env->fcr31 & 0x3) == 0) \
|
||||||
FDT2 &= 0x8000000000000000ULL; \
|
FDT2 &= FLOAT_SIGN64; \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
FLOAT_OP(name, s) \
|
FLOAT_OP(name, s) \
|
||||||
|
@ -988,7 +1015,7 @@ FLOAT_OP(name, s) \
|
||||||
FST2 = 0x7fbfffff; \
|
FST2 = 0x7fbfffff; \
|
||||||
else if (GET_FP_CAUSE(env->fcr31) & FP_UNDERFLOW) { \
|
else if (GET_FP_CAUSE(env->fcr31) & FP_UNDERFLOW) { \
|
||||||
if ((env->fcr31 & 0x3) == 0) \
|
if ((env->fcr31 & 0x3) == 0) \
|
||||||
FST2 &= 0x80000000ULL; \
|
FST2 &= FLOAT_SIGN32; \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
FLOAT_OP(name, ps) \
|
FLOAT_OP(name, ps) \
|
||||||
|
@ -1002,8 +1029,8 @@ FLOAT_OP(name, ps) \
|
||||||
FSTH2 = 0x7fbfffff; \
|
FSTH2 = 0x7fbfffff; \
|
||||||
} else if (GET_FP_CAUSE(env->fcr31) & FP_UNDERFLOW) { \
|
} else if (GET_FP_CAUSE(env->fcr31) & FP_UNDERFLOW) { \
|
||||||
if ((env->fcr31 & 0x3) == 0) { \
|
if ((env->fcr31 & 0x3) == 0) { \
|
||||||
FST2 &= 0x80000000ULL; \
|
FST2 &= FLOAT_SIGN32; \
|
||||||
FSTH2 &= 0x80000000ULL; \
|
FSTH2 &= FLOAT_SIGN32; \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
@ -1013,36 +1040,58 @@ FLOAT_BINOP(mul)
|
||||||
FLOAT_BINOP(div)
|
FLOAT_BINOP(div)
|
||||||
#undef FLOAT_BINOP
|
#undef FLOAT_BINOP
|
||||||
|
|
||||||
/* binary operations, MIPS specific */
|
/* MIPS specific binary operations */
|
||||||
#define FLOAT_BINOP(name) \
|
FLOAT_OP(recip2, d)
|
||||||
FLOAT_OP(name, d) \
|
{
|
||||||
{ \
|
set_float_exception_flags(0, &env->fp_status);
|
||||||
set_float_exception_flags(0, &env->fp_status); \
|
FDT2 = float64_mul(FDT0, FDT2, &env->fp_status);
|
||||||
/* XXX: not implemented */ \
|
FDT2 = float64_sub(FDT2, FLOAT_ONE64, &env->fp_status) ^ FLOAT_SIGN64;
|
||||||
/* FDT2 = float64_ ## name (FDT0, FDT1, &env->fp_status);*/ \
|
update_fcr31();
|
||||||
do_raise_exception(EXCP_RI); \
|
}
|
||||||
update_fcr31(); \
|
FLOAT_OP(recip2, s)
|
||||||
} \
|
{
|
||||||
FLOAT_OP(name, s) \
|
set_float_exception_flags(0, &env->fp_status);
|
||||||
{ \
|
FST2 = float32_mul(FST0, FST2, &env->fp_status);
|
||||||
set_float_exception_flags(0, &env->fp_status); \
|
FST2 = float32_sub(FST2, FLOAT_ONE32, &env->fp_status) ^ FLOAT_SIGN32;
|
||||||
/* XXX: not implemented */ \
|
update_fcr31();
|
||||||
/* FST2 = float32_ ## name (FST0, FST1, &env->fp_status);*/ \
|
}
|
||||||
do_raise_exception(EXCP_RI); \
|
FLOAT_OP(recip2, ps)
|
||||||
update_fcr31(); \
|
{
|
||||||
} \
|
set_float_exception_flags(0, &env->fp_status);
|
||||||
FLOAT_OP(name, ps) \
|
FST2 = float32_mul(FST0, FST2, &env->fp_status);
|
||||||
{ \
|
FSTH2 = float32_mul(FSTH0, FSTH2, &env->fp_status);
|
||||||
set_float_exception_flags(0, &env->fp_status); \
|
FST2 = float32_sub(FST2, FLOAT_ONE32, &env->fp_status) ^ FLOAT_SIGN32;
|
||||||
/* XXX: not implemented */ \
|
FSTH2 = float32_sub(FSTH2, FLOAT_ONE32, &env->fp_status) ^ FLOAT_SIGN32;
|
||||||
/* FST2 = float32_ ## name (FST0, FST1, &env->fp_status);*/ \
|
update_fcr31();
|
||||||
/* FSTH2 = float32_ ## name (FSTH0, FSTH1, &env->fp_status);*/ \
|
}
|
||||||
do_raise_exception(EXCP_RI); \
|
|
||||||
update_fcr31(); \
|
FLOAT_OP(rsqrt2, d)
|
||||||
|
{
|
||||||
|
set_float_exception_flags(0, &env->fp_status);
|
||||||
|
FDT2 = float64_mul(FDT0, FDT2, &env->fp_status);
|
||||||
|
FDT2 = float64_sub(FDT2, FLOAT_ONE64, &env->fp_status);
|
||||||
|
FDT2 = float64_div(FDT2, FLOAT_TWO64, &env->fp_status) ^ FLOAT_SIGN64;
|
||||||
|
update_fcr31();
|
||||||
|
}
|
||||||
|
FLOAT_OP(rsqrt2, s)
|
||||||
|
{
|
||||||
|
set_float_exception_flags(0, &env->fp_status);
|
||||||
|
FST2 = float32_mul(FST0, FST2, &env->fp_status);
|
||||||
|
FST2 = float32_sub(FST2, FLOAT_ONE32, &env->fp_status);
|
||||||
|
FST2 = float32_div(FST2, FLOAT_TWO32, &env->fp_status) ^ FLOAT_SIGN32;
|
||||||
|
update_fcr31();
|
||||||
|
}
|
||||||
|
FLOAT_OP(rsqrt2, ps)
|
||||||
|
{
|
||||||
|
set_float_exception_flags(0, &env->fp_status);
|
||||||
|
FST2 = float32_mul(FST0, FST2, &env->fp_status);
|
||||||
|
FSTH2 = float32_mul(FSTH0, FSTH2, &env->fp_status);
|
||||||
|
FST2 = float32_sub(FST2, FLOAT_ONE32, &env->fp_status);
|
||||||
|
FSTH2 = float32_sub(FSTH2, FLOAT_ONE32, &env->fp_status);
|
||||||
|
FST2 = float32_div(FST2, FLOAT_TWO32, &env->fp_status) ^ FLOAT_SIGN32;
|
||||||
|
FSTH2 = float32_div(FSTH2, FLOAT_TWO32, &env->fp_status) ^ FLOAT_SIGN32;
|
||||||
|
update_fcr31();
|
||||||
}
|
}
|
||||||
FLOAT_BINOP(rsqrt2)
|
|
||||||
FLOAT_BINOP(recip2)
|
|
||||||
#undef FLOAT_BINOP
|
|
||||||
|
|
||||||
FLOAT_OP(addr, ps)
|
FLOAT_OP(addr, ps)
|
||||||
{
|
{
|
||||||
|
@ -1060,6 +1109,7 @@ FLOAT_OP(mulr, ps)
|
||||||
update_fcr31();
|
update_fcr31();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* compare operations */
|
||||||
#define FOP_COND_D(op, cond) \
|
#define FOP_COND_D(op, cond) \
|
||||||
void do_cmp_d_ ## op (long cc) \
|
void do_cmp_d_ ## op (long cc) \
|
||||||
{ \
|
{ \
|
||||||
|
@ -1073,8 +1123,8 @@ void do_cmp_d_ ## op (long cc) \
|
||||||
void do_cmpabs_d_ ## op (long cc) \
|
void do_cmpabs_d_ ## op (long cc) \
|
||||||
{ \
|
{ \
|
||||||
int c; \
|
int c; \
|
||||||
FDT0 &= ~(1ULL << 63); \
|
FDT0 &= ~FLOAT_SIGN64; \
|
||||||
FDT1 &= ~(1ULL << 63); \
|
FDT1 &= ~FLOAT_SIGN64; \
|
||||||
c = cond; \
|
c = cond; \
|
||||||
update_fcr31(); \
|
update_fcr31(); \
|
||||||
if (c) \
|
if (c) \
|
||||||
|
@ -1131,8 +1181,8 @@ void do_cmp_s_ ## op (long cc) \
|
||||||
void do_cmpabs_s_ ## op (long cc) \
|
void do_cmpabs_s_ ## op (long cc) \
|
||||||
{ \
|
{ \
|
||||||
int c; \
|
int c; \
|
||||||
FST0 &= ~(1 << 31); \
|
FST0 &= ~FLOAT_SIGN32; \
|
||||||
FST1 &= ~(1 << 31); \
|
FST1 &= ~FLOAT_SIGN32; \
|
||||||
c = cond; \
|
c = cond; \
|
||||||
update_fcr31(); \
|
update_fcr31(); \
|
||||||
if (c) \
|
if (c) \
|
||||||
|
@ -1194,10 +1244,10 @@ void do_cmp_ps_ ## op (long cc) \
|
||||||
void do_cmpabs_ps_ ## op (long cc) \
|
void do_cmpabs_ps_ ## op (long cc) \
|
||||||
{ \
|
{ \
|
||||||
int cl, ch; \
|
int cl, ch; \
|
||||||
FST0 &= ~(1 << 31); \
|
FST0 &= ~FLOAT_SIGN32; \
|
||||||
FSTH0 &= ~(1 << 31); \
|
FSTH0 &= ~FLOAT_SIGN32; \
|
||||||
FST1 &= ~(1 << 31); \
|
FST1 &= ~FLOAT_SIGN32; \
|
||||||
FSTH1 &= ~(1 << 31); \
|
FSTH1 &= ~FLOAT_SIGN32; \
|
||||||
cl = condl; \
|
cl = condl; \
|
||||||
ch = condh; \
|
ch = condh; \
|
||||||
update_fcr31(); \
|
update_fcr31(); \
|
||||||
|
|
|
@ -4551,7 +4551,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
|
||||||
case FOP(31, 16):
|
case FOP(31, 16):
|
||||||
check_cp1_64bitmode(ctx);
|
check_cp1_64bitmode(ctx);
|
||||||
GEN_LOAD_FREG_FTN(WT0, fs);
|
GEN_LOAD_FREG_FTN(WT0, fs);
|
||||||
GEN_LOAD_FREG_FTN(WT2, fd);
|
GEN_LOAD_FREG_FTN(WT2, ft);
|
||||||
gen_op_float_rsqrt2_s();
|
gen_op_float_rsqrt2_s();
|
||||||
GEN_STORE_FTN_FREG(fd, WT2);
|
GEN_STORE_FTN_FREG(fd, WT2);
|
||||||
opn = "rsqrt2.s";
|
opn = "rsqrt2.s";
|
||||||
|
@ -5036,8 +5036,8 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
|
||||||
check_cp1_64bitmode(ctx);
|
check_cp1_64bitmode(ctx);
|
||||||
GEN_LOAD_FREG_FTN(WT0, fs);
|
GEN_LOAD_FREG_FTN(WT0, fs);
|
||||||
GEN_LOAD_FREG_FTN(WTH0, fs);
|
GEN_LOAD_FREG_FTN(WTH0, fs);
|
||||||
GEN_LOAD_FREG_FTN(WT2, fd);
|
GEN_LOAD_FREG_FTN(WT2, ft);
|
||||||
GEN_LOAD_FREG_FTN(WTH2, fd);
|
GEN_LOAD_FREG_FTN(WTH2, ft);
|
||||||
gen_op_float_rsqrt2_ps();
|
gen_op_float_rsqrt2_ps();
|
||||||
GEN_STORE_FTN_FREG(fd, WT2);
|
GEN_STORE_FTN_FREG(fd, WT2);
|
||||||
GEN_STORE_FTN_FREG(fd, WTH2);
|
GEN_STORE_FTN_FREG(fd, WTH2);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue