Commit 2a44f7f173649e90b6f48c85d08f009c6fe765bd

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