From 36d239587370c6ccfc53d7f6acc624ce5d61fe84 Mon Sep 17 00:00:00 2001 From: ths Date: Wed, 28 Feb 2007 22:37:42 +0000 Subject: [PATCH] MIPS FPU dynamic activation, part 1, by Herve Poussineau. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2463 c046a42c-6fe2-441c-8c8c-71466251a162 --- exec-all.h | 3 +- gdbstub.c | 50 ++++++++------- linux-user/main.c | 6 +- target-mips/cpu.h | 4 +- target-mips/exec.h | 2 - target-mips/mips-defs.h | 13 ++-- target-mips/op.c | 9 --- target-mips/op_helper.c | 2 - target-mips/op_mem.c | 2 - target-mips/translate.c | 134 ++++++++++++++++++---------------------- 10 files changed, 95 insertions(+), 130 deletions(-) diff --git a/exec-all.h b/exec-all.h index 82ef3acdca..73b85436c0 100644 --- a/exec-all.h +++ b/exec-all.h @@ -581,13 +581,12 @@ static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr) } pd = env->tlb_table[is_user][index].addr_code & ~TARGET_PAGE_MASK; if (pd > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) { - cpu_abort(env, "Trying to execute code outside RAM or ROM at 0x%08lx\n", addr); + cpu_abort(env, "Trying to execute code outside RAM or ROM at 0x" TARGET_FMT_lx "\n", addr); } return addr + env->tlb_table[is_user][index].addend - (unsigned long)phys_ram_base; } #endif - #ifdef USE_KQEMU #define KQEMU_MODIFY_PAGE_MASK (0xff & ~(VGA_DIRTY_FLAG | CODE_DIRTY_FLAG)) diff --git a/gdbstub.c b/gdbstub.c index 324af4d194..d1f1044894 100644 --- a/gdbstub.c +++ b/gdbstub.c @@ -568,20 +568,21 @@ static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf) *(uint32_t *)ptr = tswapl(env->PC); ptr += 4; -#ifdef MIPS_USES_FPU - for (i = 0; i < 32; i++) + if (env->CP0_Config1 & (1 << CP0C1_FP)) { - *(uint32_t *)ptr = tswapl(FPR_W (env, i)); + for (i = 0; i < 32; i++) + { + *(uint32_t *)ptr = tswapl(FPR_W (env, i)); + ptr += 4; + } + + *(uint32_t *)ptr = tswapl(env->fcr31); + ptr += 4; + + *(uint32_t *)ptr = tswapl(env->fcr0); ptr += 4; } - *(uint32_t *)ptr = tswapl(env->fcr31); - ptr += 4; - - *(uint32_t *)ptr = tswapl(env->fcr0); - ptr += 4; -#endif - /* 32 FP registers, fsr, fir, fp. Not yet implemented. */ /* what's 'fp' mean here? */ @@ -629,27 +630,28 @@ static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size) env->PC = tswapl(*(uint32_t *)ptr); ptr += 4; -#ifdef MIPS_USES_FPU - for (i = 0; i < 32; i++) + if (env->CP0_Config1 & (1 << CP0C1_FP)) { - FPR_W (env, i) = tswapl(*(uint32_t *)ptr); + for (i = 0; i < 32; i++) + { + FPR_W (env, i) = tswapl(*(uint32_t *)ptr); + ptr += 4; + } + + env->fcr31 = tswapl(*(uint32_t *)ptr) & 0x0183FFFF; ptr += 4; - } - env->fcr31 = tswapl(*(uint32_t *)ptr) & 0x0183FFFF; - ptr += 4; + env->fcr0 = tswapl(*(uint32_t *)ptr); + ptr += 4; - env->fcr0 = tswapl(*(uint32_t *)ptr); - ptr += 4; - - /* set rounding mode */ - RESTORE_ROUNDING_MODE; + /* set rounding mode */ + RESTORE_ROUNDING_MODE; #ifndef CONFIG_SOFTFLOAT - /* no floating point exception for native float */ - SET_FP_ENABLE(env->fcr31, 0); -#endif + /* no floating point exception for native float */ + SET_FP_ENABLE(env->fcr31, 0); #endif + } } #elif defined (TARGET_SH4) static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf) diff --git a/linux-user/main.c b/linux-user/main.c index 7199372b30..3eb573db69 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -1838,9 +1838,9 @@ int main(int argc, char **argv) env->gpr[i] = regs->regs[i]; } env->PC = regs->cp0_epc; -#ifdef MIPS_USES_FPU - env->CP0_Status |= (1 << CP0St_CU1); -#endif + if (env->CP0_Config1 & (1 << CP0C1_FP)) { + env->CP0_Status |= (1 << CP0St_CU1); + } } #elif defined(TARGET_SH4) { diff --git a/target-mips/cpu.h b/target-mips/cpu.h index 6068813dc6..21651beb0e 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -63,7 +63,6 @@ struct CPUMIPSState { #endif target_ulong HI, LO; uint32_t DCR; /* ? */ -#if defined(MIPS_USES_FPU) /* Floating point registers */ fpr_t fpr[16]; #define FPR(cpu, n) ((fpr_t*)&(cpu)->fpr[(n) / 2]) @@ -97,8 +96,7 @@ struct CPUMIPSState { #define FP_DIV0 8 #define FP_INVALID 16 #define FP_UNIMPLEMENTED 32 - -#endif + #if defined(MIPS_USES_R4K_TLB) tlb_t tlb[MIPS_TLB_MAX]; uint32_t tlb_in_use; diff --git a/target-mips/exec.h b/target-mips/exec.h index 1e9fa8e691..3815a00c42 100644 --- a/target-mips/exec.h +++ b/target-mips/exec.h @@ -115,12 +115,10 @@ void do_tlbwi (void); void do_tlbwr (void); void do_tlbp (void); void do_tlbr (void); -#ifdef MIPS_USES_FPU void dump_fpu(CPUState *env); void fpu_dump_state(CPUState *env, FILE *f, int (*fpu_fprintf)(FILE *f, const char *fmt, ...), int flags); -#endif void dump_sc (void); void do_lwl_raw (uint32_t); void do_lwr_raw (uint32_t); diff --git a/target-mips/mips-defs.h b/target-mips/mips-defs.h index 83480c6ab4..a78bef55ec 100644 --- a/target-mips/mips-defs.h +++ b/target-mips/mips-defs.h @@ -45,19 +45,14 @@ 2-way Icache, 64 sets Dcache, 16 bytes Dcache line, 2-way Dcache, no coprocessor2 attached, no MDMX support attached, no performance counters, watch registers present, - no code compression, EJTAG present, FPU enable bit depending on - MIPS_USES_FPU */ -#define MIPS_CONFIG1_1 \ + no code compression, EJTAG present, no FPU */ +#define MIPS_CONFIG1 \ ((1 << CP0C1_M) | ((MIPS_TLB_NB - 1) << CP0C1_MMU) | \ (0x0 << CP0C1_IS) | (0x3 << CP0C1_IL) | (0x1 << CP0C1_IA) | \ (0x0 << CP0C1_DS) | (0x3 << CP0C1_DL) | (0x1 << CP0C1_DA) | \ (0 << CP0C1_C2) | (0 << CP0C1_MD) | (0 << CP0C1_PC) | \ - (1 << CP0C1_WR) | (0 << CP0C1_CA) | (1 << CP0C1_EP)) -#ifdef MIPS_USES_FPU -#define MIPS_CONFIG1 (MIPS_CONFIG1_1 | (1 << CP0C1_FP)) -#else -#define MIPS_CONFIG1 (MIPS_CONFIG1_1 | (0 << CP0C1_FP)) -#endif + (1 << CP0C1_WR) | (0 << CP0C1_CA) | (1 << CP0C1_EP) | \ + (0 << CP0C1_FP)) /* Have config3, no tertiary/secondary caches implemented */ #define MIPS_CONFIG2 \ ((1 << CP0C2_M)) diff --git a/target-mips/op.c b/target-mips/op.c index 9b8dd60d9d..21795ad370 100644 --- a/target-mips/op.c +++ b/target-mips/op.c @@ -144,8 +144,6 @@ CALL_FROM_TB2(func, arg0, arg1); #include "op_template.c" #undef TN -#ifdef MIPS_USES_FPU - #define SFREG 0 #define DFREG 0 #include "fop_template.c" @@ -279,8 +277,6 @@ CALL_FROM_TB2(func, arg0, arg1); #include "fop_template.c" #undef FTN -#endif - void op_dup_T0 (void) { T2 = T0; @@ -924,7 +920,6 @@ void op_movz (void) RETURN(); } -#ifdef MIPS_USES_FPU void op_movf (void) { if (!(env->fcr31 & PARAM1)) @@ -938,7 +933,6 @@ void op_movt (void) env->gpr[PARAM2] = env->gpr[PARAM3]; RETURN(); } -#endif /* Tests */ #define OP_COND(name, cond) \ @@ -1645,8 +1639,6 @@ void op_dmtc0_errorepc (void) RETURN(); } -#ifdef MIPS_USES_FPU - #if 0 # define DEBUG_FPU_STATE() CALL_FROM_TB1(dump_fpu, env) #else @@ -2001,7 +1993,6 @@ void op_bc1t (void) DEBUG_FPU_STATE(); RETURN(); } -#endif /* MIPS_USES_FPU */ #if defined(MIPS_USES_R4K_TLB) void op_tlbwi (void) diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index 2e2df38a24..a262ea6684 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -331,7 +331,6 @@ void do_mtc0_status_irqraise_debug(void) fprintf(logfile, "Raise pending IRQs\n"); } -#ifdef MIPS_USES_FPU #include "softfloat.h" void fpu_handle_exception(void) @@ -370,7 +369,6 @@ void fpu_handle_exception(void) SET_FP_CAUSE(env->fcr31, 0); #endif } -#endif /* MIPS_USES_FPU */ /* TLB management */ #if defined(MIPS_USES_R4K_TLB) diff --git a/target-mips/op_mem.c b/target-mips/op_mem.c index a3289793b0..823cfe8092 100644 --- a/target-mips/op_mem.c +++ b/target-mips/op_mem.c @@ -192,7 +192,6 @@ void glue(op_scd, MEMSUFFIX) (void) } #endif /* MIPS_HAS_MIPS64 */ -#ifdef MIPS_USES_FPU void glue(op_lwc1, MEMSUFFIX) (void) { WT0 = glue(ldl, MEMSUFFIX)(T0); @@ -213,4 +212,3 @@ void glue(op_sdc1, MEMSUFFIX) (void) glue(stq, MEMSUFFIX)(T0, DT0); RETURN(); } -#endif diff --git a/target-mips/translate.c b/target-mips/translate.c index 7576fa3b38..5a77e906f1 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -391,8 +391,6 @@ GEN32(gen_op_load_gpr_T2, gen_op_load_gpr_T2_gpr); GEN32(gen_op_store_T0_gpr, gen_op_store_T0_gpr_gpr); GEN32(gen_op_store_T1_gpr, gen_op_store_T1_gpr_gpr); -#ifdef MIPS_USES_FPU - static const char *fregnames[] = { "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", @@ -476,8 +474,6 @@ static inline void gen_cmp_ ## fmt(int n) \ FOP_CONDS(d) FOP_CONDS(s) -#endif /* MIPS_USES_FPU */ - typedef struct DisasContext { struct TranslationBlock *tb; target_ulong pc, saved_pc; @@ -640,12 +636,10 @@ OP_LD_TABLE(bu); OP_ST_TABLE(b); OP_LD_TABLE(l); OP_ST_TABLE(c); -#ifdef MIPS_USES_FPU OP_LD_TABLE(wc1); OP_ST_TABLE(wc1); OP_LD_TABLE(dc1); OP_ST_TABLE(dc1); -#endif /* Load and store */ static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt, @@ -794,8 +788,6 @@ static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt, MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]); } -#ifdef MIPS_USES_FPU - /* Load and store */ static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft, int base, int16_t offset) @@ -843,8 +835,6 @@ static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft, MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]); } -#endif /* MIPS_USES_FPU */ - /* Arithmetic with immediate operand */ static void gen_arith_imm (DisasContext *ctx, uint32_t opc, int rt, int rs, int16_t imm) @@ -4111,8 +4101,6 @@ static void gen_cp0 (DisasContext *ctx, uint32_t opc, int rt, int rd) MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd); } -#ifdef MIPS_USES_FPU - /* CP1 Branches (before delay slot) */ static void gen_compute_branch1 (DisasContext *ctx, uint32_t op, int32_t offset) @@ -4531,8 +4519,6 @@ static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf) gen_op_movt(ccbit, rd, rs); } -#endif /* MIPS_USES_FPU */ - /* ISA extensions (ASEs) */ /* MIPS16 extension to MIPS32 */ /* SmartMIPS extension to MIPS32 */ @@ -4555,7 +4541,7 @@ static void gen_blikely(DisasContext *ctx) gen_set_label(l1); } -static void decode_opc (DisasContext *ctx) +static void decode_opc (CPUState *env, DisasContext *ctx) { int32_t offset; int rs, rt, rd, sa; @@ -4631,13 +4617,15 @@ static void decode_opc (DisasContext *ctx) /* Treat as a noop. */ break; -#ifdef MIPS_USES_FPU case OPC_MOVCI: - gen_op_cp1_enabled(); - gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7, - (ctx->opcode >> 16) & 1); + if (env->CP0_Config1 & (1 << CP0C1_FP)) { + gen_op_cp1_enabled(); + gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7, + (ctx->opcode >> 16) & 1); + } else { + generate_exception(ctx, EXCP_RI); + } break; -#endif #ifdef MIPS_HAS_MIPS64 /* MIPS64 specific opcodes */ @@ -4868,47 +4856,47 @@ static void decode_opc (DisasContext *ctx) case OPC_LDC1: case OPC_SWC1: case OPC_SDC1: -#if defined(MIPS_USES_FPU) - save_cpu_state(ctx, 1); - gen_op_cp1_enabled(); - gen_flt_ldst(ctx, op, rt, rs, imm); -#else - generate_exception_err(ctx, EXCP_CpU, 1); -#endif + if (env->CP0_Config1 & (1 << CP0C1_FP)) { + save_cpu_state(ctx, 1); + gen_op_cp1_enabled(); + gen_flt_ldst(ctx, op, rt, rs, imm); + } else { + generate_exception_err(ctx, EXCP_CpU, 1); + } break; case OPC_CP1: -#if defined(MIPS_USES_FPU) - save_cpu_state(ctx, 1); - gen_op_cp1_enabled(); - op1 = MASK_CP1(ctx->opcode); - switch (op1) { - case OPC_MFC1: - case OPC_CFC1: - case OPC_MTC1: - case OPC_CTC1: + if (env->CP0_Config1 & (1 << CP0C1_FP)) { + save_cpu_state(ctx, 1); + gen_op_cp1_enabled(); + op1 = MASK_CP1(ctx->opcode); + switch (op1) { + case OPC_MFC1: + case OPC_CFC1: + case OPC_MTC1: + case OPC_CTC1: #ifdef MIPS_HAS_MIPS64 - case OPC_DMFC1: - case OPC_DMTC1: + case OPC_DMFC1: + case OPC_DMTC1: #endif - gen_cp1(ctx, op1, rt, rd); - break; - case OPC_BC1: - gen_compute_branch1(ctx, MASK_CP1_BCOND(ctx->opcode), imm << 2); - return; - case OPC_S_FMT: - case OPC_D_FMT: - case OPC_W_FMT: - case OPC_L_FMT: - gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa); - break; - default: - generate_exception_err(ctx, EXCP_RI, 1); - break; + gen_cp1(ctx, op1, rt, rd); + break; + case OPC_BC1: + gen_compute_branch1(ctx, MASK_CP1_BCOND(ctx->opcode), imm << 2); + return; + case OPC_S_FMT: + case OPC_D_FMT: + case OPC_W_FMT: + case OPC_L_FMT: + gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa); + break; + default: + generate_exception_err(ctx, EXCP_RI, 1); + break; + } + } else { + generate_exception_err(ctx, EXCP_CpU, 1); } -#else - generate_exception_err(ctx, EXCP_CpU, 1); -#endif break; /* COP2. */ @@ -4921,18 +4909,20 @@ static void decode_opc (DisasContext *ctx) generate_exception_err(ctx, EXCP_CpU, 2); break; -#ifdef MIPS_USES_FPU case OPC_CP3: - gen_op_cp1_enabled(); - op1 = MASK_CP3(ctx->opcode); - switch (op1) { - /* Not implemented */ - default: - generate_exception_err(ctx, EXCP_RI, 1); - break; + if (env->CP0_Config1 & (1 << CP0C1_FP)) { + gen_op_cp1_enabled(); + op1 = MASK_CP3(ctx->opcode); + switch (op1) { + /* Not implemented */ + default: + generate_exception_err(ctx, EXCP_RI, 1); + break; + } + } else { + generate_exception(ctx, EXCP_RI); } break; -#endif #ifdef MIPS_HAS_MIPS64 /* MIPS64 opcodes */ @@ -5079,7 +5069,7 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, gen_opc_instr_start[lj] = 1; } ctx.opcode = ldl_code(ctx.pc); - decode_opc(&ctx); + decode_opc(env, &ctx); ctx.pc += 4; if (env->singlestep_enabled) @@ -5148,8 +5138,6 @@ int gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb) return gen_intermediate_code_internal(env, tb, 1); } -#ifdef MIPS_USES_FPU - void fpu_dump_state(CPUState *env, FILE *f, int (*fpu_fprintf)(FILE *f, const char *fmt, ...), int flags) @@ -5184,8 +5172,6 @@ void dump_fpu (CPUState *env) } } -#endif /* MIPS_USES_FPU */ - #if defined(MIPS_HAS_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS) /* Debug help: The architecture requires 32bit code to maintain proper sign-extened values on 64bit machines. */ @@ -5248,10 +5234,8 @@ void cpu_dump_state (CPUState *env, FILE *f, c0_status, env->CP0_Cause, env->CP0_EPC); cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n", env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr); -#ifdef MIPS_USES_FPU if (c0_status & (1 << CP0St_CU1)) fpu_dump_state(env, f, cpu_fprintf, flags); -#endif #if defined(MIPS_HAS_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS) cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags); #endif @@ -5295,6 +5279,10 @@ void cpu_reset (CPUMIPSState *env) env->CP0_EBase = 0x80000000; env->CP0_Config0 = MIPS_CONFIG0; env->CP0_Config1 = MIPS_CONFIG1; +#ifdef MIPS_USES_FPU + /* basic FPU register support */ + env->CP0_Config1 |= (1 << CP0C1_FP); +#endif env->CP0_Config2 = MIPS_CONFIG2; env->CP0_Config3 = MIPS_CONFIG3; env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL); @@ -5309,9 +5297,7 @@ void cpu_reset (CPUMIPSState *env) env->hflags |= MIPS_HFLAG_UM; env->user_mode_only = 1; #endif -#ifdef MIPS_USES_FPU - env->fcr0 = MIPS_FCR0; -#endif + env->fcr0 = MIPS_FCR0; /* XXX some guesswork here, values are CPU specific */ env->SYNCI_Step = 16; env->CCRes = 2;