diff --git a/linux-user/e2k/cpu_loop.c b/linux-user/e2k/cpu_loop.c index 648547b460..4d435ef49e 100644 --- a/linux-user/e2k/cpu_loop.c +++ b/linux-user/e2k/cpu_loop.c @@ -57,6 +57,7 @@ void cpu_loop(CPUE2KState *env) ); if (ret == -TARGET_ERESTARTSYS) { /* TODO: restart syscall */ + abort(); } else if (ret != -TARGET_QEMU_ESIGRETURN) { unsigned int i; @@ -65,6 +66,7 @@ void cpu_loop(CPUE2KState *env) regs[(i + offset) % WREGS_SIZE] = 0; } } + env->ip = env->nip; break; } default: diff --git a/target/e2k/cpu.c b/target/e2k/cpu.c index a6c42eff2d..2e052e6cac 100644 --- a/target/e2k/cpu.c +++ b/target/e2k/cpu.c @@ -73,6 +73,14 @@ static const struct e2k_def_t e2k_defs[] = { } }; +static inline void cpu_dump_state_wd(CPUE2KState *env, FILE *f, int flags) +{ + int wbs = GET_FIELD(env->cr1_lo, CR1_LO_WBS_OFF, CR1_LO_WBS_END); + int wsz = GET_FIELD(env->cr1_lo, CR1_LO_WPSZ_OFF, CR1_LO_WPSZ_END); + + qemu_fprintf(f, "wbs = %#x, wsz = %#x\n", wbs, wsz); +} + static inline void cpu_dump_state_br(CPUE2KState *env, FILE *f, int flags) { uint32_t br = GET_FIELD(env->cr1_hi, CR1_HI_BR_OFF, CR1_HI_BR_END); @@ -106,7 +114,7 @@ void e2k_cpu_dump_state(CPUState *cs, FILE *f, int flags) env->cr1_hi, env->cr1_lo); qemu_fprintf(f, "usd_hi: %016lx, usd_lo: %016lx\n", env->usd_hi, env->usd_lo); -/* TODO qemu_fprintf(f, "wbs: %d, wsz: %d\n", (int) env->wbs, (int) env->wsz); */ + cpu_dump_state_wd(env, f, flags); cpu_dump_state_br(env, f, flags); qemu_fprintf(f, "lsr: %016lx\n", env->lsr); diff --git a/target/e2k/cpu.h b/target/e2k/cpu.h index 4d49a20d95..e525ea95d0 100644 --- a/target/e2k/cpu.h +++ b/target/e2k/cpu.h @@ -70,7 +70,34 @@ void e2k_tcg_initialize(void); #define PSP_LO_WRITE_OFF 60 #define PSP_LO_WRITE_BIT (1UL << PSP_LO_WRITE_OFF) -#define PSHTP +#define PSHTP_IND_OFF 0 +#define PSHTP_IND_END 11 +#define PSHTP_IND_LEN (PSHTP_IND_END - PSHTP_IND_OFF + 1) +#define PSHTP_FXIND_OFF 16 +#define PSHTP_FXIND_END 26 +#define PSHTP_FXIND_LEN (PSHTP_FXIND_END - PSHTP_FXIND_OFF + 1) +#define PSHTP_TIND_OFF 32 +#define PSHTP_TIND_END 42 +#define PSHTP_TIND_LEN (PSHTP_TIND_END - PSHTP_TIND_OFF + 1) +#define PSHTP_FX_OFF 48 +#define PSHTP_FX_BIT (1UL << PSHTP_FX_OFF) + +#define USD_LO_BASE_OFF 0 +#define USD_LO_BASE_END 47 +#define USD_LO_BASE_LEN (USD_LO_BASE_END - USD_LO_BASE_OFF + 1) +#define USD_LO_PROTECTED_OFF 58 +#define USD_LO_PROTECTED_BIT (1UL << USD_LO_PROTECTED_OFF) +#define USD_LO_READ_OFF 59 +#define USD_LO_READ_BIT (1UL << USD_LO_READ_OFF) +#define USD_LO_WRITE_OFF 60 +#define USD_LO_WRITE_BIT (1UL << USD_LO_WRITE_OFF) + +#define USD_HI_CURPTR_OFF 0 +#define USD_HI_CURPTR_END 31 +#define USD_HI_CURPTR_LEN (USD_HI_CURPTR_END - USD_HI_CURPTR_OFF + 1) +#define USD_HI_SIZE_OFF 32 +#define USD_HI_SIZE_END 63 +#define USD_HI_SIZE_LEN (USD_HI_SIZE_END - USD_HI_SIZE_OFF + 1) #define CR1_HI_BR_OFF 0 #define CR1_HI_BR_END 27 @@ -180,6 +207,13 @@ typedef struct CPUArchState { uint64_t lsr; /* loop status register */ uint32_t call_wbs; + uint32_t woff; /* holds wbs * 2 */ + uint32_t wsize; /* holds wsz * 2 */ + uint32_t boff; /* holds rbs * 2 */ + uint32_t bsize; /* holds rsz * 2 + 2 */ + uint32_t bcur; /* holds rcur * 2 */ + uint32_t psize; /* holds psz */ + uint32_t pcur; /* holds pcur */ uint64_t usd_lo; uint64_t usd_hi; @@ -191,6 +225,8 @@ typedef struct CPUArchState { target_ulong ip; /* instruction address */ target_ulong nip; /* next instruction address */ + uint32_t cond; /* branch condition */ + uint32_t pfpfr; // Packed Floating Point Flag Register (PFPFR) uint32_t fpcr; // Floating point control register (FPCR) uint32_t fpsr; // Floating point state register (FPSR) @@ -274,6 +310,21 @@ static inline void e2k_state_pcs_size_set(CPUE2KState *env, size_t size) PCSP_HI_SIZE_LEN); } +static inline target_ulong e2k_state_ps_base_get(CPUE2KState *env) +{ + return GET_FIELD(env->psp_lo, PSP_LO_BASE_OFF, PSP_LO_BASE_END); +} + +static inline size_t e2k_state_ps_ind_get(CPUE2KState *env) +{ + return GET_FIELD(env->psp_hi, PSP_HI_IND_OFF, PSP_HI_IND_LEN); +} + +static inline void e2k_state_ps_ind_set(CPUE2KState *env, size_t ind) +{ + env->psp_hi = SET_FIELD(env->psp_hi, ind, PSP_HI_IND_OFF, PSP_HI_IND_LEN); +} + static inline int e2k_state_wbs_get(CPUE2KState *env) { return GET_FIELD(env->cr1_lo, CR1_LO_WBS_OFF, CR1_LO_WBS_END); diff --git a/target/e2k/helper.c b/target/e2k/helper.c index ada999d347..6913a16e8e 100644 --- a/target/e2k/helper.c +++ b/target/e2k/helper.c @@ -6,10 +6,52 @@ #include "exec/helper-proto.h" #include "translate.h" +static inline void save_state(CPUE2KState *env) +{ + uint32_t br = 0; + + br = SET_FIELD(br, env->boff / 2, BR_RBS_OFF, BR_RBS_LEN); + br = SET_FIELD(br, (env->bsize - 2) / 2, BR_RSZ_OFF, BR_RSZ_LEN); + br = SET_FIELD(br, env->bcur / 2, BR_RCUR_OFF, BR_RCUR_LEN); + br = SET_FIELD(br, env->psize, BR_PSZ_OFF, BR_PSZ_LEN); + br = SET_FIELD(br, env->pcur, BR_PCUR_OFF, BR_PCUR_LEN); + + env->cr1_hi = SET_FIELD(env->cr1_hi, br, CR1_HI_BR_OFF + BR_BN_OFF, + BR_BN_LEN); + + env->cr1_lo = SET_FIELD(env->cr1_lo, env->wsize / 2, + CR1_LO_WPSZ_OFF, CR1_LO_WPSZ_LEN); +} + +static inline void restore_state(CPUE2KState *env) +{ + uint32_t br; + int rbs, rsz, rcur, psz, pcur, wsz, wbs; + + br = GET_FIELD(env->cr1_hi, CR1_HI_BR_OFF, CR1_HI_BR_LEN); + rbs = GET_FIELD(br, BR_RBS_OFF, BR_RBS_END); + rsz = GET_FIELD(br, BR_RSZ_OFF, BR_RSZ_END); + rcur = GET_FIELD(br, BR_RCUR_OFF, BR_RCUR_END); + psz = GET_FIELD(br, BR_PSZ_OFF, BR_PSZ_END); + pcur = GET_FIELD(br, BR_PCUR_OFF, BR_PCUR_END); + + wbs = GET_FIELD(env->cr1_lo, CR1_LO_WBS_OFF, CR1_LO_WBS_END); + wsz = GET_FIELD(env->cr1_lo, CR1_LO_WPSZ_OFF, CR1_LO_WPSZ_END); + + env->boff = rbs * 2; + env->bsize = rsz * 2 + 2; + env->bcur = rcur * 2; + env->psize = psz; + env->pcur = pcur; + + env->woff = wbs * 2; + env->wsize = wsz * 2; +} + void helper_raise_exception(CPUE2KState *env, int tt) { CPUState *cs = env_cpu(env); - + save_state(env); cs->exception_index = tt; cpu_loop_exit(cs); } @@ -33,10 +75,11 @@ static void pcs_push(CPUE2KState *env) e2k_state_pcs_index_set(env, offset + 32); } -static void pcs_pop(CPUE2KState *env) +static uint64_t pcs_pop(CPUE2KState *env) { size_t offset = e2k_state_pcs_index_get(env); uint64_t *pcsp = (uint64_t *) (e2k_state_pcs_base_get(env) + offset - 32); + uint64_t tgt; if (offset < 32) { /* TODO: SIGKILL */ @@ -44,11 +87,47 @@ static void pcs_pop(CPUE2KState *env) } memcpy(&env->pf, pcsp, 8); - memcpy(&env->ip, pcsp + 1, 8); + memcpy(&tgt, pcsp + 1, 8); memcpy(&env->cr1_lo, pcsp + 2, 8); memcpy(&env->cr1_hi, pcsp + 3, 8); e2k_state_pcs_index_set(env, offset - 32); + + return tgt; +} + +static void ps_push(CPUE2KState *env, unsigned int wbs, size_t len) +{ + unsigned int i; + size_t index = e2k_state_ps_ind_get(env); + uint64_t *p = (uint64_t*) (e2k_state_ps_base_get(env) + index); + + /* TODO: push FX registers */ + /* TODO: stack overflow */ + + for (i = 0; i < len; i++) { + uint64_t reg = env->wregs[(wbs + i) % WREGS_SIZE]; + memcpy(p + i, ®, sizeof(uint64_t)); + } + + e2k_state_ps_ind_set(env, index + len * sizeof(uint64_t)); +} + +static void ps_pop(CPUE2KState *env, unsigned int wbs, size_t len) +{ + unsigned int i; + size_t index = e2k_state_ps_ind_get(env) - len * sizeof(uint64_t); + uint64_t *p = (uint64_t*) (e2k_state_ps_base_get(env) + index); + + /* TODO: pop FX registers */ + /* TODO: stack overflow */ + + for (i = 0; i < len; i++) { + uint64_t *reg = &env->wregs[(wbs + i) % WREGS_SIZE]; + memcpy(reg, p + i, sizeof(uint64_t)); + } + + e2k_state_ps_ind_set(env, index); } static inline void do_call(CPUE2KState *env, target_ulong ctpr) @@ -57,7 +136,7 @@ static inline void do_call(CPUE2KState *env, target_ulong ctpr) wbs = e2k_state_wbs_get(env); wsz = e2k_state_wsz_get(env); - new_wbs = (wbs + env->call_wbs) % WREGS_SIZE; + new_wbs = (wbs + env->call_wbs) % (WREGS_SIZE / 2); new_wsz = wsz - env->call_wbs; if (new_wsz < 0) { @@ -67,104 +146,101 @@ static inline void do_call(CPUE2KState *env, target_ulong ctpr) /* save procedure chain info */ pcs_push(env); + /* save regs */ + ps_push(env, wbs * 2, env->call_wbs * 2); e2k_state_wbs_set(env, new_wbs); e2k_state_wsz_set(env, new_wsz); - env->ip = GET_FIELD(ctpr, CTPR_BASE_OFF, CTPR_BASE_END); + /* restore woff, wsize, etc */ + restore_state(env); } -static void do_return(CPUE2KState *env) +static uint64_t do_return(CPUE2KState *env) { -// uint64_t *psp = (uint64_t *) GET_FIELD(env->psp_lo, PSP_LO_BASE_OFF, -// PSP_LO_BASE_END); + int new_wbs, old_wbs; + uint64_t tgt; + + old_wbs = e2k_state_wbs_get(env) * 2; /* restore procedure chain info */ - pcs_pop(env); + tgt = pcs_pop(env); - // TODO: restore regs + new_wbs = e2k_state_wbs_get(env) * 2; + + if (old_wbs < new_wbs) { + old_wbs += WREGS_SIZE; + } + + ps_pop(env, new_wbs, old_wbs - new_wbs); + + /* restore woff, wsize, etc */ + restore_state(env); + + return tgt; } -void helper_call(CPUE2KState *env, target_ulong cond, target_ulong ctpr) +static inline void reset_ctprs(CPUE2KState *env) { - unsigned int i = 0; - - if (!cond) { - env->ip = env->nip; - return; - } + unsigned int i; for (i = 0; i < 4; i++) { env->ctprs[i] = 0; } +} - switch (GET_FIELD(ctpr, CTPR_TAG_OFF, CTPR_TAG_END)) { +target_ulong helper_jump(CPUE2KState *env, int i) +{ + return helper_branch(env, i, true); +} + +target_ulong helper_branch(CPUE2KState *env, int i, target_ulong cond) +{ + CPUState *cs = env_cpu(env); + uint64_t ctpr = env->ctprs[i]; + target_ulong tgt = 0; + int ctpr_tag = GET_FIELD(ctpr, CTPR_TAG_OFF, CTPR_TAG_END); + + save_state(env); + + switch (ctpr_tag) { + case CTPR_TAG_RETURN: + if (cond) { + tgt = do_return(env); + reset_ctprs(env); + } + break; + case CTPR_TAG_DISP: { + /* TODO: ldisp */ + + if (env->call_wbs != 0 && cond) { + do_call(env, ctpr); + reset_ctprs(env); + } + tgt = GET_FIELD(ctpr, CTPR_BASE_OFF, CTPR_BASE_END); + break; + } case CTPR_TAG_SDISP: { - CPUState *cs = env_cpu(env); - - env->ip = env->nip; - cs->exception_index = E2K_EXCP_SYSCALL; + if (cond) { + if (env->call_wbs != 0) { + reset_ctprs(env); + cs->exception_index = E2K_EXCP_SYSCALL; + cpu_loop_exit(cs); + } else { + cs->exception_index = E2K_EXCP_UNIMPL; + cpu_loop_exit(cs); + } + } + break; + } + default: { + cs->exception_index = E2K_EXCP_UNIMPL; cpu_loop_exit(cs); break; } - case CTPR_TAG_DISP: { - do_call(env, ctpr); - break; - } - default: - /* TODO: exception */ - abort(); - break; - } -} - -/* FIXME: combine with helper_call? */ -void helper_jump(CPUE2KState *env, target_ulong cond, target_ulong ctpr) -{ - if (!cond) { - env->ip = env->nip; - return; } - switch (GET_FIELD(ctpr, CTPR_TAG_OFF, CTPR_TAG_END)) { - case CTPR_TAG_DISP: { - env->ip = GET_FIELD(ctpr, CTPR_BASE_OFF, CTPR_BASE_END); - break; - } - case CTPR_TAG_RETURN: - do_return(env); - break; - default: - /* TODO: exception */ - abort(); - break; - } -} - -void helper_setwd(CPUE2KState *env, uint32_t lts0) -{ - int wsz = GET_FIELD(lts0, 5, 11); - /* TODO: store nfx */ -// int nfx = GET_BIT(lts0, 4); - - /* TODO: push wregs */ - - e2k_state_wsz_set(env, wsz); - - if (env->version >= 3) { -// int dbl = GET_BIT(lts0, 3); - /* TODO: store dbl */ - } -} - -void helper_setbn(CPUE2KState *env, uint32_t cs1) -{ - env->cr1_hi = SET_FIELD( - env->cr1_hi, - GET_FIELD(cs1, 0, 17), - CR1_HI_BR_OFF + BR_BN_OFF, - BR_BN_LEN - ); + return tgt; } uint64_t helper_sxt(uint64_t x, uint64_t y) @@ -240,34 +316,14 @@ void helper_state_reg_set(CPUE2KState *env, int reg, uint64_t val) } } -void helper_save_rcur(CPUE2KState *env, int rcur) -{ - env->cr1_hi = SET_FIELD( - env->cr1_hi, - rcur / 2, - CR1_HI_BR_OFF + BR_RCUR_OFF, - BR_RCUR_LEN - ); -} - -void helper_save_pcur(CPUE2KState *env, int pcur) -{ - env->cr1_hi = SET_FIELD( - env->cr1_hi, - pcur, - CR1_HI_BR_OFF + BR_PCUR_OFF, - BR_PCUR_LEN - ); -} - uint64_t helper_getsp(CPUE2KState *env, uint64_t src2) { - uint64_t base = GET_FIELD(env->psp_lo, PSP_LO_BASE_OFF, PSP_LO_BASE_END); + uint64_t base = GET_FIELD(env->usd_lo, USD_LO_BASE_OFF, USD_LO_BASE_END); base += src2; /* TODO: stack overflow */ - env->psp_lo = SET_FIELD(env->psp_lo, base, PSP_LO_BASE_OFF, - PSP_LO_BASE_LEN); + env->usd_lo = SET_FIELD(env->usd_lo, base, USD_LO_BASE_OFF, + USD_LO_BASE_LEN); return base; } diff --git a/target/e2k/helper.h b/target/e2k/helper.h index 0bd8d00227..de77bce0d2 100644 --- a/target/e2k/helper.h +++ b/target/e2k/helper.h @@ -1,13 +1,9 @@ DEF_HELPER_2(raise_exception, noreturn, env, int) -DEF_HELPER_3(call, void, env, tl, tl) -DEF_HELPER_3(jump, void, env, tl, tl) +DEF_HELPER_2(jump, tl, env, int) +DEF_HELPER_3(branch, tl, env, int, tl) DEF_HELPER_2(sxt, i64, i64, i64) DEF_HELPER_1(debug_i32, void, i32) DEF_HELPER_1(debug_i64, void, i64) -DEF_HELPER_2(setwd, void, env, i32) -DEF_HELPER_2(setbn, void, env, i32) DEF_HELPER_2(state_reg_get, i64, env, int) DEF_HELPER_3(state_reg_set, void, env, int, i64) -DEF_HELPER_2(save_rcur, void, env, int) -DEF_HELPER_2(save_pcur, void, env, int) DEF_HELPER_2(getsp, i64, env, i64) /* FIXME: return tl? */ diff --git a/target/e2k/translate.c b/target/e2k/translate.c index 7e917f793a..9cdca525c2 100644 --- a/target/e2k/translate.c +++ b/target/e2k/translate.c @@ -190,8 +190,6 @@ static inline void save_state(DisasContext *dc) { tcg_gen_movi_tl(e2k_cs.pc, dc->pc); tcg_gen_movi_tl(e2k_cs.npc, dc->npc); - gen_helper_save_rcur(cpu_env, e2k_cs.bcur); - gen_helper_save_pcur(cpu_env, e2k_cs.pcur); } void e2k_gen_exception(DisasContext *dc, int which) @@ -282,7 +280,8 @@ static void e2k_tr_init_disas_context(DisasContextBase *db, CPUState *cs) E2KCPU *cpu = E2K_CPU(cs); CPUE2KState *env = &cpu->env; - dc->pc = dc->base.pc_first; + dc->pc = 0; + dc->npc = dc->base.pc_first; dc->version = env->version; } @@ -306,11 +305,12 @@ static void e2k_tr_translate_insn(DisasContextBase *db, CPUState *cs) E2KCPU *cpu = E2K_CPU(cs); CPUE2KState *env = &cpu->env; UnpackedBundle *bundle = &dc->bundle; + unsigned int bundle_len; - dc->pc = dc->base.pc_next; - unsigned int bundle_len = unpack_bundle(env, dc->pc, bundle); + dc->pc = dc->npc; + bundle_len = unpack_bundle(env, dc->pc, bundle); /* TODO: exception, check bundle_len */ - dc->base.pc_next = dc->npc = dc->pc + bundle_len; + dc->npc = dc->base.pc_next = dc->pc + bundle_len; e2k_alc_gen(dc); e2k_control_gen(dc); @@ -334,31 +334,8 @@ static void e2k_tr_translate_insn(DisasContextBase *db, CPUState *cs) static void e2k_tr_tb_start(DisasContextBase *db, CPUState *cs) { - DisasContext *dc = container_of(db, DisasContext, base); - E2KCPU *cpu = E2K_CPU(cs); - CPUE2KState *env = &cpu->env; - uint32_t br; - int wbs, wsz, rbs, rsz, rcur, psz, pcur; - - wbs = e2k_state_wbs_get(env); - wsz = e2k_state_wsz_get(env); - br = GET_FIELD(env->cr1_hi, CR1_HI_BR_OFF, CR1_HI_BR_END); - rbs = GET_FIELD(br, BR_RBS_OFF, BR_RBS_END); - rsz = GET_FIELD(br, BR_RSZ_OFF, BR_RSZ_END); - rcur = GET_FIELD(br, BR_RCUR_OFF, BR_RCUR_END); - psz = GET_FIELD(br, BR_PSZ_OFF, BR_PSZ_END); - pcur = GET_FIELD(br, BR_PCUR_OFF, BR_PCUR_END); - - e2k_cs.woff = tcg_const_i32(wbs * 2); - e2k_cs.wsize = tcg_const_i32(wsz * 2); - e2k_cs.boff = tcg_const_i32(rbs * 2); - e2k_cs.bsize = tcg_const_i32((rsz + 1) * 2); - e2k_cs.bcur = tcg_const_i32(rcur * 2); - e2k_cs.psize = tcg_const_i32(psz); - e2k_cs.pcur = tcg_const_i32(pcur); - - dc->is_call = false; - dc->jmp.cond = tcg_const_i64(0); + tcg_gen_movi_tl(e2k_cs.cond, 0); + tcg_gen_movi_i32(e2k_cs.call_wbs, 0); } static void e2k_tr_tb_stop(DisasContextBase *db, CPUState *cs) @@ -371,42 +348,58 @@ static void e2k_tr_tb_stop(DisasContextBase *db, CPUState *cs) case DISAS_TOO_MANY: break; case DISAS_NORETURN: { - save_state(dc); /* exception */ tcg_gen_exit_tb(NULL, 0); break; } - case DISAS_STATIC_JUMP: - save_state(dc); + case DISAS_JUMP_STATIC: tcg_gen_movi_tl(e2k_cs.pc, dc->jmp.dest); tcg_gen_exit_tb(NULL, 0); break; - case DISAS_DYNAMIC_JUMP: { - save_state(dc); - gen_helper_jump(cpu_env, dc->jmp.cond, e2k_cs.ctprs[dc->jump_ctpr]); + case DISAS_BRANCH_STATIC: { + TCGv z = tcg_const_tl(0); + TCGv t = tcg_const_tl(dc->jmp.dest); + TCGv f = tcg_const_tl(dc->npc); + + tcg_gen_movcond_tl(TCG_COND_NE, e2k_cs.pc, e2k_cs.cond, z, t, f); tcg_gen_exit_tb(NULL, 0); + + tcg_temp_free(f); + tcg_temp_free(t); + tcg_temp_free(z); break; } - case DISAS_CALL: { + case DISAS_JUMP: { + TCGv_i32 ctpr = tcg_const_i32(dc->jump_ctpr); + save_state(dc); - gen_helper_call(cpu_env, dc->jmp.cond, e2k_cs.ctprs[dc->jump_ctpr]); + gen_helper_jump(e2k_cs.pc, cpu_env, ctpr); tcg_gen_exit_tb(NULL, 0); + + tcg_temp_free_i32(ctpr); + break; + } + case DISAS_BRANCH: { + TCGv_i32 ctpr = tcg_const_i32(dc->jump_ctpr); + TCGv z = tcg_const_tl(0); + TCGv t = tcg_temp_new(); + TCGv f = tcg_const_tl(dc->npc); + + save_state(dc); + gen_helper_branch(t, cpu_env, ctpr, e2k_cs.cond); + tcg_gen_movcond_tl(TCG_COND_NE, e2k_cs.pc, e2k_cs.cond, z, t, f); + tcg_gen_exit_tb(NULL, 0); + + tcg_temp_free(f); + tcg_temp_free(t); + tcg_temp_free(z); + tcg_temp_free_i32(ctpr); break; } default: g_assert_not_reached(); break; } - - tcg_temp_free_i32(e2k_cs.woff); - tcg_temp_free_i32(e2k_cs.wsize); - tcg_temp_free_i32(e2k_cs.boff); - tcg_temp_free_i32(e2k_cs.bsize); - tcg_temp_free_i32(e2k_cs.bcur); - tcg_temp_free_i32(e2k_cs.psize); - tcg_temp_free_i32(e2k_cs.pcur); - - tcg_temp_free(dc->jmp.cond); } static void e2k_tr_disas_log(const DisasContextBase *db, @@ -447,6 +440,13 @@ void e2k_tcg_initialize(void) { static const struct { TCGv_i32 *ptr; int off; const char *name; } r32[] = { { &e2k_cs.call_wbs, offsetof(CPUE2KState, call_wbs), "call_wbs" }, + { &e2k_cs.woff, offsetof(CPUE2KState, woff), "woff" }, + { &e2k_cs.wsize, offsetof(CPUE2KState, wsize), "wsize" }, + { &e2k_cs.boff, offsetof(CPUE2KState, boff), "boff" }, + { &e2k_cs.bsize, offsetof(CPUE2KState, bsize), "bsize" }, + { &e2k_cs.bcur, offsetof(CPUE2KState, bcur), "bcur" }, + { &e2k_cs.psize, offsetof(CPUE2KState, psize), "psize" }, + { &e2k_cs.pcur, offsetof(CPUE2KState, pcur), "pcur" }, }; static const struct { TCGv_i64 *ptr; int off; const char *name; } r64[] = { @@ -457,6 +457,7 @@ void e2k_tcg_initialize(void) { static const struct { TCGv *ptr; int off; const char *name; } rtl[] = { { &e2k_cs.pc, offsetof(CPUE2KState, ip), "pc" }, { &e2k_cs.npc, offsetof(CPUE2KState, nip), "npc" }, + { &e2k_cs.cond, offsetof(CPUE2KState, cond), "cond" }, }; unsigned int i; diff --git a/target/e2k/translate.h b/target/e2k/translate.h index 44dfd032b9..f9089a1904 100644 --- a/target/e2k/translate.h +++ b/target/e2k/translate.h @@ -4,9 +4,20 @@ #include "tcg/tcg-op.h" #include "exec/translator.h" -#define DISAS_STATIC_JUMP DISAS_TARGET_0 -#define DISAS_DYNAMIC_JUMP DISAS_TARGET_1 -#define DISAS_CALL DISAS_TARGET_2 +/* ibranch disp */ +#define DISAS_JUMP_STATIC DISAS_TARGET_0 +/* ibranch disp ? cond */ +#define DISAS_BRANCH_STATIC DISAS_TARGET_1 +/* + * ct %ctprN + * call %ctprN, wbs=M + * */ +#define DISAS_JUMP DISAS_TARGET_2 +/* + * ct %ctprN ? cond + * call %ctprN, wbs=M ? cond + */ +#define DISAS_BRANCH DISAS_TARGET_3 #define IS_BASED(i) (((i) & 0x80) == 0) #define IS_REGULAR(i) (((i) & 0xc0) == 0x80) @@ -47,6 +58,7 @@ typedef struct CPUE2KStateTCG { TCGv pc; TCGv npc; TCGv ctprs[4]; + TCGv cond; TCGv_i64 lsr; TCGv_i32 call_wbs; TCGv_i64 wregs[WREGS_SIZE]; @@ -110,7 +122,6 @@ typedef struct DisasContext { UnpackedBundle bundle; target_ulong pc; target_ulong npc; - bool is_call; int jump_ctpr; int mmuidx; @@ -130,7 +141,6 @@ typedef struct DisasContext { /* TODO: move to CPUE2KState */ struct { target_ulong dest; /* ibranch dst */ - TCGv_i64 cond; } jmp; } DisasContext; diff --git a/target/e2k/translate/control.c b/target/e2k/translate/control.c index 112bb0a0d8..31c2423c0f 100644 --- a/target/e2k/translate/control.c +++ b/target/e2k/translate/control.c @@ -36,26 +36,20 @@ static inline void gen_lcnt_dec(TCGv_i64 ret, TCGv_i64 lsr) tcg_temp_free_i32(zero); } -static inline void gen_pcur_inc(TCGv_i32 ret) +static inline void gen_dec_cur(TCGv_i32 ret, TCGv_i32 cur, int val, + TCGv_i32 size) { TCGv_i32 t0 = tcg_temp_new_i32(); + TCGv_i32 t1 = tcg_temp_new_i32(); + TCGv_i32 t2 = tcg_temp_new_i32(); - tcg_gen_subi_i32(t0, e2k_cs.pcur, 1); - /* FIXME: terminated by signal SIGFPE (Floating point exception */ -// tcg_gen_remu_i32(ret, t0, e2k_cs.psize); - /* FIXME: temp hack */ - e2k_gen_wrap_i32(ret, t0, e2k_cs.psize); - - tcg_temp_free_i32(t0); -} - -static inline void gen_rcur_inc(TCGv_i32 ret) -{ - TCGv_i32 t0 = tcg_temp_new_i32(); - - tcg_gen_subi_i32(t0, e2k_cs.bcur, 2); - tcg_gen_remu_i32(ret, t0, e2k_cs.bsize); + tcg_gen_addi_i32(t0, size, val); + tcg_gen_sub_i32(t1, t0, cur); + tcg_gen_remu_i32(t2, t1, size); + tcg_gen_sub_i32(ret, size, t2); + tcg_temp_free_i32(t2); + tcg_temp_free_i32(t1); tcg_temp_free_i32(t0); } @@ -130,13 +124,13 @@ void e2k_win_commit(DisasContext *dc) int abn = GET_FIELD(ss, 21, 22); int abg = GET_FIELD(ss, 23, 24); - tcg_gen_trunc_tl_i32(cond, dc->jmp.cond); + tcg_gen_trunc_tl_i32(cond, e2k_cs.cond); if (alc) { TCGv_i64 t0 = tcg_temp_new_i64(); gen_lcnt_dec(t0, e2k_cs.lsr); - gen_movcond_flag_i64(e2k_cs.lsr, alc, dc->jmp.cond, t0, e2k_cs.lsr); + gen_movcond_flag_i64(e2k_cs.lsr, alc, e2k_cs.cond, t0, e2k_cs.lsr); tcg_temp_free_i64(t0); } @@ -144,7 +138,7 @@ void e2k_win_commit(DisasContext *dc) if (abp) { TCGv_i32 t0 = tcg_temp_new_i32(); - gen_pcur_inc(t0); + gen_dec_cur(t0, e2k_cs.pcur, 1, e2k_cs.psize); gen_movcond_flag_i32(e2k_cs.pcur, abp, cond, t0, e2k_cs.pcur); tcg_temp_free_i32(t0); @@ -153,7 +147,7 @@ void e2k_win_commit(DisasContext *dc) if (abn) { TCGv_i32 t0 = tcg_temp_new_i32(); - gen_rcur_inc(t0); + gen_dec_cur(t0, e2k_cs.bcur, 2, e2k_cs.bsize); gen_movcond_flag_i32(e2k_cs.bcur, abn, cond, t0, e2k_cs.bcur); tcg_temp_free_i32(t0); @@ -277,7 +271,7 @@ static void gen_cs0(DisasContext *dc) /* Calculate a signed displacement in bytes. */ int sdisp = ((int) (disp << 4)) >> 1; dc->jmp.dest = dc->pc + sdisp; - dc->base.is_jmp = DISAS_STATIC_JUMP; + dc->base.is_jmp = DISAS_JUMP_STATIC; } } } else { @@ -405,8 +399,6 @@ static void gen_cs1(DisasContext *dc) int wsz = GET_FIELD(lts0, 5, 11); TCGv_i32 t0 = tcg_const_i32(lts0); - gen_helper_setwd(cpu_env, t0); - tcg_gen_movi_i32(e2k_cs.wsize, wsz * 2); tcg_temp_free_i32(t0); @@ -417,18 +409,10 @@ static void gen_cs1(DisasContext *dc) int rbs = GET_FIELD(cs1, BR_RBS_OFF, BR_RBS_END); int rsz = GET_FIELD(cs1, BR_RSZ_OFF, BR_RSZ_END); int rcur = GET_FIELD(cs1, BR_RCUR_OFF, BR_RCUR_END); - TCGv_ptr t0 = tcg_const_ptr(rbs * 2); - TCGv_i32 t1 = tcg_const_i32(cs1); - - /* update state*/ - gen_helper_setbn(cpu_env, t1); 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); - - tcg_temp_free_i32(t1); - tcg_temp_free_ptr(t0); } if (setbp) { @@ -485,7 +469,6 @@ static void gen_cs1(DisasContext *dc) unsigned int wbs = cs1 & 0x7f; if (ctop) { - dc->is_call = true; tcg_gen_movi_i32(e2k_cs.call_wbs, wbs); // my_printf ("call %%ctpr%d, wbs = 0x%x", ctop, wbs); // print_ctcond (info, instr->ss & 0x1ff); @@ -547,19 +530,36 @@ static void gen_jmp(DisasContext *dc) unsigned int cond_type = GET_FIELD(dc->bundle.ss, 5, 8); unsigned int ctpr = GET_FIELD(dc->bundle.ss, 10, 11); + /* TODO: check CPU behavior if present ibranch and ctpr is not zero */ + + /* TODO: different kinds of ct */ + if (ctpr != 0) { + dc->jump_ctpr = ctpr; + dc->base.is_jmp = DISAS_JUMP; + } + if (cond_type == 1) { - /* TODO: optimize ibranch with no cond */ - tcg_gen_movi_tl(dc->jmp.cond, 1); - } else if (cond_type > 1){ + tcg_gen_movi_tl(e2k_cs.cond, 1); + } else if (cond_type > 1) { + switch (dc->base.is_jmp) { + case DISAS_JUMP: + dc->base.is_jmp = DISAS_BRANCH; + break; + case DISAS_JUMP_STATIC: + dc->base.is_jmp = DISAS_BRANCH_STATIC; + break; + default: + /* FIXME: what action to do? */ + g_assert_not_reached(); + break; + } + /* TODO: single assign */ - TCGv cond = tcg_const_tl(0); TCGv preg = tcg_temp_new(); TCGv loop_end = tcg_temp_new(); TCGv not_loop_end = tcg_temp_new(); TCGv_i64 t0 = tcg_temp_new_i64(); - dc->base.is_jmp = DISAS_DYNAMIC_JUMP; - e2k_gen_preg(t0, psrc); tcg_gen_trunc_i64_tl(preg, t0); gen_is_loop_end(loop_end); @@ -569,12 +569,12 @@ static void gen_jmp(DisasContext *dc) case 0x2: case 0x6: case 0xf: - tcg_gen_mov_tl(cond, preg); + tcg_gen_mov_tl(e2k_cs.cond, preg); break; case 0x3: case 0x7: case 0xe: - tcg_gen_setcondi_tl(TCG_COND_NE, cond, preg, 1); + tcg_gen_setcondi_tl(TCG_COND_NE, e2k_cs.cond, preg, 1); break; default: break; @@ -582,18 +582,18 @@ static void gen_jmp(DisasContext *dc) switch (cond_type) { case 0x4: - tcg_gen_mov_tl(cond, loop_end); + tcg_gen_mov_tl(e2k_cs.cond, loop_end); break; case 0x5: - tcg_gen_mov_tl(cond, not_loop_end); + tcg_gen_mov_tl(e2k_cs.cond, not_loop_end); break; case 0x6: case 0xe: - tcg_gen_or_tl(cond, cond, loop_end); + tcg_gen_or_tl(e2k_cs.cond, e2k_cs.cond, loop_end); break; case 0x7: case 0xf: - tcg_gen_and_tl(cond, cond, not_loop_end); + tcg_gen_and_tl(e2k_cs.cond, e2k_cs.cond, not_loop_end); break; default: break; @@ -648,26 +648,11 @@ static void gen_jmp(DisasContext *dc) abort(); } - tcg_gen_mov_tl(dc->jmp.cond, cond); tcg_temp_free_i64(t0); tcg_temp_free(not_loop_end); tcg_temp_free(loop_end); tcg_temp_free(preg); - tcg_temp_free(cond); - } - - /* TODO: check CPU behavior if present ibranch and ctpr is not zero */ - - /* TODO: different kinds of ct */ - if (ctpr != 0) { - dc->jump_ctpr = ctpr; - - if (dc->is_call) { - dc->base.is_jmp = DISAS_CALL; - } else { - dc->base.is_jmp = DISAS_DYNAMIC_JUMP; - } } }