diff options
author | ths <ths@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-06-26 20:26:03 +0000 |
---|---|---|
committer | ths <ths@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-06-26 20:26:03 +0000 |
commit | 8dfdb87c8d675b846e12c8066922525e22bcfc50 (patch) | |
tree | b400604ee16d51051e7bbbe26ffb96510f1b5bae /target-mips | |
parent | d79acba420196a07f94b8d789972de7ff776f548 (diff) |
Implement recip1/recip2/rsqrt1/rsqrt2.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3026 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-mips')
-rw-r--r-- | target-mips/op_helper.c | 230 | ||||
-rw-r--r-- | target-mips/translate.c | 6 |
2 files changed, 143 insertions, 93 deletions
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index e4f2676707..94782252eb 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -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. */ +#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 */ unsigned int ieee_rm[] = { float_round_nearest_even, @@ -912,58 +919,78 @@ FLOAT_OP(floorw, s) WT2 = 0x7fffffff; } -/* unary operations, MIPS specific, s and d */ -#define FLOAT_UNOP(name) \ -FLOAT_OP(name, d) \ -{ \ - set_float_exception_flags(0, &env->fp_status); \ -/* XXX: not implemented */ \ -/* FDT2 = float64_ ## name (FDT0, &env->fp_status);*/ \ -do_raise_exception(EXCP_RI); \ - update_fcr31(); \ -} \ -FLOAT_OP(name, s) \ -{ \ - 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(); \ +/* MIPS specific unary operations */ +FLOAT_OP(recip, d) +{ + set_float_exception_flags(0, &env->fp_status); + FDT2 = float64_div(FLOAT_ONE64, FDT0, &env->fp_status); + update_fcr31(); +} +FLOAT_OP(recip, s) +{ + set_float_exception_flags(0, &env->fp_status); + FST2 = float32_div(FLOAT_ONE32, FST0, &env->fp_status); + update_fcr31(); } -FLOAT_UNOP(rsqrt) -FLOAT_UNOP(recip) -#undef FLOAT_UNOP -/* unary operations, MIPS specific, s, d and ps */ -#define FLOAT_UNOP(name) \ -FLOAT_OP(name, d) \ -{ \ - set_float_exception_flags(0, &env->fp_status); \ -/* XXX: not implemented */ \ -/* FDT2 = float64_ ## name (FDT0, &env->fp_status);*/ \ -do_raise_exception(EXCP_RI); \ - update_fcr31(); \ -} \ -FLOAT_OP(name, s) \ -{ \ - 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_OP(name, ps) \ -{ \ - set_float_exception_flags(0, &env->fp_status); \ -/* XXX: not implemented */ \ -/* FST2 = float32_ ## name (FST0, &env->fp_status);*/ \ -/* FSTH2 = float32_ ## name (FSTH0, &env->fp_status);*/ \ -do_raise_exception(EXCP_RI); \ - update_fcr31(); \ +FLOAT_OP(rsqrt, 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(rsqrt, 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(recip1, d) +{ + set_float_exception_flags(0, &env->fp_status); + FDT2 = float64_div(FLOAT_ONE64, FDT0, &env->fp_status); + update_fcr31(); +} +FLOAT_OP(recip1, s) +{ + set_float_exception_flags(0, &env->fp_status); + FST2 = float32_div(FLOAT_ONE32, FST0, &env->fp_status); + 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 */ #define FLOAT_BINOP(name) \ @@ -976,7 +1003,7 @@ FLOAT_OP(name, d) \ FDT2 = 0x7ff7ffffffffffffULL; \ else if (GET_FP_CAUSE(env->fcr31) & FP_UNDERFLOW) { \ if ((env->fcr31 & 0x3) == 0) \ - FDT2 &= 0x8000000000000000ULL; \ + FDT2 &= FLOAT_SIGN64; \ } \ } \ FLOAT_OP(name, s) \ @@ -988,7 +1015,7 @@ FLOAT_OP(name, s) \ FST2 = 0x7fbfffff; \ else if (GET_FP_CAUSE(env->fcr31) & FP_UNDERFLOW) { \ if ((env->fcr31 & 0x3) == 0) \ - FST2 &= 0x80000000ULL; \ + FST2 &= FLOAT_SIGN32; \ } \ } \ FLOAT_OP(name, ps) \ @@ -1002,8 +1029,8 @@ FLOAT_OP(name, ps) \ FSTH2 = 0x7fbfffff; \ } else if (GET_FP_CAUSE(env->fcr31) & FP_UNDERFLOW) { \ if ((env->fcr31 & 0x3) == 0) { \ - FST2 &= 0x80000000ULL; \ - FSTH2 &= 0x80000000ULL; \ + FST2 &= FLOAT_SIGN32; \ + FSTH2 &= FLOAT_SIGN32; \ } \ } \ } @@ -1013,36 +1040,58 @@ FLOAT_BINOP(mul) FLOAT_BINOP(div) #undef FLOAT_BINOP -/* binary operations, MIPS specific */ -#define FLOAT_BINOP(name) \ -FLOAT_OP(name, d) \ -{ \ - set_float_exception_flags(0, &env->fp_status); \ -/* XXX: not implemented */ \ -/* FDT2 = float64_ ## name (FDT0, FDT1, &env->fp_status);*/ \ -do_raise_exception(EXCP_RI); \ - update_fcr31(); \ -} \ -FLOAT_OP(name, s) \ -{ \ - set_float_exception_flags(0, &env->fp_status); \ -/* XXX: not implemented */ \ -/* FST2 = float32_ ## name (FST0, FST1, &env->fp_status);*/ \ -do_raise_exception(EXCP_RI); \ - update_fcr31(); \ -} \ -FLOAT_OP(name, ps) \ -{ \ - set_float_exception_flags(0, &env->fp_status); \ -/* XXX: not implemented */ \ -/* FST2 = float32_ ## name (FST0, FST1, &env->fp_status);*/ \ -/* FSTH2 = float32_ ## name (FSTH0, FSTH1, &env->fp_status);*/ \ -do_raise_exception(EXCP_RI); \ - update_fcr31(); \ +/* MIPS specific binary operations */ +FLOAT_OP(recip2, 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) ^ FLOAT_SIGN64; + update_fcr31(); +} +FLOAT_OP(recip2, 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) ^ FLOAT_SIGN32; + update_fcr31(); +} +FLOAT_OP(recip2, 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) ^ FLOAT_SIGN32; + FSTH2 = float32_sub(FSTH2, FLOAT_ONE32, &env->fp_status) ^ FLOAT_SIGN32; + 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) { @@ -1060,6 +1109,7 @@ FLOAT_OP(mulr, ps) update_fcr31(); } +/* compare operations */ #define FOP_COND_D(op, cond) \ 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) \ { \ int c; \ - FDT0 &= ~(1ULL << 63); \ - FDT1 &= ~(1ULL << 63); \ + FDT0 &= ~FLOAT_SIGN64; \ + FDT1 &= ~FLOAT_SIGN64; \ c = cond; \ update_fcr31(); \ if (c) \ @@ -1131,8 +1181,8 @@ void do_cmp_s_ ## op (long cc) \ void do_cmpabs_s_ ## op (long cc) \ { \ int c; \ - FST0 &= ~(1 << 31); \ - FST1 &= ~(1 << 31); \ + FST0 &= ~FLOAT_SIGN32; \ + FST1 &= ~FLOAT_SIGN32; \ c = cond; \ update_fcr31(); \ if (c) \ @@ -1194,10 +1244,10 @@ void do_cmp_ps_ ## op (long cc) \ void do_cmpabs_ps_ ## op (long cc) \ { \ int cl, ch; \ - FST0 &= ~(1 << 31); \ - FSTH0 &= ~(1 << 31); \ - FST1 &= ~(1 << 31); \ - FSTH1 &= ~(1 << 31); \ + FST0 &= ~FLOAT_SIGN32; \ + FSTH0 &= ~FLOAT_SIGN32; \ + FST1 &= ~FLOAT_SIGN32; \ + FSTH1 &= ~FLOAT_SIGN32; \ cl = condl; \ ch = condh; \ update_fcr31(); \ diff --git a/target-mips/translate.c b/target-mips/translate.c index b5a8b5b0a6..7f5141c33c 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -4551,7 +4551,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, case FOP(31, 16): check_cp1_64bitmode(ctx); GEN_LOAD_FREG_FTN(WT0, fs); - GEN_LOAD_FREG_FTN(WT2, fd); + GEN_LOAD_FREG_FTN(WT2, ft); gen_op_float_rsqrt2_s(); GEN_STORE_FTN_FREG(fd, WT2); opn = "rsqrt2.s"; @@ -5036,8 +5036,8 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, check_cp1_64bitmode(ctx); GEN_LOAD_FREG_FTN(WT0, fs); GEN_LOAD_FREG_FTN(WTH0, fs); - GEN_LOAD_FREG_FTN(WT2, fd); - GEN_LOAD_FREG_FTN(WTH2, fd); + GEN_LOAD_FREG_FTN(WT2, ft); + GEN_LOAD_FREG_FTN(WTH2, ft); gen_op_float_rsqrt2_ps(); GEN_STORE_FTN_FREG(fd, WT2); GEN_STORE_FTN_FREG(fd, WTH2); |