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]), | ... | ... |