Commit a80dde08372ca86b48363dfee019af0dc3bc97aa

Authored by bellard
1 parent 29133e9a

SPARC FPU optimization (Blue Swirl)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2023 c046a42c-6fe2-441c-8c8c-71466251a162
cpu-exec.c
@@ -175,9 +175,13 @@ static inline TranslationBlock *tb_find_fast(void) @@ -175,9 +175,13 @@ static inline TranslationBlock *tb_find_fast(void)
175 pc = env->regs[15]; 175 pc = env->regs[15];
176 #elif defined(TARGET_SPARC) 176 #elif defined(TARGET_SPARC)
177 #ifdef TARGET_SPARC64 177 #ifdef TARGET_SPARC64
178 - flags = (env->pstate << 2) | ((env->lsu & (DMMU_E | IMMU_E)) >> 2); 178 + // Combined FPU enable bits . PRIV . DMMU enabled . IMMU enabled
  179 + flags = (((env->pstate & PS_PEF) >> 1) | ((env->fprs & FPRS_FEF) << 2))
  180 + | (env->pstate & PS_PRIV) | ((env->lsu & (DMMU_E | IMMU_E)) >> 2);
179 #else 181 #else
180 - flags = env->psrs | ((env->mmuregs[0] & (MMU_E | MMU_NF)) << 1); 182 + // FPU enable . MMU enabled . MMU no-fault . Supervisor
  183 + flags = (env->psref << 3) | ((env->mmuregs[0] & (MMU_E | MMU_NF)) << 1)
  184 + | env->psrs;
181 #endif 185 #endif
182 cs_base = env->npc; 186 cs_base = env->npc;
183 pc = env->pc; 187 pc = env->pc;
target-sparc/cpu.h
@@ -78,6 +78,8 @@ @@ -78,6 +78,8 @@
78 #define PS_PRIV (1<<2) 78 #define PS_PRIV (1<<2)
79 #define PS_IE (1<<1) 79 #define PS_IE (1<<1)
80 #define PS_AG (1<<0) 80 #define PS_AG (1<<0)
  81 +
  82 +#define FPRS_FEF (1<<2)
81 #endif 83 #endif
82 84
83 /* Fcc */ 85 /* Fcc */
target-sparc/op.c
@@ -1017,15 +1017,6 @@ void OPPROTO op_trapcc_T0(void) @@ -1017,15 +1017,6 @@ void OPPROTO op_trapcc_T0(void)
1017 FORCE_RET(); 1017 FORCE_RET();
1018 } 1018 }
1019 1019
1020 -void OPPROTO op_trap_ifnofpu(void)  
1021 -{  
1022 - if (!env->psref) {  
1023 - env->exception_index = TT_NFPU_INSN;  
1024 - cpu_loop_exit();  
1025 - }  
1026 - FORCE_RET();  
1027 -}  
1028 -  
1029 void OPPROTO op_fpexception_im(void) 1020 void OPPROTO op_fpexception_im(void)
1030 { 1021 {
1031 env->exception_index = TT_FP_EXCP; 1022 env->exception_index = TT_FP_EXCP;
target-sparc/translate.c
@@ -52,6 +52,7 @@ typedef struct DisasContext { @@ -52,6 +52,7 @@ typedef struct DisasContext {
52 target_ulong jump_pc[2]; /* used when JUMP_PC pc value is used */ 52 target_ulong jump_pc[2]; /* used when JUMP_PC pc value is used */
53 int is_br; 53 int is_br;
54 int mem_idx; 54 int mem_idx;
  55 + int fpu_enabled;
55 struct TranslationBlock *tb; 56 struct TranslationBlock *tb;
56 } DisasContext; 57 } DisasContext;
57 58
@@ -935,6 +936,19 @@ static GenOpFunc * const gen_fcmpd[4] = { @@ -935,6 +936,19 @@ static GenOpFunc * const gen_fcmpd[4] = {
935 }; 936 };
936 #endif 937 #endif
937 938
  939 +static int gen_trap_ifnofpu(DisasContext * dc)
  940 +{
  941 +#if !defined(CONFIG_USER_ONLY)
  942 + if (!dc->fpu_enabled) {
  943 + save_state(dc);
  944 + gen_op_exception(TT_NFPU_INSN);
  945 + dc->is_br = 1;
  946 + return 1;
  947 + }
  948 +#endif
  949 + return 0;
  950 +}
  951 +
938 /* before an instruction, dc->pc must be static */ 952 /* before an instruction, dc->pc must be static */
939 static void disas_sparc_insn(DisasContext * dc) 953 static void disas_sparc_insn(DisasContext * dc)
940 { 954 {
@@ -981,10 +995,8 @@ static void disas_sparc_insn(DisasContext * dc) @@ -981,10 +995,8 @@ static void disas_sparc_insn(DisasContext * dc)
981 case 0x5: /* V9 FBPcc */ 995 case 0x5: /* V9 FBPcc */
982 { 996 {
983 int cc = GET_FIELD_SP(insn, 20, 21); 997 int cc = GET_FIELD_SP(insn, 20, 21);
984 -#if !defined(CONFIG_USER_ONLY)  
985 - save_state(dc);  
986 - gen_op_trap_ifnofpu();  
987 -#endif 998 + if (gen_trap_ifnofpu(dc))
  999 + goto jmp_insn;
988 target = GET_FIELD_SP(insn, 0, 18); 1000 target = GET_FIELD_SP(insn, 0, 18);
989 target = sign_extend(target, 19); 1001 target = sign_extend(target, 19);
990 target <<= 2; 1002 target <<= 2;
@@ -1002,10 +1014,8 @@ static void disas_sparc_insn(DisasContext * dc) @@ -1002,10 +1014,8 @@ static void disas_sparc_insn(DisasContext * dc)
1002 } 1014 }
1003 case 0x6: /* FBN+x */ 1015 case 0x6: /* FBN+x */
1004 { 1016 {
1005 -#if !defined(CONFIG_USER_ONLY)  
1006 - save_state(dc);  
1007 - gen_op_trap_ifnofpu();  
1008 -#endif 1017 + if (gen_trap_ifnofpu(dc))
  1018 + goto jmp_insn;
1009 target = GET_FIELD(insn, 10, 31); 1019 target = GET_FIELD(insn, 10, 31);
1010 target = sign_extend(target, 22); 1020 target = sign_extend(target, 22);
1011 target <<= 2; 1021 target <<= 2;
@@ -1079,16 +1089,16 @@ static void disas_sparc_insn(DisasContext * dc) @@ -1079,16 +1089,16 @@ static void disas_sparc_insn(DisasContext * dc)
1079 } 1089 }
1080 #endif 1090 #endif
1081 } 1091 }
1082 - save_state(dc);  
1083 cond = GET_FIELD(insn, 3, 6); 1092 cond = GET_FIELD(insn, 3, 6);
1084 if (cond == 0x8) { 1093 if (cond == 0x8) {
  1094 + save_state(dc);
1085 gen_op_trap_T0(); 1095 gen_op_trap_T0();
1086 - dc->is_br = 1;  
1087 - goto jmp_insn;  
1088 } else if (cond != 0) { 1096 } else if (cond != 0) {
1089 #ifdef TARGET_SPARC64 1097 #ifdef TARGET_SPARC64
1090 /* V9 icc/xcc */ 1098 /* V9 icc/xcc */
1091 int cc = GET_FIELD_SP(insn, 11, 12); 1099 int cc = GET_FIELD_SP(insn, 11, 12);
  1100 + flush_T2(dc);
  1101 + save_state(dc);
1092 if (cc == 0) 1102 if (cc == 0)
1093 gen_cond[0][cond](); 1103 gen_cond[0][cond]();
1094 else if (cc == 2) 1104 else if (cc == 2)
@@ -1096,10 +1106,17 @@ static void disas_sparc_insn(DisasContext * dc) @@ -1096,10 +1106,17 @@ static void disas_sparc_insn(DisasContext * dc)
1096 else 1106 else
1097 goto illegal_insn; 1107 goto illegal_insn;
1098 #else 1108 #else
  1109 + flush_T2(dc);
  1110 + save_state(dc);
1099 gen_cond[0][cond](); 1111 gen_cond[0][cond]();
1100 #endif 1112 #endif
1101 gen_op_trapcc_T0(); 1113 gen_op_trapcc_T0();
1102 } 1114 }
  1115 + gen_op_next_insn();
  1116 + gen_op_movl_T0_0();
  1117 + gen_op_exit_tb();
  1118 + dc->is_br = 1;
  1119 + goto jmp_insn;
1103 } else if (xop == 0x28) { 1120 } else if (xop == 0x28) {
1104 rs1 = GET_FIELD(insn, 13, 17); 1121 rs1 = GET_FIELD(insn, 13, 17);
1105 switch(rs1) { 1122 switch(rs1) {
@@ -1241,10 +1258,8 @@ static void disas_sparc_insn(DisasContext * dc) @@ -1241,10 +1258,8 @@ static void disas_sparc_insn(DisasContext * dc)
1241 break; 1258 break;
1242 #endif 1259 #endif
1243 } else if (xop == 0x34) { /* FPU Operations */ 1260 } else if (xop == 0x34) { /* FPU Operations */
1244 -#if !defined(CONFIG_USER_ONLY)  
1245 - save_state(dc);  
1246 - gen_op_trap_ifnofpu();  
1247 -#endif 1261 + if (gen_trap_ifnofpu(dc))
  1262 + goto jmp_insn;
1248 rs1 = GET_FIELD(insn, 13, 17); 1263 rs1 = GET_FIELD(insn, 13, 17);
1249 rs2 = GET_FIELD(insn, 27, 31); 1264 rs2 = GET_FIELD(insn, 27, 31);
1250 xop = GET_FIELD(insn, 18, 26); 1265 xop = GET_FIELD(insn, 18, 26);
@@ -1430,10 +1445,8 @@ static void disas_sparc_insn(DisasContext * dc) @@ -1430,10 +1445,8 @@ static void disas_sparc_insn(DisasContext * dc)
1430 #ifdef TARGET_SPARC64 1445 #ifdef TARGET_SPARC64
1431 int cond; 1446 int cond;
1432 #endif 1447 #endif
1433 -#if !defined(CONFIG_USER_ONLY)  
1434 - save_state(dc);  
1435 - gen_op_trap_ifnofpu();  
1436 -#endif 1448 + if (gen_trap_ifnofpu(dc))
  1449 + goto jmp_insn;
1437 rs1 = GET_FIELD(insn, 13, 17); 1450 rs1 = GET_FIELD(insn, 13, 17);
1438 rs2 = GET_FIELD(insn, 27, 31); 1451 rs2 = GET_FIELD(insn, 27, 31);
1439 xop = GET_FIELD(insn, 18, 26); 1452 xop = GET_FIELD(insn, 18, 26);
@@ -2366,10 +2379,8 @@ static void disas_sparc_insn(DisasContext * dc) @@ -2366,10 +2379,8 @@ static void disas_sparc_insn(DisasContext * dc)
2366 skip_move: ; 2379 skip_move: ;
2367 #endif 2380 #endif
2368 } else if (xop >= 0x20 && xop < 0x24) { 2381 } else if (xop >= 0x20 && xop < 0x24) {
2369 -#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)  
2370 - save_state(dc);  
2371 - gen_op_trap_ifnofpu();  
2372 -#endif 2382 + if (gen_trap_ifnofpu(dc))
  2383 + goto jmp_insn;
2373 switch (xop) { 2384 switch (xop) {
2374 case 0x20: /* load fpreg */ 2385 case 0x20: /* load fpreg */
2375 gen_op_ldst(ldf); 2386 gen_op_ldst(ldf);
@@ -2450,9 +2461,8 @@ static void disas_sparc_insn(DisasContext * dc) @@ -2450,9 +2461,8 @@ static void disas_sparc_insn(DisasContext * dc)
2450 goto illegal_insn; 2461 goto illegal_insn;
2451 } 2462 }
2452 } else if (xop > 0x23 && xop < 0x28) { 2463 } else if (xop > 0x23 && xop < 0x28) {
2453 -#if !defined(CONFIG_USER_ONLY)  
2454 - gen_op_trap_ifnofpu();  
2455 -#endif 2464 + if (gen_trap_ifnofpu(dc))
  2465 + goto jmp_insn;
2456 switch (xop) { 2466 switch (xop) {
2457 case 0x24: 2467 case 0x24:
2458 gen_op_load_fpr_FT0(rd); 2468 gen_op_load_fpr_FT0(rd);
@@ -2548,8 +2558,14 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb, @@ -2548,8 +2558,14 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb,
2548 dc->npc = (target_ulong) tb->cs_base; 2558 dc->npc = (target_ulong) tb->cs_base;
2549 #if defined(CONFIG_USER_ONLY) 2559 #if defined(CONFIG_USER_ONLY)
2550 dc->mem_idx = 0; 2560 dc->mem_idx = 0;
  2561 + dc->fpu_enabled = 1;
2551 #else 2562 #else
2552 dc->mem_idx = ((env->psrs) != 0); 2563 dc->mem_idx = ((env->psrs) != 0);
  2564 +#ifdef TARGET_SPARC64
  2565 + dc->fpu_enabled = (((env->pstate & PS_PEF) != 0) && ((env->fprs & FPRS_FEF) != 0));
  2566 +#else
  2567 + dc->fpu_enabled = ((env->psref) != 0);
  2568 +#endif
2553 #endif 2569 #endif
2554 gen_opc_ptr = gen_opc_buf; 2570 gen_opc_ptr = gen_opc_buf;
2555 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; 2571 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;