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:
		
							parent
							
								
									29133e9a0f
								
							
						
					
					
						commit
						a80dde0837
					
				@ -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;
 | 
				
			||||||
 | 
				
			|||||||
@ -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 */
 | 
				
			||||||
 | 
				
			|||||||
@ -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;
 | 
				
			||||||
 | 
				
			|||||||
@ -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;
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user