Commit 17ac975463baf6cd70538dcb741549262bdab590
1 parent
ef29a70d
More TCG updates for CRIS
* Convert parts of the jump logic to TCG. * Stores no longer have to go via T0/T1. * Use the byte and halfword ldx_code variants when appropriate for insn fetching. * Do not disassemble beyond the translation block. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4350 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
90 additions
and
64 deletions
target-cris/translate.c
... | ... | @@ -235,7 +235,7 @@ static void t_gen_lsl(TCGv d, TCGv a, TCGv b) |
235 | 235 | l1 = gen_new_label(); |
236 | 236 | /* Speculative shift. */ |
237 | 237 | tcg_gen_shl_tl(d, a, b); |
238 | - tcg_gen_brcond_tl(TCG_COND_LE, b, tcg_const_tl(31), l1); | |
238 | + tcg_gen_brcond_tl(TCG_COND_LEU, b, tcg_const_tl(31), l1); | |
239 | 239 | /* Clear dst if shift operands were to large. */ |
240 | 240 | tcg_gen_movi_tl(d, 0); |
241 | 241 | gen_set_label(l1); |
... | ... | @@ -248,7 +248,7 @@ static void t_gen_lsr(TCGv d, TCGv a, TCGv b) |
248 | 248 | l1 = gen_new_label(); |
249 | 249 | /* Speculative shift. */ |
250 | 250 | tcg_gen_shr_tl(d, a, b); |
251 | - tcg_gen_brcond_tl(TCG_COND_LE, b, tcg_const_tl(31), l1); | |
251 | + tcg_gen_brcond_tl(TCG_COND_LEU, b, tcg_const_tl(31), l1); | |
252 | 252 | /* Clear dst if shift operands were to large. */ |
253 | 253 | tcg_gen_movi_tl(d, 0); |
254 | 254 | gen_set_label(l1); |
... | ... | @@ -261,7 +261,7 @@ static void t_gen_asr(TCGv d, TCGv a, TCGv b) |
261 | 261 | l1 = gen_new_label(); |
262 | 262 | /* Speculative shift. */ |
263 | 263 | tcg_gen_sar_tl(d, a, b); |
264 | - tcg_gen_brcond_tl(TCG_COND_LE, b, tcg_const_tl(31), l1); | |
264 | + tcg_gen_brcond_tl(TCG_COND_LEU, b, tcg_const_tl(31), l1); | |
265 | 265 | /* Clear dst if shift operands were to large. */ |
266 | 266 | tcg_gen_sar_tl(d, a, tcg_const_tl(30)); |
267 | 267 | gen_set_label(l1); |
... | ... | @@ -528,6 +528,24 @@ static inline void t_gen_swapr(TCGv d, TCGv s) |
528 | 528 | tcg_gen_discard_tl(org_s); |
529 | 529 | } |
530 | 530 | |
531 | +static void t_gen_cc_jmp(target_ulong pc_true, target_ulong pc_false) | |
532 | +{ | |
533 | + TCGv btaken; | |
534 | + int l1; | |
535 | + | |
536 | + l1 = gen_new_label(); | |
537 | + btaken = tcg_temp_new(TCG_TYPE_TL); | |
538 | + | |
539 | + /* Conditional jmp. */ | |
540 | + t_gen_mov_TN_env(btaken, btaken); | |
541 | + tcg_gen_movi_tl(env_pc, pc_false); | |
542 | + tcg_gen_brcond_tl(TCG_COND_EQ, btaken, tcg_const_tl(0), l1); | |
543 | + tcg_gen_movi_tl(env_pc, pc_true); | |
544 | + gen_set_label(l1); | |
545 | + | |
546 | + tcg_gen_discard_tl(btaken); | |
547 | +} | |
548 | + | |
531 | 549 | static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest) |
532 | 550 | { |
533 | 551 | TranslationBlock *tb; |
... | ... | @@ -908,7 +926,7 @@ static void gen_tst_cc (DisasContext *dc, int cond) |
908 | 926 | break; |
909 | 927 | case CC_A: |
910 | 928 | cris_evaluate_flags(dc); |
911 | - gen_op_movl_T0_im (1); | |
929 | + tcg_gen_movi_tl(cpu_T[0], 1); | |
912 | 930 | break; |
913 | 931 | default: |
914 | 932 | BUG(); |
... | ... | @@ -957,8 +975,6 @@ void gen_load(DisasContext *dc, TCGv dst, TCGv addr, |
957 | 975 | { |
958 | 976 | int mem_index = cpu_mmu_index(dc->env); |
959 | 977 | |
960 | - /* FIXME: qemu_ld does not act as a barrier? */ | |
961 | - tcg_gen_helper_0_0(helper_dummy); | |
962 | 978 | cris_evaluate_flags(dc); |
963 | 979 | if (size == 1) { |
964 | 980 | if (sign) |
... | ... | @@ -977,21 +993,20 @@ void gen_load(DisasContext *dc, TCGv dst, TCGv addr, |
977 | 993 | } |
978 | 994 | } |
979 | 995 | |
980 | -void gen_store_T0_T1 (DisasContext *dc, unsigned int size) | |
996 | +void gen_store (DisasContext *dc, TCGv addr, TCGv val, | |
997 | + unsigned int size) | |
981 | 998 | { |
982 | 999 | int mem_index = cpu_mmu_index(dc->env); |
983 | 1000 | |
984 | - /* FIXME: qemu_st does not act as a barrier? */ | |
985 | - tcg_gen_helper_0_0(helper_dummy); | |
986 | 1001 | cris_evaluate_flags(dc); |
987 | 1002 | |
988 | 1003 | /* Remember, operands are flipped. CRIS has reversed order. */ |
989 | 1004 | if (size == 1) |
990 | - tcg_gen_qemu_st8(cpu_T[1], cpu_T[0], mem_index); | |
1005 | + tcg_gen_qemu_st8(val, addr, mem_index); | |
991 | 1006 | else if (size == 2) |
992 | - tcg_gen_qemu_st16(cpu_T[1], cpu_T[0], mem_index); | |
1007 | + tcg_gen_qemu_st16(val, addr, mem_index); | |
993 | 1008 | else |
994 | - tcg_gen_qemu_st32(cpu_T[1], cpu_T[0], mem_index); | |
1009 | + tcg_gen_qemu_st32(val, addr, mem_index); | |
995 | 1010 | } |
996 | 1011 | |
997 | 1012 | static inline void t_gen_sext(TCGv d, TCGv s, int size) |
... | ... | @@ -1096,22 +1111,28 @@ static int dec_prep_alu_m(DisasContext *dc, int s_ext, int memsize) |
1096 | 1111 | if (memsize == 1) |
1097 | 1112 | insn_len++; |
1098 | 1113 | |
1099 | - imm = ldl_code(dc->pc + 2); | |
1100 | 1114 | if (memsize != 4) { |
1101 | 1115 | if (s_ext) { |
1102 | - imm = sign_extend(imm, (memsize * 8) - 1); | |
1116 | + if (memsize == 1) | |
1117 | + imm = ldsb_code(dc->pc + 2); | |
1118 | + else | |
1119 | + imm = ldsw_code(dc->pc + 2); | |
1103 | 1120 | } else { |
1104 | 1121 | if (memsize == 1) |
1105 | - imm &= 0xff; | |
1122 | + imm = ldub_code(dc->pc + 2); | |
1106 | 1123 | else |
1107 | - imm &= 0xffff; | |
1124 | + imm = lduw_code(dc->pc + 2); | |
1108 | 1125 | } |
1109 | - } | |
1126 | + } else | |
1127 | + imm = ldl_code(dc->pc + 2); | |
1128 | + | |
1110 | 1129 | DIS(fprintf (logfile, "imm=%x rd=%d sext=%d ms=%d\n", |
1111 | 1130 | imm, rd, s_ext, memsize)); |
1112 | 1131 | tcg_gen_movi_tl(cpu_T[1], imm); |
1113 | 1132 | dc->postinc = 0; |
1114 | 1133 | } else { |
1134 | + /* FIXME: qemu_ld does not act as a barrier? */ | |
1135 | + tcg_gen_helper_0_0(helper_dummy); | |
1115 | 1136 | gen_load(dc, cpu_T[1], cpu_R[rs], memsize, 0); |
1116 | 1137 | if (s_ext) |
1117 | 1138 | t_gen_sext(cpu_T[1], cpu_T[1], memsize); |
... | ... | @@ -1250,6 +1271,8 @@ static unsigned int dec_btstq(DisasContext *dc) |
1250 | 1271 | { |
1251 | 1272 | dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4); |
1252 | 1273 | DIS(fprintf (logfile, "btstq %u, $r%d\n", dc->op1, dc->op2)); |
1274 | + | |
1275 | + cris_evaluate_flags(dc); | |
1253 | 1276 | cris_cc_mask(dc, CC_MASK_NZ); |
1254 | 1277 | t_gen_mov_TN_reg(cpu_T[0], dc->op2); |
1255 | 1278 | t_gen_mov_TN_im(cpu_T[1], dc->op1); |
... | ... | @@ -1601,6 +1624,7 @@ static unsigned int dec_btst_r(DisasContext *dc) |
1601 | 1624 | { |
1602 | 1625 | DIS(fprintf (logfile, "btst $r%u, $r%u\n", |
1603 | 1626 | dc->op1, dc->op2)); |
1627 | + cris_evaluate_flags(dc); | |
1604 | 1628 | cris_cc_mask(dc, CC_MASK_NZ); |
1605 | 1629 | dec_prep_alu_r(dc, dc->op1, dc->op2, 4, 0); |
1606 | 1630 | crisv32_alu_op(dc, CC_OP_BTST, dc->op2, 4); |
... | ... | @@ -2162,36 +2186,47 @@ static unsigned int dec_move_pm(DisasContext *dc) |
2162 | 2186 | dc->op2, dc->op1, dc->postinc ? "+]" : "]")); |
2163 | 2187 | |
2164 | 2188 | /* prepare store. Address in T0, value in T1. */ |
2189 | + if (dc->op2 == PR_CCS) | |
2190 | + cris_evaluate_flags(dc); | |
2165 | 2191 | t_gen_mov_TN_preg(cpu_T[1], dc->op2); |
2166 | - t_gen_mov_TN_reg(cpu_T[0], dc->op1); | |
2167 | - gen_store_T0_T1(dc, memsize); | |
2192 | + | |
2193 | + /* FIXME: qemu_st does not act as a barrier? */ | |
2194 | + tcg_gen_helper_0_0(helper_dummy); | |
2195 | + gen_store(dc, cpu_R[dc->op1], cpu_T[1], memsize); | |
2196 | + | |
2168 | 2197 | cris_cc_mask(dc, 0); |
2169 | 2198 | if (dc->postinc) |
2170 | - { | |
2171 | - tcg_gen_addi_tl(cpu_T[0], cpu_T[0], memsize); | |
2172 | - t_gen_mov_reg_TN(dc->op1, cpu_T[0]); | |
2173 | - } | |
2199 | + tcg_gen_addi_tl(cpu_R[dc->op1], cpu_R[dc->op1], memsize); | |
2174 | 2200 | return 2; |
2175 | 2201 | } |
2176 | 2202 | |
2177 | 2203 | static unsigned int dec_movem_mr(DisasContext *dc) |
2178 | 2204 | { |
2205 | + TCGv tmp[16]; | |
2179 | 2206 | int i; |
2180 | 2207 | |
2181 | 2208 | DIS(fprintf (logfile, "movem [$r%u%s, $r%u\n", dc->op1, |
2182 | 2209 | dc->postinc ? "+]" : "]", dc->op2)); |
2183 | 2210 | |
2211 | + /* FIXME: qemu_ld does not act as a barrier? */ | |
2212 | + tcg_gen_helper_0_0(helper_dummy); | |
2213 | + | |
2184 | 2214 | /* fetch the address into T0 and T1. */ |
2185 | - t_gen_mov_TN_reg(cpu_T[1], dc->op1); | |
2186 | 2215 | for (i = 0; i <= dc->op2; i++) { |
2216 | + tmp[i] = tcg_temp_new(TCG_TYPE_TL); | |
2187 | 2217 | /* Perform the load onto regnum i. Always dword wide. */ |
2188 | - tcg_gen_mov_tl(cpu_T[0], cpu_T[1]); | |
2189 | - gen_load(dc, cpu_R[i], cpu_T[1], 4, 0); | |
2190 | - tcg_gen_addi_tl(cpu_T[1], cpu_T[1], 4); | |
2218 | + tcg_gen_addi_tl(cpu_T[0], cpu_R[dc->op1], i * 4); | |
2219 | + gen_load(dc, tmp[i], cpu_T[0], 4, 0); | |
2191 | 2220 | } |
2221 | + | |
2222 | + for (i = 0; i <= dc->op2; i++) { | |
2223 | + tcg_gen_mov_tl(cpu_R[i], tmp[i]); | |
2224 | + tcg_gen_discard_tl(tmp[i]); | |
2225 | + } | |
2226 | + | |
2192 | 2227 | /* writeback the updated pointer value. */ |
2193 | 2228 | if (dc->postinc) |
2194 | - t_gen_mov_reg_TN(dc->op1, cpu_T[1]); | |
2229 | + tcg_gen_addi_tl(cpu_R[dc->op1], cpu_R[dc->op1], i * 4); | |
2195 | 2230 | |
2196 | 2231 | /* gen_load might want to evaluate the previous insns flags. */ |
2197 | 2232 | cris_cc_mask(dc, 0); |
... | ... | @@ -2205,23 +2240,17 @@ static unsigned int dec_movem_rm(DisasContext *dc) |
2205 | 2240 | DIS(fprintf (logfile, "movem $r%u, [$r%u%s\n", dc->op2, dc->op1, |
2206 | 2241 | dc->postinc ? "+]" : "]")); |
2207 | 2242 | |
2243 | + /* FIXME: qemu_st does not act as a barrier? */ | |
2244 | + tcg_gen_helper_0_0(helper_dummy); | |
2245 | + | |
2208 | 2246 | for (i = 0; i <= dc->op2; i++) { |
2209 | - /* Fetch register i into T1. */ | |
2210 | - t_gen_mov_TN_reg(cpu_T[1], i); | |
2211 | - /* Fetch the address into T0. */ | |
2212 | - t_gen_mov_TN_reg(cpu_T[0], dc->op1); | |
2213 | - /* Displace it. */ | |
2214 | - tcg_gen_addi_tl(cpu_T[0], cpu_T[0], i * 4); | |
2247 | + /* Displace addr. */ | |
2248 | + tcg_gen_addi_tl(cpu_T[0], cpu_R[dc->op1], i * 4); | |
2215 | 2249 | /* Perform the store. */ |
2216 | - gen_store_T0_T1(dc, 4); | |
2217 | - } | |
2218 | - if (dc->postinc) { | |
2219 | - /* T0 should point to the last written addr, advance one more | |
2220 | - step. */ | |
2221 | - tcg_gen_addi_tl(cpu_T[0], cpu_T[0], 4); | |
2222 | - /* writeback the updated pointer value. */ | |
2223 | - t_gen_mov_reg_TN(dc->op1, cpu_T[0]); | |
2250 | + gen_store(dc, cpu_T[0], cpu_R[i], 4); | |
2224 | 2251 | } |
2252 | + if (dc->postinc) | |
2253 | + tcg_gen_addi_tl(cpu_R[dc->op1], cpu_R[dc->op1], i * 4); | |
2225 | 2254 | cris_cc_mask(dc, 0); |
2226 | 2255 | return 2; |
2227 | 2256 | } |
... | ... | @@ -2236,14 +2265,12 @@ static unsigned int dec_move_rm(DisasContext *dc) |
2236 | 2265 | memsize, dc->op2, dc->op1)); |
2237 | 2266 | |
2238 | 2267 | /* prepare store. */ |
2239 | - t_gen_mov_TN_reg(cpu_T[0], dc->op1); | |
2240 | - t_gen_mov_TN_reg(cpu_T[1], dc->op2); | |
2241 | - gen_store_T0_T1(dc, memsize); | |
2268 | + /* FIXME: qemu_st does not act as a barrier? */ | |
2269 | + tcg_gen_helper_0_0(helper_dummy); | |
2270 | + gen_store(dc, cpu_R[dc->op1], cpu_R[dc->op2], memsize); | |
2271 | + | |
2242 | 2272 | if (dc->postinc) |
2243 | - { | |
2244 | - tcg_gen_addi_tl(cpu_T[0], cpu_T[0], memsize); | |
2245 | - t_gen_mov_reg_TN(dc->op1, cpu_T[0]); | |
2246 | - } | |
2273 | + tcg_gen_addi_tl(cpu_R[dc->op1], cpu_R[dc->op1], memsize); | |
2247 | 2274 | cris_cc_mask(dc, 0); |
2248 | 2275 | return 2; |
2249 | 2276 | } |
... | ... | @@ -2280,11 +2307,13 @@ static unsigned int dec_lapc_im(DisasContext *dc) |
2280 | 2307 | static unsigned int dec_jump_p(DisasContext *dc) |
2281 | 2308 | { |
2282 | 2309 | DIS(fprintf (logfile, "jump $p%u\n", dc->op2)); |
2283 | - cris_cc_mask(dc, 0); | |
2284 | 2310 | |
2311 | + if (dc->op2 == PR_CCS) | |
2312 | + cris_evaluate_flags(dc); | |
2285 | 2313 | t_gen_mov_TN_preg(cpu_T[0], dc->op2); |
2286 | 2314 | /* rete will often have low bit set to indicate delayslot. */ |
2287 | 2315 | tcg_gen_andi_tl(env_btarget, cpu_T[0], ~1); |
2316 | + cris_cc_mask(dc, 0); | |
2288 | 2317 | cris_prepare_dyn_jmp(dc); |
2289 | 2318 | return 2; |
2290 | 2319 | } |
... | ... | @@ -2298,7 +2327,8 @@ static unsigned int dec_jas_r(DisasContext *dc) |
2298 | 2327 | tcg_gen_mov_tl(env_btarget, cpu_R[dc->op1]); |
2299 | 2328 | if (dc->op2 > 15) |
2300 | 2329 | abort(); |
2301 | - tcg_gen_movi_tl(cpu_PR[dc->op2], dc->pc + 4); | |
2330 | + tcg_gen_movi_tl(cpu_T[0], dc->pc + 4); | |
2331 | + tcg_gen_mov_tl(cpu_PR[dc->op2], cpu_T[0]); | |
2302 | 2332 | |
2303 | 2333 | cris_prepare_dyn_jmp(dc); |
2304 | 2334 | return 2; |
... | ... | @@ -2312,7 +2342,7 @@ static unsigned int dec_jas_im(DisasContext *dc) |
2312 | 2342 | |
2313 | 2343 | DIS(fprintf (logfile, "jas 0x%x\n", imm)); |
2314 | 2344 | cris_cc_mask(dc, 0); |
2315 | - /* Stor the return address in Pd. */ | |
2345 | + /* Store the return address in Pd. */ | |
2316 | 2346 | tcg_gen_movi_tl(env_btarget, imm); |
2317 | 2347 | t_gen_mov_preg_TN(dc->op2, tcg_const_tl(dc->pc + 8)); |
2318 | 2348 | cris_prepare_dyn_jmp(dc); |
... | ... | @@ -2327,7 +2357,7 @@ static unsigned int dec_jasc_im(DisasContext *dc) |
2327 | 2357 | |
2328 | 2358 | DIS(fprintf (logfile, "jasc 0x%x\n", imm)); |
2329 | 2359 | cris_cc_mask(dc, 0); |
2330 | - /* Stor the return address in Pd. */ | |
2360 | + /* Store the return address in Pd. */ | |
2331 | 2361 | tcg_gen_movi_tl(cpu_T[0], imm); |
2332 | 2362 | t_gen_mov_env_TN(btarget, cpu_T[0]); |
2333 | 2363 | tcg_gen_movi_tl(cpu_T[0], dc->pc + 8 + 4); |
... | ... | @@ -2340,7 +2370,7 @@ static unsigned int dec_jasc_r(DisasContext *dc) |
2340 | 2370 | { |
2341 | 2371 | DIS(fprintf (logfile, "jasc_r $r%u, $p%u\n", dc->op1, dc->op2)); |
2342 | 2372 | cris_cc_mask(dc, 0); |
2343 | - /* Stor the return address in Pd. */ | |
2373 | + /* Store the return address in Pd. */ | |
2344 | 2374 | t_gen_mov_TN_reg(cpu_T[0], dc->op1); |
2345 | 2375 | t_gen_mov_env_TN(btarget, cpu_T[0]); |
2346 | 2376 | tcg_gen_movi_tl(cpu_T[0], dc->pc + 4 + 4); |
... | ... | @@ -2354,8 +2384,7 @@ static unsigned int dec_bcc_im(DisasContext *dc) |
2354 | 2384 | int32_t offset; |
2355 | 2385 | uint32_t cond = dc->op2; |
2356 | 2386 | |
2357 | - offset = ldl_code(dc->pc + 2); | |
2358 | - offset = sign_extend(offset, 15); | |
2387 | + offset = ldsw_code(dc->pc + 2); | |
2359 | 2388 | |
2360 | 2389 | DIS(fprintf (logfile, "b%s %d pc=%x dst=%x\n", |
2361 | 2390 | cc_name(cond), offset, |
... | ... | @@ -2579,12 +2608,10 @@ static inline unsigned int |
2579 | 2608 | cris_decoder(DisasContext *dc) |
2580 | 2609 | { |
2581 | 2610 | unsigned int insn_len = 2; |
2582 | - uint32_t tmp; | |
2583 | 2611 | int i; |
2584 | 2612 | |
2585 | 2613 | /* Load a halfword onto the instruction register. */ |
2586 | - tmp = ldl_code(dc->pc); | |
2587 | - dc->ir = tmp & 0xffff; | |
2614 | + dc->ir = lduw_code(dc->pc); | |
2588 | 2615 | |
2589 | 2616 | /* Now decode it. */ |
2590 | 2617 | dc->opcode = EXTRACT_FIELD(dc->ir, 4, 11); |
... | ... | @@ -2720,12 +2747,11 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, |
2720 | 2747 | if (dc->delayed_branch == 0) |
2721 | 2748 | { |
2722 | 2749 | if (dc->bcc == CC_A) { |
2723 | - gen_op_jmp1 (); | |
2750 | + tcg_gen_mov_tl(env_pc, env_btarget); | |
2724 | 2751 | dc->is_jmp = DISAS_JUMP; |
2725 | 2752 | } |
2726 | 2753 | else { |
2727 | - /* Conditional jmp. */ | |
2728 | - gen_op_cc_jmp (dc->delayed_pc, dc->pc); | |
2754 | + t_gen_cc_jmp(dc->delayed_pc, dc->pc); | |
2729 | 2755 | dc->is_jmp = DISAS_JUMP; |
2730 | 2756 | } |
2731 | 2757 | } |
... | ... | @@ -2785,7 +2811,7 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, |
2785 | 2811 | if (loglevel & CPU_LOG_TB_IN_ASM) { |
2786 | 2812 | fprintf(logfile, "--------------\n"); |
2787 | 2813 | fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start)); |
2788 | - target_disas(logfile, pc_start, dc->pc + 4 - pc_start, 0); | |
2814 | + target_disas(logfile, pc_start, dc->pc - pc_start, 0); | |
2789 | 2815 | fprintf(logfile, "\nisize=%d osize=%d\n", |
2790 | 2816 | dc->pc - pc_start, gen_opc_ptr - gen_opc_buf); |
2791 | 2817 | } |
... | ... | @@ -2942,5 +2968,5 @@ void cpu_reset (CPUCRISState *env) |
2942 | 2968 | void gen_pc_load(CPUState *env, struct TranslationBlock *tb, |
2943 | 2969 | unsigned long searched_pc, int pc_pos, void *puc) |
2944 | 2970 | { |
2945 | - env->pc = gen_opc_pc[pc_pos]; | |
2971 | + env->pc = gen_opc_pc[pc_pos]; | |
2946 | 2972 | } | ... | ... |