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++) for (i = 0; i < 32; i++)
{ {
if (env->CP0_Status & (1 << CP0St_FR)) 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 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); 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); 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); ptr += sizeof(target_ulong);
} }
@ -771,7 +771,7 @@ static unsigned int ieee_rm[] =
float_round_down float_round_down
}; };
#define RESTORE_ROUNDING_MODE \ #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) 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++) for (i = 0; i < 32; i++)
{ {
if (env->CP0_Status & (1 << CP0St_FR)) 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 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); 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); ptr += sizeof(target_ulong);
/* The remaining registers are assumed to be read-only. */ /* 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 each ASID change. Using the MMU modes to implement ASIDs hinges on
implementing the global bit efficiently. implementing the global bit efficiently.
- save/restore of the CPU state is not implemented (see machine.c). - 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 MIPS64
------ ------

View File

@ -84,9 +84,9 @@ struct CPUMIPSFPUContext {
#define FCR0_REV 0 #define FCR0_REV 0
/* fcsr */ /* fcsr */
uint32_t fcr31; uint32_t fcr31;
#define SET_FP_COND(num,env) do { ((env)->fcr31) |= ((num) ? (1 << ((num) + 24)) : (1 << 23)); } while(0) #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 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_COND(env) ((((env).fcr31 >> 24) & 0xfe) | (((env).fcr31 >> 23) & 0x1))
#define GET_FP_CAUSE(reg) (((reg) >> 12) & 0x3f) #define GET_FP_CAUSE(reg) (((reg) >> 12) & 0x3f)
#define GET_FP_ENABLE(reg) (((reg) >> 7) & 0x1f) #define GET_FP_ENABLE(reg) (((reg) >> 7) & 0x1f)
#define GET_FP_FLAGS(reg) (((reg) >> 2) & 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_SHADOW_SET_MAX 16
#define MIPS_TC_MAX 5 #define MIPS_TC_MAX 5
#define MIPS_FPU_MAX 1
#define MIPS_DSP_ACC 4 #define MIPS_DSP_ACC 4
typedef struct TCState TCState; typedef struct TCState TCState;
@ -170,11 +171,12 @@ struct TCState {
typedef struct CPUMIPSState CPUMIPSState; typedef struct CPUMIPSState CPUMIPSState;
struct CPUMIPSState { struct CPUMIPSState {
TCState active_tc; TCState active_tc;
CPUMIPSFPUContext active_fpu;
CPUMIPSMVPContext *mvp; CPUMIPSMVPContext *mvp;
CPUMIPSTLBContext *tlb; CPUMIPSTLBContext *tlb;
CPUMIPSFPUContext *fpu;
uint32_t current_tc; uint32_t current_tc;
uint32_t current_fpu;
uint32_t SEGBITS; uint32_t SEGBITS;
uint32_t PABITS; uint32_t PABITS;
@ -404,6 +406,7 @@ struct CPUMIPSState {
int32_t CP0_DESAVE; int32_t CP0_DESAVE;
/* We waste some space so we can handle shadow registers like TCs. */ /* We waste some space so we can handle shadow registers like TCs. */
TCState tcs[MIPS_SHADOW_SET_MAX]; TCState tcs[MIPS_SHADOW_SET_MAX];
CPUMIPSFPUContext fpus[MIPS_FPU_MAX];
/* Qemu */ /* Qemu */
int error_code; int error_code;
uint32_t hflags; /* CPU State */ 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)) if (env->CP0_Status & (1 << CP0St_FR))
env->hflags |= MIPS_HFLAG_F64; env->hflags |= MIPS_HFLAG_F64;
if (env->insn_flags & ISA_MIPS32R2) { 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; env->hflags |= MIPS_HFLAG_COP1X;
} else if (env->insn_flags & ISA_MIPS32) { } else if (env->insn_flags & ISA_MIPS32) {
if (env->hflags & MIPS_HFLAG_64) 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 */ /* 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" #include "gen-icount.h"
@ -547,6 +548,18 @@ static const char *fregnames[] =
"f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
"f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", }; "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 #ifdef MIPS_DEBUG_DISAS
#define MIPS_DEBUG(fmt, args...) \ #define MIPS_DEBUG(fmt, args...) \
do { \ do { \
@ -652,57 +665,48 @@ static inline void gen_store_srsgpr (int from, int to)
/* Floating point register moves. */ /* Floating point register moves. */
static inline void gen_load_fpr32 (TCGv t, int reg) 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) 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) static inline void gen_load_fpr64 (DisasContext *ctx, TCGv t, int reg)
{ {
if (ctx->hflags & MIPS_HFLAG_F64) { if (ctx->hflags & MIPS_HFLAG_F64)
tcg_gen_ld_i64(t, current_fpu, 8 * reg); tcg_gen_mov_i64(t, fpu_fpr64[reg]);
} else { else {
TCGv r_tmp1 = tcg_temp_new(TCG_TYPE_I32);
TCGv r_tmp2 = tcg_temp_new(TCG_TYPE_I64); 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, fpu_fpr32[reg | 1]);
tcg_gen_extu_i32_i64(t, r_tmp1);
tcg_gen_shli_i64(t, t, 32); 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, fpu_fpr32[reg & ~1]);
tcg_gen_extu_i32_i64(r_tmp2, r_tmp1);
tcg_gen_or_i64(t, t, r_tmp2); tcg_gen_or_i64(t, t, r_tmp2);
tcg_temp_free(r_tmp1);
tcg_temp_free(r_tmp2); tcg_temp_free(r_tmp2);
} }
} }
static inline void gen_store_fpr64 (DisasContext *ctx, TCGv t, int reg) static inline void gen_store_fpr64 (DisasContext *ctx, TCGv t, int reg)
{ {
if (ctx->hflags & MIPS_HFLAG_F64) { if (ctx->hflags & MIPS_HFLAG_F64)
tcg_gen_st_i64(t, current_fpu, 8 * reg); tcg_gen_mov_i64(fpu_fpr64[reg], t);
} else { else {
TCGv r_tmp = tcg_temp_new(TCG_TYPE_I32); tcg_gen_trunc_i64_i32(fpu_fpr32[reg & ~1], t);
tcg_gen_trunc_i64_i32(r_tmp, t);
tcg_gen_st_i32(r_tmp, current_fpu, 8 * (reg & ~1) + 4 * FP_ENDIAN_IDX);
tcg_gen_shri_i64(t, t, 32); tcg_gen_shri_i64(t, t, 32);
tcg_gen_trunc_i64_i32(r_tmp, t); tcg_gen_trunc_i64_i32(fpu_fpr32[reg | 1], t);
tcg_gen_st_i32(r_tmp, current_fpu, 8 * (reg | 1) + 4 * FP_ENDIAN_IDX);
tcg_temp_free(r_tmp);
} }
} }
static inline void gen_load_fpr32h (TCGv t, int reg) 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) 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) 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_tmp1 = tcg_temp_new(TCG_TYPE_I32);
TCGv r_tmp2 = 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, fpu_fcr31, 24);
tcg_gen_shri_i32(r_tmp2, r_tmp1, 24);
tcg_gen_andi_i32(r_tmp2, r_tmp2, 0xfe); 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_andi_i32(r_tmp1, r_tmp1, 0x1);
tcg_gen_or_i32(t, r_tmp1, r_tmp2); tcg_gen_or_i32(t, r_tmp1, r_tmp2);
tcg_temp_free(r_tmp1); 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(t0, rd);
gen_load_gpr(t1, rs); gen_load_gpr(t1, rs);
tcg_gen_ld_i32(r_tmp, current_fpu, offsetof(CPUMIPSFPUContext, fcr31)); tcg_gen_andi_i32(r_tmp, fpu_fcr31, ccbit);
tcg_gen_andi_i32(r_tmp, r_tmp, ccbit);
tcg_gen_brcondi_i32(cond, r_tmp, 0, l1); tcg_gen_brcondi_i32(cond, r_tmp, 0, l1);
tcg_temp_free(r_tmp); 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(fp0, fs);
gen_load_fpr32(fp1, fd); gen_load_fpr32(fp1, fd);
tcg_gen_ld_i32(r_tmp1, current_fpu, offsetof(CPUMIPSFPUContext, fcr31)); tcg_gen_andi_i32(r_tmp1, fpu_fcr31, ccbit);
tcg_gen_andi_i32(r_tmp1, r_tmp1, ccbit);
tcg_gen_brcondi_i32(cond, r_tmp1, 0, l1); tcg_gen_brcondi_i32(cond, r_tmp1, 0, l1);
tcg_gen_mov_i32(fp1, fp0); tcg_gen_mov_i32(fp1, fp0);
tcg_temp_free(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, fp0, fs);
gen_load_fpr64(ctx, fp1, fd); gen_load_fpr64(ctx, fp1, fd);
tcg_gen_ld_i32(r_tmp1, current_fpu, offsetof(CPUMIPSFPUContext, fcr31)); tcg_gen_andi_i32(r_tmp1, fpu_fcr31, ccbit);
tcg_gen_andi_i32(r_tmp1, r_tmp1, ccbit);
tcg_gen_brcondi_i32(cond, r_tmp1, 0, l1); tcg_gen_brcondi_i32(cond, r_tmp1, 0, l1);
tcg_gen_mov_i64(fp1, fp0); tcg_gen_mov_i64(fp1, fp0);
tcg_temp_free(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", 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, env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64, env->active_fpu.fp_status,
get_float_exception_flags(&env->fpu->fp_status)); get_float_exception_flags(&env->active_fpu.fp_status));
for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) { for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
fpu_fprintf(f, "%3s: ", fregnames[i]); fpu_fprintf(f, "%3s: ", fregnames[i]);
printfpr(&env->fpu->fpr[i]); printfpr(&env->active_fpu.fpr[i]);
} }
#undef printfpr #undef printfpr
@ -8706,6 +8706,7 @@ void cpu_dump_state (CPUState *env, FILE *f,
static void mips_tcg_init(void) static void mips_tcg_init(void)
{ {
int i;
static int inited; static int inited;
/* Initialize various static tables. */ /* Initialize various static tables. */
@ -8717,10 +8718,24 @@ static void mips_tcg_init(void)
offsetof(CPUState, bcond), "bcond"); offsetof(CPUState, bcond), "bcond");
btarget = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0, btarget = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0,
offsetof(CPUState, btarget), "btarget"); offsetof(CPUState, btarget), "btarget");
current_fpu = tcg_global_mem_new(TCG_TYPE_PTR, for (i = 0; i < 32; i++)
TCG_AREG0, fpu_fpr32[i] = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
offsetof(CPUState, fpu), offsetof(CPUState, active_fpu.fpr[i].w[FP_ENDIAN_IDX]),
"current_fpu"); 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 */ /* register helpers */
#undef DEF_HELPER #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) 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->user_mode_only) {
if (env->CP0_Config1 & (1 << CP0C1_FP)) if (env->CP0_Config1 & (1 << CP0C1_FP))
env->hflags |= MIPS_HFLAG_FPU; env->hflags |= MIPS_HFLAG_FPU;
#ifdef TARGET_MIPS64 #ifdef TARGET_MIPS64
if (env->fpu->fcr0 & (1 << FCR0_F64)) if (env->active_fpu.fcr0 & (1 << FCR0_F64))
env->hflags |= MIPS_HFLAG_F64; env->hflags |= MIPS_HFLAG_F64;
#endif #endif
} }