diff options
author | Richard Henderson <richard.henderson@linaro.org> | 2019-05-06 14:49:25 -0700 |
---|---|---|
committer | Richard Henderson <richard.henderson@linaro.org> | 2019-09-04 12:53:33 -0700 |
commit | 62f2b0389ff6fc7856b801bb5bee1c2d364d3e6c (patch) | |
tree | 67be040ef1a5bab9ee48aabfcaffdb15432d4409 /target/openrisc | |
parent | fe636d3722bf266c7b1bd3ca12fa53fb78ceffa0 (diff) |
target/openrisc: Add support for ORFPX64A32
This is hardware support for double-precision floating-point using
pairs of 32-bit registers. Fix latent bugs in the heretofore unused
helper_itofd and helper_ftoid. Include the bit for cpu "any".
Change the default cpu for linux-user to "any".
Reviewed-by: Stafford Horne <shorne@gmail.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'target/openrisc')
-rw-r--r-- | target/openrisc/cpu.c | 2 | ||||
-rw-r--r-- | target/openrisc/disas.c | 56 | ||||
-rw-r--r-- | target/openrisc/fpu_helper.c | 14 | ||||
-rw-r--r-- | target/openrisc/helper.h | 2 | ||||
-rw-r--r-- | target/openrisc/insns.decode | 31 | ||||
-rw-r--r-- | target/openrisc/translate.c | 230 |
6 files changed, 332 insertions, 3 deletions
diff --git a/target/openrisc/cpu.c b/target/openrisc/cpu.c index f3c8134531..b931605e62 100644 --- a/target/openrisc/cpu.c +++ b/target/openrisc/cpu.c @@ -132,7 +132,7 @@ static void openrisc_any_initfn(Object *obj) cpu->env.upr = UPR_UP | UPR_DMP | UPR_IMP | UPR_PICP | UPR_TTP | UPR_PMP; cpu->env.cpucfgr = CPUCFGR_NSGF | CPUCFGR_OB32S | CPUCFGR_OF32S | - CPUCFGR_AVRP | CPUCFGR_EVBARP; + CPUCFGR_AVRP | CPUCFGR_EVBARP | CPUCFGR_OF64A32S; /* 1Way, TLB_SIZE entries. */ cpu->env.dmmucfgr = (DMMUCFGR_NTW & (0 << 2)) diff --git a/target/openrisc/disas.c b/target/openrisc/disas.c index 7091832347..4de5c632de 100644 --- a/target/openrisc/disas.c +++ b/target/openrisc/disas.c @@ -166,3 +166,59 @@ FP_INSN(sfgt, s, "r%d, r%d", a->a, a->b) FP_INSN(sfge, s, "r%d, r%d", a->a, a->b) FP_INSN(sflt, s, "r%d, r%d", a->a, a->b) FP_INSN(sfle, s, "r%d, r%d", a->a, a->b) + +FP_INSN(add, d, "r%d,r%d, r%d,r%d, r%d,r%d", + a->d, a->d + a->dp + 1, + a->a, a->a + a->ap + 1, + a->b, a->b + a->bp + 1) +FP_INSN(sub, d, "r%d,r%d, r%d,r%d, r%d,r%d", + a->d, a->d + a->dp + 1, + a->a, a->a + a->ap + 1, + a->b, a->b + a->bp + 1) +FP_INSN(mul, d, "r%d,r%d, r%d,r%d, r%d,r%d", + a->d, a->d + a->dp + 1, + a->a, a->a + a->ap + 1, + a->b, a->b + a->bp + 1) +FP_INSN(div, d, "r%d,r%d, r%d,r%d, r%d,r%d", + a->d, a->d + a->dp + 1, + a->a, a->a + a->ap + 1, + a->b, a->b + a->bp + 1) +FP_INSN(rem, d, "r%d,r%d, r%d,r%d, r%d,r%d", + a->d, a->d + a->dp + 1, + a->a, a->a + a->ap + 1, + a->b, a->b + a->bp + 1) +FP_INSN(madd, d, "r%d,r%d, r%d,r%d, r%d,r%d", + a->d, a->d + a->dp + 1, + a->a, a->a + a->ap + 1, + a->b, a->b + a->bp + 1) + +FP_INSN(itof, d, "r%d,r%d, r%d,r%d", + a->d, a->d + a->dp + 1, + a->a, a->a + a->ap + 1) +FP_INSN(ftoi, d, "r%d,r%d, r%d,r%d", + a->d, a->d + a->dp + 1, + a->a, a->a + a->ap + 1) + +FP_INSN(stod, d, "r%d,r%d, r%d", + a->d, a->d + a->dp + 1, a->a) +FP_INSN(dtos, d, "r%d r%d,r%d", + a->d, a->a, a->a + a->ap + 1) + +FP_INSN(sfeq, d, "r%d,r%d, r%d,r%d", + a->a, a->a + a->ap + 1, + a->b, a->b + a->bp + 1) +FP_INSN(sfne, d, "r%d,r%d, r%d,r%d", + a->a, a->a + a->ap + 1, + a->b, a->b + a->bp + 1) +FP_INSN(sfgt, d, "r%d,r%d, r%d,r%d", + a->a, a->a + a->ap + 1, + a->b, a->b + a->bp + 1) +FP_INSN(sfge, d, "r%d,r%d, r%d,r%d", + a->a, a->a + a->ap + 1, + a->b, a->b + a->bp + 1) +FP_INSN(sflt, d, "r%d,r%d, r%d,r%d", + a->a, a->a + a->ap + 1, + a->b, a->b + a->bp + 1) +FP_INSN(sfle, d, "r%d,r%d, r%d,r%d", + a->a, a->a + a->ap + 1, + a->b, a->b + a->bp + 1) diff --git a/target/openrisc/fpu_helper.c b/target/openrisc/fpu_helper.c index 4cc5b297c5..9d7dfc0fb9 100644 --- a/target/openrisc/fpu_helper.c +++ b/target/openrisc/fpu_helper.c @@ -63,7 +63,7 @@ void HELPER(update_fpcsr)(CPUOpenRISCState *env) uint64_t HELPER(itofd)(CPUOpenRISCState *env, uint64_t val) { - return int32_to_float64(val, &env->fp_status); + return int64_to_float64(val, &env->fp_status); } uint32_t HELPER(itofs)(CPUOpenRISCState *env, uint32_t val) @@ -73,7 +73,7 @@ uint32_t HELPER(itofs)(CPUOpenRISCState *env, uint32_t val) uint64_t HELPER(ftoid)(CPUOpenRISCState *env, uint64_t val) { - return float32_to_int64(val, &env->fp_status); + return float64_to_int64_round_to_zero(val, &env->fp_status); } uint32_t HELPER(ftois)(CPUOpenRISCState *env, uint32_t val) @@ -81,6 +81,16 @@ uint32_t HELPER(ftois)(CPUOpenRISCState *env, uint32_t val) return float32_to_int32_round_to_zero(val, &env->fp_status); } +uint64_t HELPER(stod)(CPUOpenRISCState *env, uint32_t val) +{ + return float32_to_float64(val, &env->fp_status); +} + +uint32_t HELPER(dtos)(CPUOpenRISCState *env, uint64_t val) +{ + return float64_to_float32(val, &env->fp_status); +} + #define FLOAT_CALC(name) \ uint64_t helper_float_ ## name ## _d(CPUOpenRISCState *env, \ uint64_t fdt0, uint64_t fdt1) \ diff --git a/target/openrisc/helper.h b/target/openrisc/helper.h index 96d79a8113..94b823580e 100644 --- a/target/openrisc/helper.h +++ b/target/openrisc/helper.h @@ -30,6 +30,8 @@ DEF_HELPER_FLAGS_2(itofd, TCG_CALL_NO_RWG, i64, env, i64) DEF_HELPER_FLAGS_2(itofs, TCG_CALL_NO_RWG, i32, env, i32) DEF_HELPER_FLAGS_2(ftoid, TCG_CALL_NO_RWG, i64, env, i64) DEF_HELPER_FLAGS_2(ftois, TCG_CALL_NO_RWG, i32, env, i32) +DEF_HELPER_FLAGS_2(stod, TCG_CALL_NO_RWG, i64, env, i32) +DEF_HELPER_FLAGS_2(dtos, TCG_CALL_NO_RWG, i32, env, i64) DEF_HELPER_FLAGS_4(float_madd_s, TCG_CALL_NO_RWG, i32, env, i32, i32, i32) DEF_HELPER_FLAGS_4(float_madd_d, TCG_CALL_NO_RWG, i64, env, i64, i64, i64) diff --git a/target/openrisc/insns.decode b/target/openrisc/insns.decode index 7df81c1f22..334d4e9668 100644 --- a/target/openrisc/insns.decode +++ b/target/openrisc/insns.decode @@ -22,6 +22,9 @@ &ab a b &dal d a l &ai a i +&dab_pair d a b dp ap bp +&ab_pair a b ap bp +&da_pair d a dp ap #### # System Instructions @@ -187,3 +190,31 @@ lf_sfgt_s 110010 ----- a:5 b:5 --- 00001010 lf_sfge_s 110010 ----- a:5 b:5 --- 00001011 lf_sflt_s 110010 ----- a:5 b:5 --- 00001100 lf_sfle_s 110010 ----- a:5 b:5 --- 00001101 + +#### +# DP Instructions +#### + +@dab_pair ...... d:5 a:5 b:5 dp:1 ap:1 bp:1 ........ &dab_pair +@ab_pair ...... ..... a:5 b:5 . ap:1 bp:1 ........ &ab_pair +@da_pair ...... d:5 a:5 ..... dp:1 ap:1 . ........ &da_pair + +lf_add_d 110010 ..... ..... ..... ... 00010000 @dab_pair +lf_sub_d 110010 ..... ..... ..... ... 00010001 @dab_pair +lf_mul_d 110010 ..... ..... ..... ... 00010010 @dab_pair +lf_div_d 110010 ..... ..... ..... ... 00010011 @dab_pair +lf_rem_d 110010 ..... ..... ..... ... 00010110 @dab_pair +lf_madd_d 110010 ..... ..... ..... ... 00010111 @dab_pair + +lf_itof_d 110010 ..... ..... 00000 ..0 00010100 @da_pair +lf_ftoi_d 110010 ..... ..... 00000 ..0 00010101 @da_pair + +lf_stod_d 110010 d:5 a:5 00000 dp:1 0 0 00110100 +lf_dtos_d 110010 d:5 a:5 00000 0 ap:1 0 00110101 + +lf_sfeq_d 110010 00000 ..... ..... 0.. 00011000 @ab_pair +lf_sfne_d 110010 00000 ..... ..... 0.. 00011001 @ab_pair +lf_sfgt_d 110010 00000 ..... ..... 0.. 00011010 @ab_pair +lf_sfge_d 110010 00000 ..... ..... 0.. 00011011 @ab_pair +lf_sflt_d 110010 00000 ..... ..... 0.. 00011100 @ab_pair +lf_sfle_d 110010 00000 ..... ..... 0.. 00011101 @ab_pair diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c index 2f5c969f21..b8ef485903 100644 --- a/target/openrisc/translate.c +++ b/target/openrisc/translate.c @@ -146,6 +146,11 @@ static bool check_of32s(DisasContext *dc) return dc->cpucfgr & CPUCFGR_OF32S; } +static bool check_of64a32s(DisasContext *dc) +{ + return dc->cpucfgr & CPUCFGR_OF64A32S; +} + static TCGv cpu_R(DisasContext *dc, int reg) { if (reg == 0) { @@ -1260,6 +1265,231 @@ static bool trans_lf_sfle_s(DisasContext *dc, arg_ab *a) return do_fpcmp(dc, a, gen_helper_float_le_s, false, false); } +static bool check_pair(DisasContext *dc, int r, int p) +{ + return r + 1 + p < 32; +} + +static void load_pair(DisasContext *dc, TCGv_i64 t, int r, int p) +{ + tcg_gen_concat_i32_i64(t, cpu_R(dc, r + 1 + p), cpu_R(dc, r)); +} + +static void save_pair(DisasContext *dc, TCGv_i64 t, int r, int p) +{ + tcg_gen_extr_i64_i32(cpu_R(dc, r + 1 + p), cpu_R(dc, r), t); +} + +static bool do_dp3(DisasContext *dc, arg_dab_pair *a, + void (*fn)(TCGv_i64, TCGv_env, TCGv_i64, TCGv_i64)) +{ + TCGv_i64 t0, t1; + + if (!check_of64a32s(dc) || + !check_pair(dc, a->a, a->ap) || + !check_pair(dc, a->b, a->bp) || + !check_pair(dc, a->d, a->dp)) { + return false; + } + check_r0_write(dc, a->d); + + t0 = tcg_temp_new_i64(); + t1 = tcg_temp_new_i64(); + load_pair(dc, t0, a->a, a->ap); + load_pair(dc, t1, a->b, a->bp); + fn(t0, cpu_env, t0, t1); + save_pair(dc, t0, a->d, a->dp); + tcg_temp_free_i64(t0); + tcg_temp_free_i64(t1); + + gen_helper_update_fpcsr(cpu_env); + return true; +} + +static bool do_dp2(DisasContext *dc, arg_da_pair *a, + void (*fn)(TCGv_i64, TCGv_env, TCGv_i64)) +{ + TCGv_i64 t0; + + if (!check_of64a32s(dc) || + !check_pair(dc, a->a, a->ap) || + !check_pair(dc, a->d, a->dp)) { + return false; + } + check_r0_write(dc, a->d); + + t0 = tcg_temp_new_i64(); + load_pair(dc, t0, a->a, a->ap); + fn(t0, cpu_env, t0); + save_pair(dc, t0, a->d, a->dp); + tcg_temp_free_i64(t0); + + gen_helper_update_fpcsr(cpu_env); + return true; +} + +static bool do_dpcmp(DisasContext *dc, arg_ab_pair *a, + void (*fn)(TCGv, TCGv_env, TCGv_i64, TCGv_i64), + bool inv, bool swap) +{ + TCGv_i64 t0, t1; + + if (!check_of64a32s(dc) || + !check_pair(dc, a->a, a->ap) || + !check_pair(dc, a->b, a->bp)) { + return false; + } + + t0 = tcg_temp_new_i64(); + t1 = tcg_temp_new_i64(); + load_pair(dc, t0, a->a, a->ap); + load_pair(dc, t1, a->b, a->bp); + if (swap) { + fn(cpu_sr_f, cpu_env, t1, t0); + } else { + fn(cpu_sr_f, cpu_env, t0, t1); + } + tcg_temp_free_i64(t0); + tcg_temp_free_i64(t1); + + if (inv) { + tcg_gen_xori_tl(cpu_sr_f, cpu_sr_f, 1); + } + gen_helper_update_fpcsr(cpu_env); + return true; +} + +static bool trans_lf_add_d(DisasContext *dc, arg_dab_pair *a) +{ + return do_dp3(dc, a, gen_helper_float_add_d); +} + +static bool trans_lf_sub_d(DisasContext *dc, arg_dab_pair *a) +{ + return do_dp3(dc, a, gen_helper_float_sub_d); +} + +static bool trans_lf_mul_d(DisasContext *dc, arg_dab_pair *a) +{ + return do_dp3(dc, a, gen_helper_float_mul_d); +} + +static bool trans_lf_div_d(DisasContext *dc, arg_dab_pair *a) +{ + return do_dp3(dc, a, gen_helper_float_div_d); +} + +static bool trans_lf_rem_d(DisasContext *dc, arg_dab_pair *a) +{ + return do_dp3(dc, a, gen_helper_float_rem_d); +} + +static bool trans_lf_itof_d(DisasContext *dc, arg_da_pair *a) +{ + return do_dp2(dc, a, gen_helper_itofd); +} + +static bool trans_lf_ftoi_d(DisasContext *dc, arg_da_pair *a) +{ + return do_dp2(dc, a, gen_helper_ftoid); +} + +static bool trans_lf_stod_d(DisasContext *dc, arg_lf_stod_d *a) +{ + TCGv_i64 t0; + + if (!check_of64a32s(dc) || + !check_pair(dc, a->d, a->dp)) { + return false; + } + check_r0_write(dc, a->d); + + t0 = tcg_temp_new_i64(); + gen_helper_stod(t0, cpu_env, cpu_R(dc, a->a)); + save_pair(dc, t0, a->d, a->dp); + tcg_temp_free_i64(t0); + + gen_helper_update_fpcsr(cpu_env); + return true; +} + +static bool trans_lf_dtos_d(DisasContext *dc, arg_lf_dtos_d *a) +{ + TCGv_i64 t0; + + if (!check_of64a32s(dc) || + !check_pair(dc, a->a, a->ap)) { + return false; + } + check_r0_write(dc, a->d); + + t0 = tcg_temp_new_i64(); + load_pair(dc, t0, a->a, a->ap); + gen_helper_dtos(cpu_R(dc, a->d), cpu_env, t0); + tcg_temp_free_i64(t0); + + gen_helper_update_fpcsr(cpu_env); + return true; +} + +static bool trans_lf_madd_d(DisasContext *dc, arg_dab_pair *a) +{ + TCGv_i64 t0, t1, t2; + + if (!check_of64a32s(dc) || + !check_pair(dc, a->a, a->ap) || + !check_pair(dc, a->b, a->bp) || + !check_pair(dc, a->d, a->dp)) { + return false; + } + check_r0_write(dc, a->d); + + t0 = tcg_temp_new_i64(); + t1 = tcg_temp_new_i64(); + t2 = tcg_temp_new_i64(); + load_pair(dc, t0, a->d, a->dp); + load_pair(dc, t1, a->a, a->ap); + load_pair(dc, t2, a->b, a->bp); + gen_helper_float_madd_d(t0, cpu_env, t0, t1, t2); + save_pair(dc, t0, a->d, a->dp); + tcg_temp_free_i64(t0); + tcg_temp_free_i64(t1); + tcg_temp_free_i64(t2); + + gen_helper_update_fpcsr(cpu_env); + return true; +} + +static bool trans_lf_sfeq_d(DisasContext *dc, arg_ab_pair *a) +{ + return do_dpcmp(dc, a, gen_helper_float_eq_d, false, false); +} + +static bool trans_lf_sfne_d(DisasContext *dc, arg_ab_pair *a) +{ + return do_dpcmp(dc, a, gen_helper_float_eq_d, true, false); +} + +static bool trans_lf_sfgt_d(DisasContext *dc, arg_ab_pair *a) +{ + return do_dpcmp(dc, a, gen_helper_float_lt_d, false, true); +} + +static bool trans_lf_sfge_d(DisasContext *dc, arg_ab_pair *a) +{ + return do_dpcmp(dc, a, gen_helper_float_le_d, false, true); +} + +static bool trans_lf_sflt_d(DisasContext *dc, arg_ab_pair *a) +{ + return do_dpcmp(dc, a, gen_helper_float_lt_d, false, false); +} + +static bool trans_lf_sfle_d(DisasContext *dc, arg_ab_pair *a) +{ + return do_dpcmp(dc, a, gen_helper_float_le_d, false, false); +} + static void openrisc_tr_init_disas_context(DisasContextBase *dcb, CPUState *cs) { DisasContext *dc = container_of(dcb, DisasContext, base); |