Commit 2a44f7f173649e90b6f48c85d08f009c6fe765bd
1 parent
bf443337
CRIS translator updates
* Improve translation of the X flag (still some corner cases missing). * First shot att P flag support and conditional stores. * Improve the jump logic. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4684 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
212 additions
and
103 deletions
target-cris/translate.c
| ... | ... | @@ -73,6 +73,7 @@ TCGv cc_op; |
| 73 | 73 | TCGv cc_size; |
| 74 | 74 | TCGv cc_mask; |
| 75 | 75 | |
| 76 | +TCGv env_btaken; | |
| 76 | 77 | TCGv env_btarget; |
| 77 | 78 | TCGv env_pc; |
| 78 | 79 | |
| ... | ... | @@ -104,9 +105,16 @@ typedef struct DisasContext { |
| 104 | 105 | int flags_x; |
| 105 | 106 | |
| 106 | 107 | int clear_x; /* Clear x after this insn? */ |
| 107 | - int user; /* user or kernel mode. */ | |
| 108 | + int cpustate_changed; | |
| 109 | + unsigned int tb_flags; /* tb dependent flags. */ | |
| 108 | 110 | int is_jmp; |
| 109 | 111 | |
| 112 | +#define JMP_NOJMP 0 | |
| 113 | +#define JMP_DIRECT 1 | |
| 114 | +#define JMP_INDIRECT 2 | |
| 115 | + int jmp; /* 0=nojmp, 1=direct, 2=indirect. */ | |
| 116 | + uint32_t jmp_pc; | |
| 117 | + | |
| 110 | 118 | int delayed_branch; |
| 111 | 119 | |
| 112 | 120 | struct TranslationBlock *tb; |
| ... | ... | @@ -207,8 +215,10 @@ static inline void t_gen_mov_preg_TN(DisasContext *dc, int r, TCGv tn) |
| 207 | 215 | tcg_gen_andi_tl(cpu_PR[r], tn, 3); |
| 208 | 216 | else { |
| 209 | 217 | tcg_gen_mov_tl(cpu_PR[r], tn); |
| 210 | - if (r == PR_PID) | |
| 218 | + if (r == PR_PID) | |
| 211 | 219 | tcg_gen_helper_0_1(helper_tlb_flush_pid, tn); |
| 220 | + else if (r == PR_CCS) | |
| 221 | + dc->cpustate_changed = 1; | |
| 212 | 222 | } |
| 213 | 223 | } |
| 214 | 224 | |
| ... | ... | @@ -610,7 +620,7 @@ static void t_gen_cc_jmp(TCGv pc_true, TCGv pc_false) |
| 610 | 620 | btaken = tcg_temp_new(TCG_TYPE_TL); |
| 611 | 621 | |
| 612 | 622 | /* Conditional jmp. */ |
| 613 | - t_gen_mov_TN_env(btaken, btaken); | |
| 623 | + tcg_gen_mov_tl(btaken, env_btaken); | |
| 614 | 624 | tcg_gen_mov_tl(env_pc, pc_false); |
| 615 | 625 | tcg_gen_brcondi_tl(TCG_COND_EQ, btaken, 0, l1); |
| 616 | 626 | tcg_gen_mov_tl(env_pc, pc_true); |
| ... | ... | @@ -628,7 +638,7 @@ static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest) |
| 628 | 638 | tcg_gen_movi_tl(env_pc, dest); |
| 629 | 639 | tcg_gen_exit_tb((long)tb + n); |
| 630 | 640 | } else { |
| 631 | - tcg_gen_mov_tl(env_pc, cpu_T[0]); | |
| 641 | + tcg_gen_movi_tl(env_pc, dest); | |
| 632 | 642 | tcg_gen_exit_tb(0); |
| 633 | 643 | } |
| 634 | 644 | } |
| ... | ... | @@ -648,6 +658,9 @@ static int sign_extend(unsigned int val, unsigned int width) |
| 648 | 658 | |
| 649 | 659 | static inline void cris_clear_x_flag(DisasContext *dc) |
| 650 | 660 | { |
| 661 | + if (dc->flagx_known && dc->flags_x) | |
| 662 | + dc->flags_uptodate = 0; | |
| 663 | + | |
| 651 | 664 | dc->flagx_known = 1; |
| 652 | 665 | dc->flags_x = 0; |
| 653 | 666 | } |
| ... | ... | @@ -715,6 +728,15 @@ static void cris_evaluate_flags(DisasContext *dc) |
| 715 | 728 | } |
| 716 | 729 | break; |
| 717 | 730 | } |
| 731 | + if (dc->flagx_known) { | |
| 732 | + if (dc->flags_x) | |
| 733 | + tcg_gen_ori_tl(cpu_PR[PR_CCS], | |
| 734 | + cpu_PR[PR_CCS], X_FLAG); | |
| 735 | + else | |
| 736 | + tcg_gen_andi_tl(cpu_PR[PR_CCS], | |
| 737 | + cpu_PR[PR_CCS], ~X_FLAG); | |
| 738 | + } | |
| 739 | + | |
| 718 | 740 | dc->flags_uptodate = 1; |
| 719 | 741 | } |
| 720 | 742 | } |
| ... | ... | @@ -723,6 +745,11 @@ static void cris_cc_mask(DisasContext *dc, unsigned int mask) |
| 723 | 745 | { |
| 724 | 746 | uint32_t ovl; |
| 725 | 747 | |
| 748 | + if (!mask) { | |
| 749 | + dc->update_cc = 0; | |
| 750 | + return; | |
| 751 | + } | |
| 752 | + | |
| 726 | 753 | /* Check if we need to evaluate the condition codes due to |
| 727 | 754 | CC overlaying. */ |
| 728 | 755 | ovl = (dc->cc_mask ^ mask) & ~mask; |
| ... | ... | @@ -732,11 +759,6 @@ static void cris_cc_mask(DisasContext *dc, unsigned int mask) |
| 732 | 759 | } |
| 733 | 760 | dc->cc_mask = mask; |
| 734 | 761 | dc->update_cc = 1; |
| 735 | - | |
| 736 | - if (mask == 0) | |
| 737 | - dc->update_cc = 0; | |
| 738 | - else | |
| 739 | - dc->flags_uptodate = 0; | |
| 740 | 762 | } |
| 741 | 763 | |
| 742 | 764 | static void cris_update_cc_op(DisasContext *dc, int op, int size) |
| ... | ... | @@ -942,7 +964,7 @@ static int arith_cc(DisasContext *dc) |
| 942 | 964 | |
| 943 | 965 | static void gen_tst_cc (DisasContext *dc, int cond) |
| 944 | 966 | { |
| 945 | - int arith_opt; | |
| 967 | + int arith_opt, move_opt; | |
| 946 | 968 | |
| 947 | 969 | /* TODO: optimize more condition codes. */ |
| 948 | 970 | |
| ... | ... | @@ -955,9 +977,10 @@ static void gen_tst_cc (DisasContext *dc, int cond) |
| 955 | 977 | * code is true. |
| 956 | 978 | */ |
| 957 | 979 | arith_opt = arith_cc(dc) && !dc->flags_uptodate; |
| 980 | + move_opt = (dc->cc_op == CC_OP_MOVE) && !dc->flags_uptodate; | |
| 958 | 981 | switch (cond) { |
| 959 | 982 | case CC_EQ: |
| 960 | - if (arith_opt) { | |
| 983 | + if (arith_opt || move_opt) { | |
| 961 | 984 | /* If cc_result is zero, T0 should be |
| 962 | 985 | non-zero otherwise T0 should be zero. */ |
| 963 | 986 | int l1; |
| ... | ... | @@ -975,7 +998,7 @@ static void gen_tst_cc (DisasContext *dc, int cond) |
| 975 | 998 | } |
| 976 | 999 | break; |
| 977 | 1000 | case CC_NE: |
| 978 | - if (arith_opt) | |
| 1001 | + if (arith_opt || move_opt) | |
| 979 | 1002 | tcg_gen_mov_tl(cpu_T[0], cc_result); |
| 980 | 1003 | else { |
| 981 | 1004 | cris_evaluate_flags(dc); |
| ... | ... | @@ -990,8 +1013,7 @@ static void gen_tst_cc (DisasContext *dc, int cond) |
| 990 | 1013 | break; |
| 991 | 1014 | case CC_CC: |
| 992 | 1015 | cris_evaluate_flags(dc); |
| 993 | - tcg_gen_xori_tl(cpu_T[0], cpu_PR[PR_CCS], | |
| 994 | - C_FLAG); | |
| 1016 | + tcg_gen_xori_tl(cpu_T[0], cpu_PR[PR_CCS], C_FLAG); | |
| 995 | 1017 | tcg_gen_andi_tl(cpu_T[0], cpu_T[0], C_FLAG); |
| 996 | 1018 | break; |
| 997 | 1019 | case CC_VS: |
| ... | ... | @@ -1005,9 +1027,17 @@ static void gen_tst_cc (DisasContext *dc, int cond) |
| 1005 | 1027 | tcg_gen_andi_tl(cpu_T[0], cpu_T[0], V_FLAG); |
| 1006 | 1028 | break; |
| 1007 | 1029 | case CC_PL: |
| 1008 | - if (arith_opt) | |
| 1009 | - tcg_gen_shli_tl(cpu_T[0], cc_result, 31); | |
| 1010 | - else { | |
| 1030 | + if (arith_opt || move_opt) { | |
| 1031 | + int bits = 31; | |
| 1032 | + | |
| 1033 | + if (dc->cc_size == 1) | |
| 1034 | + bits = 7; | |
| 1035 | + else if (dc->cc_size == 2) | |
| 1036 | + bits = 15; | |
| 1037 | + | |
| 1038 | + tcg_gen_shri_tl(cpu_T[0], cc_result, bits); | |
| 1039 | + tcg_gen_xori_tl(cpu_T[0], cpu_T[0], 1); | |
| 1040 | + } else { | |
| 1011 | 1041 | cris_evaluate_flags(dc); |
| 1012 | 1042 | tcg_gen_xori_tl(cpu_T[0], cpu_PR[PR_CCS], |
| 1013 | 1043 | N_FLAG); |
| ... | ... | @@ -1015,9 +1045,15 @@ static void gen_tst_cc (DisasContext *dc, int cond) |
| 1015 | 1045 | } |
| 1016 | 1046 | break; |
| 1017 | 1047 | case CC_MI: |
| 1018 | - if (arith_opt) { | |
| 1019 | - tcg_gen_shli_tl(cpu_T[0], cc_result, 31); | |
| 1020 | - tcg_gen_xori_tl(cpu_T[0], cpu_T[0], 1); | |
| 1048 | + if (arith_opt || move_opt) { | |
| 1049 | + int bits = 31; | |
| 1050 | + | |
| 1051 | + if (dc->cc_size == 1) | |
| 1052 | + bits = 7; | |
| 1053 | + else if (dc->cc_size == 2) | |
| 1054 | + bits = 15; | |
| 1055 | + | |
| 1056 | + tcg_gen_shri_tl(cpu_T[0], cc_result, 31); | |
| 1021 | 1057 | } |
| 1022 | 1058 | else { |
| 1023 | 1059 | cris_evaluate_flags(dc); |
| ... | ... | @@ -1121,28 +1157,46 @@ static void gen_tst_cc (DisasContext *dc, int cond) |
| 1121 | 1157 | }; |
| 1122 | 1158 | } |
| 1123 | 1159 | |
| 1124 | -static void cris_prepare_cc_branch (DisasContext *dc, int offset, int cond) | |
| 1160 | +static void cris_store_direct_jmp(DisasContext *dc) | |
| 1161 | +{ | |
| 1162 | + /* Store the direct jmp state into the cpu-state. */ | |
| 1163 | + if (dc->jmp == JMP_DIRECT) { | |
| 1164 | + tcg_gen_movi_tl(env_btarget, dc->jmp_pc); | |
| 1165 | + tcg_gen_movi_tl(env_btaken, 1); | |
| 1166 | + } | |
| 1167 | +} | |
| 1168 | + | |
| 1169 | +static void cris_prepare_cc_branch (DisasContext *dc, | |
| 1170 | + int offset, int cond) | |
| 1125 | 1171 | { |
| 1126 | 1172 | /* This helps us re-schedule the micro-code to insns in delay-slots |
| 1127 | 1173 | before the actual jump. */ |
| 1128 | 1174 | dc->delayed_branch = 2; |
| 1175 | + dc->jmp_pc = dc->pc + offset; | |
| 1176 | + | |
| 1129 | 1177 | if (cond != CC_A) |
| 1130 | 1178 | { |
| 1179 | + dc->jmp = JMP_INDIRECT; | |
| 1131 | 1180 | gen_tst_cc (dc, cond); |
| 1132 | - t_gen_mov_env_TN(btaken, cpu_T[0]); | |
| 1133 | - } else | |
| 1134 | - t_gen_mov_env_TN(btaken, tcg_const_tl(1)); | |
| 1135 | - tcg_gen_movi_tl(env_btarget, dc->pc + offset); | |
| 1181 | + tcg_gen_mov_tl(env_btaken, cpu_T[0]); | |
| 1182 | + tcg_gen_movi_tl(env_btarget, dc->jmp_pc); | |
| 1183 | + } else { | |
| 1184 | + /* Allow chaining. */ | |
| 1185 | + dc->jmp = JMP_DIRECT; | |
| 1186 | + } | |
| 1136 | 1187 | } |
| 1137 | 1188 | |
| 1138 | 1189 | |
| 1139 | -/* Dynamic jumps, when the dest is in a live reg for example. */ | |
| 1140 | -void cris_prepare_dyn_jmp (DisasContext *dc) | |
| 1190 | +/* jumps, when the dest is in a live reg for example. Direct should be set | |
| 1191 | + when the dest addr is constant to allow tb chaining. */ | |
| 1192 | +static inline void cris_prepare_jmp (DisasContext *dc, unsigned int type) | |
| 1141 | 1193 | { |
| 1142 | 1194 | /* This helps us re-schedule the micro-code to insns in delay-slots |
| 1143 | 1195 | before the actual jump. */ |
| 1144 | 1196 | dc->delayed_branch = 2; |
| 1145 | - t_gen_mov_env_TN(btaken, tcg_const_tl(1)); | |
| 1197 | + dc->jmp = type; | |
| 1198 | + if (type == JMP_INDIRECT) | |
| 1199 | + tcg_gen_movi_tl(env_btaken, 1); | |
| 1146 | 1200 | } |
| 1147 | 1201 | |
| 1148 | 1202 | void gen_load(DisasContext *dc, TCGv dst, TCGv addr, |
| ... | ... | @@ -1150,6 +1204,11 @@ void gen_load(DisasContext *dc, TCGv dst, TCGv addr, |
| 1150 | 1204 | { |
| 1151 | 1205 | int mem_index = cpu_mmu_index(dc->env); |
| 1152 | 1206 | |
| 1207 | + /* If we get a fault on a delayslot we must keep the jmp state in | |
| 1208 | + the cpu-state to be able to re-execute the jmp. */ | |
| 1209 | + if (dc->delayed_branch == 1) | |
| 1210 | + cris_store_direct_jmp(dc); | |
| 1211 | + | |
| 1153 | 1212 | if (size == 1) { |
| 1154 | 1213 | if (sign) |
| 1155 | 1214 | tcg_gen_qemu_ld8s(dst, addr, mem_index); |
| ... | ... | @@ -1172,6 +1231,21 @@ void gen_store (DisasContext *dc, TCGv addr, TCGv val, |
| 1172 | 1231 | { |
| 1173 | 1232 | int mem_index = cpu_mmu_index(dc->env); |
| 1174 | 1233 | |
| 1234 | + /* If we get a fault on a delayslot we must keep the jmp state in | |
| 1235 | + the cpu-state to be able to re-execute the jmp. */ | |
| 1236 | + if (dc->delayed_branch == 1) | |
| 1237 | + cris_store_direct_jmp(dc); | |
| 1238 | + | |
| 1239 | + | |
| 1240 | + /* Conditional writes. We only support the kind were X and P are known | |
| 1241 | + at translation time. */ | |
| 1242 | + if (dc->flagx_known && dc->flags_x && (dc->tb_flags & P_FLAG)) { | |
| 1243 | + dc->postinc = 0; | |
| 1244 | + cris_evaluate_flags(dc); | |
| 1245 | + tcg_gen_ori_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], C_FLAG); | |
| 1246 | + return; | |
| 1247 | + } | |
| 1248 | + | |
| 1175 | 1249 | /* Remember, operands are flipped. CRIS has reversed order. */ |
| 1176 | 1250 | if (size == 1) |
| 1177 | 1251 | tcg_gen_qemu_st8(val, addr, mem_index); |
| ... | ... | @@ -1179,6 +1253,11 @@ void gen_store (DisasContext *dc, TCGv addr, TCGv val, |
| 1179 | 1253 | tcg_gen_qemu_st16(val, addr, mem_index); |
| 1180 | 1254 | else |
| 1181 | 1255 | tcg_gen_qemu_st32(val, addr, mem_index); |
| 1256 | + | |
| 1257 | + if (dc->flagx_known && dc->flags_x) { | |
| 1258 | + cris_evaluate_flags(dc); | |
| 1259 | + tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~C_FLAG); | |
| 1260 | + } | |
| 1182 | 1261 | } |
| 1183 | 1262 | |
| 1184 | 1263 | static inline void t_gen_sext(TCGv d, TCGv s, int size) |
| ... | ... | @@ -1352,6 +1431,8 @@ static unsigned int dec_bccq(DisasContext *dc) |
| 1352 | 1431 | tmp = offset; |
| 1353 | 1432 | offset = sign_extend(offset, 8); |
| 1354 | 1433 | |
| 1434 | + DIS(fprintf (logfile, "b%s %x\n", cc_name(cond), dc->pc + offset)); | |
| 1435 | + | |
| 1355 | 1436 | /* op2 holds the condition-code. */ |
| 1356 | 1437 | cris_cc_mask(dc, 0); |
| 1357 | 1438 | cris_prepare_cc_branch (dc, offset, cond); |
| ... | ... | @@ -1463,9 +1544,10 @@ static unsigned int dec_asrq(DisasContext *dc) |
| 1463 | 1544 | DIS(fprintf (logfile, "asrq %u, $r%d\n", dc->op1, dc->op2)); |
| 1464 | 1545 | cris_cc_mask(dc, CC_MASK_NZ); |
| 1465 | 1546 | |
| 1466 | - cris_alu(dc, CC_OP_ASR, | |
| 1547 | + tcg_gen_sari_tl(cpu_R[dc->op2], cpu_R[dc->op2], dc->op1); | |
| 1548 | + cris_alu(dc, CC_OP_MOVE, | |
| 1467 | 1549 | cpu_R[dc->op2], |
| 1468 | - cpu_R[dc->op2], tcg_const_tl(dc->op1), 4); | |
| 1550 | + cpu_R[dc->op2], cpu_R[dc->op2], 4); | |
| 1469 | 1551 | return 2; |
| 1470 | 1552 | } |
| 1471 | 1553 | static unsigned int dec_lslq(DisasContext *dc) |
| ... | ... | @@ -1475,9 +1557,11 @@ static unsigned int dec_lslq(DisasContext *dc) |
| 1475 | 1557 | |
| 1476 | 1558 | cris_cc_mask(dc, CC_MASK_NZ); |
| 1477 | 1559 | |
| 1478 | - cris_alu(dc, CC_OP_LSL, | |
| 1560 | + tcg_gen_shli_tl(cpu_R[dc->op2], cpu_R[dc->op2], dc->op1); | |
| 1561 | + | |
| 1562 | + cris_alu(dc, CC_OP_MOVE, | |
| 1479 | 1563 | cpu_R[dc->op2], |
| 1480 | - cpu_R[dc->op2], tcg_const_tl(dc->op1), 4); | |
| 1564 | + cpu_R[dc->op2], cpu_R[dc->op2], 4); | |
| 1481 | 1565 | return 2; |
| 1482 | 1566 | } |
| 1483 | 1567 | static unsigned int dec_lsrq(DisasContext *dc) |
| ... | ... | @@ -1487,9 +1571,10 @@ static unsigned int dec_lsrq(DisasContext *dc) |
| 1487 | 1571 | |
| 1488 | 1572 | cris_cc_mask(dc, CC_MASK_NZ); |
| 1489 | 1573 | |
| 1490 | - cris_alu(dc, CC_OP_LSR, | |
| 1574 | + tcg_gen_shri_tl(cpu_R[dc->op2], cpu_R[dc->op2], dc->op1); | |
| 1575 | + cris_alu(dc, CC_OP_MOVE, | |
| 1491 | 1576 | cpu_R[dc->op2], |
| 1492 | - cpu_R[dc->op2], tcg_const_tl(dc->op1), 4); | |
| 1577 | + cpu_R[dc->op2], cpu_R[dc->op2], 4); | |
| 1493 | 1578 | return 2; |
| 1494 | 1579 | } |
| 1495 | 1580 | |
| ... | ... | @@ -1962,7 +2047,6 @@ static unsigned int dec_setclrf(DisasContext *dc) |
| 1962 | 2047 | |
| 1963 | 2048 | flags = (EXTRACT_FIELD(dc->ir, 12, 15) << 4) |
| 1964 | 2049 | | EXTRACT_FIELD(dc->ir, 0, 3); |
| 1965 | - DIS(fprintf (logfile, "set=%d flags=%x\n", set, flags)); | |
| 1966 | 2050 | if (set && flags == 0) { |
| 1967 | 2051 | DIS(fprintf (logfile, "nop\n")); |
| 1968 | 2052 | return 2; |
| ... | ... | @@ -1975,13 +2059,30 @@ static unsigned int dec_setclrf(DisasContext *dc) |
| 1975 | 2059 | flags)); |
| 1976 | 2060 | } |
| 1977 | 2061 | |
| 1978 | - if (set && (flags & X_FLAG)) { | |
| 2062 | + /* User space is not allowed to touch these. Silently ignore. */ | |
| 2063 | + if (dc->tb_flags & U_FLAG) { | |
| 2064 | + flags &= ~(I_FLAG | U_FLAG); | |
| 2065 | + } | |
| 2066 | + | |
| 2067 | + if (flags & X_FLAG) { | |
| 1979 | 2068 | dc->flagx_known = 1; |
| 1980 | - dc->flags_x = X_FLAG; | |
| 1981 | - } else { | |
| 1982 | - dc->flagx_known = 0; | |
| 2069 | + if (set) | |
| 2070 | + dc->flags_x = X_FLAG; | |
| 2071 | + else | |
| 2072 | + dc->flags_x = 0; | |
| 1983 | 2073 | } |
| 1984 | 2074 | |
| 2075 | + /* Break the TB if the P flag changes. */ | |
| 2076 | + if (flags & P_FLAG) { | |
| 2077 | + if ((set && !(dc->tb_flags & P_FLAG)) | |
| 2078 | + || (!set && (dc->tb_flags & P_FLAG))) { | |
| 2079 | + tcg_gen_movi_tl(env_pc, dc->pc + 2); | |
| 2080 | + dc->is_jmp = DISAS_UPDATE; | |
| 2081 | + dc->cpustate_changed = 1; | |
| 2082 | + } | |
| 2083 | + } | |
| 2084 | + | |
| 2085 | + | |
| 1985 | 2086 | /* Simply decode the flags. */ |
| 1986 | 2087 | cris_evaluate_flags (dc); |
| 1987 | 2088 | cris_update_cc_op(dc, CC_OP_FLAGS, 4); |
| ... | ... | @@ -1989,11 +2090,11 @@ static unsigned int dec_setclrf(DisasContext *dc) |
| 1989 | 2090 | tcg_gen_movi_tl(cc_op, dc->cc_op); |
| 1990 | 2091 | |
| 1991 | 2092 | if (set) { |
| 1992 | - if (!dc->user && (flags & U_FLAG)) { | |
| 2093 | + if (!(dc->tb_flags & U_FLAG) && (flags & U_FLAG)) { | |
| 1993 | 2094 | /* Enter user mode. */ |
| 1994 | 2095 | t_gen_mov_env_TN(ksp, cpu_R[R_SP]); |
| 1995 | 2096 | tcg_gen_mov_tl(cpu_R[R_SP], cpu_PR[PR_USP]); |
| 1996 | - dc->is_jmp = DISAS_NEXT; | |
| 2097 | + dc->cpustate_changed = 1; | |
| 1997 | 2098 | } |
| 1998 | 2099 | tcg_gen_ori_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], flags); |
| 1999 | 2100 | } |
| ... | ... | @@ -2030,7 +2131,7 @@ static unsigned int dec_move_rp(DisasContext *dc) |
| 2030 | 2131 | if (dc->op2 == PR_CCS) { |
| 2031 | 2132 | cris_evaluate_flags(dc); |
| 2032 | 2133 | t_gen_mov_TN_reg(cpu_T[0], dc->op1); |
| 2033 | - if (dc->user) { | |
| 2134 | + if (dc->tb_flags & U_FLAG) { | |
| 2034 | 2135 | /* User space is not allowed to touch all flags. */ |
| 2035 | 2136 | tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0x39f); |
| 2036 | 2137 | tcg_gen_andi_tl(cpu_T[1], cpu_PR[PR_CCS], ~0x39f); |
| ... | ... | @@ -2051,16 +2152,12 @@ static unsigned int dec_move_pr(DisasContext *dc) |
| 2051 | 2152 | { |
| 2052 | 2153 | DIS(fprintf (logfile, "move $p%u, $r%u\n", dc->op1, dc->op2)); |
| 2053 | 2154 | cris_cc_mask(dc, 0); |
| 2054 | - /* Support register 0 is hardwired to zero. | |
| 2055 | - Treat it specially. */ | |
| 2056 | - if (dc->op2 == 0) | |
| 2057 | - tcg_gen_movi_tl(cpu_T[1], 0); | |
| 2058 | - else if (dc->op2 == PR_CCS) { | |
| 2155 | + | |
| 2156 | + if (dc->op2 == PR_CCS) | |
| 2059 | 2157 | cris_evaluate_flags(dc); |
| 2060 | - t_gen_mov_TN_preg(cpu_T[1], dc->op2); | |
| 2061 | - } else | |
| 2062 | - t_gen_mov_TN_preg(cpu_T[1], dc->op2); | |
| 2063 | - cris_alu(dc, CC_OP_MOVE, | |
| 2158 | + | |
| 2159 | + t_gen_mov_TN_preg(cpu_T[1], dc->op2); | |
| 2160 | + cris_alu(dc, CC_OP_MOVE, | |
| 2064 | 2161 | cpu_R[dc->op1], cpu_R[dc->op1], cpu_T[1], |
| 2065 | 2162 | preg_sizes[dc->op2]); |
| 2066 | 2163 | return 2; |
| ... | ... | @@ -2410,7 +2507,7 @@ static unsigned int dec_move_mp(DisasContext *dc) |
| 2410 | 2507 | cris_cc_mask(dc, 0); |
| 2411 | 2508 | if (dc->op2 == PR_CCS) { |
| 2412 | 2509 | cris_evaluate_flags(dc); |
| 2413 | - if (dc->user) { | |
| 2510 | + if (dc->tb_flags & U_FLAG) { | |
| 2414 | 2511 | /* User space is not allowed to touch all flags. */ |
| 2415 | 2512 | tcg_gen_andi_tl(cpu_T[1], cpu_T[1], 0x39f); |
| 2416 | 2513 | tcg_gen_andi_tl(cpu_T[0], cpu_PR[PR_CCS], ~0x39f); |
| ... | ... | @@ -2561,7 +2658,7 @@ static unsigned int dec_jump_p(DisasContext *dc) |
| 2561 | 2658 | /* rete will often have low bit set to indicate delayslot. */ |
| 2562 | 2659 | tcg_gen_andi_tl(env_btarget, cpu_T[0], ~1); |
| 2563 | 2660 | cris_cc_mask(dc, 0); |
| 2564 | - cris_prepare_dyn_jmp(dc); | |
| 2661 | + cris_prepare_jmp(dc, JMP_INDIRECT); | |
| 2565 | 2662 | return 2; |
| 2566 | 2663 | } |
| 2567 | 2664 | |
| ... | ... | @@ -2576,7 +2673,7 @@ static unsigned int dec_jas_r(DisasContext *dc) |
| 2576 | 2673 | abort(); |
| 2577 | 2674 | t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 4)); |
| 2578 | 2675 | |
| 2579 | - cris_prepare_dyn_jmp(dc); | |
| 2676 | + cris_prepare_jmp(dc, JMP_INDIRECT); | |
| 2580 | 2677 | return 2; |
| 2581 | 2678 | } |
| 2582 | 2679 | |
| ... | ... | @@ -2589,9 +2686,10 @@ static unsigned int dec_jas_im(DisasContext *dc) |
| 2589 | 2686 | DIS(fprintf (logfile, "jas 0x%x\n", imm)); |
| 2590 | 2687 | cris_cc_mask(dc, 0); |
| 2591 | 2688 | /* Store the return address in Pd. */ |
| 2592 | - tcg_gen_movi_tl(env_btarget, imm); | |
| 2593 | 2689 | t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 8)); |
| 2594 | - cris_prepare_dyn_jmp(dc); | |
| 2690 | + | |
| 2691 | + dc->jmp_pc = imm; | |
| 2692 | + cris_prepare_jmp(dc, JMP_DIRECT); | |
| 2595 | 2693 | return 6; |
| 2596 | 2694 | } |
| 2597 | 2695 | |
| ... | ... | @@ -2604,11 +2702,10 @@ static unsigned int dec_jasc_im(DisasContext *dc) |
| 2604 | 2702 | DIS(fprintf (logfile, "jasc 0x%x\n", imm)); |
| 2605 | 2703 | cris_cc_mask(dc, 0); |
| 2606 | 2704 | /* Store the return address in Pd. */ |
| 2607 | - tcg_gen_movi_tl(cpu_T[0], imm); | |
| 2608 | - tcg_gen_mov_tl(env_btarget, cpu_T[0]); | |
| 2609 | - tcg_gen_movi_tl(cpu_T[0], dc->pc + 8 + 4); | |
| 2610 | - t_gen_mov_preg_TN(dc, dc->op2, cpu_T[0]); | |
| 2611 | - cris_prepare_dyn_jmp(dc); | |
| 2705 | + t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 8 + 4)); | |
| 2706 | + | |
| 2707 | + dc->jmp_pc = imm; | |
| 2708 | + cris_prepare_jmp(dc, JMP_DIRECT); | |
| 2612 | 2709 | return 6; |
| 2613 | 2710 | } |
| 2614 | 2711 | |
| ... | ... | @@ -2617,11 +2714,9 @@ static unsigned int dec_jasc_r(DisasContext *dc) |
| 2617 | 2714 | DIS(fprintf (logfile, "jasc_r $r%u, $p%u\n", dc->op1, dc->op2)); |
| 2618 | 2715 | cris_cc_mask(dc, 0); |
| 2619 | 2716 | /* Store the return address in Pd. */ |
| 2620 | - t_gen_mov_TN_reg(cpu_T[0], dc->op1); | |
| 2621 | - tcg_gen_mov_tl(env_btarget, cpu_T[0]); | |
| 2622 | - tcg_gen_movi_tl(cpu_T[0], dc->pc + 4 + 4); | |
| 2623 | - t_gen_mov_preg_TN(dc, dc->op2, cpu_T[0]); | |
| 2624 | - cris_prepare_dyn_jmp(dc); | |
| 2717 | + tcg_gen_mov_tl(env_btarget, cpu_R[dc->op1]); | |
| 2718 | + t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 4 + 4)); | |
| 2719 | + cris_prepare_jmp(dc, JMP_INDIRECT); | |
| 2625 | 2720 | return 2; |
| 2626 | 2721 | } |
| 2627 | 2722 | |
| ... | ... | @@ -2651,12 +2746,11 @@ static unsigned int dec_bas_im(DisasContext *dc) |
| 2651 | 2746 | |
| 2652 | 2747 | DIS(fprintf (logfile, "bas 0x%x, $p%u\n", dc->pc + simm, dc->op2)); |
| 2653 | 2748 | cris_cc_mask(dc, 0); |
| 2654 | - /* Stor the return address in Pd. */ | |
| 2655 | - tcg_gen_movi_tl(cpu_T[0], dc->pc + simm); | |
| 2656 | - tcg_gen_mov_tl(env_btarget, cpu_T[0]); | |
| 2657 | - tcg_gen_movi_tl(cpu_T[0], dc->pc + 8); | |
| 2658 | - t_gen_mov_preg_TN(dc, dc->op2, cpu_T[0]); | |
| 2659 | - cris_prepare_dyn_jmp(dc); | |
| 2749 | + /* Store the return address in Pd. */ | |
| 2750 | + t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 8)); | |
| 2751 | + | |
| 2752 | + dc->jmp_pc = dc->pc + simm; | |
| 2753 | + cris_prepare_jmp(dc, JMP_DIRECT); | |
| 2660 | 2754 | return 6; |
| 2661 | 2755 | } |
| 2662 | 2756 | |
| ... | ... | @@ -2667,12 +2761,11 @@ static unsigned int dec_basc_im(DisasContext *dc) |
| 2667 | 2761 | |
| 2668 | 2762 | DIS(fprintf (logfile, "basc 0x%x, $p%u\n", dc->pc + simm, dc->op2)); |
| 2669 | 2763 | cris_cc_mask(dc, 0); |
| 2670 | - /* Stor the return address in Pd. */ | |
| 2671 | - tcg_gen_movi_tl(cpu_T[0], dc->pc + simm); | |
| 2672 | - tcg_gen_mov_tl(env_btarget, cpu_T[0]); | |
| 2673 | - tcg_gen_movi_tl(cpu_T[0], dc->pc + 12); | |
| 2674 | - t_gen_mov_preg_TN(dc, dc->op2, cpu_T[0]); | |
| 2675 | - cris_prepare_dyn_jmp(dc); | |
| 2764 | + /* Store the return address in Pd. */ | |
| 2765 | + t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 12)); | |
| 2766 | + | |
| 2767 | + dc->jmp_pc = dc->pc + simm; | |
| 2768 | + cris_prepare_jmp(dc, JMP_DIRECT); | |
| 2676 | 2769 | return 6; |
| 2677 | 2770 | } |
| 2678 | 2771 | |
| ... | ... | @@ -2699,8 +2792,7 @@ static unsigned int dec_rfe_etc(DisasContext *dc) |
| 2699 | 2792 | break; |
| 2700 | 2793 | case 6: |
| 2701 | 2794 | /* break. */ |
| 2702 | - tcg_gen_movi_tl(cpu_T[0], dc->pc); | |
| 2703 | - t_gen_mov_env_TN(pc, cpu_T[0]); | |
| 2795 | + tcg_gen_movi_tl(env_pc, dc->pc); | |
| 2704 | 2796 | /* Breaks start at 16 in the exception vector. */ |
| 2705 | 2797 | t_gen_mov_env_TN(trap_vector, |
| 2706 | 2798 | tcg_const_tl(dc->op1 + 16)); |
| ... | ... | @@ -2884,8 +2976,7 @@ static void check_breakpoint(CPUState *env, DisasContext *dc) |
| 2884 | 2976 | for(j = 0; j < env->nb_breakpoints; j++) { |
| 2885 | 2977 | if (env->breakpoints[j] == dc->pc) { |
| 2886 | 2978 | cris_evaluate_flags (dc); |
| 2887 | - tcg_gen_movi_tl(cpu_T[0], dc->pc); | |
| 2888 | - t_gen_mov_env_TN(pc, cpu_T[0]); | |
| 2979 | + tcg_gen_movi_tl(env_pc, dc->pc); | |
| 2889 | 2980 | t_gen_raise_exception(EXCP_DEBUG); |
| 2890 | 2981 | dc->is_jmp = DISAS_UPDATE; |
| 2891 | 2982 | } |
| ... | ... | @@ -2940,6 +3031,7 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, |
| 2940 | 3031 | struct DisasContext ctx; |
| 2941 | 3032 | struct DisasContext *dc = &ctx; |
| 2942 | 3033 | uint32_t next_page_start; |
| 3034 | + target_ulong npc; | |
| 2943 | 3035 | |
| 2944 | 3036 | if (!logfile) |
| 2945 | 3037 | logfile = stderr; |
| ... | ... | @@ -2968,18 +3060,24 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, |
| 2968 | 3060 | dc->cc_size_uptodate = -1; |
| 2969 | 3061 | |
| 2970 | 3062 | /* Decode TB flags. */ |
| 2971 | - dc->user = tb->flags & U_FLAG; | |
| 3063 | + dc->tb_flags = tb->flags & (P_FLAG | U_FLAG | X_FLAG); | |
| 2972 | 3064 | dc->delayed_branch = !!(tb->flags & 7); |
| 3065 | + if (dc->delayed_branch) | |
| 3066 | + dc->jmp = JMP_INDIRECT; | |
| 3067 | + else | |
| 3068 | + dc->jmp = JMP_NOJMP; | |
| 3069 | + | |
| 3070 | + dc->cpustate_changed = 0; | |
| 2973 | 3071 | |
| 2974 | 3072 | if (loglevel & CPU_LOG_TB_IN_ASM) { |
| 2975 | 3073 | fprintf(logfile, |
| 2976 | - "srch=%d pc=%x %x bt=%x ds=%lld ccs=%x\n" | |
| 3074 | + "srch=%d pc=%x %x flg=%llx bt=%x ds=%lld ccs=%x\n" | |
| 2977 | 3075 | "pid=%x usp=%x\n" |
| 2978 | 3076 | "%x.%x.%x.%x\n" |
| 2979 | 3077 | "%x.%x.%x.%x\n" |
| 2980 | 3078 | "%x.%x.%x.%x\n" |
| 2981 | 3079 | "%x.%x.%x.%x\n", |
| 2982 | - search_pc, dc->pc, dc->ppc, | |
| 3080 | + search_pc, dc->pc, dc->ppc, tb->flags, | |
| 2983 | 3081 | env->btarget, tb->flags & 7, |
| 2984 | 3082 | env->pregs[PR_CCS], |
| 2985 | 3083 | env->pregs[PR_PID], env->pregs[PR_USP], |
| ... | ... | @@ -2997,9 +3095,6 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, |
| 2997 | 3095 | do |
| 2998 | 3096 | { |
| 2999 | 3097 | check_breakpoint(env, dc); |
| 3000 | - if (dc->is_jmp == DISAS_JUMP | |
| 3001 | - || dc->is_jmp == DISAS_SWI) | |
| 3002 | - goto done; | |
| 3003 | 3098 | |
| 3004 | 3099 | if (search_pc) { |
| 3005 | 3100 | j = gen_opc_ptr - gen_opc_buf; |
| ... | ... | @@ -3034,13 +3129,20 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, |
| 3034 | 3129 | actually genereating any host code, the simulator will just |
| 3035 | 3130 | loop doing nothing for on this program location. */ |
| 3036 | 3131 | if (dc->delayed_branch) { |
| 3037 | - t_gen_mov_env_TN(dslot, tcg_const_tl(0)); | |
| 3038 | 3132 | dc->delayed_branch--; |
| 3039 | 3133 | if (dc->delayed_branch == 0) |
| 3040 | 3134 | { |
| 3041 | - t_gen_cc_jmp(env_btarget, | |
| 3042 | - tcg_const_tl(dc->pc)); | |
| 3043 | - dc->is_jmp = DISAS_JUMP; | |
| 3135 | + if (tb->flags & 7) | |
| 3136 | + t_gen_mov_env_TN(dslot, | |
| 3137 | + tcg_const_tl(0)); | |
| 3138 | + if (dc->jmp == JMP_DIRECT) { | |
| 3139 | + dc->is_jmp = DISAS_NEXT; | |
| 3140 | + } else { | |
| 3141 | + t_gen_cc_jmp(env_btarget, | |
| 3142 | + tcg_const_tl(dc->pc)); | |
| 3143 | + dc->is_jmp = DISAS_JUMP; | |
| 3144 | + } | |
| 3145 | + break; | |
| 3044 | 3146 | } |
| 3045 | 3147 | } |
| 3046 | 3148 | |
| ... | ... | @@ -3051,28 +3153,33 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, |
| 3051 | 3153 | } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end |
| 3052 | 3154 | && (dc->pc < next_page_start)); |
| 3053 | 3155 | |
| 3156 | + npc = dc->pc; | |
| 3157 | + if (dc->jmp == JMP_DIRECT && !dc->delayed_branch) | |
| 3158 | + npc = dc->jmp_pc; | |
| 3159 | + | |
| 3160 | + /* Force an update if the per-tb cpu state has changed. */ | |
| 3161 | + if (dc->is_jmp == DISAS_NEXT | |
| 3162 | + && (dc->cpustate_changed || !dc->flagx_known | |
| 3163 | + || (dc->flags_x != (tb->flags & X_FLAG)))) { | |
| 3164 | + dc->is_jmp = DISAS_UPDATE; | |
| 3165 | + tcg_gen_movi_tl(env_pc, npc); | |
| 3166 | + } | |
| 3054 | 3167 | /* Broken branch+delayslot sequence. */ |
| 3055 | 3168 | if (dc->delayed_branch == 1) { |
| 3056 | 3169 | /* Set env->dslot to the size of the branch insn. */ |
| 3057 | 3170 | t_gen_mov_env_TN(dslot, tcg_const_tl(dc->pc - dc->ppc)); |
| 3058 | - } | |
| 3059 | - | |
| 3060 | - if (!dc->is_jmp) { | |
| 3061 | - D(fprintf(logfile, "!jmp pc=%x jmp=%d db=%d\n", dc->pc, | |
| 3062 | - dc->is_jmp, dc->delayed_branch)); | |
| 3063 | - /* T0 and env_pc should hold the new pc. */ | |
| 3064 | - tcg_gen_movi_tl(cpu_T[0], dc->pc); | |
| 3065 | - tcg_gen_mov_tl(env_pc, cpu_T[0]); | |
| 3171 | + cris_store_direct_jmp(dc); | |
| 3066 | 3172 | } |
| 3067 | 3173 | |
| 3068 | 3174 | cris_evaluate_flags (dc); |
| 3069 | - done: | |
| 3175 | + | |
| 3070 | 3176 | if (__builtin_expect(env->singlestep_enabled, 0)) { |
| 3177 | + tcg_gen_movi_tl(env_pc, npc); | |
| 3071 | 3178 | t_gen_raise_exception(EXCP_DEBUG); |
| 3072 | 3179 | } else { |
| 3073 | 3180 | switch(dc->is_jmp) { |
| 3074 | 3181 | case DISAS_NEXT: |
| 3075 | - gen_goto_tb(dc, 1, dc->pc); | |
| 3182 | + gen_goto_tb(dc, 1, npc); | |
| 3076 | 3183 | break; |
| 3077 | 3184 | default: |
| 3078 | 3185 | case DISAS_JUMP: |
| ... | ... | @@ -3207,7 +3314,9 @@ CPUCRISState *cpu_cris_init (const char *cpu_model) |
| 3207 | 3314 | env_btarget = tcg_global_mem_new(TCG_TYPE_PTR, TCG_AREG0, |
| 3208 | 3315 | offsetof(CPUState, btarget), |
| 3209 | 3316 | "btarget"); |
| 3210 | - | |
| 3317 | + env_btaken = tcg_global_mem_new(TCG_TYPE_PTR, TCG_AREG0, | |
| 3318 | + offsetof(CPUState, btaken), | |
| 3319 | + "btaken"); | |
| 3211 | 3320 | for (i = 0; i < 16; i++) { |
| 3212 | 3321 | cpu_R[i] = tcg_global_mem_new(TCG_TYPE_PTR, TCG_AREG0, |
| 3213 | 3322 | offsetof(CPUState, regs[i]), | ... | ... |