Skip to content

Commit

Permalink
target-s390x: implement BRC using goto_tb
Browse files Browse the repository at this point in the history
Signed-off-by: Ulrich Hecht <uli@suse.de>
  • Loading branch information
Ulrich Hecht committed Aug 25, 2010
1 parent b5e5565 commit 0643237
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 29 deletions.
1 change: 0 additions & 1 deletion target-s390x/helpers.h
Expand Up @@ -15,7 +15,6 @@ DEF_HELPER_FLAGS_1(set_cc_comp_s64, TCG_CALL_PURE|TCG_CALL_CONST, i32, s64)
DEF_HELPER_FLAGS_1(set_cc_nz_u32, TCG_CALL_PURE|TCG_CALL_CONST, i32, i32) DEF_HELPER_FLAGS_1(set_cc_nz_u32, TCG_CALL_PURE|TCG_CALL_CONST, i32, i32)
DEF_HELPER_FLAGS_1(set_cc_nz_u64, TCG_CALL_PURE|TCG_CALL_CONST, i32, i64) DEF_HELPER_FLAGS_1(set_cc_nz_u64, TCG_CALL_PURE|TCG_CALL_CONST, i32, i64)
DEF_HELPER_FLAGS_2(set_cc_icm, TCG_CALL_PURE|TCG_CALL_CONST, i32, i32, i32) DEF_HELPER_FLAGS_2(set_cc_icm, TCG_CALL_PURE|TCG_CALL_CONST, i32, i32, i32)
DEF_HELPER_4(brc, void, i32, i32, i64, s32)
DEF_HELPER_3(brctg, void, i64, i64, s32) DEF_HELPER_3(brctg, void, i64, i64, s32)
DEF_HELPER_3(brct, void, i32, i64, s32) DEF_HELPER_3(brct, void, i32, i64, s32)
DEF_HELPER_4(brcl, void, i32, i32, i64, s64) DEF_HELPER_4(brcl, void, i32, i32, i64, s64)
Expand Down
11 changes: 0 additions & 11 deletions target-s390x/op_helper.c
Expand Up @@ -270,17 +270,6 @@ uint32_t HELPER(set_cc_icm)(uint32_t mask, uint32_t val)
return cc; return cc;
} }


/* relative conditional branch */
void HELPER(brc)(uint32_t cc, uint32_t mask, uint64_t pc, int32_t offset)
{
if ( mask & ( 1 << (3 - cc) ) ) {
env->psw.addr = pc + offset;
}
else {
env->psw.addr = pc + 4;
}
}

/* branch relative on 64-bit count (condition is computed inline, this only /* branch relative on 64-bit count (condition is computed inline, this only
does the branch */ does the branch */
void HELPER(brctg)(uint64_t flag, uint64_t pc, int32_t offset) void HELPER(brctg)(uint64_t flag, uint64_t pc, int32_t offset)
Expand Down
71 changes: 54 additions & 17 deletions target-s390x/translate.c
Expand Up @@ -48,6 +48,7 @@ struct DisasContext {
uint64_t pc; uint64_t pc;
int is_jmp; int is_jmp;
CPUS390XState *env; CPUS390XState *env;
struct TranslationBlock *tb;
}; };


#define DISAS_EXCP 4 #define DISAS_EXCP 4
Expand Down Expand Up @@ -346,23 +347,55 @@ static void gen_bcr(uint32_t mask, int tr, uint64_t offset)
tcg_temp_free(target); tcg_temp_free(target);
} }


static void gen_brc(uint32_t mask, uint64_t pc, int32_t offset) static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong pc)
{ {
TCGv p; TranslationBlock *tb;
TCGv_i32 m, o;
tb = s->tb;
/* NOTE: we handle the case where the TB spans two pages here */
if ((pc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK) ||
(pc & TARGET_PAGE_MASK) == ((s->pc - 1) & TARGET_PAGE_MASK)) {
/* jump to same page: we can use a direct jump */
tcg_gen_mov_i32(global_cc, cc);
tcg_gen_goto_tb(tb_num);
tcg_gen_movi_i64(psw_addr, pc);
tcg_gen_exit_tb((long)tb + tb_num);
} else {
/* jump to another page: currently not optimized */
tcg_gen_movi_i64(psw_addr, pc);
tcg_gen_mov_i32(global_cc, cc);
tcg_gen_exit_tb(0);
}
}

static void gen_brc(uint32_t mask, DisasContext *s, int32_t offset)
{
TCGv_i32 r;
TCGv_i32 tmp, tmp2;
int skip;


if (mask == 0xf) { /* unconditional */ if (mask == 0xf) { /* unconditional */
tcg_gen_movi_i64(psw_addr, pc + offset); //tcg_gen_movi_i64(psw_addr, s->pc + offset);
gen_goto_tb(s, 0, s->pc + offset);
} }
else { else {
m = tcg_const_i32(mask); tmp = tcg_const_i32(3);
p = tcg_const_i64(pc); tcg_gen_sub_i32(tmp, tmp, cc); /* 3 - cc */
o = tcg_const_i32(offset); tmp2 = tcg_const_i32(1);
gen_helper_brc(cc, m, p, o); tcg_gen_shl_i32(tmp2, tmp2, tmp); /* 1 << (3 - cc) */
tcg_temp_free(m); r = tcg_const_i32(mask);
tcg_temp_free(p); tcg_gen_and_i32(r, r, tmp2); /* mask & (1 << (3 - cc)) */
tcg_temp_free(o); tcg_temp_free(tmp);
tcg_temp_free(tmp2);
skip = gen_new_label();
tcg_gen_brcondi_i32(TCG_COND_EQ, r, 0, skip);
gen_goto_tb(s, 0, s->pc + offset);
gen_set_label(skip);
gen_goto_tb(s, 1, s->pc + 4);
//tcg_gen_mov_i32(global_cc, cc);
tcg_temp_free(r);
} }
s->is_jmp = DISAS_TB_JUMP;
} }


static void gen_set_cc_add64(TCGv v1, TCGv v2, TCGv vr) static void gen_set_cc_add64(TCGv v1, TCGv v2, TCGv vr)
Expand Down Expand Up @@ -1130,9 +1163,7 @@ static void disas_a7(DisasContext *s, int op, int r1, int i2)
tcg_temp_free(tmp2); tcg_temp_free(tmp2);
break; break;
case 0x4: /* brc m1, i2 */ case 0x4: /* brc m1, i2 */
/* FIXME: optimize m1 == 0xf (unconditional) case */ gen_brc(r1, s, i2 * 2);
gen_brc(r1, s->pc, i2 * 2);
s->is_jmp = DISAS_JUMP;
return; return;
case 0x5: /* BRAS R1,I2 [RI] */ case 0x5: /* BRAS R1,I2 [RI] */
tmp = tcg_const_i64(s->pc + 4); tmp = tcg_const_i64(s->pc + 4);
Expand Down Expand Up @@ -2726,6 +2757,7 @@ static inline void gen_intermediate_code_internal (CPUState *env,
dc.env = env; dc.env = env;
dc.pc = pc_start; dc.pc = pc_start;
dc.is_jmp = DISAS_NEXT; dc.is_jmp = DISAS_NEXT;
dc.tb = tb;


gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;


Expand Down Expand Up @@ -2765,8 +2797,11 @@ static inline void gen_intermediate_code_internal (CPUState *env,
num_insns++; num_insns++;
} while (!dc.is_jmp && gen_opc_ptr < gen_opc_end && dc.pc < next_page_start } while (!dc.is_jmp && gen_opc_ptr < gen_opc_end && dc.pc < next_page_start
&& num_insns < max_insns && !env->singlestep_enabled); && num_insns < max_insns && !env->singlestep_enabled);
tcg_gen_mov_i32(global_cc, cc);
tcg_temp_free(cc); if (dc.is_jmp != DISAS_TB_JUMP) {
tcg_gen_mov_i32(global_cc, cc);
tcg_temp_free(cc);
}


if (!dc.is_jmp) { if (!dc.is_jmp) {
tcg_gen_st_i64(tcg_const_i64(dc.pc), cpu_env, offsetof(CPUState, psw.addr)); tcg_gen_st_i64(tcg_const_i64(dc.pc), cpu_env, offsetof(CPUState, psw.addr));
Expand All @@ -2781,7 +2816,9 @@ static inline void gen_intermediate_code_internal (CPUState *env,
if (tb->cflags & CF_LAST_IO) if (tb->cflags & CF_LAST_IO)
gen_io_end(); gen_io_end();
/* Generate the return instruction */ /* Generate the return instruction */
tcg_gen_exit_tb(0); if (dc.is_jmp != DISAS_TB_JUMP) {
tcg_gen_exit_tb(0);
}
gen_icount_end(tb, num_insns); gen_icount_end(tb, num_insns);
*gen_opc_ptr = INDEX_op_end; *gen_opc_ptr = INDEX_op_end;
if (search_pc) { if (search_pc) {
Expand Down

0 comments on commit 0643237

Please sign in to comment.