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) */ |