Move the active FPU registers into env again, and use more TCG registers

to access them.

Signed-off-by: Thiemo Seufer <ths@networkno.de>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5252 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
ths 2008-09-18 11:57:27 +00:00
parent a1cf28f469
commit f01be15458
7 changed files with 338 additions and 322 deletions

View file

@ -731,16 +731,16 @@ static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
for (i = 0; i < 32; i++)
{
if (env->CP0_Status & (1 << CP0St_FR))
*(target_ulong *)ptr = tswapl(env->fpu->fpr[i].d);
*(target_ulong *)ptr = tswapl(env->active_fpu.fpr[i].d);
else
*(target_ulong *)ptr = tswap32(env->fpu->fpr[i].w[FP_ENDIAN_IDX]);
*(target_ulong *)ptr = tswap32(env->active_fpu.fpr[i].w[FP_ENDIAN_IDX]);
ptr += sizeof(target_ulong);
}
*(target_ulong *)ptr = (int32_t)tswap32(env->fpu->fcr31);
*(target_ulong *)ptr = (int32_t)tswap32(env->active_fpu.fcr31);
ptr += sizeof(target_ulong);
*(target_ulong *)ptr = (int32_t)tswap32(env->fpu->fcr0);
*(target_ulong *)ptr = (int32_t)tswap32(env->active_fpu.fcr0);
ptr += sizeof(target_ulong);
}
@ -771,7 +771,7 @@ static unsigned int ieee_rm[] =
float_round_down
};
#define RESTORE_ROUNDING_MODE \
set_float_rounding_mode(ieee_rm[env->fpu->fcr31 & 3], &env->fpu->fp_status)
set_float_rounding_mode(ieee_rm[env->active_fpu.fcr31 & 3], &env->active_fpu.fp_status)
static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
{
@ -808,13 +808,13 @@ static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
for (i = 0; i < 32; i++)
{
if (env->CP0_Status & (1 << CP0St_FR))
env->fpu->fpr[i].d = tswapl(*(target_ulong *)ptr);
env->active_fpu.fpr[i].d = tswapl(*(target_ulong *)ptr);
else
env->fpu->fpr[i].w[FP_ENDIAN_IDX] = tswapl(*(target_ulong *)ptr);
env->active_fpu.fpr[i].w[FP_ENDIAN_IDX] = tswapl(*(target_ulong *)ptr);
ptr += sizeof(target_ulong);
}
env->fpu->fcr31 = tswapl(*(target_ulong *)ptr) & 0xFF83FFFF;
env->active_fpu.fcr31 = tswapl(*(target_ulong *)ptr) & 0xFF83FFFF;
ptr += sizeof(target_ulong);
/* The remaining registers are assumed to be read-only. */

View file

@ -30,11 +30,6 @@ General
each ASID change. Using the MMU modes to implement ASIDs hinges on
implementing the global bit efficiently.
- save/restore of the CPU state is not implemented (see machine.c).
- Improve cpu state handling:
Step 1) Collect all the TC state in a single struct, so we need only
a single global pointer for the active TC.
Step 2) Use only a single TC context as working context, and copy the
contexts on TC switch. Likewise for FPU contexts.
MIPS64
------

View file

@ -84,9 +84,9 @@ struct CPUMIPSFPUContext {
#define FCR0_REV 0
/* fcsr */
uint32_t fcr31;
#define SET_FP_COND(num,env) do { ((env)->fcr31) |= ((num) ? (1 << ((num) + 24)) : (1 << 23)); } while(0)
#define CLEAR_FP_COND(num,env) do { ((env)->fcr31) &= ~((num) ? (1 << ((num) + 24)) : (1 << 23)); } while(0)
#define GET_FP_COND(env) ((((env)->fcr31 >> 24) & 0xfe) | (((env)->fcr31 >> 23) & 0x1))
#define SET_FP_COND(num,env) do { ((env).fcr31) |= ((num) ? (1 << ((num) + 24)) : (1 << 23)); } while(0)
#define CLEAR_FP_COND(num,env) do { ((env).fcr31) &= ~((num) ? (1 << ((num) + 24)) : (1 << 23)); } while(0)
#define GET_FP_COND(env) ((((env).fcr31 >> 24) & 0xfe) | (((env).fcr31 >> 23) & 0x1))
#define GET_FP_CAUSE(reg) (((reg) >> 12) & 0x3f)
#define GET_FP_ENABLE(reg) (((reg) >> 7) & 0x1f)
#define GET_FP_FLAGS(reg) (((reg) >> 2) & 0x1f)
@ -132,6 +132,7 @@ typedef struct mips_def_t mips_def_t;
#define MIPS_SHADOW_SET_MAX 16
#define MIPS_TC_MAX 5
#define MIPS_FPU_MAX 1
#define MIPS_DSP_ACC 4
typedef struct TCState TCState;
@ -170,11 +171,12 @@ struct TCState {
typedef struct CPUMIPSState CPUMIPSState;
struct CPUMIPSState {
TCState active_tc;
CPUMIPSFPUContext active_fpu;
CPUMIPSMVPContext *mvp;
CPUMIPSTLBContext *tlb;
CPUMIPSFPUContext *fpu;
uint32_t current_tc;
uint32_t current_fpu;
uint32_t SEGBITS;
uint32_t PABITS;
@ -404,6 +406,7 @@ struct CPUMIPSState {
int32_t CP0_DESAVE;
/* We waste some space so we can handle shadow registers like TCs. */
TCState tcs[MIPS_SHADOW_SET_MAX];
CPUMIPSFPUContext fpus[MIPS_FPU_MAX];
/* Qemu */
int error_code;
uint32_t hflags; /* CPU State */

View file

@ -86,7 +86,7 @@ static inline void compute_hflags(CPUState *env)
if (env->CP0_Status & (1 << CP0St_FR))
env->hflags |= MIPS_HFLAG_F64;
if (env->insn_flags & ISA_MIPS32R2) {
if (env->fpu->fcr0 & (1 << FCR0_F64))
if (env->active_fpu.fcr0 & (1 << FCR0_F64))
env->hflags |= MIPS_HFLAG_COP1X;
} else if (env->insn_flags & ISA_MIPS32) {
if (env->hflags & MIPS_HFLAG_64)

File diff suppressed because it is too large Load diff

View file

@ -423,7 +423,8 @@ enum {
};
/* global register indices */
static TCGv cpu_env, bcond, btarget, current_fpu;
static TCGv cpu_env, bcond, btarget;
static TCGv fpu_fpr32[32], fpu_fpr32h[32], fpu_fpr64[32], fpu_fcr0, fpu_fcr31;
#include "gen-icount.h"
@ -547,6 +548,18 @@ static const char *fregnames[] =
"f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
"f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", };
static const char *fregnames_64[] =
{ "F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7",
"F8", "F9", "F10", "F11", "F12", "F13", "F14", "F15",
"F16", "F17", "F18", "F19", "F20", "F21", "F22", "F23",
"F24", "F25", "F26", "F27", "F28", "F29", "F30", "F31", };
static const char *fregnames_h[] =
{ "h0", "h1", "h2", "h3", "h4", "h5", "h6", "h7",
"h8", "h9", "h10", "h11", "h12", "h13", "h14", "h15",
"h16", "h17", "h18", "h19", "h20", "h21", "h22", "h23",
"h24", "h25", "h26", "h27", "h28", "h29", "h30", "h31", };
#ifdef MIPS_DEBUG_DISAS
#define MIPS_DEBUG(fmt, args...) \
do { \
@ -652,57 +665,48 @@ static inline void gen_store_srsgpr (int from, int to)
/* Floating point register moves. */
static inline void gen_load_fpr32 (TCGv t, int reg)
{
tcg_gen_ld_i32(t, current_fpu, 8 * reg + 4 * FP_ENDIAN_IDX);
tcg_gen_mov_i32(t, fpu_fpr32[reg]);
}
static inline void gen_store_fpr32 (TCGv t, int reg)
{
tcg_gen_st_i32(t, current_fpu, 8 * reg + 4 * FP_ENDIAN_IDX);
tcg_gen_mov_i32(fpu_fpr32[reg], t);
}
static inline void gen_load_fpr64 (DisasContext *ctx, TCGv t, int reg)
{
if (ctx->hflags & MIPS_HFLAG_F64) {
tcg_gen_ld_i64(t, current_fpu, 8 * reg);
} else {
TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
if (ctx->hflags & MIPS_HFLAG_F64)
tcg_gen_mov_i64(t, fpu_fpr64[reg]);
else {
TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64);
tcg_gen_ld_i32(r_tmp1, current_fpu, 8 * (reg | 1) + 4 * FP_ENDIAN_IDX);
tcg_gen_extu_i32_i64(t, r_tmp1);
tcg_gen_extu_i32_i64(t, fpu_fpr32[reg | 1]);
tcg_gen_shli_i64(t, t, 32);
tcg_gen_ld_i32(r_tmp1, current_fpu, 8 * (reg & ~1) + 4 * FP_ENDIAN_IDX);
tcg_gen_extu_i32_i64(r_tmp2, r_tmp1);
tcg_gen_extu_i32_i64(r_tmp2, fpu_fpr32[reg & ~1]);
tcg_gen_or_i64(t, t, r_tmp2);
tcg_temp_free(r_tmp1);
tcg_temp_free(r_tmp2);
}
}
static inline void gen_store_fpr64 (DisasContext *ctx, TCGv t, int reg)
{
if (ctx->hflags & MIPS_HFLAG_F64) {
tcg_gen_st_i64(t, current_fpu, 8 * reg);
} else {
TCGv r_tmp = tcg_temp_new(TCG_TYPE_I32);
tcg_gen_trunc_i64_i32(r_tmp, t);
tcg_gen_st_i32(r_tmp, current_fpu, 8 * (reg & ~1) + 4 * FP_ENDIAN_IDX);
if (ctx->hflags & MIPS_HFLAG_F64)
tcg_gen_mov_i64(fpu_fpr64[reg], t);
else {
tcg_gen_trunc_i64_i32(fpu_fpr32[reg & ~1], t);
tcg_gen_shri_i64(t, t, 32);
tcg_gen_trunc_i64_i32(r_tmp, t);
tcg_gen_st_i32(r_tmp, current_fpu, 8 * (reg | 1) + 4 * FP_ENDIAN_IDX);
tcg_temp_free(r_tmp);
tcg_gen_trunc_i64_i32(fpu_fpr32[reg | 1], t);
}
}
static inline void gen_load_fpr32h (TCGv t, int reg)
{
tcg_gen_ld_i32(t, current_fpu, 8 * reg + 4 * !FP_ENDIAN_IDX);
tcg_gen_mov_i32(t, fpu_fpr32h[reg]);
}
static inline void gen_store_fpr32h (TCGv t, int reg)
{
tcg_gen_st_i32(t, current_fpu, 8 * reg + 4 * !FP_ENDIAN_IDX);
tcg_gen_mov_i32(fpu_fpr32h[reg], t);
}
static inline void get_fp_cond (TCGv t)
@ -710,10 +714,9 @@ static inline void get_fp_cond (TCGv t)
TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I32);
tcg_gen_ld_i32(r_tmp1, current_fpu, offsetof(CPUMIPSFPUContext, fcr31));
tcg_gen_shri_i32(r_tmp2, r_tmp1, 24);
tcg_gen_shri_i32(r_tmp2, fpu_fcr31, 24);
tcg_gen_andi_i32(r_tmp2, r_tmp2, 0xfe);
tcg_gen_shri_i32(r_tmp1, r_tmp1, 23);
tcg_gen_shri_i32(r_tmp1, fpu_fcr31, 23);
tcg_gen_andi_i32(r_tmp1, r_tmp1, 0x1);
tcg_gen_or_i32(t, r_tmp1, r_tmp2);
tcg_temp_free(r_tmp1);
@ -6009,8 +6012,7 @@ static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
gen_load_gpr(t0, rd);
gen_load_gpr(t1, rs);
tcg_gen_ld_i32(r_tmp, current_fpu, offsetof(CPUMIPSFPUContext, fcr31));
tcg_gen_andi_i32(r_tmp, r_tmp, ccbit);
tcg_gen_andi_i32(r_tmp, fpu_fcr31, ccbit);
tcg_gen_brcondi_i32(cond, r_tmp, 0, l1);
tcg_temp_free(r_tmp);
@ -6043,8 +6045,7 @@ static inline void gen_movcf_s (int fs, int fd, int cc, int tf)
gen_load_fpr32(fp0, fs);
gen_load_fpr32(fp1, fd);
tcg_gen_ld_i32(r_tmp1, current_fpu, offsetof(CPUMIPSFPUContext, fcr31));
tcg_gen_andi_i32(r_tmp1, r_tmp1, ccbit);
tcg_gen_andi_i32(r_tmp1, fpu_fcr31, ccbit);
tcg_gen_brcondi_i32(cond, r_tmp1, 0, l1);
tcg_gen_mov_i32(fp1, fp0);
tcg_temp_free(fp0);
@ -6075,8 +6076,7 @@ static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int t
gen_load_fpr64(ctx, fp0, fs);
gen_load_fpr64(ctx, fp1, fd);
tcg_gen_ld_i32(r_tmp1, current_fpu, offsetof(CPUMIPSFPUContext, fcr31));
tcg_gen_andi_i32(r_tmp1, r_tmp1, ccbit);
tcg_gen_andi_i32(r_tmp1, fpu_fcr31, ccbit);
tcg_gen_brcondi_i32(cond, r_tmp1, 0, l1);
tcg_gen_mov_i64(fp1, fp0);
tcg_temp_free(fp0);
@ -8632,11 +8632,11 @@ static void fpu_dump_state(CPUState *env, FILE *f,
fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%08x(0x%02x)\n",
env->fpu->fcr0, env->fpu->fcr31, is_fpu64, env->fpu->fp_status,
get_float_exception_flags(&env->fpu->fp_status));
env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64, env->active_fpu.fp_status,
get_float_exception_flags(&env->active_fpu.fp_status));
for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
fpu_fprintf(f, "%3s: ", fregnames[i]);
printfpr(&env->fpu->fpr[i]);
printfpr(&env->active_fpu.fpr[i]);
}
#undef printfpr
@ -8706,6 +8706,7 @@ void cpu_dump_state (CPUState *env, FILE *f,
static void mips_tcg_init(void)
{
int i;
static int inited;
/* Initialize various static tables. */
@ -8717,10 +8718,24 @@ static void mips_tcg_init(void)
offsetof(CPUState, bcond), "bcond");
btarget = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0,
offsetof(CPUState, btarget), "btarget");
current_fpu = tcg_global_mem_new(TCG_TYPE_PTR,
TCG_AREG0,
offsetof(CPUState, fpu),
"current_fpu");
for (i = 0; i < 32; i++)
fpu_fpr32[i] = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
offsetof(CPUState, active_fpu.fpr[i].w[FP_ENDIAN_IDX]),
fregnames[i]);
for (i = 0; i < 32; i++)
fpu_fpr64[i] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0,
offsetof(CPUState, active_fpu.fpr[i]),
fregnames_64[i]);
for (i = 0; i < 32; i++)
fpu_fpr32h[i] = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
offsetof(CPUState, active_fpu.fpr[i].w[!FP_ENDIAN_IDX]),
fregnames_h[i]);
fpu_fcr0 = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
offsetof(CPUState, active_fpu.fcr0),
"fcr0");
fpu_fcr31 = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
offsetof(CPUState, active_fpu.fcr31),
"fcr31");
/* register helpers */
#undef DEF_HELPER

View file

@ -489,14 +489,17 @@ static void mmu_init (CPUMIPSState *env, const mips_def_t *def)
static void fpu_init (CPUMIPSState *env, const mips_def_t *def)
{
env->fpu = qemu_mallocz(sizeof(CPUMIPSFPUContext));
int i;
env->fpu->fcr0 = def->CP1_fcr0;
for (i = 0; i < MIPS_FPU_MAX; i++)
env->fpus[i].fcr0 = def->CP1_fcr0;
memcpy(&env->active_fpu, &env->fpus[0], sizeof(env->active_fpu));
if (env->user_mode_only) {
if (env->CP0_Config1 & (1 << CP0C1_FP))
env->hflags |= MIPS_HFLAG_FPU;
#ifdef TARGET_MIPS64
if (env->fpu->fcr0 & (1 << FCR0_F64))
if (env->active_fpu.fcr0 & (1 << FCR0_F64))
env->hflags |= MIPS_HFLAG_F64;
#endif
}