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