On 03/31/2016 04:55 AM, Aleksandar Markovic wrote: > Hi, Richard, what would you think about this approach: > > Functionality of <ABS|NEG>.<S|D> and <CVT|FLOOR|CEIL|TRUNC|ROUND>.<L|W>.<S|D> > instructions is dependent on flags ABS2008 and NAN2008 in FCR31. There are > MIPS architectures (for example mips32r5) that allow implementations > with different values of these flags. So, in order to detect the desired > behavior in translate-time, insn_flags field can't be used - and, therefore, > it makes sense to add two new members to the MIPS's DisasContext: > > typedef struct DisasContext { > . . . > bool nan2008; > bool abs2008; > } DisasContext; > > Their initialization could be in gen_intermediate_code_internal(): > > ctx.nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1; > ctx.abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1; > > Now, ABS.D (and all <ABS|NEG>.<S|D>) handling might look like this: > > case OPC_ABS_D: > check_cp1_registers(ctx, fs | fd); > { > TCGv_i64 fp0 = tcg_temp_new_i64(); > > gen_load_fpr64(ctx, fp0, fs); > if (ctx->abs2008) { > tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL); > } else { > gen_helper_float_abs_d(fp0, fp0); > } > gen_store_fpr64(ctx, fp0, fd); > tcg_temp_free_i64(fp0); > } > opn = "abs.d"; > break; > > Here, 2008-style ABS.D is implemented inline, without a helper, and > gen_helper_float_abs_d() is an old pre-2008 helper that would be intact > (the same as it is currently) with this change.
Yes, that's exactly what I had in mind. > On the other hand, CVT.L.D (and all <CVT|FLOOR|CEIL|TRUNC|ROUND>.<L|W>.<S|D>) > handling would take this form: > > case OPC_CVT_L_D: > check_cp1_64bitmode(ctx); > { > TCGv_i64 fp0 = tcg_temp_new_i64(); > > gen_load_fpr64(ctx, fp0, fs); > if (ctx->nan2008) { > gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0); > } else { > gen_helper_float_cvt_l_d(fp0, cpu_env, fp0); > } > gen_store_fpr64(ctx, fp0, fd); > tcg_temp_free_i64(fp0); > } > opn = "cvt.l.d"; > break; > > Function helper_float_cvt_2008_l_d() is a new, only-2008-style helper for > CVT.L.D and would look like this: > > uint64_t helper_float_cvt_2008_l_d(CPUMIPSState *env, uint64_t fdt0) > { > uint64_t dt2; > > dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status); > if (get_float_exception_flags(&env->active_fpu.fp_status) > & (float_flag_invalid | float_flag_overflow)) { > dt2 = DBL_TO_INT64_OVERFLOW(fdt0) > } > update_fcr31(env, GETPC()); > return dt2; > } That looks fine as well. r~