mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-03 07:43:54 -06:00
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>
This commit is contained in:
parent
fe636d3722
commit
62f2b0389f
7 changed files with 333 additions and 4 deletions
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue