Revision 2a44f7f1
b/target-cris/translate.c | ||
---|---|---|
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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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]), |
Also available in: Unified diff