Loading target-mips/op.c +97 −0 Original line number Diff line number Diff line Loading @@ -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(); } Loading @@ -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(); } Loading @@ -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(); } Loading @@ -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(); } Loading @@ -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(); } Loading @@ -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(); } Loading @@ -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(); } Loading @@ -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(); } Loading @@ -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(); } Loading @@ -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(); } Loading @@ -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(); } Loading @@ -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(); } Loading @@ -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(); } Loading Loading @@ -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) Loading Loading @@ -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) Loading Loading @@ -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, Loading target-mips/translate.c +83 −40 Original line number Diff line number Diff line Loading @@ -490,33 +490,36 @@ FGEN32(gen_op_store_fpr_WTH1, gen_op_store_fpr_WTH1_fpr); FGEN32(gen_op_load_fpr_WTH2, gen_op_load_fpr_WTH2_fpr); FGEN32(gen_op_store_fpr_WTH2, gen_op_store_fpr_WTH2_fpr); #define FOP_CONDS(fmt) \ static GenOpFunc1 * cond_ ## fmt ## _table[16] = { \ gen_op_cmp_ ## fmt ## _f, \ gen_op_cmp_ ## fmt ## _un, \ gen_op_cmp_ ## fmt ## _eq, \ gen_op_cmp_ ## fmt ## _ueq, \ gen_op_cmp_ ## fmt ## _olt, \ gen_op_cmp_ ## fmt ## _ult, \ gen_op_cmp_ ## fmt ## _ole, \ gen_op_cmp_ ## fmt ## _ule, \ gen_op_cmp_ ## fmt ## _sf, \ gen_op_cmp_ ## fmt ## _ngle, \ gen_op_cmp_ ## fmt ## _seq, \ gen_op_cmp_ ## fmt ## _ngl, \ gen_op_cmp_ ## fmt ## _lt, \ gen_op_cmp_ ## fmt ## _nge, \ gen_op_cmp_ ## fmt ## _le, \ gen_op_cmp_ ## fmt ## _ngt, \ #define FOP_CONDS(type, fmt) \ static GenOpFunc1 * cond ## type ## _ ## fmt ## _table[16] = { \ gen_op_cmp ## type ## _ ## fmt ## _f, \ gen_op_cmp ## type ## _ ## fmt ## _un, \ gen_op_cmp ## type ## _ ## fmt ## _eq, \ gen_op_cmp ## type ## _ ## fmt ## _ueq, \ gen_op_cmp ## type ## _ ## fmt ## _olt, \ gen_op_cmp ## type ## _ ## fmt ## _ult, \ gen_op_cmp ## type ## _ ## fmt ## _ole, \ gen_op_cmp ## type ## _ ## fmt ## _ule, \ gen_op_cmp ## type ## _ ## fmt ## _sf, \ gen_op_cmp ## type ## _ ## fmt ## _ngle, \ gen_op_cmp ## type ## _ ## fmt ## _seq, \ gen_op_cmp ## type ## _ ## fmt ## _ngl, \ gen_op_cmp ## type ## _ ## fmt ## _lt, \ gen_op_cmp ## type ## _ ## fmt ## _nge, \ gen_op_cmp ## type ## _ ## fmt ## _le, \ gen_op_cmp ## type ## _ ## fmt ## _ngt, \ }; \ static inline void gen_cmp_ ## fmt(int n, long cc) \ static inline void gen_cmp ## type ## _ ## fmt(int n, long cc) \ { \ cond_ ## fmt ## _table[n](cc); \ cond ## type ## _ ## fmt ## _table[n](cc); \ } FOP_CONDS(d) FOP_CONDS(s) FOP_CONDS(ps) FOP_CONDS(, d) FOP_CONDS(abs, d) FOP_CONDS(, s) FOP_CONDS(abs, s) FOP_CONDS(, ps) FOP_CONDS(abs, ps) typedef struct DisasContext { struct TranslationBlock *tb; Loading Loading @@ -4453,7 +4456,25 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, "c.le", "c.ngt", }; int binary = 0; const char *condnames_abs[] = { "cabs.f", "cabs.un", "cabs.eq", "cabs.ueq", "cabs.olt", "cabs.ult", "cabs.ole", "cabs.ule", "cabs.sf", "cabs.ngle", "cabs.seq", "cabs.ngl", "cabs.lt", "cabs.nge", "cabs.le", "cabs.ngt", }; enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP; uint32_t func = ctx->opcode & 0x3f; switch (ctx->opcode & FOP(0x3f, 0x1f)) { Loading @@ -4463,7 +4484,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, gen_op_float_add_s(); GEN_STORE_FTN_FREG(fd, WT2); opn = "add.s"; binary = 1; optype = BINOP; break; case FOP(1, 16): GEN_LOAD_FREG_FTN(WT0, fs); Loading @@ -4471,7 +4492,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, gen_op_float_sub_s(); GEN_STORE_FTN_FREG(fd, WT2); opn = "sub.s"; binary = 1; optype = BINOP; break; case FOP(2, 16): GEN_LOAD_FREG_FTN(WT0, fs); Loading @@ -4479,7 +4500,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, gen_op_float_mul_s(); GEN_STORE_FTN_FREG(fd, WT2); opn = "mul.s"; binary = 1; optype = BINOP; break; case FOP(3, 16): GEN_LOAD_FREG_FTN(WT0, fs); Loading @@ -4487,7 +4508,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, gen_op_float_div_s(); GEN_STORE_FTN_FREG(fd, WT2); opn = "div.s"; binary = 1; optype = BINOP; break; case FOP(4, 16): GEN_LOAD_FREG_FTN(WT0, fs); Loading Loading @@ -4635,8 +4656,13 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, case FOP(63, 16): GEN_LOAD_FREG_FTN(WT0, fs); GEN_LOAD_FREG_FTN(WT1, ft); if (ctx->opcode & (1 << 6)) { gen_cmpabs_s(func-48, cc); opn = condnames_abs[func-48]; } else { gen_cmp_s(func-48, cc); opn = condnames[func-48]; } break; case FOP(0, 17): CHECK_FR(ctx, fs | ft | fd); Loading @@ -4645,7 +4671,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, gen_op_float_add_d(); GEN_STORE_FTN_FREG(fd, DT2); opn = "add.d"; binary = 1; optype = BINOP; break; case FOP(1, 17): CHECK_FR(ctx, fs | ft | fd); Loading @@ -4654,7 +4680,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, gen_op_float_sub_d(); GEN_STORE_FTN_FREG(fd, DT2); opn = "sub.d"; binary = 1; optype = BINOP; break; case FOP(2, 17): CHECK_FR(ctx, fs | ft | fd); Loading @@ -4663,7 +4689,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, gen_op_float_mul_d(); GEN_STORE_FTN_FREG(fd, DT2); opn = "mul.d"; binary = 1; optype = BINOP; break; case FOP(3, 17): CHECK_FR(ctx, fs | ft | fd); Loading @@ -4672,7 +4698,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, gen_op_float_div_d(); GEN_STORE_FTN_FREG(fd, DT2); opn = "div.d"; binary = 1; optype = BINOP; break; case FOP(4, 17): CHECK_FR(ctx, fs | fd); Loading Loading @@ -4801,8 +4827,13 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, CHECK_FR(ctx, fs | ft); GEN_LOAD_FREG_FTN(DT0, fs); GEN_LOAD_FREG_FTN(DT1, ft); if (ctx->opcode & (1 << 6)) { gen_cmpabs_d(func-48, cc); opn = condnames_abs[func-48]; } else { gen_cmp_d(func-48, cc); opn = condnames[func-48]; } break; case FOP(32, 17): CHECK_FR(ctx, fs); Loading Loading @@ -5042,18 +5073,30 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, GEN_LOAD_FREG_FTN(WTH0, fs); GEN_LOAD_FREG_FTN(WT1, ft); GEN_LOAD_FREG_FTN(WTH1, ft); if (ctx->opcode & (1 << 6)) { gen_cmpabs_ps(func-48, cc); opn = condnames_abs[func-48]; } else { gen_cmp_ps(func-48, cc); opn = condnames[func-48]; } break; default: MIPS_INVAL(opn); generate_exception (ctx, EXCP_RI); return; } if (binary) switch (optype) { case BINOP: MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]); else break; case CMPOP: MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]); break; default: MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]); break; } } /* Coprocessor 3 (FPU) */ Loading Loading
target-mips/op.c +97 −0 Original line number Diff line number Diff line Loading @@ -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(); } Loading @@ -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(); } Loading @@ -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(); } Loading @@ -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(); } Loading @@ -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(); } Loading @@ -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(); } Loading @@ -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(); } Loading @@ -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(); } Loading @@ -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(); } Loading @@ -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(); } Loading @@ -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(); } Loading @@ -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(); } Loading @@ -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(); } Loading Loading @@ -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) Loading Loading @@ -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) Loading Loading @@ -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, Loading
target-mips/translate.c +83 −40 Original line number Diff line number Diff line Loading @@ -490,33 +490,36 @@ FGEN32(gen_op_store_fpr_WTH1, gen_op_store_fpr_WTH1_fpr); FGEN32(gen_op_load_fpr_WTH2, gen_op_load_fpr_WTH2_fpr); FGEN32(gen_op_store_fpr_WTH2, gen_op_store_fpr_WTH2_fpr); #define FOP_CONDS(fmt) \ static GenOpFunc1 * cond_ ## fmt ## _table[16] = { \ gen_op_cmp_ ## fmt ## _f, \ gen_op_cmp_ ## fmt ## _un, \ gen_op_cmp_ ## fmt ## _eq, \ gen_op_cmp_ ## fmt ## _ueq, \ gen_op_cmp_ ## fmt ## _olt, \ gen_op_cmp_ ## fmt ## _ult, \ gen_op_cmp_ ## fmt ## _ole, \ gen_op_cmp_ ## fmt ## _ule, \ gen_op_cmp_ ## fmt ## _sf, \ gen_op_cmp_ ## fmt ## _ngle, \ gen_op_cmp_ ## fmt ## _seq, \ gen_op_cmp_ ## fmt ## _ngl, \ gen_op_cmp_ ## fmt ## _lt, \ gen_op_cmp_ ## fmt ## _nge, \ gen_op_cmp_ ## fmt ## _le, \ gen_op_cmp_ ## fmt ## _ngt, \ #define FOP_CONDS(type, fmt) \ static GenOpFunc1 * cond ## type ## _ ## fmt ## _table[16] = { \ gen_op_cmp ## type ## _ ## fmt ## _f, \ gen_op_cmp ## type ## _ ## fmt ## _un, \ gen_op_cmp ## type ## _ ## fmt ## _eq, \ gen_op_cmp ## type ## _ ## fmt ## _ueq, \ gen_op_cmp ## type ## _ ## fmt ## _olt, \ gen_op_cmp ## type ## _ ## fmt ## _ult, \ gen_op_cmp ## type ## _ ## fmt ## _ole, \ gen_op_cmp ## type ## _ ## fmt ## _ule, \ gen_op_cmp ## type ## _ ## fmt ## _sf, \ gen_op_cmp ## type ## _ ## fmt ## _ngle, \ gen_op_cmp ## type ## _ ## fmt ## _seq, \ gen_op_cmp ## type ## _ ## fmt ## _ngl, \ gen_op_cmp ## type ## _ ## fmt ## _lt, \ gen_op_cmp ## type ## _ ## fmt ## _nge, \ gen_op_cmp ## type ## _ ## fmt ## _le, \ gen_op_cmp ## type ## _ ## fmt ## _ngt, \ }; \ static inline void gen_cmp_ ## fmt(int n, long cc) \ static inline void gen_cmp ## type ## _ ## fmt(int n, long cc) \ { \ cond_ ## fmt ## _table[n](cc); \ cond ## type ## _ ## fmt ## _table[n](cc); \ } FOP_CONDS(d) FOP_CONDS(s) FOP_CONDS(ps) FOP_CONDS(, d) FOP_CONDS(abs, d) FOP_CONDS(, s) FOP_CONDS(abs, s) FOP_CONDS(, ps) FOP_CONDS(abs, ps) typedef struct DisasContext { struct TranslationBlock *tb; Loading Loading @@ -4453,7 +4456,25 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, "c.le", "c.ngt", }; int binary = 0; const char *condnames_abs[] = { "cabs.f", "cabs.un", "cabs.eq", "cabs.ueq", "cabs.olt", "cabs.ult", "cabs.ole", "cabs.ule", "cabs.sf", "cabs.ngle", "cabs.seq", "cabs.ngl", "cabs.lt", "cabs.nge", "cabs.le", "cabs.ngt", }; enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP; uint32_t func = ctx->opcode & 0x3f; switch (ctx->opcode & FOP(0x3f, 0x1f)) { Loading @@ -4463,7 +4484,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, gen_op_float_add_s(); GEN_STORE_FTN_FREG(fd, WT2); opn = "add.s"; binary = 1; optype = BINOP; break; case FOP(1, 16): GEN_LOAD_FREG_FTN(WT0, fs); Loading @@ -4471,7 +4492,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, gen_op_float_sub_s(); GEN_STORE_FTN_FREG(fd, WT2); opn = "sub.s"; binary = 1; optype = BINOP; break; case FOP(2, 16): GEN_LOAD_FREG_FTN(WT0, fs); Loading @@ -4479,7 +4500,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, gen_op_float_mul_s(); GEN_STORE_FTN_FREG(fd, WT2); opn = "mul.s"; binary = 1; optype = BINOP; break; case FOP(3, 16): GEN_LOAD_FREG_FTN(WT0, fs); Loading @@ -4487,7 +4508,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, gen_op_float_div_s(); GEN_STORE_FTN_FREG(fd, WT2); opn = "div.s"; binary = 1; optype = BINOP; break; case FOP(4, 16): GEN_LOAD_FREG_FTN(WT0, fs); Loading Loading @@ -4635,8 +4656,13 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, case FOP(63, 16): GEN_LOAD_FREG_FTN(WT0, fs); GEN_LOAD_FREG_FTN(WT1, ft); if (ctx->opcode & (1 << 6)) { gen_cmpabs_s(func-48, cc); opn = condnames_abs[func-48]; } else { gen_cmp_s(func-48, cc); opn = condnames[func-48]; } break; case FOP(0, 17): CHECK_FR(ctx, fs | ft | fd); Loading @@ -4645,7 +4671,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, gen_op_float_add_d(); GEN_STORE_FTN_FREG(fd, DT2); opn = "add.d"; binary = 1; optype = BINOP; break; case FOP(1, 17): CHECK_FR(ctx, fs | ft | fd); Loading @@ -4654,7 +4680,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, gen_op_float_sub_d(); GEN_STORE_FTN_FREG(fd, DT2); opn = "sub.d"; binary = 1; optype = BINOP; break; case FOP(2, 17): CHECK_FR(ctx, fs | ft | fd); Loading @@ -4663,7 +4689,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, gen_op_float_mul_d(); GEN_STORE_FTN_FREG(fd, DT2); opn = "mul.d"; binary = 1; optype = BINOP; break; case FOP(3, 17): CHECK_FR(ctx, fs | ft | fd); Loading @@ -4672,7 +4698,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, gen_op_float_div_d(); GEN_STORE_FTN_FREG(fd, DT2); opn = "div.d"; binary = 1; optype = BINOP; break; case FOP(4, 17): CHECK_FR(ctx, fs | fd); Loading Loading @@ -4801,8 +4827,13 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, CHECK_FR(ctx, fs | ft); GEN_LOAD_FREG_FTN(DT0, fs); GEN_LOAD_FREG_FTN(DT1, ft); if (ctx->opcode & (1 << 6)) { gen_cmpabs_d(func-48, cc); opn = condnames_abs[func-48]; } else { gen_cmp_d(func-48, cc); opn = condnames[func-48]; } break; case FOP(32, 17): CHECK_FR(ctx, fs); Loading Loading @@ -5042,18 +5073,30 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, GEN_LOAD_FREG_FTN(WTH0, fs); GEN_LOAD_FREG_FTN(WT1, ft); GEN_LOAD_FREG_FTN(WTH1, ft); if (ctx->opcode & (1 << 6)) { gen_cmpabs_ps(func-48, cc); opn = condnames_abs[func-48]; } else { gen_cmp_ps(func-48, cc); opn = condnames[func-48]; } break; default: MIPS_INVAL(opn); generate_exception (ctx, EXCP_RI); return; } if (binary) switch (optype) { case BINOP: MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]); else break; case CMPOP: MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]); break; default: MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]); break; } } /* Coprocessor 3 (FPU) */ Loading