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,6 +73,7 @@ TCGv cc_op; | ||
73 | TCGv cc_size; | 73 | TCGv cc_size; |
74 | TCGv cc_mask; | 74 | TCGv cc_mask; |
75 | 75 | ||
76 | +TCGv env_btaken; | ||
76 | TCGv env_btarget; | 77 | TCGv env_btarget; |
77 | TCGv env_pc; | 78 | TCGv env_pc; |
78 | 79 | ||
@@ -104,9 +105,16 @@ typedef struct DisasContext { | @@ -104,9 +105,16 @@ typedef struct DisasContext { | ||
104 | int flags_x; | 105 | int flags_x; |
105 | 106 | ||
106 | int clear_x; /* Clear x after this insn? */ | 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 | int is_jmp; | 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 | int delayed_branch; | 118 | int delayed_branch; |
111 | 119 | ||
112 | struct TranslationBlock *tb; | 120 | struct TranslationBlock *tb; |
@@ -207,8 +215,10 @@ static inline void t_gen_mov_preg_TN(DisasContext *dc, int r, TCGv tn) | @@ -207,8 +215,10 @@ static inline void t_gen_mov_preg_TN(DisasContext *dc, int r, TCGv tn) | ||
207 | tcg_gen_andi_tl(cpu_PR[r], tn, 3); | 215 | tcg_gen_andi_tl(cpu_PR[r], tn, 3); |
208 | else { | 216 | else { |
209 | tcg_gen_mov_tl(cpu_PR[r], tn); | 217 | tcg_gen_mov_tl(cpu_PR[r], tn); |
210 | - if (r == PR_PID) | 218 | + if (r == PR_PID) |
211 | tcg_gen_helper_0_1(helper_tlb_flush_pid, tn); | 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,7 +620,7 @@ static void t_gen_cc_jmp(TCGv pc_true, TCGv pc_false) | ||
610 | btaken = tcg_temp_new(TCG_TYPE_TL); | 620 | btaken = tcg_temp_new(TCG_TYPE_TL); |
611 | 621 | ||
612 | /* Conditional jmp. */ | 622 | /* Conditional jmp. */ |
613 | - t_gen_mov_TN_env(btaken, btaken); | 623 | + tcg_gen_mov_tl(btaken, env_btaken); |
614 | tcg_gen_mov_tl(env_pc, pc_false); | 624 | tcg_gen_mov_tl(env_pc, pc_false); |
615 | tcg_gen_brcondi_tl(TCG_COND_EQ, btaken, 0, l1); | 625 | tcg_gen_brcondi_tl(TCG_COND_EQ, btaken, 0, l1); |
616 | tcg_gen_mov_tl(env_pc, pc_true); | 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,7 +638,7 @@ static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest) | ||
628 | tcg_gen_movi_tl(env_pc, dest); | 638 | tcg_gen_movi_tl(env_pc, dest); |
629 | tcg_gen_exit_tb((long)tb + n); | 639 | tcg_gen_exit_tb((long)tb + n); |
630 | } else { | 640 | } else { |
631 | - tcg_gen_mov_tl(env_pc, cpu_T[0]); | 641 | + tcg_gen_movi_tl(env_pc, dest); |
632 | tcg_gen_exit_tb(0); | 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,6 +658,9 @@ static int sign_extend(unsigned int val, unsigned int width) | ||
648 | 658 | ||
649 | static inline void cris_clear_x_flag(DisasContext *dc) | 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 | dc->flagx_known = 1; | 664 | dc->flagx_known = 1; |
652 | dc->flags_x = 0; | 665 | dc->flags_x = 0; |
653 | } | 666 | } |
@@ -715,6 +728,15 @@ static void cris_evaluate_flags(DisasContext *dc) | @@ -715,6 +728,15 @@ static void cris_evaluate_flags(DisasContext *dc) | ||
715 | } | 728 | } |
716 | break; | 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 | dc->flags_uptodate = 1; | 740 | dc->flags_uptodate = 1; |
719 | } | 741 | } |
720 | } | 742 | } |
@@ -723,6 +745,11 @@ static void cris_cc_mask(DisasContext *dc, unsigned int mask) | @@ -723,6 +745,11 @@ static void cris_cc_mask(DisasContext *dc, unsigned int mask) | ||
723 | { | 745 | { |
724 | uint32_t ovl; | 746 | uint32_t ovl; |
725 | 747 | ||
748 | + if (!mask) { | ||
749 | + dc->update_cc = 0; | ||
750 | + return; | ||
751 | + } | ||
752 | + | ||
726 | /* Check if we need to evaluate the condition codes due to | 753 | /* Check if we need to evaluate the condition codes due to |
727 | CC overlaying. */ | 754 | CC overlaying. */ |
728 | ovl = (dc->cc_mask ^ mask) & ~mask; | 755 | ovl = (dc->cc_mask ^ mask) & ~mask; |
@@ -732,11 +759,6 @@ static void cris_cc_mask(DisasContext *dc, unsigned int mask) | @@ -732,11 +759,6 @@ static void cris_cc_mask(DisasContext *dc, unsigned int mask) | ||
732 | } | 759 | } |
733 | dc->cc_mask = mask; | 760 | dc->cc_mask = mask; |
734 | dc->update_cc = 1; | 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 | static void cris_update_cc_op(DisasContext *dc, int op, int size) | 764 | static void cris_update_cc_op(DisasContext *dc, int op, int size) |
@@ -942,7 +964,7 @@ static int arith_cc(DisasContext *dc) | @@ -942,7 +964,7 @@ static int arith_cc(DisasContext *dc) | ||
942 | 964 | ||
943 | static void gen_tst_cc (DisasContext *dc, int cond) | 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 | /* TODO: optimize more condition codes. */ | 969 | /* TODO: optimize more condition codes. */ |
948 | 970 | ||
@@ -955,9 +977,10 @@ static void gen_tst_cc (DisasContext *dc, int cond) | @@ -955,9 +977,10 @@ static void gen_tst_cc (DisasContext *dc, int cond) | ||
955 | * code is true. | 977 | * code is true. |
956 | */ | 978 | */ |
957 | arith_opt = arith_cc(dc) && !dc->flags_uptodate; | 979 | arith_opt = arith_cc(dc) && !dc->flags_uptodate; |
980 | + move_opt = (dc->cc_op == CC_OP_MOVE) && !dc->flags_uptodate; | ||
958 | switch (cond) { | 981 | switch (cond) { |
959 | case CC_EQ: | 982 | case CC_EQ: |
960 | - if (arith_opt) { | 983 | + if (arith_opt || move_opt) { |
961 | /* If cc_result is zero, T0 should be | 984 | /* If cc_result is zero, T0 should be |
962 | non-zero otherwise T0 should be zero. */ | 985 | non-zero otherwise T0 should be zero. */ |
963 | int l1; | 986 | int l1; |
@@ -975,7 +998,7 @@ static void gen_tst_cc (DisasContext *dc, int cond) | @@ -975,7 +998,7 @@ static void gen_tst_cc (DisasContext *dc, int cond) | ||
975 | } | 998 | } |
976 | break; | 999 | break; |
977 | case CC_NE: | 1000 | case CC_NE: |
978 | - if (arith_opt) | 1001 | + if (arith_opt || move_opt) |
979 | tcg_gen_mov_tl(cpu_T[0], cc_result); | 1002 | tcg_gen_mov_tl(cpu_T[0], cc_result); |
980 | else { | 1003 | else { |
981 | cris_evaluate_flags(dc); | 1004 | cris_evaluate_flags(dc); |
@@ -990,8 +1013,7 @@ static void gen_tst_cc (DisasContext *dc, int cond) | @@ -990,8 +1013,7 @@ static void gen_tst_cc (DisasContext *dc, int cond) | ||
990 | break; | 1013 | break; |
991 | case CC_CC: | 1014 | case CC_CC: |
992 | cris_evaluate_flags(dc); | 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 | tcg_gen_andi_tl(cpu_T[0], cpu_T[0], C_FLAG); | 1017 | tcg_gen_andi_tl(cpu_T[0], cpu_T[0], C_FLAG); |
996 | break; | 1018 | break; |
997 | case CC_VS: | 1019 | case CC_VS: |
@@ -1005,9 +1027,17 @@ static void gen_tst_cc (DisasContext *dc, int cond) | @@ -1005,9 +1027,17 @@ static void gen_tst_cc (DisasContext *dc, int cond) | ||
1005 | tcg_gen_andi_tl(cpu_T[0], cpu_T[0], V_FLAG); | 1027 | tcg_gen_andi_tl(cpu_T[0], cpu_T[0], V_FLAG); |
1006 | break; | 1028 | break; |
1007 | case CC_PL: | 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 | cris_evaluate_flags(dc); | 1041 | cris_evaluate_flags(dc); |
1012 | tcg_gen_xori_tl(cpu_T[0], cpu_PR[PR_CCS], | 1042 | tcg_gen_xori_tl(cpu_T[0], cpu_PR[PR_CCS], |
1013 | N_FLAG); | 1043 | N_FLAG); |
@@ -1015,9 +1045,15 @@ static void gen_tst_cc (DisasContext *dc, int cond) | @@ -1015,9 +1045,15 @@ static void gen_tst_cc (DisasContext *dc, int cond) | ||
1015 | } | 1045 | } |
1016 | break; | 1046 | break; |
1017 | case CC_MI: | 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 | else { | 1058 | else { |
1023 | cris_evaluate_flags(dc); | 1059 | cris_evaluate_flags(dc); |
@@ -1121,28 +1157,46 @@ static void gen_tst_cc (DisasContext *dc, int cond) | @@ -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 | /* This helps us re-schedule the micro-code to insns in delay-slots | 1172 | /* This helps us re-schedule the micro-code to insns in delay-slots |
1127 | before the actual jump. */ | 1173 | before the actual jump. */ |
1128 | dc->delayed_branch = 2; | 1174 | dc->delayed_branch = 2; |
1175 | + dc->jmp_pc = dc->pc + offset; | ||
1176 | + | ||
1129 | if (cond != CC_A) | 1177 | if (cond != CC_A) |
1130 | { | 1178 | { |
1179 | + dc->jmp = JMP_INDIRECT; | ||
1131 | gen_tst_cc (dc, cond); | 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 | /* This helps us re-schedule the micro-code to insns in delay-slots | 1194 | /* This helps us re-schedule the micro-code to insns in delay-slots |
1143 | before the actual jump. */ | 1195 | before the actual jump. */ |
1144 | dc->delayed_branch = 2; | 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 | void gen_load(DisasContext *dc, TCGv dst, TCGv addr, | 1202 | void gen_load(DisasContext *dc, TCGv dst, TCGv addr, |
@@ -1150,6 +1204,11 @@ 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 | int mem_index = cpu_mmu_index(dc->env); | 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 | if (size == 1) { | 1212 | if (size == 1) { |
1154 | if (sign) | 1213 | if (sign) |
1155 | tcg_gen_qemu_ld8s(dst, addr, mem_index); | 1214 | tcg_gen_qemu_ld8s(dst, addr, mem_index); |
@@ -1172,6 +1231,21 @@ void gen_store (DisasContext *dc, TCGv addr, TCGv val, | @@ -1172,6 +1231,21 @@ void gen_store (DisasContext *dc, TCGv addr, TCGv val, | ||
1172 | { | 1231 | { |
1173 | int mem_index = cpu_mmu_index(dc->env); | 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 | /* Remember, operands are flipped. CRIS has reversed order. */ | 1249 | /* Remember, operands are flipped. CRIS has reversed order. */ |
1176 | if (size == 1) | 1250 | if (size == 1) |
1177 | tcg_gen_qemu_st8(val, addr, mem_index); | 1251 | tcg_gen_qemu_st8(val, addr, mem_index); |
@@ -1179,6 +1253,11 @@ void gen_store (DisasContext *dc, TCGv addr, TCGv val, | @@ -1179,6 +1253,11 @@ void gen_store (DisasContext *dc, TCGv addr, TCGv val, | ||
1179 | tcg_gen_qemu_st16(val, addr, mem_index); | 1253 | tcg_gen_qemu_st16(val, addr, mem_index); |
1180 | else | 1254 | else |
1181 | tcg_gen_qemu_st32(val, addr, mem_index); | 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 | static inline void t_gen_sext(TCGv d, TCGv s, int size) | 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,6 +1431,8 @@ static unsigned int dec_bccq(DisasContext *dc) | ||
1352 | tmp = offset; | 1431 | tmp = offset; |
1353 | offset = sign_extend(offset, 8); | 1432 | offset = sign_extend(offset, 8); |
1354 | 1433 | ||
1434 | + DIS(fprintf (logfile, "b%s %x\n", cc_name(cond), dc->pc + offset)); | ||
1435 | + | ||
1355 | /* op2 holds the condition-code. */ | 1436 | /* op2 holds the condition-code. */ |
1356 | cris_cc_mask(dc, 0); | 1437 | cris_cc_mask(dc, 0); |
1357 | cris_prepare_cc_branch (dc, offset, cond); | 1438 | cris_prepare_cc_branch (dc, offset, cond); |
@@ -1463,9 +1544,10 @@ static unsigned int dec_asrq(DisasContext *dc) | @@ -1463,9 +1544,10 @@ static unsigned int dec_asrq(DisasContext *dc) | ||
1463 | DIS(fprintf (logfile, "asrq %u, $r%d\n", dc->op1, dc->op2)); | 1544 | DIS(fprintf (logfile, "asrq %u, $r%d\n", dc->op1, dc->op2)); |
1464 | cris_cc_mask(dc, CC_MASK_NZ); | 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 | cpu_R[dc->op2], | 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 | return 2; | 1551 | return 2; |
1470 | } | 1552 | } |
1471 | static unsigned int dec_lslq(DisasContext *dc) | 1553 | static unsigned int dec_lslq(DisasContext *dc) |
@@ -1475,9 +1557,11 @@ static unsigned int dec_lslq(DisasContext *dc) | @@ -1475,9 +1557,11 @@ static unsigned int dec_lslq(DisasContext *dc) | ||
1475 | 1557 | ||
1476 | cris_cc_mask(dc, CC_MASK_NZ); | 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 | cpu_R[dc->op2], | 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 | return 2; | 1565 | return 2; |
1482 | } | 1566 | } |
1483 | static unsigned int dec_lsrq(DisasContext *dc) | 1567 | static unsigned int dec_lsrq(DisasContext *dc) |
@@ -1487,9 +1571,10 @@ static unsigned int dec_lsrq(DisasContext *dc) | @@ -1487,9 +1571,10 @@ static unsigned int dec_lsrq(DisasContext *dc) | ||
1487 | 1571 | ||
1488 | cris_cc_mask(dc, CC_MASK_NZ); | 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 | cpu_R[dc->op2], | 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 | return 2; | 1578 | return 2; |
1494 | } | 1579 | } |
1495 | 1580 | ||
@@ -1962,7 +2047,6 @@ static unsigned int dec_setclrf(DisasContext *dc) | @@ -1962,7 +2047,6 @@ static unsigned int dec_setclrf(DisasContext *dc) | ||
1962 | 2047 | ||
1963 | flags = (EXTRACT_FIELD(dc->ir, 12, 15) << 4) | 2048 | flags = (EXTRACT_FIELD(dc->ir, 12, 15) << 4) |
1964 | | EXTRACT_FIELD(dc->ir, 0, 3); | 2049 | | EXTRACT_FIELD(dc->ir, 0, 3); |
1965 | - DIS(fprintf (logfile, "set=%d flags=%x\n", set, flags)); | ||
1966 | if (set && flags == 0) { | 2050 | if (set && flags == 0) { |
1967 | DIS(fprintf (logfile, "nop\n")); | 2051 | DIS(fprintf (logfile, "nop\n")); |
1968 | return 2; | 2052 | return 2; |
@@ -1975,13 +2059,30 @@ static unsigned int dec_setclrf(DisasContext *dc) | @@ -1975,13 +2059,30 @@ static unsigned int dec_setclrf(DisasContext *dc) | ||
1975 | flags)); | 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 | dc->flagx_known = 1; | 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 | /* Simply decode the flags. */ | 2086 | /* Simply decode the flags. */ |
1986 | cris_evaluate_flags (dc); | 2087 | cris_evaluate_flags (dc); |
1987 | cris_update_cc_op(dc, CC_OP_FLAGS, 4); | 2088 | cris_update_cc_op(dc, CC_OP_FLAGS, 4); |
@@ -1989,11 +2090,11 @@ static unsigned int dec_setclrf(DisasContext *dc) | @@ -1989,11 +2090,11 @@ static unsigned int dec_setclrf(DisasContext *dc) | ||
1989 | tcg_gen_movi_tl(cc_op, dc->cc_op); | 2090 | tcg_gen_movi_tl(cc_op, dc->cc_op); |
1990 | 2091 | ||
1991 | if (set) { | 2092 | if (set) { |
1992 | - if (!dc->user && (flags & U_FLAG)) { | 2093 | + if (!(dc->tb_flags & U_FLAG) && (flags & U_FLAG)) { |
1993 | /* Enter user mode. */ | 2094 | /* Enter user mode. */ |
1994 | t_gen_mov_env_TN(ksp, cpu_R[R_SP]); | 2095 | t_gen_mov_env_TN(ksp, cpu_R[R_SP]); |
1995 | tcg_gen_mov_tl(cpu_R[R_SP], cpu_PR[PR_USP]); | 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 | tcg_gen_ori_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], flags); | 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,7 +2131,7 @@ static unsigned int dec_move_rp(DisasContext *dc) | ||
2030 | if (dc->op2 == PR_CCS) { | 2131 | if (dc->op2 == PR_CCS) { |
2031 | cris_evaluate_flags(dc); | 2132 | cris_evaluate_flags(dc); |
2032 | t_gen_mov_TN_reg(cpu_T[0], dc->op1); | 2133 | t_gen_mov_TN_reg(cpu_T[0], dc->op1); |
2033 | - if (dc->user) { | 2134 | + if (dc->tb_flags & U_FLAG) { |
2034 | /* User space is not allowed to touch all flags. */ | 2135 | /* User space is not allowed to touch all flags. */ |
2035 | tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0x39f); | 2136 | tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0x39f); |
2036 | tcg_gen_andi_tl(cpu_T[1], cpu_PR[PR_CCS], ~0x39f); | 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,16 +2152,12 @@ static unsigned int dec_move_pr(DisasContext *dc) | ||
2051 | { | 2152 | { |
2052 | DIS(fprintf (logfile, "move $p%u, $r%u\n", dc->op1, dc->op2)); | 2153 | DIS(fprintf (logfile, "move $p%u, $r%u\n", dc->op1, dc->op2)); |
2053 | cris_cc_mask(dc, 0); | 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 | cris_evaluate_flags(dc); | 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 | cpu_R[dc->op1], cpu_R[dc->op1], cpu_T[1], | 2161 | cpu_R[dc->op1], cpu_R[dc->op1], cpu_T[1], |
2065 | preg_sizes[dc->op2]); | 2162 | preg_sizes[dc->op2]); |
2066 | return 2; | 2163 | return 2; |
@@ -2410,7 +2507,7 @@ static unsigned int dec_move_mp(DisasContext *dc) | @@ -2410,7 +2507,7 @@ static unsigned int dec_move_mp(DisasContext *dc) | ||
2410 | cris_cc_mask(dc, 0); | 2507 | cris_cc_mask(dc, 0); |
2411 | if (dc->op2 == PR_CCS) { | 2508 | if (dc->op2 == PR_CCS) { |
2412 | cris_evaluate_flags(dc); | 2509 | cris_evaluate_flags(dc); |
2413 | - if (dc->user) { | 2510 | + if (dc->tb_flags & U_FLAG) { |
2414 | /* User space is not allowed to touch all flags. */ | 2511 | /* User space is not allowed to touch all flags. */ |
2415 | tcg_gen_andi_tl(cpu_T[1], cpu_T[1], 0x39f); | 2512 | tcg_gen_andi_tl(cpu_T[1], cpu_T[1], 0x39f); |
2416 | tcg_gen_andi_tl(cpu_T[0], cpu_PR[PR_CCS], ~0x39f); | 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,7 +2658,7 @@ static unsigned int dec_jump_p(DisasContext *dc) | ||
2561 | /* rete will often have low bit set to indicate delayslot. */ | 2658 | /* rete will often have low bit set to indicate delayslot. */ |
2562 | tcg_gen_andi_tl(env_btarget, cpu_T[0], ~1); | 2659 | tcg_gen_andi_tl(env_btarget, cpu_T[0], ~1); |
2563 | cris_cc_mask(dc, 0); | 2660 | cris_cc_mask(dc, 0); |
2564 | - cris_prepare_dyn_jmp(dc); | 2661 | + cris_prepare_jmp(dc, JMP_INDIRECT); |
2565 | return 2; | 2662 | return 2; |
2566 | } | 2663 | } |
2567 | 2664 | ||
@@ -2576,7 +2673,7 @@ static unsigned int dec_jas_r(DisasContext *dc) | @@ -2576,7 +2673,7 @@ static unsigned int dec_jas_r(DisasContext *dc) | ||
2576 | abort(); | 2673 | abort(); |
2577 | t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 4)); | 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 | return 2; | 2677 | return 2; |
2581 | } | 2678 | } |
2582 | 2679 | ||
@@ -2589,9 +2686,10 @@ static unsigned int dec_jas_im(DisasContext *dc) | @@ -2589,9 +2686,10 @@ static unsigned int dec_jas_im(DisasContext *dc) | ||
2589 | DIS(fprintf (logfile, "jas 0x%x\n", imm)); | 2686 | DIS(fprintf (logfile, "jas 0x%x\n", imm)); |
2590 | cris_cc_mask(dc, 0); | 2687 | cris_cc_mask(dc, 0); |
2591 | /* Store the return address in Pd. */ | 2688 | /* Store the return address in Pd. */ |
2592 | - tcg_gen_movi_tl(env_btarget, imm); | ||
2593 | t_gen_mov_preg_TN(dc, dc->op2, tcg_const_tl(dc->pc + 8)); | 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 | return 6; | 2693 | return 6; |
2596 | } | 2694 | } |
2597 | 2695 | ||
@@ -2604,11 +2702,10 @@ static unsigned int dec_jasc_im(DisasContext *dc) | @@ -2604,11 +2702,10 @@ static unsigned int dec_jasc_im(DisasContext *dc) | ||
2604 | DIS(fprintf (logfile, "jasc 0x%x\n", imm)); | 2702 | DIS(fprintf (logfile, "jasc 0x%x\n", imm)); |
2605 | cris_cc_mask(dc, 0); | 2703 | cris_cc_mask(dc, 0); |
2606 | /* Store the return address in Pd. */ | 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 | return 6; | 2709 | return 6; |
2613 | } | 2710 | } |
2614 | 2711 | ||
@@ -2617,11 +2714,9 @@ static unsigned int dec_jasc_r(DisasContext *dc) | @@ -2617,11 +2714,9 @@ static unsigned int dec_jasc_r(DisasContext *dc) | ||
2617 | DIS(fprintf (logfile, "jasc_r $r%u, $p%u\n", dc->op1, dc->op2)); | 2714 | DIS(fprintf (logfile, "jasc_r $r%u, $p%u\n", dc->op1, dc->op2)); |
2618 | cris_cc_mask(dc, 0); | 2715 | cris_cc_mask(dc, 0); |
2619 | /* Store the return address in Pd. */ | 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 | return 2; | 2720 | return 2; |
2626 | } | 2721 | } |
2627 | 2722 | ||
@@ -2651,12 +2746,11 @@ static unsigned int dec_bas_im(DisasContext *dc) | @@ -2651,12 +2746,11 @@ static unsigned int dec_bas_im(DisasContext *dc) | ||
2651 | 2746 | ||
2652 | DIS(fprintf (logfile, "bas 0x%x, $p%u\n", dc->pc + simm, dc->op2)); | 2747 | DIS(fprintf (logfile, "bas 0x%x, $p%u\n", dc->pc + simm, dc->op2)); |
2653 | cris_cc_mask(dc, 0); | 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 | return 6; | 2754 | return 6; |
2661 | } | 2755 | } |
2662 | 2756 | ||
@@ -2667,12 +2761,11 @@ static unsigned int dec_basc_im(DisasContext *dc) | @@ -2667,12 +2761,11 @@ static unsigned int dec_basc_im(DisasContext *dc) | ||
2667 | 2761 | ||
2668 | DIS(fprintf (logfile, "basc 0x%x, $p%u\n", dc->pc + simm, dc->op2)); | 2762 | DIS(fprintf (logfile, "basc 0x%x, $p%u\n", dc->pc + simm, dc->op2)); |
2669 | cris_cc_mask(dc, 0); | 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 | return 6; | 2769 | return 6; |
2677 | } | 2770 | } |
2678 | 2771 | ||
@@ -2699,8 +2792,7 @@ static unsigned int dec_rfe_etc(DisasContext *dc) | @@ -2699,8 +2792,7 @@ static unsigned int dec_rfe_etc(DisasContext *dc) | ||
2699 | break; | 2792 | break; |
2700 | case 6: | 2793 | case 6: |
2701 | /* break. */ | 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 | /* Breaks start at 16 in the exception vector. */ | 2796 | /* Breaks start at 16 in the exception vector. */ |
2705 | t_gen_mov_env_TN(trap_vector, | 2797 | t_gen_mov_env_TN(trap_vector, |
2706 | tcg_const_tl(dc->op1 + 16)); | 2798 | tcg_const_tl(dc->op1 + 16)); |
@@ -2884,8 +2976,7 @@ static void check_breakpoint(CPUState *env, DisasContext *dc) | @@ -2884,8 +2976,7 @@ static void check_breakpoint(CPUState *env, DisasContext *dc) | ||
2884 | for(j = 0; j < env->nb_breakpoints; j++) { | 2976 | for(j = 0; j < env->nb_breakpoints; j++) { |
2885 | if (env->breakpoints[j] == dc->pc) { | 2977 | if (env->breakpoints[j] == dc->pc) { |
2886 | cris_evaluate_flags (dc); | 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 | t_gen_raise_exception(EXCP_DEBUG); | 2980 | t_gen_raise_exception(EXCP_DEBUG); |
2890 | dc->is_jmp = DISAS_UPDATE; | 2981 | dc->is_jmp = DISAS_UPDATE; |
2891 | } | 2982 | } |
@@ -2940,6 +3031,7 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, | @@ -2940,6 +3031,7 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, | ||
2940 | struct DisasContext ctx; | 3031 | struct DisasContext ctx; |
2941 | struct DisasContext *dc = &ctx; | 3032 | struct DisasContext *dc = &ctx; |
2942 | uint32_t next_page_start; | 3033 | uint32_t next_page_start; |
3034 | + target_ulong npc; | ||
2943 | 3035 | ||
2944 | if (!logfile) | 3036 | if (!logfile) |
2945 | logfile = stderr; | 3037 | logfile = stderr; |
@@ -2968,18 +3060,24 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, | @@ -2968,18 +3060,24 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, | ||
2968 | dc->cc_size_uptodate = -1; | 3060 | dc->cc_size_uptodate = -1; |
2969 | 3061 | ||
2970 | /* Decode TB flags. */ | 3062 | /* Decode TB flags. */ |
2971 | - dc->user = tb->flags & U_FLAG; | 3063 | + dc->tb_flags = tb->flags & (P_FLAG | U_FLAG | X_FLAG); |
2972 | dc->delayed_branch = !!(tb->flags & 7); | 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 | if (loglevel & CPU_LOG_TB_IN_ASM) { | 3072 | if (loglevel & CPU_LOG_TB_IN_ASM) { |
2975 | fprintf(logfile, | 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 | "pid=%x usp=%x\n" | 3075 | "pid=%x usp=%x\n" |
2978 | "%x.%x.%x.%x\n" | 3076 | "%x.%x.%x.%x\n" |
2979 | "%x.%x.%x.%x\n" | 3077 | "%x.%x.%x.%x\n" |
2980 | "%x.%x.%x.%x\n" | 3078 | "%x.%x.%x.%x\n" |
2981 | "%x.%x.%x.%x\n", | 3079 | "%x.%x.%x.%x\n", |
2982 | - search_pc, dc->pc, dc->ppc, | 3080 | + search_pc, dc->pc, dc->ppc, tb->flags, |
2983 | env->btarget, tb->flags & 7, | 3081 | env->btarget, tb->flags & 7, |
2984 | env->pregs[PR_CCS], | 3082 | env->pregs[PR_CCS], |
2985 | env->pregs[PR_PID], env->pregs[PR_USP], | 3083 | env->pregs[PR_PID], env->pregs[PR_USP], |
@@ -2997,9 +3095,6 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, | @@ -2997,9 +3095,6 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, | ||
2997 | do | 3095 | do |
2998 | { | 3096 | { |
2999 | check_breakpoint(env, dc); | 3097 | check_breakpoint(env, dc); |
3000 | - if (dc->is_jmp == DISAS_JUMP | ||
3001 | - || dc->is_jmp == DISAS_SWI) | ||
3002 | - goto done; | ||
3003 | 3098 | ||
3004 | if (search_pc) { | 3099 | if (search_pc) { |
3005 | j = gen_opc_ptr - gen_opc_buf; | 3100 | j = gen_opc_ptr - gen_opc_buf; |
@@ -3034,13 +3129,20 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, | @@ -3034,13 +3129,20 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, | ||
3034 | actually genereating any host code, the simulator will just | 3129 | actually genereating any host code, the simulator will just |
3035 | loop doing nothing for on this program location. */ | 3130 | loop doing nothing for on this program location. */ |
3036 | if (dc->delayed_branch) { | 3131 | if (dc->delayed_branch) { |
3037 | - t_gen_mov_env_TN(dslot, tcg_const_tl(0)); | ||
3038 | dc->delayed_branch--; | 3132 | dc->delayed_branch--; |
3039 | if (dc->delayed_branch == 0) | 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,28 +3153,33 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, | ||
3051 | } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end | 3153 | } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end |
3052 | && (dc->pc < next_page_start)); | 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 | /* Broken branch+delayslot sequence. */ | 3167 | /* Broken branch+delayslot sequence. */ |
3055 | if (dc->delayed_branch == 1) { | 3168 | if (dc->delayed_branch == 1) { |
3056 | /* Set env->dslot to the size of the branch insn. */ | 3169 | /* Set env->dslot to the size of the branch insn. */ |
3057 | t_gen_mov_env_TN(dslot, tcg_const_tl(dc->pc - dc->ppc)); | 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 | cris_evaluate_flags (dc); | 3174 | cris_evaluate_flags (dc); |
3069 | - done: | 3175 | + |
3070 | if (__builtin_expect(env->singlestep_enabled, 0)) { | 3176 | if (__builtin_expect(env->singlestep_enabled, 0)) { |
3177 | + tcg_gen_movi_tl(env_pc, npc); | ||
3071 | t_gen_raise_exception(EXCP_DEBUG); | 3178 | t_gen_raise_exception(EXCP_DEBUG); |
3072 | } else { | 3179 | } else { |
3073 | switch(dc->is_jmp) { | 3180 | switch(dc->is_jmp) { |
3074 | case DISAS_NEXT: | 3181 | case DISAS_NEXT: |
3075 | - gen_goto_tb(dc, 1, dc->pc); | 3182 | + gen_goto_tb(dc, 1, npc); |
3076 | break; | 3183 | break; |
3077 | default: | 3184 | default: |
3078 | case DISAS_JUMP: | 3185 | case DISAS_JUMP: |
@@ -3207,7 +3314,9 @@ CPUCRISState *cpu_cris_init (const char *cpu_model) | @@ -3207,7 +3314,9 @@ CPUCRISState *cpu_cris_init (const char *cpu_model) | ||
3207 | env_btarget = tcg_global_mem_new(TCG_TYPE_PTR, TCG_AREG0, | 3314 | env_btarget = tcg_global_mem_new(TCG_TYPE_PTR, TCG_AREG0, |
3208 | offsetof(CPUState, btarget), | 3315 | offsetof(CPUState, btarget), |
3209 | "btarget"); | 3316 | "btarget"); |
3210 | - | 3317 | + env_btaken = tcg_global_mem_new(TCG_TYPE_PTR, TCG_AREG0, |
3318 | + offsetof(CPUState, btaken), | ||
3319 | + "btaken"); | ||
3211 | for (i = 0; i < 16; i++) { | 3320 | for (i = 0; i < 16; i++) { |
3212 | cpu_R[i] = tcg_global_mem_new(TCG_TYPE_PTR, TCG_AREG0, | 3321 | cpu_R[i] = tcg_global_mem_new(TCG_TYPE_PTR, TCG_AREG0, |
3213 | offsetof(CPUState, regs[i]), | 3322 | offsetof(CPUState, regs[i]), |