SPARC FPU optimization (Blue Swirl)

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2023 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
bellard 2006-06-26 19:53:29 +00:00
parent 29133e9a0f
commit a80dde0837
4 changed files with 50 additions and 37 deletions

View File

@ -175,9 +175,13 @@ static inline TranslationBlock *tb_find_fast(void)
pc = env->regs[15]; pc = env->regs[15];
#elif defined(TARGET_SPARC) #elif defined(TARGET_SPARC)
#ifdef TARGET_SPARC64 #ifdef TARGET_SPARC64
flags = (env->pstate << 2) | ((env->lsu & (DMMU_E | IMMU_E)) >> 2); // Combined FPU enable bits . PRIV . DMMU enabled . IMMU enabled
flags = (((env->pstate & PS_PEF) >> 1) | ((env->fprs & FPRS_FEF) << 2))
| (env->pstate & PS_PRIV) | ((env->lsu & (DMMU_E | IMMU_E)) >> 2);
#else #else
flags = env->psrs | ((env->mmuregs[0] & (MMU_E | MMU_NF)) << 1); // FPU enable . MMU enabled . MMU no-fault . Supervisor
flags = (env->psref << 3) | ((env->mmuregs[0] & (MMU_E | MMU_NF)) << 1)
| env->psrs;
#endif #endif
cs_base = env->npc; cs_base = env->npc;
pc = env->pc; pc = env->pc;

View File

@ -78,6 +78,8 @@
#define PS_PRIV (1<<2) #define PS_PRIV (1<<2)
#define PS_IE (1<<1) #define PS_IE (1<<1)
#define PS_AG (1<<0) #define PS_AG (1<<0)
#define FPRS_FEF (1<<2)
#endif #endif
/* Fcc */ /* Fcc */

View File

@ -1017,15 +1017,6 @@ void OPPROTO op_trapcc_T0(void)
FORCE_RET(); FORCE_RET();
} }
void OPPROTO op_trap_ifnofpu(void)
{
if (!env->psref) {
env->exception_index = TT_NFPU_INSN;
cpu_loop_exit();
}
FORCE_RET();
}
void OPPROTO op_fpexception_im(void) void OPPROTO op_fpexception_im(void)
{ {
env->exception_index = TT_FP_EXCP; env->exception_index = TT_FP_EXCP;

View File

@ -52,6 +52,7 @@ typedef struct DisasContext {
target_ulong jump_pc[2]; /* used when JUMP_PC pc value is used */ target_ulong jump_pc[2]; /* used when JUMP_PC pc value is used */
int is_br; int is_br;
int mem_idx; int mem_idx;
int fpu_enabled;
struct TranslationBlock *tb; struct TranslationBlock *tb;
} DisasContext; } DisasContext;
@ -935,6 +936,19 @@ static GenOpFunc * const gen_fcmpd[4] = {
}; };
#endif #endif
static int gen_trap_ifnofpu(DisasContext * dc)
{
#if !defined(CONFIG_USER_ONLY)
if (!dc->fpu_enabled) {
save_state(dc);
gen_op_exception(TT_NFPU_INSN);
dc->is_br = 1;
return 1;
}
#endif
return 0;
}
/* before an instruction, dc->pc must be static */ /* before an instruction, dc->pc must be static */
static void disas_sparc_insn(DisasContext * dc) static void disas_sparc_insn(DisasContext * dc)
{ {
@ -981,10 +995,8 @@ static void disas_sparc_insn(DisasContext * dc)
case 0x5: /* V9 FBPcc */ case 0x5: /* V9 FBPcc */
{ {
int cc = GET_FIELD_SP(insn, 20, 21); int cc = GET_FIELD_SP(insn, 20, 21);
#if !defined(CONFIG_USER_ONLY) if (gen_trap_ifnofpu(dc))
save_state(dc); goto jmp_insn;
gen_op_trap_ifnofpu();
#endif
target = GET_FIELD_SP(insn, 0, 18); target = GET_FIELD_SP(insn, 0, 18);
target = sign_extend(target, 19); target = sign_extend(target, 19);
target <<= 2; target <<= 2;
@ -1002,10 +1014,8 @@ static void disas_sparc_insn(DisasContext * dc)
} }
case 0x6: /* FBN+x */ case 0x6: /* FBN+x */
{ {
#if !defined(CONFIG_USER_ONLY) if (gen_trap_ifnofpu(dc))
save_state(dc); goto jmp_insn;
gen_op_trap_ifnofpu();
#endif
target = GET_FIELD(insn, 10, 31); target = GET_FIELD(insn, 10, 31);
target = sign_extend(target, 22); target = sign_extend(target, 22);
target <<= 2; target <<= 2;
@ -1079,16 +1089,16 @@ static void disas_sparc_insn(DisasContext * dc)
} }
#endif #endif
} }
save_state(dc);
cond = GET_FIELD(insn, 3, 6); cond = GET_FIELD(insn, 3, 6);
if (cond == 0x8) { if (cond == 0x8) {
save_state(dc);
gen_op_trap_T0(); gen_op_trap_T0();
dc->is_br = 1;
goto jmp_insn;
} else if (cond != 0) { } else if (cond != 0) {
#ifdef TARGET_SPARC64 #ifdef TARGET_SPARC64
/* V9 icc/xcc */ /* V9 icc/xcc */
int cc = GET_FIELD_SP(insn, 11, 12); int cc = GET_FIELD_SP(insn, 11, 12);
flush_T2(dc);
save_state(dc);
if (cc == 0) if (cc == 0)
gen_cond[0][cond](); gen_cond[0][cond]();
else if (cc == 2) else if (cc == 2)
@ -1096,10 +1106,17 @@ static void disas_sparc_insn(DisasContext * dc)
else else
goto illegal_insn; goto illegal_insn;
#else #else
flush_T2(dc);
save_state(dc);
gen_cond[0][cond](); gen_cond[0][cond]();
#endif #endif
gen_op_trapcc_T0(); gen_op_trapcc_T0();
} }
gen_op_next_insn();
gen_op_movl_T0_0();
gen_op_exit_tb();
dc->is_br = 1;
goto jmp_insn;
} else if (xop == 0x28) { } else if (xop == 0x28) {
rs1 = GET_FIELD(insn, 13, 17); rs1 = GET_FIELD(insn, 13, 17);
switch(rs1) { switch(rs1) {
@ -1241,10 +1258,8 @@ static void disas_sparc_insn(DisasContext * dc)
break; break;
#endif #endif
} else if (xop == 0x34) { /* FPU Operations */ } else if (xop == 0x34) { /* FPU Operations */
#if !defined(CONFIG_USER_ONLY) if (gen_trap_ifnofpu(dc))
save_state(dc); goto jmp_insn;
gen_op_trap_ifnofpu();
#endif
rs1 = GET_FIELD(insn, 13, 17); rs1 = GET_FIELD(insn, 13, 17);
rs2 = GET_FIELD(insn, 27, 31); rs2 = GET_FIELD(insn, 27, 31);
xop = GET_FIELD(insn, 18, 26); xop = GET_FIELD(insn, 18, 26);
@ -1430,10 +1445,8 @@ static void disas_sparc_insn(DisasContext * dc)
#ifdef TARGET_SPARC64 #ifdef TARGET_SPARC64
int cond; int cond;
#endif #endif
#if !defined(CONFIG_USER_ONLY) if (gen_trap_ifnofpu(dc))
save_state(dc); goto jmp_insn;
gen_op_trap_ifnofpu();
#endif
rs1 = GET_FIELD(insn, 13, 17); rs1 = GET_FIELD(insn, 13, 17);
rs2 = GET_FIELD(insn, 27, 31); rs2 = GET_FIELD(insn, 27, 31);
xop = GET_FIELD(insn, 18, 26); xop = GET_FIELD(insn, 18, 26);
@ -2366,10 +2379,8 @@ static void disas_sparc_insn(DisasContext * dc)
skip_move: ; skip_move: ;
#endif #endif
} else if (xop >= 0x20 && xop < 0x24) { } else if (xop >= 0x20 && xop < 0x24) {
#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64) if (gen_trap_ifnofpu(dc))
save_state(dc); goto jmp_insn;
gen_op_trap_ifnofpu();
#endif
switch (xop) { switch (xop) {
case 0x20: /* load fpreg */ case 0x20: /* load fpreg */
gen_op_ldst(ldf); gen_op_ldst(ldf);
@ -2450,9 +2461,8 @@ static void disas_sparc_insn(DisasContext * dc)
goto illegal_insn; goto illegal_insn;
} }
} else if (xop > 0x23 && xop < 0x28) { } else if (xop > 0x23 && xop < 0x28) {
#if !defined(CONFIG_USER_ONLY) if (gen_trap_ifnofpu(dc))
gen_op_trap_ifnofpu(); goto jmp_insn;
#endif
switch (xop) { switch (xop) {
case 0x24: case 0x24:
gen_op_load_fpr_FT0(rd); gen_op_load_fpr_FT0(rd);
@ -2548,8 +2558,14 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb,
dc->npc = (target_ulong) tb->cs_base; dc->npc = (target_ulong) tb->cs_base;
#if defined(CONFIG_USER_ONLY) #if defined(CONFIG_USER_ONLY)
dc->mem_idx = 0; dc->mem_idx = 0;
dc->fpu_enabled = 1;
#else #else
dc->mem_idx = ((env->psrs) != 0); dc->mem_idx = ((env->psrs) != 0);
#ifdef TARGET_SPARC64
dc->fpu_enabled = (((env->pstate & PS_PEF) != 0) && ((env->fprs & FPRS_FEF) != 0));
#else
dc->fpu_enabled = ((env->psref) != 0);
#endif
#endif #endif
gen_opc_ptr = gen_opc_buf; gen_opc_ptr = gen_opc_buf;
gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;