e2k: refactor gen stubs

This commit is contained in:
Denis Drakhnia 2024-01-01 20:15:38 +02:00
parent 518d02f403
commit b3baf0539d
1 changed files with 64 additions and 83 deletions

View File

@ -6986,46 +6986,14 @@ static void gen_ct_cond(DisasContext *ctx)
}
}
static inline TCGCond cond_from_advance(int advance)
static void gen_dec_wrapi_i32(TCGv_i32 ret, TCGv_i32 cur, int n,
int size)
{
switch (advance) {
case 0x01: return TCG_COND_EQ;
case 0x02: return TCG_COND_NE;
case 0x03: return TCG_COND_ALWAYS;
default: return TCG_COND_NEVER;
}
}
TCGv_i32 s = tcg_constant_i32(size);
static void gen_movcond_flag_i32(TCGv_i32 ret, int flag, TCGv_i32 cond,
TCGv_i32 v1, TCGv_i32 v2)
{
TCGv_i32 one = tcg_constant_i32(1);
TCGCond c = cond_from_advance(flag);
tcg_gen_movcond_i32(c, ret, cond, one, v1, v2);
}
static void gen_dec_wrap(TCGv_i32 ret, TCGv_i32 cur, int n,
TCGv_i32 size)
{
TCGv_i32 t0 = tcg_temp_new_i32();
tcg_gen_addi_i32(t0, size, n);
tcg_gen_sub_i32(t0, t0, cur);
tcg_gen_remu_i32(t0, t0, size);
tcg_gen_sub_i32(ret, size, t0);
}
static inline void gen_cur_dec(DisasContext *ctx, TCGv_i32 ret, int cond,
TCGv_i32 cur, int n, TCGv_i32 size)
{
TCGLabel *l0 = gen_new_label();
TCGv_i32 t0 = tcg_temp_new_i32();
tcg_gen_brcondi_i32(TCG_COND_EQ, size, 0, l0);
gen_dec_wrap(t0, cur, n, size);
gen_movcond_flag_i32(ret, cond, cpu_ct_cond, t0, cur);
gen_set_label(l0);
tcg_gen_sub_i32(ret, tcg_constant_i32(n + size), cur);
tcg_gen_remu_i32(ret, ret, s);
tcg_gen_sub_i32(ret, s, ret);
}
#define IMPL_GEN_DEC_SAT(name, S) \
@ -7061,43 +7029,6 @@ static void gen_advance_loop_counters(void)
tcg_gen_movcond_i32(TCG_COND_NE, cpu_lsr_ecnt, t4, z, t3, cpu_lsr_ecnt);
}
static void gen_stubs(DisasContext *ctx)
{
uint32_t ss = ctx->bundle.ss;
int alc = extract32(ss, 16, 2);
int abp = extract32(ss, 18, 2);
int abn = extract32(ss, 21, 2);
int abg = extract32(ss, 23, 2);
int vfdi = extract32(ss, 26, 1);
if (alc) {
TCGLabel *l0 = gen_new_label();
TCGCond cond = cond_from_advance(alc);
tcg_gen_brcondi_i32(tcg_invert_cond(cond), cpu_ct_cond, 1, l0);
gen_advance_loop_counters();
gen_set_label(l0);
}
if (abp) {
gen_cur_dec(ctx, cpu_pcur, abp, cpu_pcur, 1, cpu_psize);
}
if (abn) {
gen_cur_dec(ctx, cpu_bcur, abn, cpu_bcur, 2, cpu_bsize);
}
if (abg != 0) {
// TODO: impl abg
e2k_todo_illop(ctx, "abg");
}
if (vfdi != 0) {
// TODO: impl vfdi
e2k_todo_illop(ctx, "vfdi");
}
}
static target_ulong do_decode(DisasContext *ctx, CPUState *cs)
{
E2KCPU *cpu = E2K_CPU(cs);
@ -7340,8 +7271,28 @@ static void gen_loop_end_init(DisasContext *ctx)
}
}
#define ALCT 1
#define ALCF 2
#define ABPT 1
#define ABPF 2
#define ABNT 1
#define ABNF 2
#define ABGD 1
#define ABGI 2
static void do_branch(DisasContext *ctx, target_ulong pc_next)
{
TCGLabel *branch_taken = NULL;
uint32_t ss = ctx->bundle.ss;
int alc, abp, abn, abg, vfdi;
alc = abp = abn = abg = vfdi = 0;
abg = extract32(ss, 23, 2);
vfdi = extract32(ss, 26, 1);
// TODO: e2k abg
// TODO: e2k vfdi
/* FIXME: save PC only when necessary. */
gen_save_pc(ctx->base.pc_next);
@ -7352,19 +7303,50 @@ static void do_branch(DisasContext *ctx, target_ulong pc_next)
gen_set_label(l0);
}
if (ctx->ct.type != CT_NONE && ctx->ct.cond_type > 1) {
branch_taken = gen_new_label();
tcg_gen_brcondi_i32(TCG_COND_NE, cpu_ct_cond, 0, branch_taken);
}
if (ctx->bundle.ss_present) {
alc = extract32(ss, 16, 2);
abp = extract32(ss, 18, 2);
abn = extract32(ss, 21, 2);
if (alc & ALCF) {
gen_advance_loop_counters();
}
if (abp & ABPF) {
gen_dec_wrapi_i32(cpu_pcur, cpu_pcur, 1, ctx->p_size);
}
if (abn & ABNF) {
gen_dec_wrapi_i32(cpu_bcur, cpu_bcur, 2, ctx->b_size);
}
}
if (ctx->ct.type == CT_NONE) {
return;
} else if (ctx->ct.cond_type > 1) {
gen_goto_tb(ctx, TB_EXIT_IDX1, pc_next);
gen_set_label(branch_taken);
}
if (alc & ALCT) {
gen_advance_loop_counters();
}
if (abp & ABPT) {
gen_dec_wrapi_i32(cpu_pcur, cpu_pcur, 1, ctx->p_size);
}
if (abn & ABNT) {
gen_dec_wrapi_i32(cpu_bcur, cpu_bcur, 2, ctx->b_size);
}
ctx->base.is_jmp = DISAS_NORETURN;
if (ctx->ct.cond_type > 1) {
TCGLabel *l0 = gen_new_label();
tcg_gen_brcondi_i32(TCG_COND_NE, cpu_ct_cond, 0, l0);
gen_goto_tb(ctx, TB_EXIT_IDX1, pc_next);
gen_set_label(l0);
}
switch(ctx->ct.type) {
case CT_NONE:
break;
@ -7519,7 +7501,6 @@ static void e2k_tr_translate_insn(DisasContextBase *db, CPUState *cs)
gen_vfrpsz(ctx);
gen_setbn(ctx);
gen_setbp(ctx);
gen_stubs(ctx);
do_branch(ctx, pc_next);
}
break;