Commit 5a1e8ffbe746b2ba4fb8dbdebf3f99d2403fb53e
1 parent
287c4b84
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
Showing
2 changed files
with
180 additions
and
40 deletions
target-mips/op.c
@@ -1965,6 +1965,9 @@ FLOAT_OP(roundl, d) | @@ -1965,6 +1965,9 @@ FLOAT_OP(roundl, d) | ||
1965 | set_float_rounding_mode(float_round_nearest_even, &env->fp_status); | 1965 | set_float_rounding_mode(float_round_nearest_even, &env->fp_status); |
1966 | DT2 = float64_round_to_int(FDT0, &env->fp_status); | 1966 | DT2 = float64_round_to_int(FDT0, &env->fp_status); |
1967 | RESTORE_ROUNDING_MODE; | 1967 | RESTORE_ROUNDING_MODE; |
1968 | + update_fcr31(); | ||
1969 | + if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) | ||
1970 | + DT2 = 0x7fffffffffffffffULL; | ||
1968 | DEBUG_FPU_STATE(); | 1971 | DEBUG_FPU_STATE(); |
1969 | RETURN(); | 1972 | RETURN(); |
1970 | } | 1973 | } |
@@ -1973,6 +1976,9 @@ FLOAT_OP(roundl, s) | @@ -1973,6 +1976,9 @@ FLOAT_OP(roundl, s) | ||
1973 | set_float_rounding_mode(float_round_nearest_even, &env->fp_status); | 1976 | set_float_rounding_mode(float_round_nearest_even, &env->fp_status); |
1974 | DT2 = float32_round_to_int(FST0, &env->fp_status); | 1977 | DT2 = float32_round_to_int(FST0, &env->fp_status); |
1975 | RESTORE_ROUNDING_MODE; | 1978 | RESTORE_ROUNDING_MODE; |
1979 | + update_fcr31(); | ||
1980 | + if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) | ||
1981 | + DT2 = 0x7fffffffffffffffULL; | ||
1976 | DEBUG_FPU_STATE(); | 1982 | DEBUG_FPU_STATE(); |
1977 | RETURN(); | 1983 | RETURN(); |
1978 | } | 1984 | } |
@@ -1981,6 +1987,9 @@ FLOAT_OP(roundw, d) | @@ -1981,6 +1987,9 @@ FLOAT_OP(roundw, d) | ||
1981 | set_float_rounding_mode(float_round_nearest_even, &env->fp_status); | 1987 | set_float_rounding_mode(float_round_nearest_even, &env->fp_status); |
1982 | WT2 = float64_round_to_int(FDT0, &env->fp_status); | 1988 | WT2 = float64_round_to_int(FDT0, &env->fp_status); |
1983 | RESTORE_ROUNDING_MODE; | 1989 | RESTORE_ROUNDING_MODE; |
1990 | + update_fcr31(); | ||
1991 | + if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) | ||
1992 | + WT2 = 0x7fffffff; | ||
1984 | DEBUG_FPU_STATE(); | 1993 | DEBUG_FPU_STATE(); |
1985 | RETURN(); | 1994 | RETURN(); |
1986 | } | 1995 | } |
@@ -1989,6 +1998,9 @@ FLOAT_OP(roundw, s) | @@ -1989,6 +1998,9 @@ FLOAT_OP(roundw, s) | ||
1989 | set_float_rounding_mode(float_round_nearest_even, &env->fp_status); | 1998 | set_float_rounding_mode(float_round_nearest_even, &env->fp_status); |
1990 | WT2 = float32_round_to_int(FST0, &env->fp_status); | 1999 | WT2 = float32_round_to_int(FST0, &env->fp_status); |
1991 | RESTORE_ROUNDING_MODE; | 2000 | RESTORE_ROUNDING_MODE; |
2001 | + update_fcr31(); | ||
2002 | + if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) | ||
2003 | + WT2 = 0x7fffffff; | ||
1992 | DEBUG_FPU_STATE(); | 2004 | DEBUG_FPU_STATE(); |
1993 | RETURN(); | 2005 | RETURN(); |
1994 | } | 2006 | } |
@@ -1996,24 +2008,36 @@ FLOAT_OP(roundw, s) | @@ -1996,24 +2008,36 @@ FLOAT_OP(roundw, s) | ||
1996 | FLOAT_OP(truncl, d) | 2008 | FLOAT_OP(truncl, d) |
1997 | { | 2009 | { |
1998 | DT2 = float64_to_int64_round_to_zero(FDT0, &env->fp_status); | 2010 | DT2 = float64_to_int64_round_to_zero(FDT0, &env->fp_status); |
2011 | + update_fcr31(); | ||
2012 | + if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) | ||
2013 | + DT2 = 0x7fffffffffffffffULL; | ||
1999 | DEBUG_FPU_STATE(); | 2014 | DEBUG_FPU_STATE(); |
2000 | RETURN(); | 2015 | RETURN(); |
2001 | } | 2016 | } |
2002 | FLOAT_OP(truncl, s) | 2017 | FLOAT_OP(truncl, s) |
2003 | { | 2018 | { |
2004 | DT2 = float32_to_int64_round_to_zero(FST0, &env->fp_status); | 2019 | DT2 = float32_to_int64_round_to_zero(FST0, &env->fp_status); |
2020 | + update_fcr31(); | ||
2021 | + if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) | ||
2022 | + DT2 = 0x7fffffffffffffffULL; | ||
2005 | DEBUG_FPU_STATE(); | 2023 | DEBUG_FPU_STATE(); |
2006 | RETURN(); | 2024 | RETURN(); |
2007 | } | 2025 | } |
2008 | FLOAT_OP(truncw, d) | 2026 | FLOAT_OP(truncw, d) |
2009 | { | 2027 | { |
2010 | WT2 = float64_to_int32_round_to_zero(FDT0, &env->fp_status); | 2028 | WT2 = float64_to_int32_round_to_zero(FDT0, &env->fp_status); |
2029 | + update_fcr31(); | ||
2030 | + if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) | ||
2031 | + WT2 = 0x7fffffff; | ||
2011 | DEBUG_FPU_STATE(); | 2032 | DEBUG_FPU_STATE(); |
2012 | RETURN(); | 2033 | RETURN(); |
2013 | } | 2034 | } |
2014 | FLOAT_OP(truncw, s) | 2035 | FLOAT_OP(truncw, s) |
2015 | { | 2036 | { |
2016 | WT2 = float32_to_int32_round_to_zero(FST0, &env->fp_status); | 2037 | WT2 = float32_to_int32_round_to_zero(FST0, &env->fp_status); |
2038 | + update_fcr31(); | ||
2039 | + if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) | ||
2040 | + WT2 = 0x7fffffff; | ||
2017 | DEBUG_FPU_STATE(); | 2041 | DEBUG_FPU_STATE(); |
2018 | RETURN(); | 2042 | RETURN(); |
2019 | } | 2043 | } |
@@ -2023,6 +2047,9 @@ FLOAT_OP(ceill, d) | @@ -2023,6 +2047,9 @@ FLOAT_OP(ceill, d) | ||
2023 | set_float_rounding_mode(float_round_up, &env->fp_status); | 2047 | set_float_rounding_mode(float_round_up, &env->fp_status); |
2024 | DT2 = float64_round_to_int(FDT0, &env->fp_status); | 2048 | DT2 = float64_round_to_int(FDT0, &env->fp_status); |
2025 | RESTORE_ROUNDING_MODE; | 2049 | RESTORE_ROUNDING_MODE; |
2050 | + update_fcr31(); | ||
2051 | + if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) | ||
2052 | + DT2 = 0x7fffffffffffffffULL; | ||
2026 | DEBUG_FPU_STATE(); | 2053 | DEBUG_FPU_STATE(); |
2027 | RETURN(); | 2054 | RETURN(); |
2028 | } | 2055 | } |
@@ -2031,6 +2058,9 @@ FLOAT_OP(ceill, s) | @@ -2031,6 +2058,9 @@ FLOAT_OP(ceill, s) | ||
2031 | set_float_rounding_mode(float_round_up, &env->fp_status); | 2058 | set_float_rounding_mode(float_round_up, &env->fp_status); |
2032 | DT2 = float32_round_to_int(FST0, &env->fp_status); | 2059 | DT2 = float32_round_to_int(FST0, &env->fp_status); |
2033 | RESTORE_ROUNDING_MODE; | 2060 | RESTORE_ROUNDING_MODE; |
2061 | + update_fcr31(); | ||
2062 | + if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) | ||
2063 | + DT2 = 0x7fffffffffffffffULL; | ||
2034 | DEBUG_FPU_STATE(); | 2064 | DEBUG_FPU_STATE(); |
2035 | RETURN(); | 2065 | RETURN(); |
2036 | } | 2066 | } |
@@ -2039,6 +2069,9 @@ FLOAT_OP(ceilw, d) | @@ -2039,6 +2069,9 @@ FLOAT_OP(ceilw, d) | ||
2039 | set_float_rounding_mode(float_round_up, &env->fp_status); | 2069 | set_float_rounding_mode(float_round_up, &env->fp_status); |
2040 | WT2 = float64_round_to_int(FDT0, &env->fp_status); | 2070 | WT2 = float64_round_to_int(FDT0, &env->fp_status); |
2041 | RESTORE_ROUNDING_MODE; | 2071 | RESTORE_ROUNDING_MODE; |
2072 | + update_fcr31(); | ||
2073 | + if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) | ||
2074 | + WT2 = 0x7fffffff; | ||
2042 | DEBUG_FPU_STATE(); | 2075 | DEBUG_FPU_STATE(); |
2043 | RETURN(); | 2076 | RETURN(); |
2044 | } | 2077 | } |
@@ -2047,6 +2080,9 @@ FLOAT_OP(ceilw, s) | @@ -2047,6 +2080,9 @@ FLOAT_OP(ceilw, s) | ||
2047 | set_float_rounding_mode(float_round_up, &env->fp_status); | 2080 | set_float_rounding_mode(float_round_up, &env->fp_status); |
2048 | WT2 = float32_round_to_int(FST0, &env->fp_status); | 2081 | WT2 = float32_round_to_int(FST0, &env->fp_status); |
2049 | RESTORE_ROUNDING_MODE; | 2082 | RESTORE_ROUNDING_MODE; |
2083 | + update_fcr31(); | ||
2084 | + if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) | ||
2085 | + WT2 = 0x7fffffff; | ||
2050 | DEBUG_FPU_STATE(); | 2086 | DEBUG_FPU_STATE(); |
2051 | RETURN(); | 2087 | RETURN(); |
2052 | } | 2088 | } |
@@ -2056,6 +2092,9 @@ FLOAT_OP(floorl, d) | @@ -2056,6 +2092,9 @@ FLOAT_OP(floorl, d) | ||
2056 | set_float_rounding_mode(float_round_down, &env->fp_status); | 2092 | set_float_rounding_mode(float_round_down, &env->fp_status); |
2057 | DT2 = float64_round_to_int(FDT0, &env->fp_status); | 2093 | DT2 = float64_round_to_int(FDT0, &env->fp_status); |
2058 | RESTORE_ROUNDING_MODE; | 2094 | RESTORE_ROUNDING_MODE; |
2095 | + update_fcr31(); | ||
2096 | + if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) | ||
2097 | + DT2 = 0x7fffffffffffffffULL; | ||
2059 | DEBUG_FPU_STATE(); | 2098 | DEBUG_FPU_STATE(); |
2060 | RETURN(); | 2099 | RETURN(); |
2061 | } | 2100 | } |
@@ -2064,6 +2103,9 @@ FLOAT_OP(floorl, s) | @@ -2064,6 +2103,9 @@ FLOAT_OP(floorl, s) | ||
2064 | set_float_rounding_mode(float_round_down, &env->fp_status); | 2103 | set_float_rounding_mode(float_round_down, &env->fp_status); |
2065 | DT2 = float32_round_to_int(FST0, &env->fp_status); | 2104 | DT2 = float32_round_to_int(FST0, &env->fp_status); |
2066 | RESTORE_ROUNDING_MODE; | 2105 | RESTORE_ROUNDING_MODE; |
2106 | + update_fcr31(); | ||
2107 | + if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) | ||
2108 | + DT2 = 0x7fffffffffffffffULL; | ||
2067 | DEBUG_FPU_STATE(); | 2109 | DEBUG_FPU_STATE(); |
2068 | RETURN(); | 2110 | RETURN(); |
2069 | } | 2111 | } |
@@ -2072,6 +2114,9 @@ FLOAT_OP(floorw, d) | @@ -2072,6 +2114,9 @@ FLOAT_OP(floorw, d) | ||
2072 | set_float_rounding_mode(float_round_down, &env->fp_status); | 2114 | set_float_rounding_mode(float_round_down, &env->fp_status); |
2073 | WT2 = float64_round_to_int(FDT0, &env->fp_status); | 2115 | WT2 = float64_round_to_int(FDT0, &env->fp_status); |
2074 | RESTORE_ROUNDING_MODE; | 2116 | RESTORE_ROUNDING_MODE; |
2117 | + update_fcr31(); | ||
2118 | + if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) | ||
2119 | + WT2 = 0x7fffffff; | ||
2075 | DEBUG_FPU_STATE(); | 2120 | DEBUG_FPU_STATE(); |
2076 | RETURN(); | 2121 | RETURN(); |
2077 | } | 2122 | } |
@@ -2080,6 +2125,9 @@ FLOAT_OP(floorw, s) | @@ -2080,6 +2125,9 @@ FLOAT_OP(floorw, s) | ||
2080 | set_float_rounding_mode(float_round_down, &env->fp_status); | 2125 | set_float_rounding_mode(float_round_down, &env->fp_status); |
2081 | WT2 = float32_round_to_int(FST0, &env->fp_status); | 2126 | WT2 = float32_round_to_int(FST0, &env->fp_status); |
2082 | RESTORE_ROUNDING_MODE; | 2127 | RESTORE_ROUNDING_MODE; |
2128 | + update_fcr31(); | ||
2129 | + if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) | ||
2130 | + WT2 = 0x7fffffff; | ||
2083 | DEBUG_FPU_STATE(); | 2131 | DEBUG_FPU_STATE(); |
2084 | RETURN(); | 2132 | RETURN(); |
2085 | } | 2133 | } |
@@ -2396,6 +2444,20 @@ void op_cmp_d_ ## op (void) \ | @@ -2396,6 +2444,20 @@ void op_cmp_d_ ## op (void) \ | ||
2396 | CLEAR_FP_COND(PARAM1, env); \ | 2444 | CLEAR_FP_COND(PARAM1, env); \ |
2397 | DEBUG_FPU_STATE(); \ | 2445 | DEBUG_FPU_STATE(); \ |
2398 | RETURN(); \ | 2446 | RETURN(); \ |
2447 | +} \ | ||
2448 | +void op_cmpabs_d_ ## op (void) \ | ||
2449 | +{ \ | ||
2450 | + int c; \ | ||
2451 | + FDT0 &= ~(1ULL << 63); \ | ||
2452 | + FDT1 &= ~(1ULL << 63); \ | ||
2453 | + c = cond; \ | ||
2454 | + update_fcr31(); \ | ||
2455 | + if (c) \ | ||
2456 | + SET_FP_COND(PARAM1, env); \ | ||
2457 | + else \ | ||
2458 | + CLEAR_FP_COND(PARAM1, env); \ | ||
2459 | + DEBUG_FPU_STATE(); \ | ||
2460 | + RETURN(); \ | ||
2399 | } | 2461 | } |
2400 | 2462 | ||
2401 | int float64_is_unordered(int sig, float64 a, float64 b STATUS_PARAM) | 2463 | int float64_is_unordered(int sig, float64 a, float64 b STATUS_PARAM) |
@@ -2444,6 +2506,20 @@ void op_cmp_s_ ## op (void) \ | @@ -2444,6 +2506,20 @@ void op_cmp_s_ ## op (void) \ | ||
2444 | CLEAR_FP_COND(PARAM1, env); \ | 2506 | CLEAR_FP_COND(PARAM1, env); \ |
2445 | DEBUG_FPU_STATE(); \ | 2507 | DEBUG_FPU_STATE(); \ |
2446 | RETURN(); \ | 2508 | RETURN(); \ |
2509 | +} \ | ||
2510 | +void op_cmpabs_s_ ## op (void) \ | ||
2511 | +{ \ | ||
2512 | + int c; \ | ||
2513 | + FST0 &= ~(1 << 31); \ | ||
2514 | + FST1 &= ~(1 << 31); \ | ||
2515 | + c = cond; \ | ||
2516 | + update_fcr31(); \ | ||
2517 | + if (c) \ | ||
2518 | + SET_FP_COND(PARAM1, env); \ | ||
2519 | + else \ | ||
2520 | + CLEAR_FP_COND(PARAM1, env); \ | ||
2521 | + DEBUG_FPU_STATE(); \ | ||
2522 | + RETURN(); \ | ||
2447 | } | 2523 | } |
2448 | 2524 | ||
2449 | flag float32_is_unordered(int sig, float32 a, float32 b STATUS_PARAM) | 2525 | flag float32_is_unordered(int sig, float32 a, float32 b STATUS_PARAM) |
@@ -2498,6 +2574,27 @@ void op_cmp_ps_ ## op (void) \ | @@ -2498,6 +2574,27 @@ void op_cmp_ps_ ## op (void) \ | ||
2498 | CLEAR_FP_COND(PARAM1 + 1, env); \ | 2574 | CLEAR_FP_COND(PARAM1 + 1, env); \ |
2499 | DEBUG_FPU_STATE(); \ | 2575 | DEBUG_FPU_STATE(); \ |
2500 | RETURN(); \ | 2576 | RETURN(); \ |
2577 | +} \ | ||
2578 | +void op_cmpabs_ps_ ## op (void) \ | ||
2579 | +{ \ | ||
2580 | + int cl, ch; \ | ||
2581 | + FST0 &= ~(1 << 31); \ | ||
2582 | + FSTH0 &= ~(1 << 31); \ | ||
2583 | + FST1 &= ~(1 << 31); \ | ||
2584 | + FSTH1 &= ~(1 << 31); \ | ||
2585 | + cl = condl; \ | ||
2586 | + ch = condh; \ | ||
2587 | + update_fcr31(); \ | ||
2588 | + if (cl) \ | ||
2589 | + SET_FP_COND(PARAM1, env); \ | ||
2590 | + else \ | ||
2591 | + CLEAR_FP_COND(PARAM1, env); \ | ||
2592 | + if (ch) \ | ||
2593 | + SET_FP_COND(PARAM1 + 1, env); \ | ||
2594 | + else \ | ||
2595 | + CLEAR_FP_COND(PARAM1 + 1, env); \ | ||
2596 | + DEBUG_FPU_STATE(); \ | ||
2597 | + RETURN(); \ | ||
2501 | } | 2598 | } |
2502 | 2599 | ||
2503 | /* NOTE: the comma operator will make "cond" to eval to false, | 2600 | /* NOTE: the comma operator will make "cond" to eval to false, |
target-mips/translate.c
@@ -490,33 +490,36 @@ FGEN32(gen_op_store_fpr_WTH1, gen_op_store_fpr_WTH1_fpr); | @@ -490,33 +490,36 @@ FGEN32(gen_op_store_fpr_WTH1, gen_op_store_fpr_WTH1_fpr); | ||
490 | FGEN32(gen_op_load_fpr_WTH2, gen_op_load_fpr_WTH2_fpr); | 490 | FGEN32(gen_op_load_fpr_WTH2, gen_op_load_fpr_WTH2_fpr); |
491 | FGEN32(gen_op_store_fpr_WTH2, gen_op_store_fpr_WTH2_fpr); | 491 | FGEN32(gen_op_store_fpr_WTH2, gen_op_store_fpr_WTH2_fpr); |
492 | 492 | ||
493 | -#define FOP_CONDS(fmt) \ | ||
494 | -static GenOpFunc1 * cond_ ## fmt ## _table[16] = { \ | ||
495 | - gen_op_cmp_ ## fmt ## _f, \ | ||
496 | - gen_op_cmp_ ## fmt ## _un, \ | ||
497 | - gen_op_cmp_ ## fmt ## _eq, \ | ||
498 | - gen_op_cmp_ ## fmt ## _ueq, \ | ||
499 | - gen_op_cmp_ ## fmt ## _olt, \ | ||
500 | - gen_op_cmp_ ## fmt ## _ult, \ | ||
501 | - gen_op_cmp_ ## fmt ## _ole, \ | ||
502 | - gen_op_cmp_ ## fmt ## _ule, \ | ||
503 | - gen_op_cmp_ ## fmt ## _sf, \ | ||
504 | - gen_op_cmp_ ## fmt ## _ngle, \ | ||
505 | - gen_op_cmp_ ## fmt ## _seq, \ | ||
506 | - gen_op_cmp_ ## fmt ## _ngl, \ | ||
507 | - gen_op_cmp_ ## fmt ## _lt, \ | ||
508 | - gen_op_cmp_ ## fmt ## _nge, \ | ||
509 | - gen_op_cmp_ ## fmt ## _le, \ | ||
510 | - gen_op_cmp_ ## fmt ## _ngt, \ | 493 | +#define FOP_CONDS(type, fmt) \ |
494 | +static GenOpFunc1 * cond ## type ## _ ## fmt ## _table[16] = { \ | ||
495 | + gen_op_cmp ## type ## _ ## fmt ## _f, \ | ||
496 | + gen_op_cmp ## type ## _ ## fmt ## _un, \ | ||
497 | + gen_op_cmp ## type ## _ ## fmt ## _eq, \ | ||
498 | + gen_op_cmp ## type ## _ ## fmt ## _ueq, \ | ||
499 | + gen_op_cmp ## type ## _ ## fmt ## _olt, \ | ||
500 | + gen_op_cmp ## type ## _ ## fmt ## _ult, \ | ||
501 | + gen_op_cmp ## type ## _ ## fmt ## _ole, \ | ||
502 | + gen_op_cmp ## type ## _ ## fmt ## _ule, \ | ||
503 | + gen_op_cmp ## type ## _ ## fmt ## _sf, \ | ||
504 | + gen_op_cmp ## type ## _ ## fmt ## _ngle, \ | ||
505 | + gen_op_cmp ## type ## _ ## fmt ## _seq, \ | ||
506 | + gen_op_cmp ## type ## _ ## fmt ## _ngl, \ | ||
507 | + gen_op_cmp ## type ## _ ## fmt ## _lt, \ | ||
508 | + gen_op_cmp ## type ## _ ## fmt ## _nge, \ | ||
509 | + gen_op_cmp ## type ## _ ## fmt ## _le, \ | ||
510 | + gen_op_cmp ## type ## _ ## fmt ## _ngt, \ | ||
511 | }; \ | 511 | }; \ |
512 | -static inline void gen_cmp_ ## fmt(int n, long cc) \ | 512 | +static inline void gen_cmp ## type ## _ ## fmt(int n, long cc) \ |
513 | { \ | 513 | { \ |
514 | - cond_ ## fmt ## _table[n](cc); \ | 514 | + cond ## type ## _ ## fmt ## _table[n](cc); \ |
515 | } | 515 | } |
516 | 516 | ||
517 | -FOP_CONDS(d) | ||
518 | -FOP_CONDS(s) | ||
519 | -FOP_CONDS(ps) | 517 | +FOP_CONDS(, d) |
518 | +FOP_CONDS(abs, d) | ||
519 | +FOP_CONDS(, s) | ||
520 | +FOP_CONDS(abs, s) | ||
521 | +FOP_CONDS(, ps) | ||
522 | +FOP_CONDS(abs, ps) | ||
520 | 523 | ||
521 | typedef struct DisasContext { | 524 | typedef struct DisasContext { |
522 | struct TranslationBlock *tb; | 525 | struct TranslationBlock *tb; |
@@ -4453,7 +4456,25 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, | @@ -4453,7 +4456,25 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, | ||
4453 | "c.le", | 4456 | "c.le", |
4454 | "c.ngt", | 4457 | "c.ngt", |
4455 | }; | 4458 | }; |
4456 | - int binary = 0; | 4459 | + const char *condnames_abs[] = { |
4460 | + "cabs.f", | ||
4461 | + "cabs.un", | ||
4462 | + "cabs.eq", | ||
4463 | + "cabs.ueq", | ||
4464 | + "cabs.olt", | ||
4465 | + "cabs.ult", | ||
4466 | + "cabs.ole", | ||
4467 | + "cabs.ule", | ||
4468 | + "cabs.sf", | ||
4469 | + "cabs.ngle", | ||
4470 | + "cabs.seq", | ||
4471 | + "cabs.ngl", | ||
4472 | + "cabs.lt", | ||
4473 | + "cabs.nge", | ||
4474 | + "cabs.le", | ||
4475 | + "cabs.ngt", | ||
4476 | + }; | ||
4477 | + enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP; | ||
4457 | uint32_t func = ctx->opcode & 0x3f; | 4478 | uint32_t func = ctx->opcode & 0x3f; |
4458 | 4479 | ||
4459 | switch (ctx->opcode & FOP(0x3f, 0x1f)) { | 4480 | switch (ctx->opcode & FOP(0x3f, 0x1f)) { |
@@ -4463,7 +4484,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, | @@ -4463,7 +4484,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, | ||
4463 | gen_op_float_add_s(); | 4484 | gen_op_float_add_s(); |
4464 | GEN_STORE_FTN_FREG(fd, WT2); | 4485 | GEN_STORE_FTN_FREG(fd, WT2); |
4465 | opn = "add.s"; | 4486 | opn = "add.s"; |
4466 | - binary = 1; | 4487 | + optype = BINOP; |
4467 | break; | 4488 | break; |
4468 | case FOP(1, 16): | 4489 | case FOP(1, 16): |
4469 | GEN_LOAD_FREG_FTN(WT0, fs); | 4490 | GEN_LOAD_FREG_FTN(WT0, fs); |
@@ -4471,7 +4492,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, | @@ -4471,7 +4492,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, | ||
4471 | gen_op_float_sub_s(); | 4492 | gen_op_float_sub_s(); |
4472 | GEN_STORE_FTN_FREG(fd, WT2); | 4493 | GEN_STORE_FTN_FREG(fd, WT2); |
4473 | opn = "sub.s"; | 4494 | opn = "sub.s"; |
4474 | - binary = 1; | 4495 | + optype = BINOP; |
4475 | break; | 4496 | break; |
4476 | case FOP(2, 16): | 4497 | case FOP(2, 16): |
4477 | GEN_LOAD_FREG_FTN(WT0, fs); | 4498 | GEN_LOAD_FREG_FTN(WT0, fs); |
@@ -4479,7 +4500,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, | @@ -4479,7 +4500,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, | ||
4479 | gen_op_float_mul_s(); | 4500 | gen_op_float_mul_s(); |
4480 | GEN_STORE_FTN_FREG(fd, WT2); | 4501 | GEN_STORE_FTN_FREG(fd, WT2); |
4481 | opn = "mul.s"; | 4502 | opn = "mul.s"; |
4482 | - binary = 1; | 4503 | + optype = BINOP; |
4483 | break; | 4504 | break; |
4484 | case FOP(3, 16): | 4505 | case FOP(3, 16): |
4485 | GEN_LOAD_FREG_FTN(WT0, fs); | 4506 | GEN_LOAD_FREG_FTN(WT0, fs); |
@@ -4487,7 +4508,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, | @@ -4487,7 +4508,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, | ||
4487 | gen_op_float_div_s(); | 4508 | gen_op_float_div_s(); |
4488 | GEN_STORE_FTN_FREG(fd, WT2); | 4509 | GEN_STORE_FTN_FREG(fd, WT2); |
4489 | opn = "div.s"; | 4510 | opn = "div.s"; |
4490 | - binary = 1; | 4511 | + optype = BINOP; |
4491 | break; | 4512 | break; |
4492 | case FOP(4, 16): | 4513 | case FOP(4, 16): |
4493 | GEN_LOAD_FREG_FTN(WT0, fs); | 4514 | GEN_LOAD_FREG_FTN(WT0, fs); |
@@ -4635,8 +4656,13 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, | @@ -4635,8 +4656,13 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, | ||
4635 | case FOP(63, 16): | 4656 | case FOP(63, 16): |
4636 | GEN_LOAD_FREG_FTN(WT0, fs); | 4657 | GEN_LOAD_FREG_FTN(WT0, fs); |
4637 | GEN_LOAD_FREG_FTN(WT1, ft); | 4658 | GEN_LOAD_FREG_FTN(WT1, ft); |
4638 | - gen_cmp_s(func-48, cc); | ||
4639 | - opn = condnames[func-48]; | 4659 | + if (ctx->opcode & (1 << 6)) { |
4660 | + gen_cmpabs_s(func-48, cc); | ||
4661 | + opn = condnames_abs[func-48]; | ||
4662 | + } else { | ||
4663 | + gen_cmp_s(func-48, cc); | ||
4664 | + opn = condnames[func-48]; | ||
4665 | + } | ||
4640 | break; | 4666 | break; |
4641 | case FOP(0, 17): | 4667 | case FOP(0, 17): |
4642 | CHECK_FR(ctx, fs | ft | fd); | 4668 | CHECK_FR(ctx, fs | ft | fd); |
@@ -4645,7 +4671,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, | @@ -4645,7 +4671,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, | ||
4645 | gen_op_float_add_d(); | 4671 | gen_op_float_add_d(); |
4646 | GEN_STORE_FTN_FREG(fd, DT2); | 4672 | GEN_STORE_FTN_FREG(fd, DT2); |
4647 | opn = "add.d"; | 4673 | opn = "add.d"; |
4648 | - binary = 1; | 4674 | + optype = BINOP; |
4649 | break; | 4675 | break; |
4650 | case FOP(1, 17): | 4676 | case FOP(1, 17): |
4651 | CHECK_FR(ctx, fs | ft | fd); | 4677 | CHECK_FR(ctx, fs | ft | fd); |
@@ -4654,7 +4680,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, | @@ -4654,7 +4680,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, | ||
4654 | gen_op_float_sub_d(); | 4680 | gen_op_float_sub_d(); |
4655 | GEN_STORE_FTN_FREG(fd, DT2); | 4681 | GEN_STORE_FTN_FREG(fd, DT2); |
4656 | opn = "sub.d"; | 4682 | opn = "sub.d"; |
4657 | - binary = 1; | 4683 | + optype = BINOP; |
4658 | break; | 4684 | break; |
4659 | case FOP(2, 17): | 4685 | case FOP(2, 17): |
4660 | CHECK_FR(ctx, fs | ft | fd); | 4686 | CHECK_FR(ctx, fs | ft | fd); |
@@ -4663,7 +4689,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, | @@ -4663,7 +4689,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, | ||
4663 | gen_op_float_mul_d(); | 4689 | gen_op_float_mul_d(); |
4664 | GEN_STORE_FTN_FREG(fd, DT2); | 4690 | GEN_STORE_FTN_FREG(fd, DT2); |
4665 | opn = "mul.d"; | 4691 | opn = "mul.d"; |
4666 | - binary = 1; | 4692 | + optype = BINOP; |
4667 | break; | 4693 | break; |
4668 | case FOP(3, 17): | 4694 | case FOP(3, 17): |
4669 | CHECK_FR(ctx, fs | ft | fd); | 4695 | CHECK_FR(ctx, fs | ft | fd); |
@@ -4672,7 +4698,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, | @@ -4672,7 +4698,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, | ||
4672 | gen_op_float_div_d(); | 4698 | gen_op_float_div_d(); |
4673 | GEN_STORE_FTN_FREG(fd, DT2); | 4699 | GEN_STORE_FTN_FREG(fd, DT2); |
4674 | opn = "div.d"; | 4700 | opn = "div.d"; |
4675 | - binary = 1; | 4701 | + optype = BINOP; |
4676 | break; | 4702 | break; |
4677 | case FOP(4, 17): | 4703 | case FOP(4, 17): |
4678 | CHECK_FR(ctx, fs | fd); | 4704 | CHECK_FR(ctx, fs | fd); |
@@ -4801,8 +4827,13 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, | @@ -4801,8 +4827,13 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, | ||
4801 | CHECK_FR(ctx, fs | ft); | 4827 | CHECK_FR(ctx, fs | ft); |
4802 | GEN_LOAD_FREG_FTN(DT0, fs); | 4828 | GEN_LOAD_FREG_FTN(DT0, fs); |
4803 | GEN_LOAD_FREG_FTN(DT1, ft); | 4829 | GEN_LOAD_FREG_FTN(DT1, ft); |
4804 | - gen_cmp_d(func-48, cc); | ||
4805 | - opn = condnames[func-48]; | 4830 | + if (ctx->opcode & (1 << 6)) { |
4831 | + gen_cmpabs_d(func-48, cc); | ||
4832 | + opn = condnames_abs[func-48]; | ||
4833 | + } else { | ||
4834 | + gen_cmp_d(func-48, cc); | ||
4835 | + opn = condnames[func-48]; | ||
4836 | + } | ||
4806 | break; | 4837 | break; |
4807 | case FOP(32, 17): | 4838 | case FOP(32, 17): |
4808 | CHECK_FR(ctx, fs); | 4839 | CHECK_FR(ctx, fs); |
@@ -5042,18 +5073,30 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, | @@ -5042,18 +5073,30 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, | ||
5042 | GEN_LOAD_FREG_FTN(WTH0, fs); | 5073 | GEN_LOAD_FREG_FTN(WTH0, fs); |
5043 | GEN_LOAD_FREG_FTN(WT1, ft); | 5074 | GEN_LOAD_FREG_FTN(WT1, ft); |
5044 | GEN_LOAD_FREG_FTN(WTH1, ft); | 5075 | GEN_LOAD_FREG_FTN(WTH1, ft); |
5045 | - gen_cmp_ps(func-48, cc); | ||
5046 | - opn = condnames[func-48]; | 5076 | + if (ctx->opcode & (1 << 6)) { |
5077 | + gen_cmpabs_ps(func-48, cc); | ||
5078 | + opn = condnames_abs[func-48]; | ||
5079 | + } else { | ||
5080 | + gen_cmp_ps(func-48, cc); | ||
5081 | + opn = condnames[func-48]; | ||
5082 | + } | ||
5047 | break; | 5083 | break; |
5048 | default: | 5084 | default: |
5049 | MIPS_INVAL(opn); | 5085 | MIPS_INVAL(opn); |
5050 | generate_exception (ctx, EXCP_RI); | 5086 | generate_exception (ctx, EXCP_RI); |
5051 | return; | 5087 | return; |
5052 | } | 5088 | } |
5053 | - if (binary) | 5089 | + switch (optype) { |
5090 | + case BINOP: | ||
5054 | MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]); | 5091 | MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]); |
5055 | - else | 5092 | + break; |
5093 | + case CMPOP: | ||
5094 | + MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]); | ||
5095 | + break; | ||
5096 | + default: | ||
5056 | MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]); | 5097 | MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]); |
5098 | + break; | ||
5099 | + } | ||
5057 | } | 5100 | } |
5058 | 5101 | ||
5059 | /* Coprocessor 3 (FPU) */ | 5102 | /* Coprocessor 3 (FPU) */ |