Skip to content

Commit

Permalink
target/sparc: Split psr and xcc into components
Browse files Browse the repository at this point in the history
Step in removing CC_OP: change the representation of CC_OP_FLAGS.
The 8 bits are distributed between 6 variables, which should make
it easy to keep up to date.

The code within cc_helper.c is quite ugly but is only temporary.

Tested-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Acked-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
  • Loading branch information
rth7680 committed Nov 5, 2023
1 parent b1fa27f commit 2a1905c
Show file tree
Hide file tree
Showing 7 changed files with 289 additions and 270 deletions.
6 changes: 2 additions & 4 deletions linux-user/sparc/cpu_loop.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,10 +197,8 @@ static uint32_t do_getpsr(CPUSPARCState *env)
/* Avoid ifdefs below for the abi32 and abi64 paths. */
#ifdef TARGET_ABI32
#define TARGET_TT_SYSCALL (TT_TRAP + 0x10) /* t_linux */
#define syscall_cc psr
#else
#define TARGET_TT_SYSCALL (TT_TRAP + 0x6d) /* tl0_linux64 */
#define syscall_cc xcc
#endif

/* Avoid ifdefs below for the v9 and pre-v9 hw traps. */
Expand Down Expand Up @@ -240,10 +238,10 @@ void cpu_loop (CPUSPARCState *env)
break;
}
if ((abi_ulong)ret >= (abi_ulong)(-515)) {
env->syscall_cc |= PSR_CARRY;
set_syscall_C(env, 1);
ret = -ret;
} else {
env->syscall_cc &= ~PSR_CARRY;
set_syscall_C(env, 0);
}
env->regwptr[0] = ret;
/* next instruction */
Expand Down
17 changes: 12 additions & 5 deletions linux-user/sparc/target_cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,17 @@
# define TARGET_STACK_BIAS 0
#endif

static void set_syscall_C(CPUSPARCState *env, bool val)
{
#ifndef TARGET_SPARC64
env->icc_C = val;
#elif defined(TARGET_ABI32)
env->icc_C = (uint64_t)val << 32;
#else
env->xcc_C = val;
#endif
}

static inline void cpu_clone_regs_child(CPUSPARCState *env, target_ulong newsp,
unsigned flags)
{
Expand Down Expand Up @@ -58,11 +69,7 @@ static inline void cpu_clone_regs_child(CPUSPARCState *env, target_ulong newsp,
* do the pc advance twice.
*/
env->regwptr[WREG_O0] = 0;
#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
env->xcc &= ~PSR_CARRY;
#else
env->psr &= ~PSR_CARRY;
#endif
set_syscall_C(env, 0);
env->pc = env->npc;
env->npc = env->npc + 4;
}
Expand Down
51 changes: 24 additions & 27 deletions target/sparc/cc_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,6 @@
#include "cpu.h"
#include "exec/helper-proto.h"

static uint32_t compute_all_flags(CPUSPARCState *env)
{
return env->psr & PSR_ICC;
}

static uint32_t compute_C_flags(CPUSPARCState *env)
{
return env->psr & PSR_CARRY;
}

static inline uint32_t get_NZ_icc(int32_t dst)
{
uint32_t ret = 0;
Expand All @@ -44,16 +34,6 @@ static inline uint32_t get_NZ_icc(int32_t dst)
}

#ifdef TARGET_SPARC64
static uint32_t compute_all_flags_xcc(CPUSPARCState *env)
{
return env->xcc & PSR_ICC;
}

static uint32_t compute_C_flags_xcc(CPUSPARCState *env)
{
return env->xcc & PSR_CARRY;
}

static inline uint32_t get_NZ_xcc(target_long dst)
{
uint32_t ret = 0;
Expand Down Expand Up @@ -422,7 +402,6 @@ typedef struct CCTable {

static const CCTable icc_table[CC_OP_NB] = {
/* CC_OP_DYNAMIC should never happen */
[CC_OP_FLAGS] = { compute_all_flags, compute_C_flags },
[CC_OP_DIV] = { compute_all_div, compute_C_div },
[CC_OP_ADD] = { compute_all_add, compute_C_add },
[CC_OP_ADDX] = { compute_all_addx, compute_C_addx },
Expand All @@ -438,7 +417,6 @@ static const CCTable icc_table[CC_OP_NB] = {
#ifdef TARGET_SPARC64
static const CCTable xcc_table[CC_OP_NB] = {
/* CC_OP_DYNAMIC should never happen */
[CC_OP_FLAGS] = { compute_all_flags_xcc, compute_C_flags_xcc },
[CC_OP_DIV] = { compute_all_logic_xcc, compute_C_logic },
[CC_OP_ADD] = { compute_all_add_xcc, compute_C_add_xcc },
[CC_OP_ADDX] = { compute_all_addx_xcc, compute_C_addx_xcc },
Expand All @@ -454,18 +432,37 @@ static const CCTable xcc_table[CC_OP_NB] = {

void helper_compute_psr(CPUSPARCState *env)
{
uint32_t new_psr;
if (CC_OP == CC_OP_FLAGS) {
return;
}

new_psr = icc_table[CC_OP].compute_all(env);
env->psr = new_psr;
uint32_t icc = icc_table[CC_OP].compute_all(env);
#ifdef TARGET_SPARC64
new_psr = xcc_table[CC_OP].compute_all(env);
env->xcc = new_psr;
uint32_t xcc = xcc_table[CC_OP].compute_all(env);

env->cc_N = deposit64(-(icc & PSR_NEG), 32, 32, -(xcc & PSR_NEG));
env->cc_V = deposit64(-(icc & PSR_OVF), 32, 32, -(xcc & PSR_OVF));
env->icc_C = (uint64_t)icc << (32 - PSR_CARRY_SHIFT);
env->xcc_C = (xcc >> PSR_CARRY_SHIFT) & 1;
env->xcc_Z = ~xcc & PSR_ZERO;
#else
env->cc_N = -(icc & PSR_NEG);
env->cc_V = -(icc & PSR_OVF);
env->icc_C = (icc >> PSR_CARRY_SHIFT) & 1;
#endif
env->icc_Z = ~icc & PSR_ZERO;

CC_OP = CC_OP_FLAGS;
}

uint32_t helper_compute_C_icc(CPUSPARCState *env)
{
if (CC_OP == CC_OP_FLAGS) {
#ifdef TARGET_SPARC64
return extract64(env->icc_C, 32, 1);
#else
return env->icc_C;
#endif
}
return icc_table[CC_OP].compute_c(env) >> PSR_CARRY_SHIFT;
}
30 changes: 27 additions & 3 deletions target/sparc/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ enum {
*/
enum {
CC_OP_DYNAMIC, /* must use dynamic code to get cc_op */
CC_OP_FLAGS, /* all cc are back in status register */
CC_OP_FLAGS, /* all cc are back in cc_*_[NZCV] registers */
CC_OP_DIV, /* modify N, Z and V, C = 0*/
CC_OP_ADD, /* modify all flags, CC_DST = res, CC_SRC = src1 */
CC_OP_ADDX, /* modify all flags, CC_DST = res, CC_SRC = src1 */
Expand Down Expand Up @@ -458,6 +458,32 @@ struct CPUArchState {
target_ulong npc; /* next program counter */
target_ulong y; /* multiply/divide register */

/*
* Bit 31 is for icc, bit 63 for xcc.
* Other bits are garbage.
*/
target_long cc_N;
target_long cc_V;

/*
* Z is represented as == 0; any non-zero value is !Z.
* For sparc64, the high 32-bits of icc.Z are garbage.
*/
target_ulong icc_Z;
#ifdef TARGET_SPARC64
target_ulong xcc_Z;
#endif

/*
* For sparc32, icc.C is boolean.
* For sparc64, xcc.C is boolean;
* icc.C is bit 32 with other bits garbage.
*/
target_ulong icc_C;
#ifdef TARGET_SPARC64
target_ulong xcc_C;
#endif

/* emulator internal flags handling */
target_ulong cc_src, cc_src2;
target_ulong cc_dst;
Expand All @@ -466,7 +492,6 @@ struct CPUArchState {
target_ulong cond; /* conditional branch result (XXX: save it in a
temporary register when possible) */

uint32_t psr; /* processor state register */
target_ulong fsr; /* FPU state register */
CPU_DoubleU fpr[TARGET_DPREGS]; /* floating point registers */
uint32_t cwp; /* index of current register window (extracted
Expand Down Expand Up @@ -522,7 +547,6 @@ struct CPUArchState {
#define MAXTL_MAX 8
#define MAXTL_MASK (MAXTL_MAX - 1)
trap_state ts[MAXTL_MAX];
uint32_t xcc; /* Extended integer condition codes */
uint32_t asi;
uint32_t pstate;
uint32_t tl;
Expand Down
45 changes: 44 additions & 1 deletion target/sparc/machine.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,42 @@ static const VMStateInfo vmstate_psr = {
.put = put_psr,
};

#ifdef TARGET_SPARC64
static int get_xcc(QEMUFile *f, void *opaque, size_t size,
const VMStateField *field)
{
SPARCCPU *cpu = opaque;
CPUSPARCState *env = &cpu->env;
uint32_t val = qemu_get_be32(f);

/* Do not clobber icc.[NV] */
env->cc_N = deposit64(env->cc_N, 32, 32, -(val & PSR_NEG));
env->cc_V = deposit64(env->cc_V, 32, 32, -(val & PSR_OVF));
env->xcc_Z = ~val & PSR_ZERO;
env->xcc_C = (val >> PSR_CARRY_SHIFT) & 1;

return 0;
}

static int put_xcc(QEMUFile *f, void *opaque, size_t size,
const VMStateField *field, JSONWriter *vmdesc)
{
SPARCCPU *cpu = opaque;
CPUSPARCState *env = &cpu->env;
uint32_t val = cpu_get_ccr(env);

/* Extract just xcc out of ccr and shift into legacy position. */
qemu_put_be32(f, (val & 0xf0) << (20 - 4));
return 0;
}

static const VMStateInfo vmstate_xcc = {
.name = "xcc",
.get = get_xcc,
.put = put_xcc,
};
#endif

static int cpu_pre_save(void *opaque)
{
SPARCCPU *cpu = opaque;
Expand Down Expand Up @@ -155,7 +191,14 @@ const VMStateDescription vmstate_sparc_cpu = {
VMSTATE_UINT32(env.mmu_version, SPARCCPU),
VMSTATE_STRUCT_ARRAY(env.ts, SPARCCPU, MAXTL_MAX, 0,
vmstate_trap_state, trap_state),
VMSTATE_UINT32(env.xcc, SPARCCPU),
{
.name = "xcc",
.version_id = 0,
.size = sizeof(uint32_t),
.info = &vmstate_xcc,
.flags = VMS_SINGLE,
.offset = 0,
},
VMSTATE_UINT32(env.asi, SPARCCPU),
VMSTATE_UINT32(env.pstate, SPARCCPU),
VMSTATE_UINT32(env.tl, SPARCCPU),
Expand Down

0 comments on commit 2a1905c

Please sign in to comment.