target/sparc: Add FQ and FSR.QNE

Add support for, and migrate, a single-entry fp
instruction queue for sparc32.

Signed-off-by: Carl Hauser <chauser@pullman.com>
[rth: Split from a larger patch;
      adjust representation with union;
      add migration state]
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Acked-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Tested-by: Carl Hauser <chauser@pullman.com>
This commit is contained in:
Carl Hauser 2024-08-16 10:02:41 +10:00 committed by Richard Henderson
parent a4eb31c678
commit e412e9973a
3 changed files with 51 additions and 0 deletions

View File

@ -184,6 +184,8 @@ enum {
#define FSR_FTT_SEQ_ERROR (4ULL << 14) #define FSR_FTT_SEQ_ERROR (4ULL << 14)
#define FSR_FTT_INVAL_FPR (6ULL << 14) #define FSR_FTT_INVAL_FPR (6ULL << 14)
#define FSR_QNE (1ULL << 13)
#define FSR_FCC0_SHIFT 10 #define FSR_FCC0_SHIFT 10
#define FSR_FCC1_SHIFT 32 #define FSR_FCC1_SHIFT 32
#define FSR_FCC2_SHIFT 34 #define FSR_FCC2_SHIFT 34
@ -438,6 +440,26 @@ struct CPUArchState {
uint32_t fsr_cexc_ftt; /* cexc, ftt */ uint32_t fsr_cexc_ftt; /* cexc, ftt */
uint32_t fcc[TARGET_FCCREGS]; /* fcc* */ uint32_t fcc[TARGET_FCCREGS]; /* fcc* */
#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
/*
* Single-element FPU fault queue, with address and insn,
* packaged into the double-word with which it is stored.
*/
uint32_t fsr_qne; /* qne */
union {
uint64_t d;
struct {
#if HOST_BIG_ENDIAN
uint32_t addr;
uint32_t insn;
#else
uint32_t insn;
uint32_t addr;
#endif
} s;
} fq;
#endif
CPU_DoubleU fpr[TARGET_DPREGS]; /* floating point registers */ CPU_DoubleU fpr[TARGET_DPREGS]; /* floating point registers */
uint32_t cwp; /* index of current register window (extracted uint32_t cwp; /* index of current register window (extracted
from PSR) */ from PSR) */

View File

@ -545,6 +545,8 @@ target_ulong cpu_get_fsr(CPUSPARCState *env)
fsr |= (uint64_t)env->fcc[1] << FSR_FCC1_SHIFT; fsr |= (uint64_t)env->fcc[1] << FSR_FCC1_SHIFT;
fsr |= (uint64_t)env->fcc[2] << FSR_FCC2_SHIFT; fsr |= (uint64_t)env->fcc[2] << FSR_FCC2_SHIFT;
fsr |= (uint64_t)env->fcc[3] << FSR_FCC3_SHIFT; fsr |= (uint64_t)env->fcc[3] << FSR_FCC3_SHIFT;
#elif !defined(CONFIG_USER_ONLY)
fsr |= env->fsr_qne;
#endif #endif
/* VER is kept completely separate until re-assembly. */ /* VER is kept completely separate until re-assembly. */
@ -591,6 +593,8 @@ void cpu_put_fsr(CPUSPARCState *env, target_ulong fsr)
env->fcc[1] = extract64(fsr, FSR_FCC1_SHIFT, 2); env->fcc[1] = extract64(fsr, FSR_FCC1_SHIFT, 2);
env->fcc[2] = extract64(fsr, FSR_FCC2_SHIFT, 2); env->fcc[2] = extract64(fsr, FSR_FCC2_SHIFT, 2);
env->fcc[3] = extract64(fsr, FSR_FCC3_SHIFT, 2); env->fcc[3] = extract64(fsr, FSR_FCC3_SHIFT, 2);
#elif !defined(CONFIG_USER_ONLY)
env->fsr_qne = fsr & FSR_QNE;
#endif #endif
set_fsr_nonsplit(env, fsr); set_fsr_nonsplit(env, fsr);

View File

@ -143,6 +143,24 @@ static const VMStateInfo vmstate_xcc = {
.get = get_xcc, .get = get_xcc,
.put = put_xcc, .put = put_xcc,
}; };
#else
static bool fq_needed(void *opaque)
{
SPARCCPU *cpu = opaque;
return cpu->env.fsr_qne;
}
static const VMStateDescription vmstate_fq = {
.name = "cpu/fq",
.version_id = 1,
.minimum_version_id = 1,
.needed = fq_needed,
.fields = (const VMStateField[]) {
VMSTATE_UINT32(env.fq.s.addr, SPARCCPU),
VMSTATE_UINT32(env.fq.s.insn, SPARCCPU),
VMSTATE_END_OF_LIST()
},
};
#endif #endif
static int cpu_pre_save(void *opaque) static int cpu_pre_save(void *opaque)
@ -265,4 +283,11 @@ const VMStateDescription vmstate_sparc_cpu = {
#endif #endif
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
}, },
#ifndef TARGET_SPARC64
.subsections = (const VMStateDescription * const []) {
&vmstate_fq,
NULL
},
#endif
}; };