diff options
author | ths <ths@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-05-11 17:08:26 +0000 |
---|---|---|
committer | ths <ths@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-05-11 17:08:26 +0000 |
commit | 5a1e8ffbe746b2ba4fb8dbdebf3f99d2403fb53e (patch) | |
tree | a8e309aacb48d8b6f3ed2fb5e685411efa1a81b6 /target-mips/op.c | |
parent | 287c4b84f49d86176f9fd2ea7d06872dd8c1f2ca (diff) | |
download | qemu-5a1e8ffbe746b2ba4fb8dbdebf3f99d2403fb53e.zip qemu-5a1e8ffbe746b2ba4fb8dbdebf3f99d2403fb53e.tar.gz qemu-5a1e8ffbe746b2ba4fb8dbdebf3f99d2403fb53e.tar.bz2 |
Implemented cabs FP instructions, and improve exception handling for
trunc/floor/ceil/round.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2804 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-mips/op.c')
-rw-r--r-- | target-mips/op.c | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/target-mips/op.c b/target-mips/op.c index 15c541c..748f997 100644 --- a/target-mips/op.c +++ b/target-mips/op.c @@ -1965,6 +1965,9 @@ FLOAT_OP(roundl, d) set_float_rounding_mode(float_round_nearest_even, &env->fp_status); DT2 = float64_round_to_int(FDT0, &env->fp_status); RESTORE_ROUNDING_MODE; + update_fcr31(); + if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) + DT2 = 0x7fffffffffffffffULL; DEBUG_FPU_STATE(); RETURN(); } @@ -1973,6 +1976,9 @@ FLOAT_OP(roundl, s) set_float_rounding_mode(float_round_nearest_even, &env->fp_status); DT2 = float32_round_to_int(FST0, &env->fp_status); RESTORE_ROUNDING_MODE; + update_fcr31(); + if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) + DT2 = 0x7fffffffffffffffULL; DEBUG_FPU_STATE(); RETURN(); } @@ -1981,6 +1987,9 @@ FLOAT_OP(roundw, d) set_float_rounding_mode(float_round_nearest_even, &env->fp_status); WT2 = float64_round_to_int(FDT0, &env->fp_status); RESTORE_ROUNDING_MODE; + update_fcr31(); + if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) + WT2 = 0x7fffffff; DEBUG_FPU_STATE(); RETURN(); } @@ -1989,6 +1998,9 @@ FLOAT_OP(roundw, s) set_float_rounding_mode(float_round_nearest_even, &env->fp_status); WT2 = float32_round_to_int(FST0, &env->fp_status); RESTORE_ROUNDING_MODE; + update_fcr31(); + if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) + WT2 = 0x7fffffff; DEBUG_FPU_STATE(); RETURN(); } @@ -1996,24 +2008,36 @@ FLOAT_OP(roundw, s) FLOAT_OP(truncl, d) { DT2 = float64_to_int64_round_to_zero(FDT0, &env->fp_status); + update_fcr31(); + if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) + DT2 = 0x7fffffffffffffffULL; DEBUG_FPU_STATE(); RETURN(); } FLOAT_OP(truncl, s) { DT2 = float32_to_int64_round_to_zero(FST0, &env->fp_status); + update_fcr31(); + if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) + DT2 = 0x7fffffffffffffffULL; DEBUG_FPU_STATE(); RETURN(); } FLOAT_OP(truncw, d) { WT2 = float64_to_int32_round_to_zero(FDT0, &env->fp_status); + update_fcr31(); + if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) + WT2 = 0x7fffffff; DEBUG_FPU_STATE(); RETURN(); } FLOAT_OP(truncw, s) { WT2 = float32_to_int32_round_to_zero(FST0, &env->fp_status); + update_fcr31(); + if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) + WT2 = 0x7fffffff; DEBUG_FPU_STATE(); RETURN(); } @@ -2023,6 +2047,9 @@ FLOAT_OP(ceill, d) set_float_rounding_mode(float_round_up, &env->fp_status); DT2 = float64_round_to_int(FDT0, &env->fp_status); RESTORE_ROUNDING_MODE; + update_fcr31(); + if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) + DT2 = 0x7fffffffffffffffULL; DEBUG_FPU_STATE(); RETURN(); } @@ -2031,6 +2058,9 @@ FLOAT_OP(ceill, s) set_float_rounding_mode(float_round_up, &env->fp_status); DT2 = float32_round_to_int(FST0, &env->fp_status); RESTORE_ROUNDING_MODE; + update_fcr31(); + if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) + DT2 = 0x7fffffffffffffffULL; DEBUG_FPU_STATE(); RETURN(); } @@ -2039,6 +2069,9 @@ FLOAT_OP(ceilw, d) set_float_rounding_mode(float_round_up, &env->fp_status); WT2 = float64_round_to_int(FDT0, &env->fp_status); RESTORE_ROUNDING_MODE; + update_fcr31(); + if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) + WT2 = 0x7fffffff; DEBUG_FPU_STATE(); RETURN(); } @@ -2047,6 +2080,9 @@ FLOAT_OP(ceilw, s) set_float_rounding_mode(float_round_up, &env->fp_status); WT2 = float32_round_to_int(FST0, &env->fp_status); RESTORE_ROUNDING_MODE; + update_fcr31(); + if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) + WT2 = 0x7fffffff; DEBUG_FPU_STATE(); RETURN(); } @@ -2056,6 +2092,9 @@ FLOAT_OP(floorl, d) set_float_rounding_mode(float_round_down, &env->fp_status); DT2 = float64_round_to_int(FDT0, &env->fp_status); RESTORE_ROUNDING_MODE; + update_fcr31(); + if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) + DT2 = 0x7fffffffffffffffULL; DEBUG_FPU_STATE(); RETURN(); } @@ -2064,6 +2103,9 @@ FLOAT_OP(floorl, s) set_float_rounding_mode(float_round_down, &env->fp_status); DT2 = float32_round_to_int(FST0, &env->fp_status); RESTORE_ROUNDING_MODE; + update_fcr31(); + if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) + DT2 = 0x7fffffffffffffffULL; DEBUG_FPU_STATE(); RETURN(); } @@ -2072,6 +2114,9 @@ FLOAT_OP(floorw, d) set_float_rounding_mode(float_round_down, &env->fp_status); WT2 = float64_round_to_int(FDT0, &env->fp_status); RESTORE_ROUNDING_MODE; + update_fcr31(); + if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) + WT2 = 0x7fffffff; DEBUG_FPU_STATE(); RETURN(); } @@ -2080,6 +2125,9 @@ FLOAT_OP(floorw, s) set_float_rounding_mode(float_round_down, &env->fp_status); WT2 = float32_round_to_int(FST0, &env->fp_status); RESTORE_ROUNDING_MODE; + update_fcr31(); + if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) + WT2 = 0x7fffffff; DEBUG_FPU_STATE(); RETURN(); } @@ -2396,6 +2444,20 @@ void op_cmp_d_ ## op (void) \ CLEAR_FP_COND(PARAM1, env); \ DEBUG_FPU_STATE(); \ RETURN(); \ +} \ +void op_cmpabs_d_ ## op (void) \ +{ \ + int c; \ + FDT0 &= ~(1ULL << 63); \ + FDT1 &= ~(1ULL << 63); \ + c = cond; \ + update_fcr31(); \ + if (c) \ + SET_FP_COND(PARAM1, env); \ + else \ + CLEAR_FP_COND(PARAM1, env); \ + DEBUG_FPU_STATE(); \ + RETURN(); \ } int float64_is_unordered(int sig, float64 a, float64 b STATUS_PARAM) @@ -2444,6 +2506,20 @@ void op_cmp_s_ ## op (void) \ CLEAR_FP_COND(PARAM1, env); \ DEBUG_FPU_STATE(); \ RETURN(); \ +} \ +void op_cmpabs_s_ ## op (void) \ +{ \ + int c; \ + FST0 &= ~(1 << 31); \ + FST1 &= ~(1 << 31); \ + c = cond; \ + update_fcr31(); \ + if (c) \ + SET_FP_COND(PARAM1, env); \ + else \ + CLEAR_FP_COND(PARAM1, env); \ + DEBUG_FPU_STATE(); \ + RETURN(); \ } flag float32_is_unordered(int sig, float32 a, float32 b STATUS_PARAM) @@ -2498,6 +2574,27 @@ void op_cmp_ps_ ## op (void) \ CLEAR_FP_COND(PARAM1 + 1, env); \ DEBUG_FPU_STATE(); \ RETURN(); \ +} \ +void op_cmpabs_ps_ ## op (void) \ +{ \ + int cl, ch; \ + FST0 &= ~(1 << 31); \ + FSTH0 &= ~(1 << 31); \ + FST1 &= ~(1 << 31); \ + FSTH1 &= ~(1 << 31); \ + cl = condl; \ + ch = condh; \ + update_fcr31(); \ + if (cl) \ + SET_FP_COND(PARAM1, env); \ + else \ + CLEAR_FP_COND(PARAM1, env); \ + if (ch) \ + SET_FP_COND(PARAM1 + 1, env); \ + else \ + CLEAR_FP_COND(PARAM1 + 1, env); \ + DEBUG_FPU_STATE(); \ + RETURN(); \ } /* NOTE: the comma operator will make "cond" to eval to false, |