diff --git a/target/e2k/cpu.h b/target/e2k/cpu.h index 1e32032d2e..65479b026a 100644 --- a/target/e2k/cpu.h +++ b/target/e2k/cpu.h @@ -58,6 +58,7 @@ typedef enum { } CtprTag; typedef enum { + CTPR_OPC_DISP = 0x0, CTPR_OPC_LDISP = 0x1, } CtprOpc; @@ -618,7 +619,14 @@ typedef struct CPUArchState { E2KBnState bn; E2KBpState bp; - uint64_t lsr; /* loop status register */ + /* loop status register */ + uint64_t lsr; + uint32_t lsr_lcnt; + uint32_t lsr_ecnt; + uint32_t lsr_vlc; + uint32_t lsr_over; + uint32_t lsr_pcnt; + uint32_t lsr_strmd; uint64_t sbr; E2KUserStackDesc usd; diff --git a/target/e2k/gdbstub.c b/target/e2k/gdbstub.c index 28c5f31c6c..436684f686 100644 --- a/target/e2k/gdbstub.c +++ b/target/e2k/gdbstub.c @@ -174,7 +174,16 @@ int e2k_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) case 344: return gdb_get_reg64(mem_buf, 0); // cutd case 345: return gdb_get_reg64(mem_buf, 0); // cuir case 346: return gdb_get_reg64(mem_buf, 0); // tsd - case 347: return gdb_get_reg64(mem_buf, env->lsr); // lsr + case 347: { // lsr + uint64_t lsr = env->lsr; + lsr = deposit64(lsr, LSR_LCNT_OFF, LSR_LCNT_LEN, env->lsr_lcnt); + lsr = deposit64(lsr, LSR_ECNT_OFF, LSR_ECNT_LEN, env->lsr_ecnt); + lsr = deposit64(lsr, LSR_VLC_OFF, 1, env->lsr_vlc); + lsr = deposit64(lsr, LSR_OVER_OFF, 1, env->lsr_over); + lsr = deposit64(lsr, LSR_PCNT_OFF, LSR_PCNT_LEN, env->lsr_pcnt); + lsr = deposit64(lsr, LSR_STRMD_OFF, LSR_STRMD_LEN, env->lsr_strmd); + return gdb_get_reg64(mem_buf, lsr); + } case 348: return gdb_get_reg64(mem_buf, env->lsr & LSR_ILCR_MASK); // ilcr default: break; diff --git a/target/e2k/helper.c b/target/e2k/helper.c index 10e5b3ca77..9d9614b862 100644 --- a/target/e2k/helper.c +++ b/target/e2k/helper.c @@ -127,7 +127,12 @@ static void ps_fill(CPUE2KState *env, int n, bool fx) static inline void ps_spill_all(CPUE2KState *env) { - ps_spill(env, env->wd.size, env->wd.fx); + ps_spill(env, env->wd.size, true); +} + +static inline void ps_fill_all(CPUE2KState *env) +{ + ps_fill(env, env->wd.size, true); } static void move_regs(CPUE2KState *env, int dst, int src, int n) @@ -225,26 +230,22 @@ void HELPER(raise_exception_no_spill)(CPUE2KState *env, int tt) cpu_loop_exit(cs); } -void HELPER(setwd)(CPUE2KState *env, uint32_t lts) +void HELPER(setwd)(CPUE2KState *env, int wsz, int nfx, int dbl) { - int i, old_size = env->wd.size, size = extract32(lts, 5, 7) * 2; + int i, size = wsz * 2; if (size < env->wd.psize) { helper_raise_exception(env, E2K_EXCP_ILLOPN); return; } + for (i = env->wd.size; i < size; i++) { + env->tags[i] = E2K_TAG_NON_NUMBER64; + } + env->wd.size = size; - env->wd.fx = extract32(lts, 4, 1) == 0; - - if (env->version >= 3) { - bool dbl = extract32(lts, 3, 1); - env->wdbl = dbl; - } - - for (i = 0; i < size - old_size; i++) { - env->tags[old_size + i] = E2K_TAG_NON_NUMBER64; - } + env->wd.fx = nfx == 0; + env->wdbl = dbl; } bool e2k_cpu_tlb_fill(CPUState *cs, vaddr address, int size, @@ -270,7 +271,7 @@ void e2k_break_save_state(CPUE2KState *env) void HELPER(break_restore_state)(CPUE2KState *env) { proc_chain_restore(env); - ps_fill(env, env->wd.size, env->wd.fx); + ps_fill_all(env); env->is_bp = false; } diff --git a/target/e2k/helper.h b/target/e2k/helper.h index cc62750c97..0925bcab6a 100644 --- a/target/e2k/helper.h +++ b/target/e2k/helper.h @@ -22,7 +22,7 @@ DEF_HELPER_3(state_reg_write_i64, void, env, int, i64) DEF_HELPER_3(state_reg_write_i32, void, env, int, i32) DEF_HELPER_2(getsp, i64, env, i32) /* FIXME: return tl? */ DEF_HELPER_1(break_restore_state, void, env) -DEF_HELPER_2(setwd, void, env, i32) +DEF_HELPER_4(setwd, void, env, int, int, int) DEF_HELPER_2(probe_read_access, int, env, tl) DEF_HELPER_2(probe_write_access, int, env, tl) diff --git a/target/e2k/helper_int.c b/target/e2k/helper_int.c index e47bf6b88f..52460f12a5 100644 --- a/target/e2k/helper_int.c +++ b/target/e2k/helper_int.c @@ -34,7 +34,6 @@ static uint64_t* state_reg_ptr(CPUE2KState *env, int idx) { switch (idx) { case 0x80: return &env->upsr; /* %upsr */ - case 0x83: return &env->lsr; /* %lsr */ default: return NULL; } } @@ -78,6 +77,15 @@ uint32_t helper_state_reg_read_i32(CPUE2KState *env, int idx) void helper_state_reg_write_i64(CPUE2KState *env, int idx, uint64_t val) { switch(idx) { + case 0x83: /* %lsr */ + env->lsr = val; + env->lsr_lcnt = extract64(val, LSR_LCNT_OFF, LSR_LCNT_LEN); + env->lsr_ecnt = extract64(val, LSR_ECNT_OFF, LSR_ECNT_LEN); + env->lsr_vlc = extract64(val, LSR_VLC_OFF, 1); + env->lsr_over = extract64(val, LSR_OVER_OFF, 1); + env->lsr_pcnt = extract64(val, LSR_PCNT_OFF, LSR_PCNT_LEN); + env->lsr_strmd = extract64(val, LSR_STRMD_OFF, LSR_STRMD_LEN); + break; case 0x85: /* %fpcr */ env->fpcr.raw = val; e2k_update_fp_status(env); @@ -100,6 +108,9 @@ void helper_state_reg_write_i64(CPUE2KState *env, int idx, uint64_t val) void helper_state_reg_write_i32(CPUE2KState *env, int idx, uint32_t val) { switch (idx) { + case 0x83: /* %lsr */ + env->lsr_lcnt = val; + break; case 0x85: /* %fpcr */ env->fpcr.raw = val; e2k_update_fp_status(env); diff --git a/target/e2k/meson.build b/target/e2k/meson.build index f2f994a68f..0174e45dc5 100644 --- a/target/e2k/meson.build +++ b/target/e2k/meson.build @@ -11,7 +11,6 @@ e2k_ss.add(files( 'translate.c', 'translate/alc.c', 'translate/aau.c', - 'translate/control.c', 'translate/plu.c', 'translate/state.c', )) diff --git a/target/e2k/translate.c b/target/e2k/translate.c index bf674c6f4f..77299f17d7 100644 --- a/target/e2k/translate.c +++ b/target/e2k/translate.c @@ -6,6 +6,68 @@ struct CPUE2KStateTCG e2k_cs; +static inline uint64_t ctpr_new(uint8_t tag, uint8_t opc, uint8_t ipd, + target_ulong base) +{ + uint64_t ctpr = 0; + ctpr = deposit64(ctpr, CTPR_BASE_OFF, CTPR_BASE_LEN, base); + ctpr = deposit64(ctpr, CTPR_TAG_OFF, CTPR_TAG_LEN, tag); + ctpr = deposit64(ctpr, CTPR_IPD_OFF, CTPR_IPD_LEN, ipd); + ctpr = deposit64(ctpr, CTPR_OPC_OFF, CTPR_OPC_LEN, opc); + return ctpr; +} + +static inline uint64_t ctpr_new_disp(DisasContext *ctx, Cs0Disp *disp) +{ + target_ulong base = ctx->pc + disp->sdisp; + return ctpr_new(CTPR_TAG_DISP, disp->opc, disp->ipd, base); +} + +static void gen_goto_tb(DisasContext *ctx, int tb_num, target_ulong pc) +{ + if (translator_use_goto_tb(&ctx->base, pc)) { + /* jump to same page: we can use a direct jump */ + tcg_gen_goto_tb(tb_num); + tcg_gen_movi_tl(e2k_cs.pc, pc); + tcg_gen_exit_tb(ctx->base.tb, tb_num); + } else { + /* jump to another page: currently not optimized */ + tcg_gen_movi_tl(e2k_cs.pc, pc); + tcg_gen_exit_tb(NULL, 0); + } +} + +void e2k_tr_gen_exception(DisasContext *ctx, int which) +{ + TCGv_i32 t = tcg_const_i32(which); + + e2k_gen_save_cpu_state(ctx); + gen_helper_raise_exception(cpu_env, t); + ctx->base.is_jmp = DISAS_NORETURN; + + tcg_temp_free_i32(t); +} + +void e2k_tr_gen_exception_no_spill(DisasContext *ctx, int excp) +{ + TCGv_i32 t0 = tcg_const_i32(excp); + + e2k_gen_save_cpu_state(ctx); + gen_helper_raise_exception_no_spill(cpu_env, t0); + ctx->base.is_jmp = DISAS_NORETURN; + + tcg_temp_free_i32(t0); +} + +static inline void illop(DisasContext *ctx) +{ + e2k_tr_gen_exception(ctx, E2K_EXCP_ILLOPC); +} + +//////////////////////////////////////////////////////////////////// +//// Decode +//////////////////////////////////////////////////////////////////// + /* returns zero if bundle is invalid */ static size_t unpack_bundle(CPUE2KState *env, DisasContext *ctx) { @@ -186,40 +248,251 @@ static size_t unpack_bundle(CPUE2KState *env, DisasContext *ctx) return 8 + extract32(hs, 4, 3) * 8; } -static void gen_goto_tb(DisasContext *ctx, int tb_num, target_ulong pc) +static inline uint8_t ss_extract_ipd(const UnpackedBundle *raw) { - if (translator_use_goto_tb(&ctx->base, pc)) { - /* jump to same page: we can use a direct jump */ - tcg_gen_goto_tb(tb_num); - tcg_gen_movi_tl(e2k_cs.pc, pc); - tcg_gen_exit_tb(ctx->base.tb, tb_num); + return raw->ss_present ? extract32(raw->ss, 30, 2) : 3; +} + +static inline int32_t cs0_extract_sdisp(const UnpackedBundle *raw) +{ + return sextract32(raw->cs0, 0, 28) << 3; +} + +static inline void decode_cs1(DisasContext *ctx, const UnpackedBundle *raw) +{ + enum { + SETR0, + SETR1, + SETEI, + WAIT, + SETBR, + CALL, + MAS_OPC, + FLUSHR, + BG + }; + + Bundle *bundle = &ctx->bundle2; + Cs1 *ret = &bundle->cs1; + uint32_t cs1 = raw->cs1; + int opc = extract32(cs1, 28, 4); + + ret->type = CS1_NONE; + if (!raw->cs1_present) { + return; + } + + if (opc == SETR0 || opc == SETR1 || opc == SETBR) { + Cs1Setr *setr = &ret->setr; + setr->type = 0; + if (opc == SETR0 || opc == SETR1) { + uint32_t lts0 = raw->lts[0]; + if (!raw->lts_present[0]) { + illop(ctx); + return; + } + setr->type |= opc == SETR1 ? SETR_VFRPSZ : 0; + setr->type |= SETR_WD; + setr->wsz = extract32(lts0, 5, 7); + setr->nfx = extract32(lts0, 4, 1); + if (ctx->version >= 3) { + setr->dbl = extract32(lts0, 3, 1); + } + } + if (extract32(cs1, 26, 1)) { + setr->type |= SETR_BN; + setr->rbs = extract32(cs1, BR_RBS_OFF, BR_RBS_LEN); + setr->rsz = extract32(cs1, BR_RSZ_OFF, BR_RSZ_LEN); + setr->rcur = extract32(cs1, BR_RCUR_OFF, BR_RCUR_LEN); + } + if (extract32(cs1, 27, 1)) { + setr->type |= SETR_BP; + setr->psz = extract32(cs1, BR_PSZ_OFF, BR_PSZ_LEN); + } + ret->type = CS1_SETR; + } else if (opc == SETEI) { + if (extract32(cs1, 27, 1)) { + if (ctx->version < 2) { + illop(ctx); + return; + } + ret->type = CS1_SETSFT; + } else { + ret->type = CS1_SETEI; + ret->ei = extract32(cs1, 0, 8); + } + } else if (opc == WAIT) { + ret->type = CS1_WAIT; + ret->wait.all_c = extract32(cs1, 0, 1); + ret->wait.all_e = extract32(cs1, 1, 1); + ret->wait.st_c = extract32(cs1, 2, 1); + ret->wait.ld_c = extract32(cs1, 3, 1); + ret->wait.fl_c = extract32(cs1, 4, 1); + ret->wait.ma_c = extract32(cs1, 5, 1); + + if (ctx->version >= 2) { + ret->wait.trap = extract32(cs1, 6, 1); + } + + if (ctx->version >= 5) { + if (ret->wait.st_c) { + ret->wait.sas = extract32(cs1, 7, 1); + } + if (ret->wait.ld_c) { + ret->wait.sal = extract32(cs1, 8, 1); + } + } + } else if (opc == CALL) { + int ctop = extract32(raw->ss, 10, 2); + int wbs = extract32(cs1, 0, 7); + if (ctop) { + ret->type = CS1_CALL; + ret->call_wbs = wbs; + } else { + int cs1_ctopc = extract32(cs1, 7, 3); + int cs0_opc = extract32(raw->cs0, 28, 4); + int disp = extract32(raw->cs0, 1, 5); + if (cs1_ctopc != 2 || cs0_opc != 0 || !raw->cs0_present) { + illop(ctx); + return; + } + ret->type = CS1_HCALL; + ret->hcall.disp = disp; + ret->hcall.wbs = wbs; + } + } else if (opc == MAS_OPC) { + ret->type = CS1_MAS; + ret->mas[0] = extract32(cs1, 21, 7); + ret->mas[2] = extract32(cs1, 14, 7); + ret->mas[3] = extract32(cs1, 7, 7); + ret->mas[5] = extract32(cs1, 0, 7); + } else if (opc == FLUSHR) { + ret->type = CS1_FLUSH; + ret->flush.flushr = (cs1 & 1) != 0; + ret->flush.flushc = (cs1 & 2) != 0; + } else if (opc == BG) { + ret->type = CS1_VFBG; + ret->vfbg.umask = extract32(cs1, 0, 8); + ret->vfbg.dmask = extract32(cs1, 8, 8); + ret->vfbg.chkm4 = extract32(cs1, 16, 1); } else { - /* jump to another page: currently not optimized */ - tcg_gen_movi_tl(e2k_cs.pc, pc); - tcg_gen_exit_tb(NULL, 0); + illop(ctx); } } -void e2k_tr_gen_exception(DisasContext *ctx, int which) +static inline void decode_cs0(DisasContext *ctx, const UnpackedBundle *raw) { - TCGv_i32 t = tcg_const_i32(which); + Bundle *bundle = &ctx->bundle2; + Cs0 *ret = &bundle->cs0; + uint32_t cs0 = raw->cs0; + int ctpr = extract32(cs0, 30, 2); + int ctp_opc = extract32(cs0, 28, 2); + int param_type = extract32(cs0, 0, 3); - e2k_gen_save_cpu_state(ctx); - gen_helper_raise_exception(cpu_env, t); - ctx->base.is_jmp = DISAS_NORETURN; + if (!raw->cs0_present) { + ret->type = CS0_NONE; + return; + } else if (ctpr > 0) { + switch(ctp_opc) { + case 0: // disp + case 1: // ldisp + if (ctp_opc == 1 && ctpr != 2) { + illop(ctx); + return; + } + ret->type = CS0_DISP; + ret->disp.opc = ctp_opc; + ret->disp.ctpr = ctpr; + ret->disp.sdisp = cs0_extract_sdisp(raw); + ret->disp.ipd = ss_extract_ipd(raw); + break; + case 2: + ret->type = CS0_SDISP; + ret->sdisp.ctpr = ctpr; + ret->sdisp.disp = extract32(cs0, 0, 28); + ret->sdisp.ipd = ss_extract_ipd(raw); + break; + case 3: + if (param_type == 0 && ctpr == 3) { + ret->type = CS0_RETURN; + } else if (param_type == 1) { + ret->type = CS0_GETTSD; + } + break; + } + } else { + switch(ctp_opc) { + case 0: + ret->type = CS0_IBRANCH; + ret->ibranch.sdisp = cs0_extract_sdisp(raw); + break; + case 1: + ret->type = CS0_PREF; + ret->pref.prefr = extract32(cs0, 0, 2); + ret->pref.ipd = extract32(cs0, 3, 1); + ret->pref.disp = extract32(cs0, 4, 24); + break; + case 2: + ret->type = CS0_PUTTSD; + break; + case 3: + if (param_type == 0) { + ret->type = CS0_DONE; + } else if (param_type == 3) { + ret->type = CS0_HRET; + } else if (param_type == 4) { + ret->type = CS0_GLAUNCH; + } + break; + } + } - tcg_temp_free_i32(t); + switch(ret->type) { + case CS0_NONE: + illop(ctx); + break; + case CS0_IBRANCH: + case CS0_DONE: + case CS0_HRET: + case CS0_GLAUNCH: + if (!raw->ss_present + || extract32(raw->ss, 10, 2) != 0 + || extract32(raw->ss, 0, 9) == 0 + || bundle->cs1.type == CS1_CALL + || bundle->cs1.type == CS1_HCALL) + { + ret->type = CS0_NONE; + illop(ctx); + } + break; + default: + break; + } } -void e2k_tr_gen_exception_no_spill(DisasContext *ctx, int excp) +static inline void decode_ct_cond(DisasContext *ctx, const UnpackedBundle *raw) { - TCGv_i32 t0 = tcg_const_i32(excp); + ctx->ct.type = CT_NONE; + ctx->ct.cond_type = 0; + int ctpr = extract32(raw->ss, 10, 2); + if (ctpr != 0) { + if (ctx->ct.type == CT_NONE) { + ctx->ct.type = CT_JUMP; + } + ctx->ct.u.ctpr = e2k_cs.ctprs[ctpr - 1]; + } + ctx->ct.psrc = extract32(raw->ss, 0, 5); + ctx->ct.cond_type = extract32(raw->ss, 5, 4); +} - e2k_gen_save_cpu_state(ctx); - gen_helper_raise_exception_no_spill(cpu_env, t0); - ctx->base.is_jmp = DISAS_NORETURN; +//////////////////////////////////////////////////////////////////// +//// Generate +//////////////////////////////////////////////////////////////////// - tcg_temp_free_i32(t0); +static inline void gen_set_ctpr(int index, uint64_t ctpr) +{ + assert(0 < index && index < 4); + tcg_gen_movi_i64(e2k_cs.ctprs[index - 1], ctpr); } static inline void gen_ctpr_tag(TCGv_i64 ret, TCGv_i64 ctpr) @@ -241,6 +514,394 @@ static inline void gen_goto_ctpr_disp(TCGv_i64 ctpr) tcg_temp_free_i64(t0); } +static inline void gen_vfrpsz(DisasContext *ctx) +{ + Cs1 *cs1 = &ctx->bundle2.cs1; + Cs1Setr *setr = &cs1->setr; + + if (cs1->type == CS1_SETR && (setr->type & SETR_VFRPSZ)) { + e2k_todo_illop(ctx, "vfrpsz"); + } +} + +static inline void gen_setwd(DisasContext *ctx) +{ + Cs1 *cs1 = &ctx->bundle2.cs1; + Cs1Setr *setr = &cs1->setr; + + if (cs1->type == CS1_SETR && (setr->type & SETR_WD)) { + TCGv_i32 t0 = tcg_const_i32(setr->wsz); + TCGv_i32 t1 = tcg_const_i32(setr->nfx); + TCGv_i32 t2 = tcg_const_i32(setr->dbl); + gen_helper_setwd(cpu_env, t0, t1, t2); + tcg_temp_free_i32(t2); + tcg_temp_free_i32(t1); + tcg_temp_free_i32(t0); + } +} + +static inline void gen_setbn(DisasContext *ctx) +{ + Cs1 *cs1 = &ctx->bundle2.cs1; + Cs1Setr *setr = &cs1->setr; + + if (cs1->type == CS1_SETR && (setr->type & SETR_BN)) { + tcg_gen_movi_i32(e2k_cs.boff, setr->rbs * 2); + tcg_gen_movi_i32(e2k_cs.bsize, (setr->rsz + 1) * 2); + tcg_gen_movi_i32(e2k_cs.bcur, setr->rcur * 2); + } +} + +static inline void gen_setbp(DisasContext *ctx) +{ + Cs1 *cs1 = &ctx->bundle2.cs1; + Cs1Setr *setr = &cs1->setr; + + if (cs1->type == CS1_SETR && (setr->type & SETR_BP)) { + tcg_gen_movi_i32(e2k_cs.psize, setr->psz); + tcg_gen_movi_i32(e2k_cs.pcur, 0); + } +} + +static inline void gen_setr(DisasContext *ctx) +{ + gen_vfrpsz(ctx); + gen_setwd(ctx); + gen_setbn(ctx); + gen_setbp(ctx); +} + +static inline void gen_cs1(DisasContext *ctx) +{ + Cs1 *cs1 = &ctx->bundle2.cs1; + + switch(cs1->type) { + case CS1_NONE: + case CS1_MAS: + case CS1_SETR: + break; + case CS1_CALL: + ctx->ct.type = CT_CALL; + ctx->ct.wbs = cs1->call_wbs; + break; + case CS1_WAIT: + e2k_todo(ctx, "wait"); + break; + case CS1_FLUSH: + e2k_todo(ctx, "flush"); + break; + default: + e2k_todo_illop(ctx, "unimplemented %d", cs1->type); + break; + } +} + +static inline void gen_cs0(DisasContext *ctx) +{ + Cs0 *cs0 = &ctx->bundle2.cs0; + + switch(cs0->type) { + case CS0_NONE: + break; + case CS0_IBRANCH: + ctx->ct.type = CT_IBRANCH; + ctx->ct.u.target = ctx->pc + cs0->ibranch.sdisp; + break; + case CS0_DISP: { + uint64_t ctpr = ctpr_new_disp(ctx, &cs0->disp); + gen_set_ctpr(cs0->disp.ctpr, ctpr); + break; + } + case CS0_SDISP: { + // TODO: real sdisp target address + target_ulong target = (0xe2UL << 40) | cs0->sdisp.disp; + uint64_t ctpr = ctpr_new(CTPR_TAG_SDISP, 0, cs0->sdisp.ipd, target); + gen_set_ctpr(cs0->sdisp.ctpr, ctpr); + break; + } + case CS0_RETURN: { + TCGv_i32 t0 = tcg_const_i32(cs0->ret.ipd); + gen_helper_prep_return(e2k_cs.ctprs[2], cpu_env, t0); + tcg_temp_free_i32(t0); + break; + } + default: + e2k_todo_illop(ctx, "unimplemented %d", cs0->type); + break; + } +} + +static inline void gen_ct_cond(DisasContext *ctx) +{ + ControlTransfer *ct = &ctx->ct; + TCGv_i32 pcond, lcond; + + if (ct->type == CT_NONE) { + return; + } + + if (ct->cond_type == 1) { + tcg_gen_movi_i32(e2k_cs.ct_cond, 1); + return; + } + + pcond = tcg_temp_new_i32(); + lcond = tcg_temp_new_i32(); + + switch (ct->cond_type) { + case 0x2: + case 0x6: + case 0xf: + /* %predN */ + e2k_gen_preg_i32(pcond, ct->psrc); + break; + case 0x3: + case 0x7: + case 0xe: { + TCGv_i32 t0 = tcg_temp_new_i32(); + e2k_gen_preg_i32(t0, ct->psrc); + tcg_gen_setcondi_i32(TCG_COND_EQ, pcond, t0, 0); + tcg_temp_free_i32(t0); + break; + } + default: + break; + } + + switch (ct->cond_type) { + case 0x4: + case 0x6: + case 0xe: + /* #LOOP_END */ + e2k_gen_is_loop_end_i32(lcond); + break; + case 0x5: + case 0x7: + case 0xf: { /* #NOT_LOOP_END */ + TCGv_i32 t0 = tcg_temp_new_i32(); + e2k_gen_is_loop_end_i32(t0); + tcg_gen_setcondi_i32(TCG_COND_EQ, lcond, t0, 0); + tcg_temp_free_i32(t0); + break; + } + } + + switch (ct->cond_type) { + case 0x2: + case 0x3: + /* {,~}%predN */ + tcg_gen_mov_i32(e2k_cs.ct_cond, pcond); + break; + case 0x4: + case 0x5: + /* #{,NOT_}LOOP_END */ + tcg_gen_mov_i32(e2k_cs.ct_cond, lcond); + break; + case 0x6: + case 0xe: { + /* {,~}%predN || #LOOP_END */ + TCGv_i32 z = tcg_const_i32(0); + TCGv_i32 t0 = tcg_temp_new_i32(); + + tcg_gen_or_i32(t0, pcond, lcond); + tcg_gen_movcond_i32(TCG_COND_EQ, e2k_cs.ct_cond, e2k_cs.lsr_pcnt, z, t0, lcond); + tcg_temp_free_i32(t0); + tcg_temp_free_i32(z); + break; + } + case 0x7: + case 0xf: { + /* {,~}%predN && #NOT_LOOP_END */ + TCGv_i32 z = tcg_const_i32(0); + TCGv_i32 t0 = tcg_temp_new_i32(); + + tcg_gen_and_i32(t0, pcond, lcond); + tcg_gen_movcond_i32(TCG_COND_EQ, e2k_cs.ct_cond, e2k_cs.lsr_pcnt, z, t0, lcond); + tcg_temp_free_i32(t0); + tcg_temp_free_i32(z); + break; + } + case 0x8: + /* %MLOCK || %dt_alM */ + if (ct->psrc & 0xf) { +// static const int conv[] = {0, 1, 3, 4}; + int i; + + e2k_todo(ctx, "%%MLOCK || %%dt_alM"); + // %dt_al + for (i = 0; i < 4; i++) { + if (ct->psrc & (1 << i)) { + // i + } + } + } else { + /* %MLOCK */ + if (ctx->mlock) { + tcg_gen_mov_i32(e2k_cs.ct_cond, ctx->mlock); + } else { + tcg_gen_movi_i32(e2k_cs.ct_cond, 0); + } + } + break; + case 0x9: { + /* `lock_cond || pl_cond' control transfer conditions. */ + unsigned int type = (ct->psrc & 0x18) >> 3; + if (type == 0) { +// static const int cmp_num_to_alc[] = {0, 1, 3, 4}; +// unsigned int cmp_num = (psrc & 0x6) >> 1; +// unsigned int neg = psrc & 0x1; +// +// my_printf ("%%MLOCK || %s%%cmp%d", neg ? "~" : "", +// cmp_num_to_alc[cmp_num]); + e2k_todo(ctx, "%%MLOCK || %%cmpN"); + } else if (type == 1) { +// unsigned int cmp_jk = (psrc & 0x4) >> 2; +// unsigned int negj = (psrc & 0x2) >> 1; +// unsigned int negk = psrc & 0x1; +// +// my_printf ("%%MLOCK || %s%%cmp%d || %s%%cmp%d", +// negj ? "~" : "", cmp_jk == 0 ? 0 : 3, +// negk ? "~" : "", cmp_jk == 0 ? 1 : 4); + e2k_todo(ctx, "%%MLOCK || %%cmpN || %%cmpM"); + } else if (type == 2) { +// unsigned int clp_num = (psrc & 0x6) >> 1; +// unsigned int neg = psrc & 0x1; + + // "%%MLOCK || %s%%clp%d", neg ? "~" : "", clp_num + e2k_todo(ctx, "%%MLOCK || %%clpN"); + } + break; + } + default: + e2k_todo_illop(ctx, "undefined control transfer type %#x", ct->cond_type); + break; + } + + tcg_temp_free_i32(lcond); + tcg_temp_free_i32(pcond); +} + +static inline TCGCond cond_from_advance(int advance) +{ + 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; + } +} + +static void gen_movcond_flag_i32(TCGv_i32 ret, int flag, TCGv_i32 cond, + TCGv_i32 v1, TCGv_i32 v2) +{ + TCGv_i32 one = tcg_const_i32(1); + TCGCond c = cond_from_advance(flag); + + tcg_gen_movcond_i32(c, ret, cond, one, v1, v2); + tcg_temp_free_i32(one); +} + +static inline 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); + + tcg_temp_free_i32(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, e2k_cs.ct_cond, t0, cur); + gen_set_label(l0); + + tcg_temp_free_i32(t0); +} + +static void gen_dec_sat_i32(TCGv_i32 ret, TCGv_i32 arg0) +{ + TCGv_i32 t0 = tcg_const_i32(0); + TCGv_i32 t1 = tcg_temp_new_i32(); + tcg_gen_subi_i32(t1, arg0, 1); + tcg_gen_movcond_i32(TCG_COND_EQ, ret, arg0, t0, arg0, t1); + tcg_temp_free_i32(t1); + tcg_temp_free_i32(t0); +} + +static void gen_advance_loop_counters(void) +{ + TCGv_i32 z = tcg_const_i32(0); + TCGv_i32 t0 = tcg_temp_new_i32(); + TCGv_i32 t1 = tcg_temp_new_i32(); + TCGv_i32 t2 = tcg_temp_new_i32(); + TCGv_i32 t3 = tcg_temp_new_i32(); + + gen_dec_sat_i32(e2k_cs.lsr_pcnt, e2k_cs.lsr_pcnt); + gen_dec_sat_i32(e2k_cs.lsr_lcnt, e2k_cs.lsr_lcnt); + tcg_gen_setcondi_i32(TCG_COND_EQ, t0, e2k_cs.lsr_pcnt, 0); + tcg_gen_setcondi_i32(TCG_COND_EQ, t1, e2k_cs.lsr_lcnt, 0); + tcg_gen_mov_i32(e2k_cs.lsr_over, t1); + tcg_gen_and_i32(t2, t0, t1); + gen_dec_sat_i32(t3, e2k_cs.lsr_ecnt); + tcg_gen_movcond_i32(TCG_COND_NE, e2k_cs.lsr_ecnt, t2, z, t3, e2k_cs.lsr_ecnt); + + tcg_temp_free_i32(t3); + tcg_temp_free_i32(t2); + tcg_temp_free_i32(t1); + tcg_temp_free_i32(t0); + tcg_temp_free_i32(z); +} + +static inline 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), e2k_cs.ct_cond, 1, l0); + gen_advance_loop_counters(); + gen_set_label(l0); + } + + if (abp) { + TCGv_i32 t0 = tcg_temp_local_new_i32(); + tcg_gen_addi_i32(t0, e2k_cs.psize, 1); + gen_cur_dec(ctx, e2k_cs.pcur, abp, e2k_cs.pcur, 1, t0); + tcg_temp_free_i32(t0); + } + + if (abn) { + gen_cur_dec(ctx, e2k_cs.bcur, abn, e2k_cs.bcur, 2, e2k_cs.bsize); + } + + if (abg != 0) { + // TODO: impl abg + e2k_todo_illop(ctx, "abg"); + } + + if (vfdi != 0) { + // TODO: impl vfdi + e2k_todo_illop(ctx, "vfdi"); + } +} + static inline target_ulong do_decode(DisasContext *ctx, CPUState *cs) { E2KCPU *cpu = E2K_CPU(cs); @@ -255,6 +916,10 @@ static inline target_ulong do_decode(DisasContext *ctx, CPUState *cs) e2k_tr_gen_exception(ctx, E2K_EXCP_ILLOPC); } + decode_cs1(ctx, &ctx->bundle); + decode_cs0(ctx, &ctx->bundle); + decode_ct_cond(ctx, &ctx->bundle); + return ctx->pc + len; } @@ -264,35 +929,15 @@ static inline target_ulong do_decode(DisasContext *ctx, CPUState *cs) */ static inline void do_execute(DisasContext *ctx) { - e2k_control_execute(ctx); + ctx->loop_mode = (ctx->bundle.hs & (1 << 10)) != 0; + gen_cs0(ctx); + gen_cs1(ctx); e2k_alc_execute(ctx); - if (ctx->bundle.ss_present) { - e2k_decode_jmp(ctx); - } + gen_ct_cond(ctx); e2k_aau_execute(ctx); e2k_plu_execute(ctx); } -static inline void do_window_bounds_check(DisasContext *ctx) -{ - if (ctx->max_wreg < ctx->max_wreg_cur) { - TCGLabel *l0 = gen_new_label(); - ctx->max_wreg = ctx->max_wreg_cur; - tcg_gen_brcondi_i32(TCG_COND_GT, e2k_cs.wd_size, ctx->max_wreg, l0); - e2k_gen_exception(E2K_EXCP_MAPERR); - gen_set_label(l0); - } - - if (ctx->max_breg < ctx->max_breg_cur) { - TCGLabel *l0 = gen_new_label(); - ctx->max_breg = ctx->max_breg_cur; - tcg_gen_brcondi_i32(TCG_COND_GT, e2k_cs.bsize, ctx->max_breg, l0); - e2k_gen_exception(E2K_EXCP_MAPERR); - gen_set_label(l0); - } - -} - /* * Writes results of instructions from a bundle to the state * @@ -303,11 +948,11 @@ static inline void do_window_bounds_check(DisasContext *ctx) * */ static inline void do_commit(DisasContext *ctx) { - e2k_control_window_change(ctx); + gen_setr(ctx); e2k_alc_commit(ctx); e2k_aau_commit(ctx); e2k_plu_commit(ctx); - e2k_stubs_commit(ctx); + gen_stubs(ctx); } static inline void do_branch(DisasContext *ctx, target_ulong pc_next) @@ -327,7 +972,7 @@ static inline void do_branch(DisasContext *ctx, target_ulong pc_next) ctx->base.is_jmp = DISAS_NORETURN; - if (ctx->ct.is_branch) { + if (ctx->ct.cond_type > 1) { TCGLabel *l0 = gen_new_label(); tcg_gen_brcondi_i32(TCG_COND_NE, e2k_cs.ct_cond, 0, l0); gen_goto_tb(ctx, TB_EXIT_IDX1, pc_next); @@ -395,12 +1040,10 @@ static void e2k_tr_init_disas_context(DisasContextBase *db, CPUState *cs) static void e2k_tr_tb_start(DisasContextBase *db, CPUState *cs) { - DisasContext *ctx = container_of(db, DisasContext, base); +// DisasContext *ctx = container_of(db, DisasContext, base); E2KCPU *cpu = E2K_CPU(cs); CPUE2KState *env = &cpu->env; - ctx->max_wreg = -1; - ctx->max_breg = -1; tcg_gen_movi_i32(e2k_cs.ct_cond, 0); if (env->is_bp) { @@ -417,10 +1060,9 @@ static void e2k_tr_insn_start(DisasContextBase *db, CPUState *cs) tcg_gen_insn_start(ctx->base.pc_next); - ctx->max_wreg_cur = -1; - ctx->max_breg_cur = -1; - ctx->do_check_illtag = false; memset(ctx->mas, 0, sizeof(ctx->mas)); + memset(&ctx->bundle2, 0, sizeof(ctx->bundle2)); + ctx->do_check_illtag = false; ctx->illtag = e2k_get_temp_i32(ctx); tcg_gen_movi_i32(ctx->illtag, 0); } @@ -432,7 +1074,6 @@ static void e2k_tr_translate_insn(DisasContextBase *db, CPUState *cs) pc_next = do_decode(ctx, cs); do_execute(ctx); - do_window_bounds_check(ctx); do_commit(ctx); do_branch(ctx, pc_next); @@ -506,6 +1147,12 @@ void e2k_tcg_initialize(void) { { &e2k_cs.pcur, offsetof(CPUE2KState, bp.cur), "pcur" }, { &e2k_cs.is_bp, offsetof(CPUE2KState, is_bp), "is_bp" }, { &e2k_cs.wdbl, offsetof(CPUE2KState, wdbl), "wdbl" }, + { &e2k_cs.lsr_lcnt, offsetof(CPUE2KState, lsr_lcnt), "lsr_lcnt" }, + { &e2k_cs.lsr_ecnt, offsetof(CPUE2KState, lsr_ecnt), "lsr_ecnt" }, + { &e2k_cs.lsr_vlc, offsetof(CPUE2KState, lsr_vlc), "lsr_vlc" }, + { &e2k_cs.lsr_over, offsetof(CPUE2KState, lsr_over), "lsr_over" }, + { &e2k_cs.lsr_pcnt, offsetof(CPUE2KState, lsr_pcnt), "lsr_pcnt" }, + { &e2k_cs.lsr_strmd, offsetof(CPUE2KState, lsr_strmd), "lsr_strmd" }, { &e2k_cs.aasti_tags, offsetof(CPUE2KState, aau.sti_tags), "aasti_tags" }, { &e2k_cs.aaind_tags, offsetof(CPUE2KState, aau.ind_tags), "aaind_tags" }, { &e2k_cs.aaincr_tags, offsetof(CPUE2KState, aau.incr_tags), "aaincr_tags" }, @@ -514,7 +1161,6 @@ void e2k_tcg_initialize(void) { static const struct { TCGv_i64 *ptr; int off; const char *name; } r64[] = { { &e2k_cs.pregs, offsetof(CPUE2KState, pregs), "pregs" }, - { &e2k_cs.lsr, offsetof(CPUE2KState, lsr), "lsr" }, }; static const struct { TCGv *ptr; int off; const char *name; } rtl[] = { diff --git a/target/e2k/translate.h b/target/e2k/translate.h index 72ae76e7bb..1b519006ca 100644 --- a/target/e2k/translate.h +++ b/target/e2k/translate.h @@ -40,7 +40,6 @@ typedef struct CPUE2KStateTCG { TCGv_i32 ct_cond; TCGv_i32 is_bp; /* breakpoint flag */ TCGv_i32 wdbl; - TCGv_i64 lsr; TCGv_i32 wd_base; /* holds wbs * 2 */ TCGv_i32 wd_size; /* holds wsz * 2 */ TCGv_i32 boff; /* holds rbs * 2 */ @@ -49,6 +48,13 @@ typedef struct CPUE2KStateTCG { TCGv_i64 pregs; TCGv_i32 psize; /* holds psz */ TCGv_i32 pcur; /* holds pcur */ + /* lsr */ + TCGv_i32 lsr_lcnt; + TCGv_i32 lsr_ecnt; + TCGv_i32 lsr_vlc; + TCGv_i32 lsr_over; + TCGv_i32 lsr_pcnt; + TCGv_i32 lsr_strmd; /* AAU */ TCGv_i32 aasti[16]; TCGv_i32 aasti_tags; @@ -63,7 +69,7 @@ typedef struct CPUE2KStateTCG { extern struct CPUE2KStateTCG e2k_cs; -typedef struct UnpackedBundle { +typedef struct { uint32_t hs; uint32_t ss; uint32_t als[6]; @@ -86,6 +92,140 @@ typedef struct UnpackedBundle { bool cds_present[3]; } UnpackedBundle; +typedef struct { + int32_t sdisp; /* CS0 28:0 */ +} Cs0IBranch, Cs0Puttsd; + +typedef struct { + int32_t sdisp; /* CS0 28:0 */ + uint8_t ipd; /* SS 31:30 */ + uint8_t ctpr; /* CS0 31:30 */ + uint8_t opc; +} Cs0Disp; + +typedef struct { + uint32_t disp; /* CS0 28:0 */ + uint8_t ipd; /* SS 31:30 */ + uint8_t ctpr; /* CS0 31:30 */ +} Cs0SDisp; + +typedef struct { + uint8_t ipd; +} Cs0Return; + +typedef struct { + uint32_t disp; /* 28:4 */ + uint8_t prefr; /* 2:0 */ + uint8_t ipd; /* 3 */ +} Cs0Pref; + +typedef enum { + CS0_NONE, + CS0_IBRANCH, + CS0_PREF, + CS0_PUTTSD, + CS0_DONE, + CS0_HRET, + CS0_GLAUNCH, + CS0_DISP, + CS0_SDISP, + CS0_GETTSD, + CS0_RETURN, +} Cs0Type; + +typedef struct { + Cs0Type type; + union { + Cs0IBranch ibranch; + Cs0Puttsd puttsd; + Cs0Disp disp; + Cs0SDisp sdisp; + Cs0Pref pref; + Cs0Return ret; + }; +} Cs0; + +typedef enum { + SETR_VFRPSZ = 0x01, + SETR_WD = 0x02, + SETR_BN = 0x04, + SETR_BP = 0x08, +} SetrType; + +typedef struct { + SetrType type; + uint8_t rpsz; + uint8_t wsz; + bool nfx; + bool dbl; + uint8_t rbs; + uint8_t rsz; + uint8_t rcur; + uint8_t psz; +} Cs1Setr; + +typedef struct { + bool ma_c; + bool fl_c; + bool ld_c; + bool st_c; + bool all_e; + bool all_c; + /* v2+ */ + bool trap; + /* v5+ */ + bool sal; + bool sas; +} Cs1Wait; + +typedef struct { + uint8_t wbs; + uint8_t disp; +} Cs1HCall; + +typedef struct { + bool flushr; + bool flushc; +} Cs1Flush; + +typedef struct { + bool chkm4; + uint8_t dmask; + uint8_t umask; +} Cs1Vfbg; + +typedef enum { + CS1_NONE, + CS1_SETR, + CS1_SETEI, + CS1_SETSFT, + CS1_WAIT, + CS1_CALL, + CS1_HCALL, + CS1_MAS, + CS1_FLUSH, + CS1_VFBG, +} Cs1Type; + +typedef struct { + Cs1Type type; + union { + Cs1Setr setr; + uint8_t ei; + Cs1Wait wait; + uint8_t call_wbs; + Cs1HCall hcall; + uint8_t mas[6]; + Cs1Flush flush; + Cs1Vfbg vfbg; + }; +} Cs1; + +typedef struct { + Cs0 cs0; + Cs1 cs1; +} Bundle; + typedef enum { AL_RESULT_NONE = 0, @@ -119,7 +259,6 @@ typedef struct { bool poison; union { struct { - uint8_t dst; /* %rN, 1st phase */ TCGv_i32 index; TCGv_i32 tag; union { @@ -180,18 +319,19 @@ typedef struct { TCGv_i64 ctpr; } u; int wbs; - bool is_branch; + uint8_t cond_type; + uint8_t psrc; } ControlTransfer; typedef struct DisasContext { DisasContextBase base; UnpackedBundle bundle; + Bundle bundle2; target_ulong pc; int jump_ctpr; int mmuidx; uint8_t mas[6]; bool loop_mode; - TCGv_i32 is_prologue; TCGv_i32 is_epilogue; /* optional, can be NULL */ TCGv_i32 mlock; @@ -210,16 +350,16 @@ typedef struct DisasContext { int t64_len; int ttl_len; - /* Delayed window bounds checks */ - int max_wreg; - int max_wreg_cur; - int max_breg; - int max_breg_cur; - /* Delayed illegal tag check */ TCGv_i32 illtag; bool do_check_illtag; + /* Delayed window bounds check */ + int max_r; + int max_r_cur; + int max_b; + int max_b_cur; + TCGv_i64 cond[6]; AlResult al_results[6]; TCGv_i32 al_cond[6]; @@ -244,22 +384,13 @@ static inline void e2k_gen_exception(int excp) tcg_temp_free_i32(t0); } +#define e2k_todo(ctx, fmt, ...) \ + qemu_log("%#lx: " fmt " (%s:%d)\n", ctx->pc, \ + ## __VA_ARGS__, __FILE__, __LINE__) -#define e2k_todo(ctx, fmt, ...) \ - do { \ - if (unlikely(qemu_loglevel_mask(LOG_UNIMP))) { \ - qemu_log("%#lx: todo: ", ctx->pc); \ - qemu_log(fmt, ## __VA_ARGS__); \ - qemu_log("\n"); \ - } \ - } while (0) - - -#define e2k_todo_illop(ctx, fmt, ...) \ - do { \ - e2k_todo(ctx, fmt, ## __VA_ARGS__); \ - e2k_tr_gen_exception(ctx, E2K_EXCP_ILLOPC); \ - } while (0) +#define e2k_todo_illop(ctx, fmt, ...) \ + e2k_todo(ctx, fmt, ## __VA_ARGS__); \ + e2k_tr_gen_exception(ctx, E2K_EXCP_ILLOPC) static inline void e2k_gen_mask_i64(TCGv_i64 ret, TCGv_i64 len) { @@ -360,97 +491,9 @@ static inline void e2k_gen_save_cpu_state(DisasContext *ctx) e2k_gen_save_pc(ctx->pc); } -static inline void e2k_gen_lcnt_i64(TCGv_i64 ret) -{ - tcg_gen_andi_i64(ret, e2k_cs.lsr, (1UL << 32) - 1); -} - -static inline void e2k_gen_lcnt_i32(TCGv_i32 ret) -{ - TCGv_i64 t0 = tcg_temp_new_i64(); - - e2k_gen_lcnt_i64(t0); - tcg_gen_extrl_i64_i32(ret, t0); - tcg_temp_free_i64(t0); -} - -static inline void e2k_gen_lcnt_set_i32(TCGv_i32 value) -{ - TCGv_i64 t0 = tcg_temp_new_i64(); - - tcg_gen_extu_i32_i64(t0, value); - tcg_gen_deposit_i64(e2k_cs.lsr, e2k_cs.lsr, t0, LSR_LCNT_OFF, LSR_LCNT_LEN); - tcg_temp_free_i64(t0); -} - -static inline void e2k_gen_ecnt_i64(TCGv_i64 ret) -{ - tcg_gen_extract_i64(ret, e2k_cs.lsr, LSR_ECNT_OFF, LSR_ECNT_LEN); -} - -static inline void e2k_gen_ecnt_i32(TCGv_i32 ret) -{ - TCGv_i64 t0 = tcg_temp_new_i64(); - - e2k_gen_ecnt_i64(t0); - tcg_gen_extrl_i64_i32(ret, t0); - tcg_temp_free_i64(t0); -} - -static inline void e2k_gen_ecnt_set_i32(TCGv_i32 value) -{ - TCGv_i64 t0 = tcg_temp_new_i64(); - - tcg_gen_extu_i32_i64(t0, value); - tcg_gen_deposit_i64(e2k_cs.lsr, e2k_cs.lsr, t0, LSR_ECNT_OFF, LSR_ECNT_LEN); - tcg_temp_free_i64(t0); -} - -static inline void e2k_gen_pcnt_i32(TCGv_i32 ret) -{ - TCGv_i64 t0 = tcg_temp_new_i64(); - - tcg_gen_extract_i64(t0, e2k_cs.lsr, LSR_PCNT_OFF, LSR_PCNT_LEN); - tcg_gen_extrl_i64_i32(ret, t0); - tcg_temp_free_i64(t0); -} - -static inline void e2k_gen_pcnt_set_i32(TCGv_i32 value) -{ - TCGv_i64 t0 = tcg_temp_new_i64(); - - tcg_gen_extu_i32_i64(t0, value); - tcg_gen_deposit_i64(e2k_cs.lsr, e2k_cs.lsr, t0, LSR_PCNT_OFF, LSR_PCNT_LEN); - tcg_temp_free_i64(t0); -} - -static inline void e2k_gen_lsr_strem_i32(TCGv_i32 ret) -{ - TCGv_i64 t0 = tcg_temp_new_i64(); - - tcg_gen_extract_i64(t0, e2k_cs.lsr, LSR_STRMD_OFF, LSR_STRMD_LEN); - tcg_gen_extrl_i64_i32(ret, t0); - tcg_temp_free_i64(t0); -} - -static inline void e2k_gen_lsr_strem_set_i32(TCGv_i32 value) -{ - TCGv_i64 t0 = tcg_temp_new_i64(); - - tcg_gen_extu_i32_i64(t0, value); - tcg_gen_deposit_i64(e2k_cs.lsr, e2k_cs.lsr, t0, LSR_STRMD_OFF, - LSR_STRMD_LEN); - tcg_temp_free_i64(t0); -} - static inline void e2k_gen_lcntex(TCGv_i32 ret) { - TCGv_i32 t0 = tcg_temp_new_i32(); - - tcg_gen_extrl_i64_i32(t0, e2k_cs.lsr); - tcg_gen_setcondi_i32(TCG_COND_EQ, ret, t0, 0); - - tcg_temp_free_i32(t0); + tcg_gen_setcondi_i32(TCG_COND_EQ, ret, e2k_cs.lsr_lcnt, 0); } void e2k_gen_store_preg(int idx, TCGv_i32 val); @@ -493,17 +536,13 @@ void e2k_gen_reg_index_from_gregi(TCGv_i32 ret, int idx); static inline void e2k_gen_reg_index(DisasContext *ctx, TCGv_i32 ret, uint8_t arg) { if (IS_BASED(arg)) { - int index = GET_BASED(arg); - ctx->max_breg_cur = MAX(ctx->max_breg_cur, index); - e2k_gen_reg_index_from_bregi(ret, index); + e2k_gen_reg_index_from_bregi(ret, GET_BASED(arg)); } else if (IS_REGULAR(arg)) { - int index = GET_REGULAR(arg); - ctx->max_wreg_cur = MAX(ctx->max_wreg_cur, index); - e2k_gen_reg_index_from_wregi(ret, index); + e2k_gen_reg_index_from_wregi(ret, GET_REGULAR(arg)); } else if (IS_GLOBAL(arg)) { e2k_gen_reg_index_from_gregi(ret, GET_GLOBAL(arg)); } else { - e2k_gen_exception(E2K_EXCP_ILLOPN); + e2k_tr_gen_exception(ctx, E2K_EXCP_ILLOPN); } } @@ -519,52 +558,19 @@ void e2k_gen_xreg_write_i64(TCGv_i64 value, TCGv_i32 idx); void e2k_gen_xreg_write_i32(TCGv_i32 value, TCGv_i32 idx); void e2k_gen_xreg_write16u_i32(TCGv_i32 value, TCGv_i32 idx); -void e2k_gen_preg_i64(TCGv_i64 ret, int reg); void e2k_gen_preg_i32(TCGv_i32 ret, int reg); -TCGv_i64 e2k_get_preg(DisasContext *dc, int reg); void e2k_gen_cond_i32(DisasContext *ctx, TCGv_i32 ret, uint8_t psrc); -static inline void e2k_gen_cond_i64(DisasContext *ctx, TCGv_i64 ret, - uint8_t psrc) -{ - TCGv_i32 t0 = tcg_temp_new_i32(); - - e2k_gen_cond_i32(ctx, t0, psrc); - tcg_gen_extu_i32_i64(ret, t0); - - tcg_temp_free_i32(t0); -} - -static inline void e2k_gen_is_last_iter(TCGv_i32 ret) -{ - TCGv_i32 t0 = tcg_temp_new_i32(); - TCGv_i32 t1 = tcg_temp_new_i32(); - TCGv_i64 t2 = tcg_temp_new_i64(); - TCGv_i32 t3 = tcg_temp_new_i32(); - - e2k_gen_lcnt_i32(t0); - tcg_gen_setcondi_i32(TCG_COND_LTU, t1, t0, 2); - tcg_gen_andi_i64(t2, e2k_cs.lsr, LSR_VLC_BIT); - tcg_gen_setcondi_i64(TCG_COND_NE, t2, t2, 0); - tcg_gen_extrl_i64_i32(t3, t2); - tcg_gen_and_i32(ret, t1, t3); - - tcg_temp_free_i32(t3); - tcg_temp_free_i64(t2); - tcg_temp_free_i32(t1); - tcg_temp_free_i32(t0); -} - static inline void e2k_gen_is_loop_end_i32(TCGv_i32 ret) { TCGv_i32 t0 = tcg_temp_new_i32(); TCGv_i32 t1 = tcg_temp_new_i32(); TCGv_i32 t2 = tcg_temp_new_i32(); - e2k_gen_ecnt_i32(t0); - tcg_gen_setcondi_i32(TCG_COND_EQ, t1, t0, 0); - e2k_gen_is_last_iter(t2); - tcg_gen_and_i32(ret, t1, t2); + tcg_gen_setcondi_i32(TCG_COND_EQ, t0, e2k_cs.lsr_ecnt, 0); + tcg_gen_setcondi_i32(TCG_COND_LTU, t1, e2k_cs.lsr_lcnt, 2); + tcg_gen_and_i32(t2, t0, t1); + tcg_gen_and_i32(ret, t2, e2k_cs.lsr_vlc); tcg_temp_free_i32(t2); tcg_temp_free_i32(t1); @@ -572,8 +578,6 @@ static inline void e2k_gen_is_loop_end_i32(TCGv_i32 ret) } void e2k_decode_jmp(DisasContext *ctx); -void e2k_control_execute(DisasContext *ctx); -void e2k_control_window_change(DisasContext *ctx); void e2k_stubs_commit(DisasContext *ctx); void alc_init(DisasContext *ctx); diff --git a/target/e2k/translate/aau.c b/target/e2k/translate/aau.c index f70dfae74c..76a4259450 100644 --- a/target/e2k/translate/aau.c +++ b/target/e2k/translate/aau.c @@ -16,14 +16,14 @@ typedef struct { uint16_t aas; }; uint8_t dst; -} Instr; +} Mova; static void gen_load_prefetch_program(DisasContext *ctx) { gen_helper_aau_load_program(cpu_env); } -static void gen_aau_result_reg64(DisasContext *ctx, Instr *instr, TCGv_i64 dst) +static void gen_aau_result_reg64(DisasContext *ctx, Mova *instr, TCGv_i64 dst) { AauResult *res = &ctx->aau_results[instr->chan]; res->type = AAU_RESULT_REG64; @@ -38,7 +38,7 @@ static void gen_aau_result_reg64(DisasContext *ctx, Instr *instr, TCGv_i64 dst) } } -static void gen_aau_result_reg32(DisasContext *ctx, Instr *instr, TCGv_i32 dst) +static void gen_aau_result_reg32(DisasContext *ctx, Mova *instr, TCGv_i32 dst) { AauResult *res = &ctx->aau_results[instr->chan]; res->type = AAU_RESULT_REG32; @@ -53,7 +53,7 @@ static void gen_aau_result_reg32(DisasContext *ctx, Instr *instr, TCGv_i32 dst) } } -static void gen_mova_i32(DisasContext *ctx, Instr *instr, TCGv ptr) +static void gen_mova_i32(DisasContext *ctx, Mova *instr, TCGv ptr) { MemOp memop = instr->be ? MO_BE : MO_LE; TCGv_i32 dst = e2k_get_temp_i32(ctx); @@ -71,7 +71,7 @@ static void gen_mova_i32(DisasContext *ctx, Instr *instr, TCGv ptr) gen_aau_result_reg32(ctx, instr, dst); } -static void gen_mova_i64(DisasContext *ctx, Instr *instr, TCGv ptr) +static void gen_mova_i64(DisasContext *ctx, Mova *instr, TCGv ptr) { TCGv_i64 dst = e2k_get_temp_i64(ctx); @@ -79,7 +79,7 @@ static void gen_mova_i64(DisasContext *ctx, Instr *instr, TCGv ptr) gen_aau_result_reg64(ctx, instr, dst); } -static inline void gen_mova_ptr(TCGv ret, Instr *instr) +static inline void gen_mova_ptr(TCGv ret, Mova *instr) { TCGv_i32 t0 = tcg_const_i32(instr->chan); TCGv_i32 t1 = tcg_const_i32(instr->area); @@ -92,7 +92,7 @@ static inline void gen_mova_ptr(TCGv ret, Instr *instr) tcg_temp_free_i32(t1); tcg_temp_free_i32(t0); } -static void gen_mova(DisasContext *ctx, Instr *instr) +static void gen_mova(DisasContext *ctx, Mova *instr) { TCGv t5 = tcg_temp_new(); @@ -142,7 +142,7 @@ void e2k_aau_execute(DisasContext *ctx) unsigned int i; for (i = 0; i < 4; i++) { - Instr instr = { 0 }; + Mova instr = { 0 }; AauResult *res = &ctx->aau_results[i]; instr.chan = i; diff --git a/target/e2k/translate/alc.c b/target/e2k/translate/alc.c index 1e14117607..29076d56b2 100644 --- a/target/e2k/translate/alc.c +++ b/target/e2k/translate/alc.c @@ -29,6 +29,7 @@ typedef struct { int chan; AlesFlag ales_present; int aaincr_len; + uint8_t mas; union { uint32_t als; struct { @@ -487,10 +488,7 @@ static inline void set_al_result_reg80_tag(Instr *instr, TCGv_i64 lo, res->reg.v64 = lo; res->reg.x32 = hi; res->reg.index = get_temp_i32(instr); - res->reg.dst = dst; - if (!IS_REGULAR(dst)) { - e2k_gen_reg_index(instr->ctx, res->reg.index, dst); - } + e2k_gen_reg_index(instr->ctx, res->reg.index, dst); } } @@ -518,12 +516,7 @@ static inline void set_al_result_reg64_tag(Instr *instr, res->reg.v64 = value; res->reg.tag = tag; res->reg.index = e2k_get_temp_i32(instr->ctx); - if (IS_REGULAR(arg)) { - res->reg.dst = arg; - } else { - res->reg.dst = 0; - e2k_gen_reg_index(instr->ctx, res->reg.index, arg); - } + e2k_gen_reg_index(instr->ctx, res->reg.index, arg); } } @@ -557,12 +550,7 @@ static inline void set_al_result_reg32_tag(Instr *instr, res->reg.v32 = value; res->reg.tag = tag; res->reg.index = e2k_get_temp_i32(instr->ctx); - if (IS_REGULAR(arg)) { - res->reg.dst = arg; - } else { - res->reg.dst = 0; - e2k_gen_reg_index(instr->ctx, res->reg.index, arg); - } + e2k_gen_reg_index(instr->ctx, res->reg.index, arg); } } @@ -689,16 +677,14 @@ static void gen_loop_mode_st(DisasContext *ctx, TCGLabel *l) { if (ctx->loop_mode) { TCGLabel *l0 = gen_new_label(); - TCGv_i32 t0 = tcg_temp_local_new_i32(); - - tcg_gen_brcondi_i32(TCG_COND_EQ, ctx->is_prologue, 1, l); + TCGv_i32 t0 = tcg_temp_new_i32(); + tcg_gen_brcondi_i32(TCG_COND_NE, e2k_cs.lsr_pcnt, 0, l); e2k_gen_is_loop_end_i32(t0); tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l0); - e2k_gen_lsr_strem_i32(t0); - tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l); - tcg_gen_subi_i32(t0, t0, 1); - e2k_gen_lsr_strem_set_i32(t0); + tcg_gen_brcondi_i32(TCG_COND_EQ, e2k_cs.lsr_strmd, 0, l); + tcg_gen_subi_i32(e2k_cs.lsr_strmd, e2k_cs.lsr_strmd, 1); gen_set_label(l0); + tcg_temp_free_i32(t0); } } @@ -1698,7 +1684,7 @@ ok_exit: static MemOp gen_mas(Instr *instr, MemOp memop, TCGv_i64 addr) { DisasContext *ctx = instr->ctx; - uint8_t mas = ctx->mas[instr->chan]; + uint8_t mas = instr->mas; if ((mas & 0x7) == 7) { int opc = mas >> 3; @@ -2140,11 +2126,10 @@ static void gen_aasti_incr(DisasContext *ctx, Instr *instr) TCGLabel *l1 = gen_new_label(); TCGv_i32 t0 = tcg_temp_local_new_i32(); - tcg_gen_brcondi_i32(TCG_COND_EQ, ctx->is_prologue, 1, l0); + tcg_gen_brcondi_i32(TCG_COND_NE, e2k_cs.lsr_pcnt, 0, l0); e2k_gen_is_loop_end_i32(t0); tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1); - e2k_gen_lsr_strem_i32(t0); - tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l0); + tcg_gen_brcondi_i32(TCG_COND_EQ, e2k_cs.lsr_strmd, 0, l0); gen_set_label(l1); } @@ -2201,7 +2186,7 @@ static void gen_aad_ptr(DisasContext *ctx, TCGv ret, Instr *instr) static void gen_staa_i64(Instr *instr) { DisasContext *ctx = instr->ctx; - uint8_t mas = ctx->mas[instr->chan]; + uint8_t mas = instr->mas; TCGLabel *l0 = gen_new_label(); Src64 s4 = get_src4_i64(instr); @@ -2256,7 +2241,7 @@ static void gen_staa_i64(Instr *instr) static void gen_staa_i32(Instr *instr, MemOp memop) { DisasContext *ctx = instr->ctx; - uint8_t mas = ctx->mas[instr->chan]; + uint8_t mas = instr->mas; TCGLabel *l0 = gen_new_label(); Src32 s4 = get_src4_i32(instr); @@ -4509,17 +4494,12 @@ static void chan_check_preds(DisasContext *ctx, int chan, TCGLabel *l) switch(kind) { case 0x2: { /* %pcntN */ - TCGv_i32 t3 = tcg_temp_new_i32(); - has_pcnt = true; - // FIXME: slow, need to store unpacked LSR for fast field access - e2k_gen_pcnt_i32(t3); - tcg_gen_setcondi_i32(TCG_COND_LEU, t2, t3, idx); + tcg_gen_setcondi_i32(TCG_COND_LEU, t2, e2k_cs.lsr_pcnt, idx); if (invert) { tcg_gen_xori_i32(t2, t2, 1); } tcg_gen_or_i32(t0, t0, t2); - tcg_temp_free_i32(t3); break; } case 0x3: /* %predN */ @@ -4564,9 +4544,9 @@ static void chan_execute(DisasContext *ctx, int chan) TCGLabel *l0 = gen_new_label(); Instr instr = { 0 }; - instr.aaincr = 0; instr.ctx = ctx; instr.chan = chan; + instr.mas = ctx->bundle2.cs1.type == CS1_MAS ? ctx->bundle2.cs1.mas[chan] : 0; instr.als = ctx->bundle.als[chan]; instr.ales = ctx->bundle.ales[chan]; instr.ales_present = ctx->bundle.ales_present[chan]; @@ -4729,18 +4709,7 @@ static inline void gen_al_result_commit_ctpr(AlResult *res) void e2k_alc_commit(DisasContext *ctx) { - unsigned int i; - - for (i = 0; i < 6; i++) { - AlResult *res = &ctx->al_results[i]; - - if (e2k_al_result_type(res->type) == AL_RESULT_REG) { - uint8_t dst = res->reg.dst; - if (IS_REGULAR(dst)) { - e2k_gen_reg_index_from_wregi(res->reg.index, GET_REGULAR(dst)); - } - } - } + int i; for (i = 0; i < 6; i++) { TCGLabel *l0 = gen_new_label(); diff --git a/target/e2k/translate/control.c b/target/e2k/translate/control.c deleted file mode 100644 index d880599bc3..0000000000 --- a/target/e2k/translate/control.c +++ /dev/null @@ -1,672 +0,0 @@ -#include "qemu/osdep.h" -#include "qemu.h" -#include "exec/log.h" -#include "translate.h" - -static inline TCGCond cond_from_advance(int advance) -{ - 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; - } -} - -static void gen_movcond_flag_i32(TCGv_i32 ret, int flag, TCGv_i32 cond, - TCGv_i32 v1, TCGv_i32 v2) -{ - TCGv_i32 one = tcg_const_i32(1); - TCGCond c = cond_from_advance(flag); - - tcg_gen_movcond_i32(c, ret, cond, one, v1, v2); - tcg_temp_free_i32(one); -} - -static inline 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); - - tcg_temp_free_i32(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, e2k_cs.ct_cond, t0, cur); - gen_set_label(l0); - - tcg_temp_free_i32(t0); -} - -static void gen_advance_pcnt(TCGv_i32 ret) -{ - TCGLabel *l0 = gen_new_label(); - TCGv_i32 t0 = tcg_temp_local_new_i32(); - TCGv_i32 t1 = tcg_temp_new_i32(); - - e2k_gen_pcnt_i32(t0); - tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l0); - tcg_gen_subi_i32(t1, t0, 1); - e2k_gen_pcnt_set_i32(t1); - gen_set_label(l0); - tcg_gen_mov_i32(ret, t0); - - tcg_temp_free_i32(t1); - tcg_temp_free_i32(t0); -} - -static inline void gen_lcnt_overflow(TCGv_i32 lcnt) -{ - TCGv_i64 t0 = tcg_temp_new_i64(); - TCGv_i64 t1 = tcg_temp_new_i64(); - - tcg_gen_extu_i32_i64(t0, lcnt); - tcg_gen_setcondi_i64(TCG_COND_EQ, t1, t0, 0); - tcg_gen_shli_i64(t1, t1, LSR_OVER_OFF); - tcg_gen_or_i64(e2k_cs.lsr, e2k_cs.lsr, t1); - - tcg_temp_free_i64(t1); - tcg_temp_free_i64(t0); -} - -static void gen_advance_lcnt(TCGv_i32 ret) -{ - TCGLabel *l0 = gen_new_label(); - TCGv_i32 t0 = tcg_temp_local_new_i32(); - - e2k_gen_lcnt_i32(t0); - tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l0); - tcg_gen_subi_i32(t0, t0, 1); - e2k_gen_lcnt_set_i32(t0); - - gen_set_label(l0); - gen_lcnt_overflow(t0); - tcg_gen_mov_i32(ret, t0); - - tcg_temp_free_i32(t0); -} - -static void gen_advance_ecnt(void) -{ - TCGLabel *l0 = gen_new_label(); - TCGv_i32 t0 = tcg_temp_local_new_i32(); - TCGv_i32 t1 = tcg_temp_new_i32(); - - e2k_gen_ecnt_i32(t0); - tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l0); - tcg_gen_subi_i32(t1, t0, 1); - e2k_gen_ecnt_set_i32(t1); - gen_set_label(l0); - - tcg_temp_free_i32(t1); - tcg_temp_free_i32(t0); -} - -static void gen_advance_loop_counters(void) -{ - TCGLabel *l0 = gen_new_label(); - TCGv_i32 t0 = tcg_temp_local_new_i32(); - TCGv_i32 t1 = tcg_temp_local_new_i32(); - - gen_advance_pcnt(t0); - gen_advance_lcnt(t1); - tcg_gen_brcondi_i32(TCG_COND_NE, t0, 0, l0); - tcg_gen_brcondi_i32(TCG_COND_NE, t1, 0, l0); - gen_advance_ecnt(); - gen_set_label(l0); - - tcg_temp_free_i32(t1); - tcg_temp_free_i32(t0); -} - -void e2k_stubs_commit(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), e2k_cs.ct_cond, 1, l0); - gen_advance_loop_counters(); - gen_set_label(l0); - } - - if (abp) { - TCGv_i32 t0 = tcg_temp_local_new_i32(); - tcg_gen_addi_i32(t0, e2k_cs.psize, 1); - gen_cur_dec(ctx, e2k_cs.pcur, abp, e2k_cs.pcur, 1, t0); - tcg_temp_free_i32(t0); - } - - if (abn) { - gen_cur_dec(ctx, e2k_cs.bcur, abn, e2k_cs.bcur, 2, e2k_cs.bsize); - } - - if (abg != 0) { - // TODO: impl abg - e2k_todo_illop(ctx, "abg"); - } - - if (vfdi != 0) { - // TODO: impl vfdi - e2k_todo_illop(ctx, "vfdi"); - } -} - -static void gen_cs0(DisasContext *dc) -{ - typedef enum { - NOTHING, - IBRANCH, - PREF, - PUTTSD, - DONE, - HRET, - GLAUNCH, - DISP, - SDISP, - GETTSD, - LDISP, - RETURN - } cs0_type; - - static cs0_type cs0_ops[4][4] = { - {IBRANCH, PREF, PUTTSD, DONE}, - {DISP, NOTHING, SDISP, GETTSD}, - {DISP, LDISP, SDISP, GETTSD}, - {DISP, NOTHING, SDISP, RETURN} - }; - const UnpackedBundle *bundle = &dc->bundle; - uint32_t cs0 = bundle->cs0; - - unsigned int ctpr = (cs0 & 0xc0000000) >> 30; - unsigned int ctp_opc = (cs0 & 0x30000000) >> 28; - unsigned int param_type = (cs0 & 0x00000007); - cs0_type type = cs0_ops[ctpr][ctp_opc]; - - if (type == RETURN && param_type == 1) { - type = GETTSD; - } else if (type == DONE) { - if (param_type == 3) { - type = HRET; - } else if (param_type == 4) { - type = GLAUNCH; - } - } - - if (type == IBRANCH || type == DONE || type == HRET || type == GLAUNCH) { - if (!bundle->ss_present || (bundle->ss & 0x00000c00)) { - e2k_tr_gen_exception(dc, E2K_EXCP_ILLOPC); - } else if ((bundle->ss & 0x1ff) - && !(bundle->cs1_present - /* CS1.opc == CALL */ - && (bundle->cs1 & 0xf0000000) >> 28 == 5 - /* CS1.param.ctopc == HCALL */ - && (bundle->cs1 & 0x380) >> 7 == 2)) - { - if (type == IBRANCH) { - int32_t sdisp = sextract32(cs0, 0, 28) << 3; - dc->ct.type = CT_IBRANCH; - dc->ct.u.target = dc->pc + sdisp; - } else { - e2k_tr_gen_exception(dc, E2K_EXCP_ILLOPC); - } - } - } else { - /* Note that according to Table B.4.1 it's possible to obtain - ` gettsd %ctpr{1,2} with an invalid value for CS0.param.type. */ - if (type == GETTSD && param_type != 1) { - e2k_tr_gen_exception(dc, E2K_EXCP_ILLOPC); - } - int ipd = bundle->ss_present ? extract32(bundle->ss, 30, 2) : 3; - if (type == DISP || type == LDISP) { - int32_t sdisp = sextract32(cs0, 0, 28) << 3; - uint64_t reg = (dc->pc + sdisp) | - ((uint64_t) CTPR_TAG_DISP << CTPR_TAG_OFF) | - ((uint64_t) ipd << CTPR_IPD_OFF); - if (type == LDISP) { - reg |= (uint64_t) CTPR_OPC_LDISP << CTPR_OPC_OFF; - } - tcg_gen_movi_tl(e2k_cs.ctprs[ctpr - 1], reg); - } else if (type == SDISP) { - unsigned int disp = extract32(cs0, 0, 28) << 11; - target_ulong base = ((uint64_t) 0xe2 << 40) | disp; - uint64_t reg = (dc->pc + base) | - ((uint64_t) CTPR_TAG_SDISP << CTPR_TAG_OFF) | - ((uint64_t) ipd << CTPR_IPD_OFF); - tcg_gen_movi_tl(e2k_cs.ctprs[ctpr - 1], reg); - } - - /* Note that RETURN is said to be COPF1. I can't understand what its - `CS0.param' is needed for: all of the bits except the three - lowermost ones are undefined, while the latter also known as "type" - field should be filled in with zeroes. */ - if (type == RETURN) { - TCGv_i32 t0 = tcg_const_i32(ipd); - - if (ctpr != 3) { - e2k_tr_gen_exception(dc, E2K_EXCP_ILLOPN); - } - - gen_helper_prep_return(e2k_cs.ctprs[2], cpu_env, t0); - tcg_temp_free_i32(t0); - } - - /* GETTSD has as meaningless `CS0.param' as RETURN. The only - difference is that its `CS0.param.type' should be equal to `1'. I - wonder if I should check for that and output something like - "invalid gettsd" if this turns out not to be the case . . . */ - if (type == GETTSD) { - // TODO: gettsd - e2k_todo_illop(dc, "gettsd"); - } - - if (type == PUTTSD) { -// unsigned int disp = (cs0 & 0x0fffffff); -// int sgnd_disp = ((int) (disp << 4)) >> 1; - /* PUTTSD obviously doesn't take %ctpr{j} parameter. TODO: beware of - an optional predicate which may control its execution which is - encoded via `SS.ctcond.psrc' and `SS.ts_opc == PUTTSDC{P,N}' in - case of `SS.type == 1' (see C.21.4). I wonder if `ct %ctpr' - encoded in `SS.ctop' under the same `SS.ctcond' takes an effect in - such a case. */ -// my_printf ("%s0x%llx", type == PUTTSD ? "" : ", ", - /* FIXME: this way I ensure that it'll work correctly - both on 32 and 64-bit hosts. */ -// (unsigned long long) (instr_addr + sgnd_disp)); - // TODO: puttsd - e2k_todo_illop(dc, "puttsd"); - } - - if (type == PREF) { -// unsigned int pdisp = (bundle->cs0 & 0x0ffffff0) >> 4; -// unsigned int ipd = (bundle->cs0 & 0x00000008) >> 3; -// unsigned int prefr = bundle->cs0 & 0x00000007; - // TODO: pref - e2k_todo_illop(dc, "pref"); - } - } -} - -static void gen_cs1(DisasContext *dc) -{ - enum { - SETR0, - SETR1, - SETEI, - WAIT, - SETBR, - CALL, - MAS_OPC, - FLUSHR, - BG - }; - - const UnpackedBundle *bundle = &dc->bundle; - unsigned int cs1 = bundle->cs1; - unsigned int opc = (cs1 & 0xf0000000) >> 28; - - if (opc == SETEI) { - bool sft = GET_BIT(cs1, 27); - - if (sft) { - if (dc->version >= 2) { - // TODO: setsft - e2k_todo_illop(dc, "setsft"); - } else { - e2k_tr_gen_exception(dc, E2K_EXCP_ILLOPC); - } - } else { -// uint8_t eir = GET_FIELD_LEN(cs1, 0, 8); - // TODO: setei - e2k_todo_illop(dc, "setei"); - } - } else if (opc == WAIT) { -// unsigned int ma_c = (cs1 & 0x00000020) >> 5; -// unsigned int fl_c = (cs1 & 0x00000010) >> 4; - unsigned int ld_c = (cs1 & 0x00000008) >> 3; - unsigned int st_c = (cs1 & 0x00000004) >> 2; -// unsigned int all_e = (cs1 & 0x00000002) >> 1; -// unsigned int all_c = cs1 & 0x00000001; - - if (dc->version >= 5) { - /* `sa{l,s}' fields are `elbrus-v5'-specific. Each of them makes sense - only in the presence of `{ld,st}_c == 1' respectively. */ - if (ld_c) { -// unsigned int sal = (cs1 & 0x00000100) >> 8; -// my_printf ("sal = %d, ", sal); - } - - if (st_c) { -// unsigned int sas = (cs1 & 0x00000080) >> 7; -// my_printf ("sas = %d, ", sas); - } - } - - if (dc->version >= 2) { - /* `trap' field was introduced starting from `elbrus-v2'. */ -// unsigned int trap = (cs1 & 0x00000040) >> 6; -// my_printf ("trap = %d, ", trap); - } - // TODO: wait - e2k_todo(dc, "wait"); -// my_printf ("ma_c = %d, fl_c = %d, ld_c = %d, st_c = %d, all_e = %d, " -// "all_c = %d", ma_c, fl_c, ld_c, st_c, all_e, all_c); - } else if (opc == CALL) { - unsigned int ctop = (bundle->ss & 0x00000c00) >> 10; - if (ctop) { - dc->ct.type = CT_CALL; - dc->ct.wbs = extract32(cs1, 0, 7); - } else { - unsigned int cs1_ctopc = (cs1 & 0x380) >> 7; - /* CS1.param.ctpopc == HCALL. CS0 is required to encode HCALL. */ - if (cs1_ctopc == 2 && bundle->cs0_present) - { - unsigned int cs0 = bundle->cs0; - unsigned int cs0_opc = (cs0 & 0xf0000000) >> 28; - if (cs0_opc == 0) { -// unsigned int hdisp = (cs0 & 0x1e) >> 1; - // TODO: hcall hdisp, wbs ? cond - e2k_todo_illop(dc, "hcall"); - } - } else { - e2k_tr_gen_exception(dc, E2K_EXCP_ILLOPC); - } - } - } else if (opc == MAS_OPC) { - dc->mas[0] = extract32(cs1, 21, 7); - dc->mas[2] = extract32(cs1, 14, 7); - dc->mas[3] = extract32(cs1, 7, 7); - dc->mas[5] = extract32(cs1, 0, 7); - } else if (opc == FLUSHR) { - if (cs1 & 0x00000001) { - // TODO: flushr - e2k_todo_illop(dc, "flushr"); - } - - if (cs1 & 0x00000002) { - // TODO: flushc - e2k_todo_illop(dc, "flushc"); - } - } else if (opc == BG) { -// unsigned int chkm4 = (cs1 & 0x00010000) >> 16; -// unsigned int dmask = (cs1 & 0x0000ff00) >> 8; -// unsigned int umsk = cs1 & 0x000000ff; - - // TODO: vfbg - e2k_todo_illop(dc, "vfbg"); - } -} - -void e2k_decode_jmp(DisasContext *ctx) -{ - int cond_type = extract32(ctx->bundle.ss, 5, 4); - int ctpr = extract32(ctx->bundle.ss, 10, 2); - - if (ctpr != 0) { - if (ctx->ct.type == CT_NONE) { - ctx->ct.type = CT_JUMP; - } - ctx->ct.u.ctpr = e2k_cs.ctprs[ctpr - 1]; - } - - ctx->ct.is_branch = cond_type > 1; - if (cond_type == 1) { - tcg_gen_movi_i32(e2k_cs.ct_cond, 1); - } else if (cond_type > 1) { - uint8_t psrc = extract32(ctx->bundle.ss, 0, 5); - TCGv_i32 pcond = tcg_temp_local_new_i32(); - TCGv_i32 lcond = tcg_temp_local_new_i32(); - - switch (cond_type) { - case 0x2: - case 0x6: - case 0xf: - /* %predN */ - e2k_gen_preg_i32(pcond, psrc); - break; - case 0x3: - case 0x7: - case 0xe: { - TCGv_i32 t0 = tcg_temp_new_i32(); - e2k_gen_preg_i32(t0, psrc); - tcg_gen_setcondi_i32(TCG_COND_EQ, pcond, t0, 0); - tcg_temp_free_i32(t0); - break; - } - default: - break; - } - - switch (cond_type) { - case 0x4: - case 0x6: - case 0xe: - /* #LOOP_END */ - e2k_gen_is_loop_end_i32(lcond); - break; - case 0x5: - case 0x7: - case 0xf: { /* #NOT_LOOP_END */ - TCGv_i32 t0 = tcg_temp_new_i32(); - e2k_gen_is_loop_end_i32(t0); - tcg_gen_setcondi_i32(TCG_COND_EQ, lcond, t0, 0); - tcg_temp_free_i32(t0); - break; - } - } - - switch (cond_type) { - case 0x2: - case 0x3: - /* {,~}%predN */ - tcg_gen_mov_i32(e2k_cs.ct_cond, pcond); - break; - case 0x4: - case 0x5: - /* #{,NOT_}LOOP_END */ - tcg_gen_mov_i32(e2k_cs.ct_cond, lcond); - break; - case 0x6: - case 0xe: { - /* {,~}%predN || #LOOP_END */ - TCGv_i32 z = tcg_const_i32(0); - TCGv_i32 t0 = tcg_temp_new_i32(); - - tcg_gen_or_i32(t0, pcond, lcond); - tcg_gen_movcond_i32(TCG_COND_EQ, e2k_cs.ct_cond, - ctx->is_prologue, z, t0, lcond); - tcg_temp_free_i32(t0); - tcg_temp_free_i32(z); - break; - } - case 0x7: - case 0xf: { - /* {,~}%predN && #NOT_LOOP_END */ - TCGv_i32 z = tcg_const_i32(0); - TCGv_i32 t0 = tcg_temp_new_i32(); - - tcg_gen_and_i32(t0, pcond, lcond); - tcg_gen_movcond_i32(TCG_COND_EQ, e2k_cs.ct_cond, - ctx->is_prologue, z, t0, lcond); - tcg_temp_free_i32(t0); - tcg_temp_free_i32(z); - break; - } - case 0x8: - /* %MLOCK || %dt_alM */ - if (psrc & 0xf) { - // static const int conv[] = {0, 1, 3, 4}; - int i; - - e2k_todo(ctx, "%%MLOCK || %%dt_alM"); - // %dt_al - for (i = 0; i < 4; i++) { - if (psrc & (1 << i)) { - // i - } - } - } else { - /* %MLOCK */ - if (ctx->mlock) { - tcg_gen_mov_i32(e2k_cs.ct_cond, ctx->mlock); - } else { - tcg_gen_movi_i32(e2k_cs.ct_cond, 0); - } - } - break; - case 0x9: { - /* `lock_cond || pl_cond' control transfer conditions. */ - unsigned int type = (psrc & 0x18) >> 3; - if (type == 0) { -// static const int cmp_num_to_alc[] = {0, 1, 3, 4}; -// unsigned int cmp_num = (psrc & 0x6) >> 1; -// unsigned int neg = psrc & 0x1; -// -// my_printf ("%%MLOCK || %s%%cmp%d", neg ? "~" : "", -// cmp_num_to_alc[cmp_num]); - e2k_todo(ctx, "%%MLOCK || %%cmpN"); - } else if (type == 1) { -// unsigned int cmp_jk = (psrc & 0x4) >> 2; -// unsigned int negj = (psrc & 0x2) >> 1; -// unsigned int negk = psrc & 0x1; - -// my_printf ("%%MLOCK || %s%%cmp%d || %s%%cmp%d", -// negj ? "~" : "", cmp_jk == 0 ? 0 : 3, -// negk ? "~" : "", cmp_jk == 0 ? 1 : 4); - e2k_todo(ctx, "%%MLOCK || %%cmpN || %%cmpM"); - } else if (type == 2) { -// unsigned int clp_num = (psrc & 0x6) >> 1; -// unsigned int neg = psrc & 0x1; - - // "%%MLOCK || %s%%clp%d", neg ? "~" : "", clp_num - e2k_todo(ctx, "%%MLOCK || %%clpN"); - } - break; - } - default: - e2k_todo_illop(ctx, "undefined control transfer type %#x", cond_type); - break; - } - - tcg_temp_free_i32(lcond); - tcg_temp_free_i32(pcond); - } -} - -void e2k_control_window_change(DisasContext *dc) -{ - enum { - SETR0, - SETR1, - SETEI, - WAIT, - SETBR, - CALL, - MAS_OPC, - FLUSHR, - BG - }; - - const UnpackedBundle *bundle = &dc->bundle; - uint32_t cs1 = bundle->cs1; - int opc = extract32(cs1, 28, 4); - - if (!dc->bundle.cs1_present) { - return; - } - - if (opc == SETR0 || opc == SETR1 || opc == SETBR) { - bool setbp = (cs1 >> 27) & 1; - bool setbn = (cs1 >> 26) & 1; - - if (opc == SETR1) { - if (!bundle->lts_present[0]) { - e2k_tr_gen_exception(dc, E2K_EXCP_ILLOPC); - } else { - /* Find out if VFRPSZ is always encoded together with SETWD. This - seems to be the case even if no SETWD has been explicitly - specified. */ -// unsigned int rpsz = (bundle->lts[0] & 0x0001f000) >> 12; - e2k_todo(dc, "vfrpsz"); - } - } - - if (opc == SETR0 || opc == SETR1) { - if (!bundle->lts_present[0]) { - e2k_tr_gen_exception(dc, E2K_EXCP_ILLOPC); - } else { - TCGv_i32 lts = tcg_const_i32(bundle->lts[0]); - - gen_helper_setwd(cpu_env, lts); - tcg_temp_free_i32(lts); - } - } - - if (setbn) { - int rbs = extract32(cs1, BR_RBS_OFF, BR_RBS_LEN); - int rsz = extract32(cs1, BR_RSZ_OFF, BR_RSZ_LEN); - int rcur = extract32(cs1, BR_RCUR_OFF, BR_RCUR_LEN); - - tcg_gen_movi_i32(e2k_cs.boff, rbs * 2); - tcg_gen_movi_i32(e2k_cs.bsize, (rsz + 1) * 2); - tcg_gen_movi_i32(e2k_cs.bcur, rcur * 2); - } - - if (setbp) { - int psz = extract32(cs1, BR_PSZ_OFF, BR_PSZ_LEN); - - tcg_gen_movi_i32(e2k_cs.psize, psz); - tcg_gen_movi_i32(e2k_cs.pcur, 0); - } - } -} - -static void gen_prologue_epilogue(DisasContext *ctx) -{ - TCGv_i32 t0 = tcg_temp_new_i32(); - - ctx->is_prologue = e2k_get_temp_i32(ctx); - e2k_gen_pcnt_i32(t0); - tcg_gen_setcondi_i32(TCG_COND_NE, ctx->is_prologue, t0, 0); - - ctx->is_epilogue = e2k_get_temp_i32(ctx); - e2k_gen_lcnt_i32(t0); - tcg_gen_setcondi_i32(TCG_COND_EQ, ctx->is_epilogue, t0, 0); - - tcg_temp_free_i32(t0); -} - -void e2k_control_execute(DisasContext *ctx) -{ - ctx->ct.type = CT_NONE; - ctx->loop_mode = (ctx->bundle.hs & (1 << 10)) != 0; - - gen_prologue_epilogue(ctx); - - if (ctx->bundle.cs0_present) { - gen_cs0(ctx); - } - - if (ctx->bundle.cs1_present) { - gen_cs1(ctx); - } -} diff --git a/target/e2k/translate/plu.c b/target/e2k/translate/plu.c index ed6fcfa2e7..ef39a3b459 100644 --- a/target/e2k/translate/plu.c +++ b/target/e2k/translate/plu.c @@ -15,13 +15,11 @@ void e2k_gen_cond_i32(DisasContext *ctx, TCGv_i32 ret, uint8_t psrc) { if (psrc & 0x80) { if (psrc == 0xc0) { - // TODO: %bgrpred - qemu_log_mask(LOG_UNIMP, "%#lx: %%bgrpred is not implemented!\n", ctx->pc); - abort(); + // %bgrpred + e2k_todo_illop(ctx, "%%bgrpred"); } else if ((psrc & 0xe0) == 0xc0) { - // TODO: %rndpredN - qemu_log_mask(LOG_UNIMP, "%#lx: %%rndpred is not implemented!\n", ctx->pc); - abort(); + // %rndpred + e2k_todo_illop(ctx, "%%rndpred"); } else { e2k_tr_gen_exception(ctx, E2K_EXCP_ILLOPN); } @@ -31,19 +29,14 @@ void e2k_gen_cond_i32(DisasContext *ctx, TCGv_i32 ret, uint8_t psrc) // %lcntex e2k_gen_lcntex(ret); } else if ((psrc & 0x40) == 0) { - // TODO: %spredMASK - qemu_log_mask(LOG_UNIMP, "%#lx: %%spred is not implemented!\n", ctx->pc); - abort(); + // %spredMASK + e2k_todo_illop(ctx, "%%spred"); } else if ((psrc & 0x60) == 0x60) { // %predN e2k_gen_preg_i32(ret, idx); } else { // %pcntN - TCGv_i32 t0 = tcg_temp_new_i32(); - - e2k_gen_pcnt_i32(t0); - tcg_gen_setcondi_i32(TCG_COND_LEU, ret, t0, idx); - tcg_temp_free_i32(t0); + tcg_gen_setcondi_i32(TCG_COND_LEU, ret, e2k_cs.lsr_pcnt, idx); } } } @@ -163,18 +156,15 @@ void e2k_plu_execute(DisasContext *ctx) tcg_gen_and_i32(lp[4 + i], p0, p1); if (vdst) { - TCGv_i32 one = tcg_const_i32(1); - TCGv_i64 t0 = tcg_temp_new_i64(); - TCGv_i32 t1 = tcg_temp_new_i32(); + TCGv_i32 z = tcg_const_i32(0); + TCGv_i32 t0 = tcg_temp_new_i32(); - e2k_gen_preg_i64(t0, pdst); - tcg_gen_extrl_i64_i32(t1, t0); - tcg_gen_movcond_i32(TCG_COND_EQ, ctx->pl_results[i].value, - p0, one, p1, t1); + e2k_gen_preg_i32(t0, pdst); + tcg_gen_movcond_i32(TCG_COND_NE, ctx->pl_results[i].value, + p0, z, p1, t0); - tcg_temp_free_i32(t1); - tcg_temp_free_i64(t0); - tcg_temp_free_i32(one); + tcg_temp_free_i32(t0); + tcg_temp_free_i32(z); } break; } diff --git a/target/e2k/translate/state.c b/target/e2k/translate/state.c index 9011a9d921..5387b41dd0 100644 --- a/target/e2k/translate/state.c +++ b/target/e2k/translate/state.c @@ -68,7 +68,7 @@ static void gen_preg_clear(TCGv_i64 ret, TCGv_i64 offset) tcg_temp_free_i64(t0); } -void e2k_gen_preg_i64(TCGv_i64 ret, int reg) +static inline void gen_preg_i64(TCGv_i64 ret, int reg) { TCGv_i64 one = tcg_const_i64(1); TCGv_i64 t0 = tcg_temp_new_i64(); @@ -90,18 +90,11 @@ void e2k_gen_preg_i32(TCGv_i32 ret, int reg) { TCGv_i64 t0 = tcg_temp_new_i64(); - e2k_gen_preg_i64(t0, reg); + gen_preg_i64(t0, reg); tcg_gen_extrl_i64_i32(ret, t0); tcg_temp_free_i64(t0); } -TCGv_i64 e2k_get_preg(DisasContext *dc, int reg) -{ - TCGv_i64 ret = e2k_get_temp_i64(dc); - e2k_gen_preg_i64(ret, reg); - return ret; -} - void e2k_gen_store_preg(int idx, TCGv_i32 val) { TCGv_i64 t0 = tcg_temp_new_i64();