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; | ... | ... |