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 | 175 | pc = env->regs[15]; |
| 176 | 176 | #elif defined(TARGET_SPARC) |
| 177 | 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 | 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 | 185 | #endif |
| 182 | 186 | cs_base = env->npc; |
| 183 | 187 | pc = env->pc; | ... | ... |
target-sparc/cpu.h
target-sparc/op.c
| ... | ... | @@ -1017,15 +1017,6 @@ void OPPROTO op_trapcc_T0(void) |
| 1017 | 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 | 1020 | void OPPROTO op_fpexception_im(void) |
| 1030 | 1021 | { |
| 1031 | 1022 | env->exception_index = TT_FP_EXCP; | ... | ... |
target-sparc/translate.c
| ... | ... | @@ -52,6 +52,7 @@ typedef struct DisasContext { |
| 52 | 52 | target_ulong jump_pc[2]; /* used when JUMP_PC pc value is used */ |
| 53 | 53 | int is_br; |
| 54 | 54 | int mem_idx; |
| 55 | + int fpu_enabled; | |
| 55 | 56 | struct TranslationBlock *tb; |
| 56 | 57 | } DisasContext; |
| 57 | 58 | |
| ... | ... | @@ -935,6 +936,19 @@ static GenOpFunc * const gen_fcmpd[4] = { |
| 935 | 936 | }; |
| 936 | 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 | 952 | /* before an instruction, dc->pc must be static */ |
| 939 | 953 | static void disas_sparc_insn(DisasContext * dc) |
| 940 | 954 | { |
| ... | ... | @@ -981,10 +995,8 @@ static void disas_sparc_insn(DisasContext * dc) |
| 981 | 995 | case 0x5: /* V9 FBPcc */ |
| 982 | 996 | { |
| 983 | 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 | 1000 | target = GET_FIELD_SP(insn, 0, 18); |
| 989 | 1001 | target = sign_extend(target, 19); |
| 990 | 1002 | target <<= 2; |
| ... | ... | @@ -1002,10 +1014,8 @@ static void disas_sparc_insn(DisasContext * dc) |
| 1002 | 1014 | } |
| 1003 | 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 | 1019 | target = GET_FIELD(insn, 10, 31); |
| 1010 | 1020 | target = sign_extend(target, 22); |
| 1011 | 1021 | target <<= 2; |
| ... | ... | @@ -1079,16 +1089,16 @@ static void disas_sparc_insn(DisasContext * dc) |
| 1079 | 1089 | } |
| 1080 | 1090 | #endif |
| 1081 | 1091 | } |
| 1082 | - save_state(dc); | |
| 1083 | 1092 | cond = GET_FIELD(insn, 3, 6); |
| 1084 | 1093 | if (cond == 0x8) { |
| 1094 | + save_state(dc); | |
| 1085 | 1095 | gen_op_trap_T0(); |
| 1086 | - dc->is_br = 1; | |
| 1087 | - goto jmp_insn; | |
| 1088 | 1096 | } else if (cond != 0) { |
| 1089 | 1097 | #ifdef TARGET_SPARC64 |
| 1090 | 1098 | /* V9 icc/xcc */ |
| 1091 | 1099 | int cc = GET_FIELD_SP(insn, 11, 12); |
| 1100 | + flush_T2(dc); | |
| 1101 | + save_state(dc); | |
| 1092 | 1102 | if (cc == 0) |
| 1093 | 1103 | gen_cond[0][cond](); |
| 1094 | 1104 | else if (cc == 2) |
| ... | ... | @@ -1096,10 +1106,17 @@ static void disas_sparc_insn(DisasContext * dc) |
| 1096 | 1106 | else |
| 1097 | 1107 | goto illegal_insn; |
| 1098 | 1108 | #else |
| 1109 | + flush_T2(dc); | |
| 1110 | + save_state(dc); | |
| 1099 | 1111 | gen_cond[0][cond](); |
| 1100 | 1112 | #endif |
| 1101 | 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 | 1120 | } else if (xop == 0x28) { |
| 1104 | 1121 | rs1 = GET_FIELD(insn, 13, 17); |
| 1105 | 1122 | switch(rs1) { |
| ... | ... | @@ -1241,10 +1258,8 @@ static void disas_sparc_insn(DisasContext * dc) |
| 1241 | 1258 | break; |
| 1242 | 1259 | #endif |
| 1243 | 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 | 1263 | rs1 = GET_FIELD(insn, 13, 17); |
| 1249 | 1264 | rs2 = GET_FIELD(insn, 27, 31); |
| 1250 | 1265 | xop = GET_FIELD(insn, 18, 26); |
| ... | ... | @@ -1430,10 +1445,8 @@ static void disas_sparc_insn(DisasContext * dc) |
| 1430 | 1445 | #ifdef TARGET_SPARC64 |
| 1431 | 1446 | int cond; |
| 1432 | 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 | 1450 | rs1 = GET_FIELD(insn, 13, 17); |
| 1438 | 1451 | rs2 = GET_FIELD(insn, 27, 31); |
| 1439 | 1452 | xop = GET_FIELD(insn, 18, 26); |
| ... | ... | @@ -2366,10 +2379,8 @@ static void disas_sparc_insn(DisasContext * dc) |
| 2366 | 2379 | skip_move: ; |
| 2367 | 2380 | #endif |
| 2368 | 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 | 2384 | switch (xop) { |
| 2374 | 2385 | case 0x20: /* load fpreg */ |
| 2375 | 2386 | gen_op_ldst(ldf); |
| ... | ... | @@ -2450,9 +2461,8 @@ static void disas_sparc_insn(DisasContext * dc) |
| 2450 | 2461 | goto illegal_insn; |
| 2451 | 2462 | } |
| 2452 | 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 | 2466 | switch (xop) { |
| 2457 | 2467 | case 0x24: |
| 2458 | 2468 | gen_op_load_fpr_FT0(rd); |
| ... | ... | @@ -2548,8 +2558,14 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb, |
| 2548 | 2558 | dc->npc = (target_ulong) tb->cs_base; |
| 2549 | 2559 | #if defined(CONFIG_USER_ONLY) |
| 2550 | 2560 | dc->mem_idx = 0; |
| 2561 | + dc->fpu_enabled = 1; | |
| 2551 | 2562 | #else |
| 2552 | 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 | 2569 | #endif |
| 2554 | 2570 | gen_opc_ptr = gen_opc_buf; |
| 2555 | 2571 | gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; | ... | ... |