Commit a80dde08372ca86b48363dfee019af0dc3bc97aa
1 parent
29133e9a
SPARC FPU optimization (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2023 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
4 changed files
with
50 additions
and
37 deletions
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
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; |