mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-08 10:13:56 -06:00
target/sparc: Introduce cpu_get_fsr, cpu_put_fsr
Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Tested-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> Acked-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> Message-Id: <20231103173841.33651-16-richard.henderson@linaro.org>
This commit is contained in:
parent
41535ca6f4
commit
1ccd6e13cc
9 changed files with 80 additions and 18 deletions
|
@ -293,7 +293,7 @@ void cpu_loop (CPUSPARCState *env)
|
||||||
case TT_FP_EXCP:
|
case TT_FP_EXCP:
|
||||||
{
|
{
|
||||||
int code = TARGET_FPE_FLTUNK;
|
int code = TARGET_FPE_FLTUNK;
|
||||||
target_ulong fsr = env->fsr;
|
target_ulong fsr = cpu_get_fsr(env);
|
||||||
|
|
||||||
if ((fsr & FSR_FTT_MASK) == FSR_FTT_IEEE_EXCP) {
|
if ((fsr & FSR_FTT_MASK) == FSR_FTT_IEEE_EXCP) {
|
||||||
if (fsr & FSR_NVC) {
|
if (fsr & FSR_NVC) {
|
||||||
|
|
|
@ -199,20 +199,21 @@ static void save_fpu(struct target_siginfo_fpu *fpu, CPUSPARCState *env)
|
||||||
for (i = 0; i < 32; ++i) {
|
for (i = 0; i < 32; ++i) {
|
||||||
__put_user(env->fpr[i].ll, &fpu->si_double_regs[i]);
|
__put_user(env->fpr[i].ll, &fpu->si_double_regs[i]);
|
||||||
}
|
}
|
||||||
__put_user(env->fsr, &fpu->si_fsr);
|
__put_user(cpu_get_fsr(env), &fpu->si_fsr);
|
||||||
__put_user(env->gsr, &fpu->si_gsr);
|
__put_user(env->gsr, &fpu->si_gsr);
|
||||||
__put_user(env->fprs, &fpu->si_fprs);
|
__put_user(env->fprs, &fpu->si_fprs);
|
||||||
#else
|
#else
|
||||||
for (i = 0; i < 16; ++i) {
|
for (i = 0; i < 16; ++i) {
|
||||||
__put_user(env->fpr[i].ll, &fpu->si_double_regs[i]);
|
__put_user(env->fpr[i].ll, &fpu->si_double_regs[i]);
|
||||||
}
|
}
|
||||||
__put_user(env->fsr, &fpu->si_fsr);
|
__put_user(cpu_get_fsr(env), &fpu->si_fsr);
|
||||||
__put_user(0, &fpu->si_fpqdepth);
|
__put_user(0, &fpu->si_fpqdepth);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void restore_fpu(struct target_siginfo_fpu *fpu, CPUSPARCState *env)
|
static void restore_fpu(struct target_siginfo_fpu *fpu, CPUSPARCState *env)
|
||||||
{
|
{
|
||||||
|
target_ulong fsr;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
#ifdef TARGET_SPARC64
|
#ifdef TARGET_SPARC64
|
||||||
|
@ -230,15 +231,16 @@ static void restore_fpu(struct target_siginfo_fpu *fpu, CPUSPARCState *env)
|
||||||
__get_user(env->fpr[i].ll, &fpu->si_double_regs[i]);
|
__get_user(env->fpr[i].ll, &fpu->si_double_regs[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
__get_user(env->fsr, &fpu->si_fsr);
|
|
||||||
__get_user(env->gsr, &fpu->si_gsr);
|
__get_user(env->gsr, &fpu->si_gsr);
|
||||||
env->fprs |= fprs;
|
env->fprs |= fprs;
|
||||||
#else
|
#else
|
||||||
for (i = 0; i < 16; ++i) {
|
for (i = 0; i < 16; ++i) {
|
||||||
__get_user(env->fpr[i].ll, &fpu->si_double_regs[i]);
|
__get_user(env->fpr[i].ll, &fpu->si_double_regs[i]);
|
||||||
}
|
}
|
||||||
__get_user(env->fsr, &fpu->si_fsr);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
__get_user(fsr, &fpu->si_fsr);
|
||||||
|
cpu_put_fsr(env, fsr);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TARGET_ARCH_HAS_SETUP_FRAME
|
#ifdef TARGET_ARCH_HAS_SETUP_FRAME
|
||||||
|
@ -662,6 +664,7 @@ void sparc64_set_context(CPUSPARCState *env)
|
||||||
__get_user(fenab, &(fpup->mcfpu_enab));
|
__get_user(fenab, &(fpup->mcfpu_enab));
|
||||||
if (fenab) {
|
if (fenab) {
|
||||||
abi_ulong fprs;
|
abi_ulong fprs;
|
||||||
|
abi_ulong fsr;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We use the FPRS from the guest only in deciding whether
|
* We use the FPRS from the guest only in deciding whether
|
||||||
|
@ -690,7 +693,8 @@ void sparc64_set_context(CPUSPARCState *env)
|
||||||
__get_user(env->fpr[i].ll, &(fpup->mcfpu_fregs.dregs[i]));
|
__get_user(env->fpr[i].ll, &(fpup->mcfpu_fregs.dregs[i]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
__get_user(env->fsr, &(fpup->mcfpu_fsr));
|
__get_user(fsr, &(fpup->mcfpu_fsr));
|
||||||
|
cpu_put_fsr(env, fsr);
|
||||||
__get_user(env->gsr, &(fpup->mcfpu_gsr));
|
__get_user(env->gsr, &(fpup->mcfpu_gsr));
|
||||||
}
|
}
|
||||||
unlock_user_struct(ucp, ucp_addr, 0);
|
unlock_user_struct(ucp, ucp_addr, 0);
|
||||||
|
|
|
@ -670,7 +670,7 @@ static void sparc_cpu_dump_state(CPUState *cs, FILE *f, int flags)
|
||||||
env->cansave, env->canrestore, env->otherwin, env->wstate,
|
env->cansave, env->canrestore, env->otherwin, env->wstate,
|
||||||
env->cleanwin, env->nwindows - 1 - env->cwp);
|
env->cleanwin, env->nwindows - 1 - env->cwp);
|
||||||
qemu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: %016x\n",
|
qemu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: %016x\n",
|
||||||
env->fsr, env->y, env->fprs);
|
cpu_get_fsr(env), env->y, env->fprs);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
qemu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
|
qemu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
|
||||||
|
@ -679,7 +679,7 @@ static void sparc_cpu_dump_state(CPUState *cs, FILE *f, int flags)
|
||||||
env->psrps ? 'P' : '-', env->psret ? 'E' : '-',
|
env->psrps ? 'P' : '-', env->psret ? 'E' : '-',
|
||||||
env->wim);
|
env->wim);
|
||||||
qemu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
|
qemu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
|
||||||
env->fsr, env->y);
|
cpu_get_fsr(env), env->y);
|
||||||
#endif
|
#endif
|
||||||
qemu_fprintf(f, "\n");
|
qemu_fprintf(f, "\n");
|
||||||
}
|
}
|
||||||
|
@ -798,6 +798,7 @@ static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||||
env->version |= env->def.maxtl << 8;
|
env->version |= env->def.maxtl << 8;
|
||||||
env->version |= env->def.nwindows - 1;
|
env->version |= env->def.nwindows - 1;
|
||||||
#endif
|
#endif
|
||||||
|
cpu_put_fsr(env, 0);
|
||||||
|
|
||||||
cpu_exec_realizefn(cs, &local_err);
|
cpu_exec_realizefn(cs, &local_err);
|
||||||
if (local_err != NULL) {
|
if (local_err != NULL) {
|
||||||
|
|
|
@ -617,7 +617,9 @@ void sparc_restore_state_to_opc(CPUState *cs,
|
||||||
const TranslationBlock *tb,
|
const TranslationBlock *tb,
|
||||||
const uint64_t *data);
|
const uint64_t *data);
|
||||||
|
|
||||||
/* cpu-exec.c */
|
/* fop_helper.c */
|
||||||
|
target_ulong cpu_get_fsr(CPUSPARCState *);
|
||||||
|
void cpu_put_fsr(CPUSPARCState *, target_ulong);
|
||||||
|
|
||||||
/* win_helper.c */
|
/* win_helper.c */
|
||||||
target_ulong cpu_get_psr(CPUSPARCState *env1);
|
target_ulong cpu_get_psr(CPUSPARCState *env1);
|
||||||
|
|
|
@ -347,10 +347,22 @@ GEN_FCMP(fcmpeq_fcc3, float128, 26, 1);
|
||||||
#undef GEN_FCMP_T
|
#undef GEN_FCMP_T
|
||||||
#undef GEN_FCMP
|
#undef GEN_FCMP
|
||||||
|
|
||||||
static void set_fsr(CPUSPARCState *env, target_ulong fsr)
|
target_ulong cpu_get_fsr(CPUSPARCState *env)
|
||||||
|
{
|
||||||
|
return env->fsr;
|
||||||
|
}
|
||||||
|
|
||||||
|
target_ulong helper_get_fsr(CPUSPARCState *env)
|
||||||
|
{
|
||||||
|
return cpu_get_fsr(env);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_fsr_nonsplit(CPUSPARCState *env, target_ulong fsr)
|
||||||
{
|
{
|
||||||
int rnd_mode;
|
int rnd_mode;
|
||||||
|
|
||||||
|
env->fsr = fsr;
|
||||||
|
|
||||||
switch (fsr & FSR_RD_MASK) {
|
switch (fsr & FSR_RD_MASK) {
|
||||||
case FSR_RD_NEAREST:
|
case FSR_RD_NEAREST:
|
||||||
rnd_mode = float_round_nearest_even;
|
rnd_mode = float_round_nearest_even;
|
||||||
|
@ -369,7 +381,12 @@ static void set_fsr(CPUSPARCState *env, target_ulong fsr)
|
||||||
set_float_rounding_mode(rnd_mode, &env->fp_status);
|
set_float_rounding_mode(rnd_mode, &env->fp_status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cpu_put_fsr(CPUSPARCState *env, target_ulong fsr)
|
||||||
|
{
|
||||||
|
set_fsr_nonsplit(env, fsr);
|
||||||
|
}
|
||||||
|
|
||||||
void helper_set_fsr(CPUSPARCState *env, target_ulong fsr)
|
void helper_set_fsr(CPUSPARCState *env, target_ulong fsr)
|
||||||
{
|
{
|
||||||
set_fsr(env, fsr);
|
set_fsr_nonsplit(env, fsr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,7 +64,7 @@ int sparc_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
|
||||||
case 69:
|
case 69:
|
||||||
return gdb_get_rega(mem_buf, env->npc);
|
return gdb_get_rega(mem_buf, env->npc);
|
||||||
case 70:
|
case 70:
|
||||||
return gdb_get_rega(mem_buf, env->fsr);
|
return gdb_get_rega(mem_buf, cpu_get_fsr(env));
|
||||||
case 71:
|
case 71:
|
||||||
return gdb_get_rega(mem_buf, 0); /* csr */
|
return gdb_get_rega(mem_buf, 0); /* csr */
|
||||||
default:
|
default:
|
||||||
|
@ -94,7 +94,7 @@ int sparc_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
|
||||||
((env->pstate & 0xfff) << 8) |
|
((env->pstate & 0xfff) << 8) |
|
||||||
cpu_get_cwp64(env));
|
cpu_get_cwp64(env));
|
||||||
case 83:
|
case 83:
|
||||||
return gdb_get_regl(mem_buf, env->fsr);
|
return gdb_get_regl(mem_buf, cpu_get_fsr(env));
|
||||||
case 84:
|
case 84:
|
||||||
return gdb_get_regl(mem_buf, env->fprs);
|
return gdb_get_regl(mem_buf, env->fprs);
|
||||||
case 85:
|
case 85:
|
||||||
|
@ -156,7 +156,7 @@ int sparc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
|
||||||
env->npc = tmp;
|
env->npc = tmp;
|
||||||
break;
|
break;
|
||||||
case 70:
|
case 70:
|
||||||
env->fsr = tmp;
|
cpu_put_fsr(env, tmp);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -191,7 +191,7 @@ int sparc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
|
||||||
cpu_put_cwp64(env, tmp & 0xff);
|
cpu_put_cwp64(env, tmp & 0xff);
|
||||||
break;
|
break;
|
||||||
case 83:
|
case 83:
|
||||||
env->fsr = tmp;
|
cpu_put_fsr(env, tmp);
|
||||||
break;
|
break;
|
||||||
case 84:
|
case 84:
|
||||||
env->fprs = tmp;
|
env->fprs = tmp;
|
||||||
|
|
|
@ -36,6 +36,7 @@ DEF_HELPER_FLAGS_4(ld_asi, TCG_CALL_NO_WG, i64, env, tl, int, i32)
|
||||||
DEF_HELPER_FLAGS_5(st_asi, TCG_CALL_NO_WG, void, env, tl, i64, int, i32)
|
DEF_HELPER_FLAGS_5(st_asi, TCG_CALL_NO_WG, void, env, tl, i64, int, i32)
|
||||||
#endif
|
#endif
|
||||||
DEF_HELPER_FLAGS_1(check_ieee_exceptions, TCG_CALL_NO_WG, tl, env)
|
DEF_HELPER_FLAGS_1(check_ieee_exceptions, TCG_CALL_NO_WG, tl, env)
|
||||||
|
DEF_HELPER_FLAGS_1(get_fsr, TCG_CALL_NO_WG_SE, tl, env)
|
||||||
DEF_HELPER_FLAGS_2(set_fsr, TCG_CALL_NO_RWG, void, env, tl)
|
DEF_HELPER_FLAGS_2(set_fsr, TCG_CALL_NO_RWG, void, env, tl)
|
||||||
DEF_HELPER_FLAGS_2(fsqrts, TCG_CALL_NO_RWG, f32, env, f32)
|
DEF_HELPER_FLAGS_2(fsqrts, TCG_CALL_NO_RWG, f32, env, f32)
|
||||||
DEF_HELPER_FLAGS_2(fsqrtd, TCG_CALL_NO_RWG, f64, env, f64)
|
DEF_HELPER_FLAGS_2(fsqrtd, TCG_CALL_NO_RWG, f64, env, f64)
|
||||||
|
|
|
@ -83,6 +83,32 @@ static const VMStateInfo vmstate_psr = {
|
||||||
.put = put_psr,
|
.put = put_psr,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int get_fsr(QEMUFile *f, void *opaque, size_t size,
|
||||||
|
const VMStateField *field)
|
||||||
|
{
|
||||||
|
SPARCCPU *cpu = opaque;
|
||||||
|
target_ulong val = qemu_get_betl(f);
|
||||||
|
|
||||||
|
cpu_put_fsr(&cpu->env, val);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int put_fsr(QEMUFile *f, void *opaque, size_t size,
|
||||||
|
const VMStateField *field, JSONWriter *vmdesc)
|
||||||
|
{
|
||||||
|
SPARCCPU *cpu = opaque;
|
||||||
|
target_ulong val = cpu_get_fsr(&cpu->env);
|
||||||
|
|
||||||
|
qemu_put_betl(f, val);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const VMStateInfo vmstate_fsr = {
|
||||||
|
.name = "fsr",
|
||||||
|
.get = get_fsr,
|
||||||
|
.put = put_fsr,
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef TARGET_SPARC64
|
#ifdef TARGET_SPARC64
|
||||||
static int get_xcc(QEMUFile *f, void *opaque, size_t size,
|
static int get_xcc(QEMUFile *f, void *opaque, size_t size,
|
||||||
const VMStateField *field)
|
const VMStateField *field)
|
||||||
|
@ -157,7 +183,6 @@ const VMStateDescription vmstate_sparc_cpu = {
|
||||||
VMSTATE_UINTTL(env.npc, SPARCCPU),
|
VMSTATE_UINTTL(env.npc, SPARCCPU),
|
||||||
VMSTATE_UINTTL(env.y, SPARCCPU),
|
VMSTATE_UINTTL(env.y, SPARCCPU),
|
||||||
{
|
{
|
||||||
|
|
||||||
.name = "psr",
|
.name = "psr",
|
||||||
.version_id = 0,
|
.version_id = 0,
|
||||||
.size = sizeof(uint32_t),
|
.size = sizeof(uint32_t),
|
||||||
|
@ -165,7 +190,14 @@ const VMStateDescription vmstate_sparc_cpu = {
|
||||||
.flags = VMS_SINGLE,
|
.flags = VMS_SINGLE,
|
||||||
.offset = 0,
|
.offset = 0,
|
||||||
},
|
},
|
||||||
VMSTATE_UINTTL(env.fsr, SPARCCPU),
|
{
|
||||||
|
.name = "fsr",
|
||||||
|
.version_id = 0,
|
||||||
|
.size = sizeof(target_ulong),
|
||||||
|
.info = &vmstate_fsr,
|
||||||
|
.flags = VMS_SINGLE,
|
||||||
|
.offset = 0,
|
||||||
|
},
|
||||||
VMSTATE_UINTTL(env.tbr, SPARCCPU),
|
VMSTATE_UINTTL(env.tbr, SPARCCPU),
|
||||||
VMSTATE_INT32(env.interrupt_index, SPARCCPU),
|
VMSTATE_INT32(env.interrupt_index, SPARCCPU),
|
||||||
VMSTATE_UINT32(env.pil_in, SPARCCPU),
|
VMSTATE_UINT32(env.pil_in, SPARCCPU),
|
||||||
|
|
|
@ -4417,13 +4417,18 @@ TRANS(LDXFSR, 64, do_ldfsr, a, MO_TEUQ, FSR_LDXFSR_MASK, FSR_LDXFSR_OLDMASK)
|
||||||
static bool do_stfsr(DisasContext *dc, arg_r_r_ri *a, MemOp mop)
|
static bool do_stfsr(DisasContext *dc, arg_r_r_ri *a, MemOp mop)
|
||||||
{
|
{
|
||||||
TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
|
TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
|
||||||
|
TCGv fsr;
|
||||||
|
|
||||||
if (addr == NULL) {
|
if (addr == NULL) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (gen_trap_ifnofpu(dc)) {
|
if (gen_trap_ifnofpu(dc)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
tcg_gen_qemu_st_tl(cpu_fsr, addr, dc->mem_idx, mop | MO_ALIGN);
|
|
||||||
|
fsr = tcg_temp_new();
|
||||||
|
gen_helper_get_fsr(fsr, tcg_env);
|
||||||
|
tcg_gen_qemu_st_tl(fsr, addr, dc->mem_idx, mop | MO_ALIGN);
|
||||||
return advance_pc(dc);
|
return advance_pc(dc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue