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 | 1965 | set_float_rounding_mode(float_round_nearest_even, &env->fp_status); |
| 1966 | 1966 | DT2 = float64_round_to_int(FDT0, &env->fp_status); |
| 1967 | 1967 | RESTORE_ROUNDING_MODE; |
| 1968 | + update_fcr31(); | |
| 1969 | + if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 1970 | + DT2 = 0x7fffffffffffffffULL; | |
| 1968 | 1971 | DEBUG_FPU_STATE(); |
| 1969 | 1972 | RETURN(); |
| 1970 | 1973 | } |
| ... | ... | @@ -1973,6 +1976,9 @@ FLOAT_OP(roundl, s) |
| 1973 | 1976 | set_float_rounding_mode(float_round_nearest_even, &env->fp_status); |
| 1974 | 1977 | DT2 = float32_round_to_int(FST0, &env->fp_status); |
| 1975 | 1978 | RESTORE_ROUNDING_MODE; |
| 1979 | + update_fcr31(); | |
| 1980 | + if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 1981 | + DT2 = 0x7fffffffffffffffULL; | |
| 1976 | 1982 | DEBUG_FPU_STATE(); |
| 1977 | 1983 | RETURN(); |
| 1978 | 1984 | } |
| ... | ... | @@ -1981,6 +1987,9 @@ FLOAT_OP(roundw, d) |
| 1981 | 1987 | set_float_rounding_mode(float_round_nearest_even, &env->fp_status); |
| 1982 | 1988 | WT2 = float64_round_to_int(FDT0, &env->fp_status); |
| 1983 | 1989 | RESTORE_ROUNDING_MODE; |
| 1990 | + update_fcr31(); | |
| 1991 | + if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 1992 | + WT2 = 0x7fffffff; | |
| 1984 | 1993 | DEBUG_FPU_STATE(); |
| 1985 | 1994 | RETURN(); |
| 1986 | 1995 | } |
| ... | ... | @@ -1989,6 +1998,9 @@ FLOAT_OP(roundw, s) |
| 1989 | 1998 | set_float_rounding_mode(float_round_nearest_even, &env->fp_status); |
| 1990 | 1999 | WT2 = float32_round_to_int(FST0, &env->fp_status); |
| 1991 | 2000 | RESTORE_ROUNDING_MODE; |
| 2001 | + update_fcr31(); | |
| 2002 | + if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 2003 | + WT2 = 0x7fffffff; | |
| 1992 | 2004 | DEBUG_FPU_STATE(); |
| 1993 | 2005 | RETURN(); |
| 1994 | 2006 | } |
| ... | ... | @@ -1996,24 +2008,36 @@ FLOAT_OP(roundw, s) |
| 1996 | 2008 | FLOAT_OP(truncl, d) |
| 1997 | 2009 | { |
| 1998 | 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 | 2014 | DEBUG_FPU_STATE(); |
| 2000 | 2015 | RETURN(); |
| 2001 | 2016 | } |
| 2002 | 2017 | FLOAT_OP(truncl, s) |
| 2003 | 2018 | { |
| 2004 | 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 | 2023 | DEBUG_FPU_STATE(); |
| 2006 | 2024 | RETURN(); |
| 2007 | 2025 | } |
| 2008 | 2026 | FLOAT_OP(truncw, d) |
| 2009 | 2027 | { |
| 2010 | 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 | 2032 | DEBUG_FPU_STATE(); |
| 2012 | 2033 | RETURN(); |
| 2013 | 2034 | } |
| 2014 | 2035 | FLOAT_OP(truncw, s) |
| 2015 | 2036 | { |
| 2016 | 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 | 2041 | DEBUG_FPU_STATE(); |
| 2018 | 2042 | RETURN(); |
| 2019 | 2043 | } |
| ... | ... | @@ -2023,6 +2047,9 @@ FLOAT_OP(ceill, d) |
| 2023 | 2047 | set_float_rounding_mode(float_round_up, &env->fp_status); |
| 2024 | 2048 | DT2 = float64_round_to_int(FDT0, &env->fp_status); |
| 2025 | 2049 | RESTORE_ROUNDING_MODE; |
| 2050 | + update_fcr31(); | |
| 2051 | + if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 2052 | + DT2 = 0x7fffffffffffffffULL; | |
| 2026 | 2053 | DEBUG_FPU_STATE(); |
| 2027 | 2054 | RETURN(); |
| 2028 | 2055 | } |
| ... | ... | @@ -2031,6 +2058,9 @@ FLOAT_OP(ceill, s) |
| 2031 | 2058 | set_float_rounding_mode(float_round_up, &env->fp_status); |
| 2032 | 2059 | DT2 = float32_round_to_int(FST0, &env->fp_status); |
| 2033 | 2060 | RESTORE_ROUNDING_MODE; |
| 2061 | + update_fcr31(); | |
| 2062 | + if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 2063 | + DT2 = 0x7fffffffffffffffULL; | |
| 2034 | 2064 | DEBUG_FPU_STATE(); |
| 2035 | 2065 | RETURN(); |
| 2036 | 2066 | } |
| ... | ... | @@ -2039,6 +2069,9 @@ FLOAT_OP(ceilw, d) |
| 2039 | 2069 | set_float_rounding_mode(float_round_up, &env->fp_status); |
| 2040 | 2070 | WT2 = float64_round_to_int(FDT0, &env->fp_status); |
| 2041 | 2071 | RESTORE_ROUNDING_MODE; |
| 2072 | + update_fcr31(); | |
| 2073 | + if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 2074 | + WT2 = 0x7fffffff; | |
| 2042 | 2075 | DEBUG_FPU_STATE(); |
| 2043 | 2076 | RETURN(); |
| 2044 | 2077 | } |
| ... | ... | @@ -2047,6 +2080,9 @@ FLOAT_OP(ceilw, s) |
| 2047 | 2080 | set_float_rounding_mode(float_round_up, &env->fp_status); |
| 2048 | 2081 | WT2 = float32_round_to_int(FST0, &env->fp_status); |
| 2049 | 2082 | RESTORE_ROUNDING_MODE; |
| 2083 | + update_fcr31(); | |
| 2084 | + if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 2085 | + WT2 = 0x7fffffff; | |
| 2050 | 2086 | DEBUG_FPU_STATE(); |
| 2051 | 2087 | RETURN(); |
| 2052 | 2088 | } |
| ... | ... | @@ -2056,6 +2092,9 @@ FLOAT_OP(floorl, d) |
| 2056 | 2092 | set_float_rounding_mode(float_round_down, &env->fp_status); |
| 2057 | 2093 | DT2 = float64_round_to_int(FDT0, &env->fp_status); |
| 2058 | 2094 | RESTORE_ROUNDING_MODE; |
| 2095 | + update_fcr31(); | |
| 2096 | + if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 2097 | + DT2 = 0x7fffffffffffffffULL; | |
| 2059 | 2098 | DEBUG_FPU_STATE(); |
| 2060 | 2099 | RETURN(); |
| 2061 | 2100 | } |
| ... | ... | @@ -2064,6 +2103,9 @@ FLOAT_OP(floorl, s) |
| 2064 | 2103 | set_float_rounding_mode(float_round_down, &env->fp_status); |
| 2065 | 2104 | DT2 = float32_round_to_int(FST0, &env->fp_status); |
| 2066 | 2105 | RESTORE_ROUNDING_MODE; |
| 2106 | + update_fcr31(); | |
| 2107 | + if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 2108 | + DT2 = 0x7fffffffffffffffULL; | |
| 2067 | 2109 | DEBUG_FPU_STATE(); |
| 2068 | 2110 | RETURN(); |
| 2069 | 2111 | } |
| ... | ... | @@ -2072,6 +2114,9 @@ FLOAT_OP(floorw, d) |
| 2072 | 2114 | set_float_rounding_mode(float_round_down, &env->fp_status); |
| 2073 | 2115 | WT2 = float64_round_to_int(FDT0, &env->fp_status); |
| 2074 | 2116 | RESTORE_ROUNDING_MODE; |
| 2117 | + update_fcr31(); | |
| 2118 | + if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 2119 | + WT2 = 0x7fffffff; | |
| 2075 | 2120 | DEBUG_FPU_STATE(); |
| 2076 | 2121 | RETURN(); |
| 2077 | 2122 | } |
| ... | ... | @@ -2080,6 +2125,9 @@ FLOAT_OP(floorw, s) |
| 2080 | 2125 | set_float_rounding_mode(float_round_down, &env->fp_status); |
| 2081 | 2126 | WT2 = float32_round_to_int(FST0, &env->fp_status); |
| 2082 | 2127 | RESTORE_ROUNDING_MODE; |
| 2128 | + update_fcr31(); | |
| 2129 | + if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID)) | |
| 2130 | + WT2 = 0x7fffffff; | |
| 2083 | 2131 | DEBUG_FPU_STATE(); |
| 2084 | 2132 | RETURN(); |
| 2085 | 2133 | } |
| ... | ... | @@ -2396,6 +2444,20 @@ void op_cmp_d_ ## op (void) \ |
| 2396 | 2444 | CLEAR_FP_COND(PARAM1, env); \ |
| 2397 | 2445 | DEBUG_FPU_STATE(); \ |
| 2398 | 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 | 2463 | int float64_is_unordered(int sig, float64 a, float64 b STATUS_PARAM) |
| ... | ... | @@ -2444,6 +2506,20 @@ void op_cmp_s_ ## op (void) \ |
| 2444 | 2506 | CLEAR_FP_COND(PARAM1, env); \ |
| 2445 | 2507 | DEBUG_FPU_STATE(); \ |
| 2446 | 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 | 2525 | flag float32_is_unordered(int sig, float32 a, float32 b STATUS_PARAM) |
| ... | ... | @@ -2498,6 +2574,27 @@ void op_cmp_ps_ ## op (void) \ |
| 2498 | 2574 | CLEAR_FP_COND(PARAM1 + 1, env); \ |
| 2499 | 2575 | DEBUG_FPU_STATE(); \ |
| 2500 | 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 | 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 | 490 | FGEN32(gen_op_load_fpr_WTH2, gen_op_load_fpr_WTH2_fpr); |
| 491 | 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 | 524 | typedef struct DisasContext { |
| 522 | 525 | struct TranslationBlock *tb; |
| ... | ... | @@ -4453,7 +4456,25 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, |
| 4453 | 4456 | "c.le", |
| 4454 | 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 | 4478 | uint32_t func = ctx->opcode & 0x3f; |
| 4458 | 4479 | |
| 4459 | 4480 | switch (ctx->opcode & FOP(0x3f, 0x1f)) { |
| ... | ... | @@ -4463,7 +4484,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, |
| 4463 | 4484 | gen_op_float_add_s(); |
| 4464 | 4485 | GEN_STORE_FTN_FREG(fd, WT2); |
| 4465 | 4486 | opn = "add.s"; |
| 4466 | - binary = 1; | |
| 4487 | + optype = BINOP; | |
| 4467 | 4488 | break; |
| 4468 | 4489 | case FOP(1, 16): |
| 4469 | 4490 | GEN_LOAD_FREG_FTN(WT0, fs); |
| ... | ... | @@ -4471,7 +4492,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, |
| 4471 | 4492 | gen_op_float_sub_s(); |
| 4472 | 4493 | GEN_STORE_FTN_FREG(fd, WT2); |
| 4473 | 4494 | opn = "sub.s"; |
| 4474 | - binary = 1; | |
| 4495 | + optype = BINOP; | |
| 4475 | 4496 | break; |
| 4476 | 4497 | case FOP(2, 16): |
| 4477 | 4498 | GEN_LOAD_FREG_FTN(WT0, fs); |
| ... | ... | @@ -4479,7 +4500,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, |
| 4479 | 4500 | gen_op_float_mul_s(); |
| 4480 | 4501 | GEN_STORE_FTN_FREG(fd, WT2); |
| 4481 | 4502 | opn = "mul.s"; |
| 4482 | - binary = 1; | |
| 4503 | + optype = BINOP; | |
| 4483 | 4504 | break; |
| 4484 | 4505 | case FOP(3, 16): |
| 4485 | 4506 | GEN_LOAD_FREG_FTN(WT0, fs); |
| ... | ... | @@ -4487,7 +4508,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, |
| 4487 | 4508 | gen_op_float_div_s(); |
| 4488 | 4509 | GEN_STORE_FTN_FREG(fd, WT2); |
| 4489 | 4510 | opn = "div.s"; |
| 4490 | - binary = 1; | |
| 4511 | + optype = BINOP; | |
| 4491 | 4512 | break; |
| 4492 | 4513 | case FOP(4, 16): |
| 4493 | 4514 | GEN_LOAD_FREG_FTN(WT0, fs); |
| ... | ... | @@ -4635,8 +4656,13 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, |
| 4635 | 4656 | case FOP(63, 16): |
| 4636 | 4657 | GEN_LOAD_FREG_FTN(WT0, fs); |
| 4637 | 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 | 4666 | break; |
| 4641 | 4667 | case FOP(0, 17): |
| 4642 | 4668 | CHECK_FR(ctx, fs | ft | fd); |
| ... | ... | @@ -4645,7 +4671,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, |
| 4645 | 4671 | gen_op_float_add_d(); |
| 4646 | 4672 | GEN_STORE_FTN_FREG(fd, DT2); |
| 4647 | 4673 | opn = "add.d"; |
| 4648 | - binary = 1; | |
| 4674 | + optype = BINOP; | |
| 4649 | 4675 | break; |
| 4650 | 4676 | case FOP(1, 17): |
| 4651 | 4677 | CHECK_FR(ctx, fs | ft | fd); |
| ... | ... | @@ -4654,7 +4680,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, |
| 4654 | 4680 | gen_op_float_sub_d(); |
| 4655 | 4681 | GEN_STORE_FTN_FREG(fd, DT2); |
| 4656 | 4682 | opn = "sub.d"; |
| 4657 | - binary = 1; | |
| 4683 | + optype = BINOP; | |
| 4658 | 4684 | break; |
| 4659 | 4685 | case FOP(2, 17): |
| 4660 | 4686 | CHECK_FR(ctx, fs | ft | fd); |
| ... | ... | @@ -4663,7 +4689,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, |
| 4663 | 4689 | gen_op_float_mul_d(); |
| 4664 | 4690 | GEN_STORE_FTN_FREG(fd, DT2); |
| 4665 | 4691 | opn = "mul.d"; |
| 4666 | - binary = 1; | |
| 4692 | + optype = BINOP; | |
| 4667 | 4693 | break; |
| 4668 | 4694 | case FOP(3, 17): |
| 4669 | 4695 | CHECK_FR(ctx, fs | ft | fd); |
| ... | ... | @@ -4672,7 +4698,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, |
| 4672 | 4698 | gen_op_float_div_d(); |
| 4673 | 4699 | GEN_STORE_FTN_FREG(fd, DT2); |
| 4674 | 4700 | opn = "div.d"; |
| 4675 | - binary = 1; | |
| 4701 | + optype = BINOP; | |
| 4676 | 4702 | break; |
| 4677 | 4703 | case FOP(4, 17): |
| 4678 | 4704 | CHECK_FR(ctx, fs | fd); |
| ... | ... | @@ -4801,8 +4827,13 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, |
| 4801 | 4827 | CHECK_FR(ctx, fs | ft); |
| 4802 | 4828 | GEN_LOAD_FREG_FTN(DT0, fs); |
| 4803 | 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 | 4837 | break; |
| 4807 | 4838 | case FOP(32, 17): |
| 4808 | 4839 | CHECK_FR(ctx, fs); |
| ... | ... | @@ -5042,18 +5073,30 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, |
| 5042 | 5073 | GEN_LOAD_FREG_FTN(WTH0, fs); |
| 5043 | 5074 | GEN_LOAD_FREG_FTN(WT1, ft); |
| 5044 | 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 | 5083 | break; |
| 5048 | 5084 | default: |
| 5049 | 5085 | MIPS_INVAL(opn); |
| 5050 | 5086 | generate_exception (ctx, EXCP_RI); |
| 5051 | 5087 | return; |
| 5052 | 5088 | } |
| 5053 | - if (binary) | |
| 5089 | + switch (optype) { | |
| 5090 | + case BINOP: | |
| 5054 | 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 | 5097 | MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]); |
| 5098 | + break; | |
| 5099 | + } | |
| 5057 | 5100 | } |
| 5058 | 5101 | |
| 5059 | 5102 | /* Coprocessor 3 (FPU) */ | ... | ... |