Commit 1000822b03f44cc0b0e624cd60e5dce8dde7d463
1 parent
ba6a9d8c
SH4: convert branch/jump instructions to TCG
(Shin-ichiro KAWASAKI) git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5111 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
2 changed files
with
54 additions
and
118 deletions
target-sh4/op.c
... | ... | @@ -37,70 +37,6 @@ static inline void cond_t(int cond) |
37 | 37 | clr_t(); |
38 | 38 | } |
39 | 39 | |
40 | -void OPPROTO op_bf_s(void) | |
41 | -{ | |
42 | - env->delayed_pc = PARAM1; | |
43 | - if (!(env->sr & SR_T)) { | |
44 | - env->flags |= DELAY_SLOT_TRUE; | |
45 | - } | |
46 | - RETURN(); | |
47 | -} | |
48 | - | |
49 | -void OPPROTO op_bt_s(void) | |
50 | -{ | |
51 | - env->delayed_pc = PARAM1; | |
52 | - if (env->sr & SR_T) { | |
53 | - env->flags |= DELAY_SLOT_TRUE; | |
54 | - } | |
55 | - RETURN(); | |
56 | -} | |
57 | - | |
58 | -void OPPROTO op_store_flags(void) | |
59 | -{ | |
60 | - env->flags &= DELAY_SLOT_TRUE; | |
61 | - env->flags |= PARAM1; | |
62 | - RETURN(); | |
63 | -} | |
64 | - | |
65 | -void OPPROTO op_bra(void) | |
66 | -{ | |
67 | - env->delayed_pc = PARAM1; | |
68 | - RETURN(); | |
69 | -} | |
70 | - | |
71 | -void OPPROTO op_braf_T0(void) | |
72 | -{ | |
73 | - env->delayed_pc = PARAM1 + T0; | |
74 | - RETURN(); | |
75 | -} | |
76 | - | |
77 | -void OPPROTO op_bsr(void) | |
78 | -{ | |
79 | - env->pr = PARAM1; | |
80 | - env->delayed_pc = PARAM2; | |
81 | - RETURN(); | |
82 | -} | |
83 | - | |
84 | -void OPPROTO op_bsrf_T0(void) | |
85 | -{ | |
86 | - env->pr = PARAM1; | |
87 | - env->delayed_pc = PARAM1 + T0; | |
88 | - RETURN(); | |
89 | -} | |
90 | - | |
91 | -void OPPROTO op_jsr_T0(void) | |
92 | -{ | |
93 | - env->pr = PARAM1; | |
94 | - env->delayed_pc = T0; | |
95 | - RETURN(); | |
96 | -} | |
97 | - | |
98 | -void OPPROTO op_rts(void) | |
99 | -{ | |
100 | - env->delayed_pc = env->pr; | |
101 | - RETURN(); | |
102 | -} | |
103 | - | |
104 | 40 | void OPPROTO op_ldtlb(void) |
105 | 41 | { |
106 | 42 | helper_ldtlb(); |
... | ... | @@ -119,13 +55,6 @@ void OPPROTO op_fschg(void) |
119 | 55 | RETURN(); |
120 | 56 | } |
121 | 57 | |
122 | -void OPPROTO op_rte(void) | |
123 | -{ | |
124 | - env->sr = env->ssr; | |
125 | - env->delayed_pc = env->spc; | |
126 | - RETURN(); | |
127 | -} | |
128 | - | |
129 | 58 | void OPPROTO op_addc_T0_T1(void) |
130 | 59 | { |
131 | 60 | helper_addc_T0_T1(); |
... | ... | @@ -257,12 +186,6 @@ void OPPROTO op_trapa(void) |
257 | 186 | RETURN(); |
258 | 187 | } |
259 | 188 | |
260 | -void OPPROTO op_jmp_T0(void) | |
261 | -{ | |
262 | - env->delayed_pc = T0; | |
263 | - RETURN(); | |
264 | -} | |
265 | - | |
266 | 189 | void OPPROTO op_ldcl_rMplus_rN_bank(void) |
267 | 190 | { |
268 | 191 | env->gregs[PARAM2] = env->gregs[PARAM1]; |
... | ... | @@ -568,28 +491,6 @@ void OPPROTO op_movl_FT0_fpul(void) |
568 | 491 | RETURN(); |
569 | 492 | } |
570 | 493 | |
571 | -void OPPROTO op_jT(void) | |
572 | -{ | |
573 | - if (env->sr & SR_T) | |
574 | - GOTO_LABEL_PARAM(1); | |
575 | - RETURN(); | |
576 | -} | |
577 | - | |
578 | -void OPPROTO op_jdelayed(void) | |
579 | -{ | |
580 | - if (env->flags & DELAY_SLOT_TRUE) { | |
581 | - env->flags &= ~DELAY_SLOT_TRUE; | |
582 | - GOTO_LABEL_PARAM(1); | |
583 | - } | |
584 | - RETURN(); | |
585 | -} | |
586 | - | |
587 | -void OPPROTO op_movl_delayed_pc_PC(void) | |
588 | -{ | |
589 | - env->pc = env->delayed_pc; | |
590 | - RETURN(); | |
591 | -} | |
592 | - | |
593 | 494 | void OPPROTO op_raise_illegal_instruction(void) |
594 | 495 | { |
595 | 496 | env->exception_index = 0x180; | ... | ... |
target-sh4/translate.c
... | ... | @@ -62,7 +62,10 @@ static TCGv cpu_env; |
62 | 62 | static TCGv cpu_gregs[24]; |
63 | 63 | static TCGv cpu_pc, cpu_sr, cpu_ssr, cpu_spc, cpu_gbr; |
64 | 64 | static TCGv cpu_vbr, cpu_sgr, cpu_dbr, cpu_mach, cpu_macl; |
65 | -static TCGv cpu_pr, cpu_fpscr, cpu_fpul; | |
65 | +static TCGv cpu_pr, cpu_fpscr, cpu_fpul, cpu_flags; | |
66 | + | |
67 | +/* internal register indexes */ | |
68 | +static TCGv cpu_flags, cpu_delayed_pc; | |
66 | 69 | |
67 | 70 | /* dyngen register indexes */ |
68 | 71 | static TCGv cpu_T[2]; |
... | ... | @@ -120,6 +123,12 @@ static void sh4_translate_init(void) |
120 | 123 | cpu_fpul = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0, |
121 | 124 | offsetof(CPUState, fpul), "FPUL"); |
122 | 125 | |
126 | + cpu_flags = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0, | |
127 | + offsetof(CPUState, flags), "_flags_"); | |
128 | + cpu_delayed_pc = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0, | |
129 | + offsetof(CPUState, delayed_pc), | |
130 | + "_delayed_pc_"); | |
131 | + | |
123 | 132 | /* register helpers */ |
124 | 133 | #undef DEF_HELPER |
125 | 134 | #define DEF_HELPER(ret, name, params) tcg_register_helper(name, #name); |
... | ... | @@ -249,7 +258,7 @@ static void gen_jump(DisasContext * ctx) |
249 | 258 | if (ctx->delayed_pc == (uint32_t) - 1) { |
250 | 259 | /* Target is not statically known, it comes necessarily from a |
251 | 260 | delayed jump as immediate jump are conditinal jumps */ |
252 | - gen_op_movl_delayed_pc_PC(); | |
261 | + tcg_gen_mov_i32(cpu_pc, cpu_delayed_pc); | |
253 | 262 | if (ctx->singlestep_enabled) |
254 | 263 | gen_op_debug(); |
255 | 264 | tcg_gen_exit_tb(0); |
... | ... | @@ -258,6 +267,16 @@ static void gen_jump(DisasContext * ctx) |
258 | 267 | } |
259 | 268 | } |
260 | 269 | |
270 | +static inline void gen_branch_slot(uint32_t delayed_pc, int t) | |
271 | +{ | |
272 | + int label = gen_new_label(); | |
273 | + tcg_gen_movi_i32(cpu_delayed_pc, delayed_pc); | |
274 | + tcg_gen_andi_i32(cpu_T[0], cpu_sr, SR_T); | |
275 | + tcg_gen_brcondi_i32(TCG_COND_NE, cpu_T[0], t ? SR_T : 0, label); | |
276 | + tcg_gen_ori_i32(cpu_flags, cpu_flags, DELAY_SLOT_TRUE); | |
277 | + gen_set_label(label); | |
278 | +} | |
279 | + | |
261 | 280 | /* Immediate conditional jump (bt or bf) */ |
262 | 281 | static void gen_conditional_jump(DisasContext * ctx, |
263 | 282 | target_ulong ift, target_ulong ifnott) |
... | ... | @@ -265,7 +284,8 @@ static void gen_conditional_jump(DisasContext * ctx, |
265 | 284 | int l1; |
266 | 285 | |
267 | 286 | l1 = gen_new_label(); |
268 | - gen_op_jT(l1); | |
287 | + tcg_gen_andi_i32(cpu_T[0], cpu_sr, SR_T); | |
288 | + tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_T[0], SR_T, l1); | |
269 | 289 | gen_goto_tb(ctx, 0, ifnott); |
270 | 290 | gen_set_label(l1); |
271 | 291 | gen_goto_tb(ctx, 1, ift); |
... | ... | @@ -277,9 +297,11 @@ static void gen_delayed_conditional_jump(DisasContext * ctx) |
277 | 297 | int l1; |
278 | 298 | |
279 | 299 | l1 = gen_new_label(); |
280 | - gen_op_jdelayed(l1); | |
300 | + tcg_gen_andi_i32(cpu_T[0], cpu_flags, DELAY_SLOT_TRUE); | |
301 | + tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_T[0], DELAY_SLOT_TRUE, l1); | |
281 | 302 | gen_goto_tb(ctx, 1, ctx->pc + 2); |
282 | 303 | gen_set_label(l1); |
304 | + tcg_gen_andi_i32(cpu_flags, cpu_flags, ~DELAY_SLOT_TRUE); | |
283 | 305 | gen_jump(ctx); |
284 | 306 | } |
285 | 307 | |
... | ... | @@ -317,6 +339,12 @@ static inline void gen_cmp_imm(int cond, TCGv t0, int32_t imm) |
317 | 339 | gen_set_label(label2); |
318 | 340 | } |
319 | 341 | |
342 | +static inline void gen_store_flags(uint32_t flags) | |
343 | +{ | |
344 | + tcg_gen_andi_i32(cpu_flags, cpu_flags, DELAY_SLOT_TRUE); | |
345 | + tcg_gen_ori_i32(cpu_flags, cpu_flags, flags); | |
346 | +} | |
347 | + | |
320 | 348 | #define B3_0 (ctx->opcode & 0xf) |
321 | 349 | #define B6_4 ((ctx->opcode >> 4) & 0x7) |
322 | 350 | #define B7_4 ((ctx->opcode >> 4) & 0xf) |
... | ... | @@ -353,7 +381,8 @@ void _decode_opc(DisasContext * ctx) |
353 | 381 | tcg_gen_andi_i32(cpu_sr, cpu_sr, ~(SR_M | SR_Q | SR_T)); |
354 | 382 | return; |
355 | 383 | case 0x000b: /* rts */ |
356 | - CHECK_NOT_DELAY_SLOT gen_op_rts(); | |
384 | + CHECK_NOT_DELAY_SLOT | |
385 | + tcg_gen_mov_i32(cpu_delayed_pc, cpu_pr); | |
357 | 386 | ctx->flags |= DELAY_SLOT; |
358 | 387 | ctx->delayed_pc = (uint32_t) - 1; |
359 | 388 | return; |
... | ... | @@ -375,7 +404,9 @@ void _decode_opc(DisasContext * ctx) |
375 | 404 | #endif |
376 | 405 | return; |
377 | 406 | case 0x002b: /* rte */ |
378 | - CHECK_NOT_DELAY_SLOT gen_op_rte(); | |
407 | + CHECK_NOT_DELAY_SLOT | |
408 | + tcg_gen_mov_i32(cpu_sr, cpu_ssr); | |
409 | + tcg_gen_mov_i32(cpu_delayed_pc, cpu_spc); | |
379 | 410 | ctx->flags |= DELAY_SLOT; |
380 | 411 | ctx->delayed_pc = (uint32_t) - 1; |
381 | 412 | return; |
... | ... | @@ -436,13 +467,15 @@ void _decode_opc(DisasContext * ctx) |
436 | 467 | return; |
437 | 468 | case 0xa000: /* bra disp */ |
438 | 469 | CHECK_NOT_DELAY_SLOT |
439 | - gen_op_bra(ctx->delayed_pc = ctx->pc + 4 + B11_0s * 2); | |
470 | + ctx->delayed_pc = ctx->pc + 4 + B11_0s * 2; | |
471 | + tcg_gen_movi_i32(cpu_delayed_pc, ctx->delayed_pc); | |
440 | 472 | ctx->flags |= DELAY_SLOT; |
441 | 473 | return; |
442 | 474 | case 0xb000: /* bsr disp */ |
443 | 475 | CHECK_NOT_DELAY_SLOT |
444 | - gen_op_bsr(ctx->pc + 4, ctx->delayed_pc = | |
445 | - ctx->pc + 4 + B11_0s * 2); | |
476 | + tcg_gen_movi_i32(cpu_pr, ctx->pc + 4); | |
477 | + ctx->delayed_pc = ctx->pc + 4 + B11_0s * 2; | |
478 | + tcg_gen_movi_i32(cpu_delayed_pc, ctx->delayed_pc); | |
446 | 479 | ctx->flags |= DELAY_SLOT; |
447 | 480 | return; |
448 | 481 | } |
... | ... | @@ -930,7 +963,7 @@ void _decode_opc(DisasContext * ctx) |
930 | 963 | return; |
931 | 964 | case 0x8f00: /* bf/s label */ |
932 | 965 | CHECK_NOT_DELAY_SLOT |
933 | - gen_op_bf_s(ctx->delayed_pc = ctx->pc + 4 + B7_0s * 2); | |
966 | + gen_branch_slot(ctx->delayed_pc = ctx->pc + 4 + B7_0s * 2, 0); | |
934 | 967 | ctx->flags |= DELAY_SLOT_CONDITIONAL; |
935 | 968 | return; |
936 | 969 | case 0x8900: /* bt label */ |
... | ... | @@ -941,7 +974,7 @@ void _decode_opc(DisasContext * ctx) |
941 | 974 | return; |
942 | 975 | case 0x8d00: /* bt/s label */ |
943 | 976 | CHECK_NOT_DELAY_SLOT |
944 | - gen_op_bt_s(ctx->delayed_pc = ctx->pc + 4 + B7_0s * 2); | |
977 | + gen_branch_slot(ctx->delayed_pc = ctx->pc + 4 + B7_0s * 2, 1); | |
945 | 978 | ctx->flags |= DELAY_SLOT_CONDITIONAL; |
946 | 979 | return; |
947 | 980 | case 0x8800: /* cmp/eq #imm,R0 */ |
... | ... | @@ -1083,13 +1116,14 @@ void _decode_opc(DisasContext * ctx) |
1083 | 1116 | switch (ctx->opcode & 0xf0ff) { |
1084 | 1117 | case 0x0023: /* braf Rn */ |
1085 | 1118 | CHECK_NOT_DELAY_SLOT tcg_gen_mov_i32(cpu_T[0], cpu_gregs[REG(B11_8)]); |
1086 | - gen_op_braf_T0(ctx->pc + 4); | |
1119 | + tcg_gen_addi_i32(cpu_delayed_pc, cpu_T[0], ctx->pc + 4); | |
1087 | 1120 | ctx->flags |= DELAY_SLOT; |
1088 | 1121 | ctx->delayed_pc = (uint32_t) - 1; |
1089 | 1122 | return; |
1090 | 1123 | case 0x0003: /* bsrf Rn */ |
1091 | 1124 | CHECK_NOT_DELAY_SLOT tcg_gen_mov_i32(cpu_T[0], cpu_gregs[REG(B11_8)]); |
1092 | - gen_op_bsrf_T0(ctx->pc + 4); | |
1125 | + tcg_gen_movi_i32(cpu_pr, ctx->pc + 4); | |
1126 | + tcg_gen_add_i32(cpu_delayed_pc, cpu_T[0], cpu_pr); | |
1093 | 1127 | ctx->flags |= DELAY_SLOT; |
1094 | 1128 | ctx->delayed_pc = (uint32_t) - 1; |
1095 | 1129 | return; |
... | ... | @@ -1107,13 +1141,14 @@ void _decode_opc(DisasContext * ctx) |
1107 | 1141 | return; |
1108 | 1142 | case 0x402b: /* jmp @Rn */ |
1109 | 1143 | CHECK_NOT_DELAY_SLOT tcg_gen_mov_i32(cpu_T[0], cpu_gregs[REG(B11_8)]); |
1110 | - gen_op_jmp_T0(); | |
1144 | + tcg_gen_mov_i32(cpu_delayed_pc, cpu_T[0]); | |
1111 | 1145 | ctx->flags |= DELAY_SLOT; |
1112 | 1146 | ctx->delayed_pc = (uint32_t) - 1; |
1113 | 1147 | return; |
1114 | 1148 | case 0x400b: /* jsr @Rn */ |
1115 | 1149 | CHECK_NOT_DELAY_SLOT tcg_gen_mov_i32(cpu_T[0], cpu_gregs[REG(B11_8)]); |
1116 | - gen_op_jsr_T0(ctx->pc + 4); | |
1150 | + tcg_gen_movi_i32(cpu_pr, ctx->pc + 4); | |
1151 | + tcg_gen_mov_i32(cpu_delayed_pc, cpu_T[0]); | |
1117 | 1152 | ctx->flags |= DELAY_SLOT; |
1118 | 1153 | ctx->delayed_pc = (uint32_t) - 1; |
1119 | 1154 | return; |
... | ... | @@ -1332,12 +1367,12 @@ void decode_opc(DisasContext * ctx) |
1332 | 1367 | |
1333 | 1368 | if (old_flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) { |
1334 | 1369 | if (ctx->flags & DELAY_SLOT_CLEARME) { |
1335 | - gen_op_store_flags(0); | |
1370 | + gen_store_flags(0); | |
1336 | 1371 | } else { |
1337 | 1372 | /* go out of the delay slot */ |
1338 | 1373 | uint32_t new_flags = ctx->flags; |
1339 | 1374 | new_flags &= ~(DELAY_SLOT | DELAY_SLOT_CONDITIONAL); |
1340 | - gen_op_store_flags(new_flags); | |
1375 | + gen_store_flags(new_flags); | |
1341 | 1376 | } |
1342 | 1377 | ctx->flags = 0; |
1343 | 1378 | ctx->bstate = BS_BRANCH; |
... | ... | @@ -1351,7 +1386,7 @@ void decode_opc(DisasContext * ctx) |
1351 | 1386 | |
1352 | 1387 | /* go into a delay slot */ |
1353 | 1388 | if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) |
1354 | - gen_op_store_flags(ctx->flags); | |
1389 | + gen_store_flags(ctx->flags); | |
1355 | 1390 | } |
1356 | 1391 | |
1357 | 1392 | static inline void |
... | ... | @@ -1448,7 +1483,7 @@ gen_intermediate_code_internal(CPUState * env, TranslationBlock * tb, |
1448 | 1483 | /* fall through */ |
1449 | 1484 | case BS_NONE: |
1450 | 1485 | if (ctx.flags) { |
1451 | - gen_op_store_flags(ctx.flags | DELAY_SLOT_CLEARME); | |
1486 | + gen_store_flags(ctx.flags | DELAY_SLOT_CLEARME); | |
1452 | 1487 | } |
1453 | 1488 | gen_goto_tb(&ctx, 0, ctx.pc); |
1454 | 1489 | break; | ... | ... |