diff --git a/linux-user/e2k/cpu_loop.c b/linux-user/e2k/cpu_loop.c index ed13946e8c..deb2cf8c7a 100644 --- a/linux-user/e2k/cpu_loop.c +++ b/linux-user/e2k/cpu_loop.c @@ -39,7 +39,7 @@ void cpu_loop(CPUE2KState *env) switch (trapnr) { case E2K_EXCP_SYSCALL: { /* TODO: wrap register indices */ - uint64_t *regs = &env->wregs[env->wbs * 2]; + uint64_t *regs = &env->wregs[env->wbs + env->syscall_wbs]; abi_ulong ret = do_syscall(env, regs[0], regs[1], regs[2], regs[3], regs[4], regs[5], regs[6], regs[7], regs[8]); @@ -62,5 +62,4 @@ void cpu_loop(CPUE2KState *env) void target_cpu_copy_regs(CPUE2KState *env, struct target_pt_regs *regs) { env->ip = regs->ip; - // TODO } diff --git a/target/e2k/cpu.h b/target/e2k/cpu.h index c1794c1071..2022152e30 100644 --- a/target/e2k/cpu.h +++ b/target/e2k/cpu.h @@ -14,7 +14,8 @@ void e2k_tcg_initialize(void); #define REG_SIZE (sizeof(target_ulong)) typedef enum { - E2K_EXCP_SYSCALL = 0x01, + E2K_EXCP_UNIMPL = 0x01, + E2K_EXCP_SYSCALL = 0x02, } Exception; struct e2k_def_t { @@ -29,14 +30,15 @@ typedef struct { target_ulong wregs[WREGS_SIZE]; // window regs target_ulong *win_ptr; uint64_t pregs; - uint32_t wbs; // window regs offset (* 2) - uint32_t wsz; // window regs size (* 2) + uint32_t wbs; // Real window regs offset, in bundle it comes divided by 2 + uint32_t wsz; // Real window regs size, in bundle it comes divided by 2 uint32_t nfx; // TODO uint32_t dbl; // TODO - uint32_t rbs; // based regs offset (* 2) - uint32_t rsz; // based regs window size (* 2 + 2) - uint32_t rcur; // based regs current index (* 2) + uint32_t rbs; // Real based regs offset, in bundle it comes divided by 2 + uint32_t rsz; // Real based regs size, in bundle it comes divided by 2 minus 2 + uint32_t rcur; // Real based regs current index, in bundle it comes divided by 2 uint32_t psz; // pred regs window size + uint32_t syscall_wbs; /* control registers */ target_ulong ctprs[3]; // Control Transfer Preparation Register (CTPR) diff --git a/target/e2k/helper.c b/target/e2k/helper.c index 924ce61db5..d53f96d8ba 100644 --- a/target/e2k/helper.c +++ b/target/e2k/helper.c @@ -13,13 +13,16 @@ void helper_raise_exception(CPUE2KState *env, int tt) cpu_loop_exit(cs); } -void helper_check_syscall_ctpr(CPUE2KState *env, uint64_t ctpr) +void helper_call(CPUE2KState *env, uint64_t ctpr, uint64_t cond) { int tag = GET_FIELD(ctpr, CTPR_TAG_OFF, CTPR_TAG_END); - if (tag == CTPR_TAG_SDISP) { + if (tag == CTPR_TAG_SDISP && cond) { CPUState *cs = env_cpu(env); cs->exception_index = E2K_EXCP_SYSCALL; cpu_loop_exit(cs); + } else { + /* TODO: call */ + abort(); } } diff --git a/target/e2k/helper.h b/target/e2k/helper.h index 1db6921d5f..43d31ba212 100644 --- a/target/e2k/helper.h +++ b/target/e2k/helper.h @@ -1,4 +1,4 @@ // include/exec/helper-proto.h needs this file DEF_HELPER_2(raise_exception, noreturn, env, int) -DEF_HELPER_2(check_syscall_ctpr, void, env, i64) +DEF_HELPER_3(call, void, env, i64, i64) diff --git a/target/e2k/translate.c b/target/e2k/translate.c index a71f232432..b2050b0eee 100644 --- a/target/e2k/translate.c +++ b/target/e2k/translate.c @@ -188,6 +188,7 @@ static target_ulong unpack_bundle(CPUE2KState *env, static inline void save_state(DisasContext *dc) { tcg_gen_movi_tl(e2k_cs.pc, dc->pc); + tcg_gen_movi_tl(e2k_cs.pc, dc->npc); } void e2k_gen_exception(DisasContext *dc, int which) @@ -233,7 +234,7 @@ static void e2k_tr_translate_insn(DisasContextBase *db, CPUState *cs) dc->pc = dc->base.pc_next; unsigned int bundle_len = unpack_bundle(env, dc->pc, bundle); /* TODO: exception, check bundle_len */ - dc->base.pc_next = dc->pc + bundle_len; + dc->base.pc_next = dc->npc = dc->pc + bundle_len; e2k_alc_gen(dc); e2k_control_gen(dc); @@ -259,6 +260,7 @@ static void e2k_tr_tb_start(DisasContextBase *db, CPUState *cs) { DisasContext *dc = container_of(db, DisasContext, base); + dc->is_call = false; dc->jmp.dest = tcg_const_i64(0); dc->jmp.cond = tcg_const_i64(0); } @@ -266,29 +268,36 @@ static void e2k_tr_tb_start(DisasContextBase *db, CPUState *cs) static void e2k_tr_tb_stop(DisasContextBase *db, CPUState *cs) { DisasContext *dc = container_of(db, DisasContext, base); - E2KCPU *cpu = E2K_CPU(cs); -// CPUE2KState *env = &cpu->env; /* Control transfer */ switch(dc->base.is_jmp) { case DISAS_NEXT: case DISAS_TOO_MANY: break; - case DISAS_NORETURN: - /* exception */ + case DISAS_CALL: { tcg_gen_movi_tl(e2k_cs.pc, dc->pc); + tcg_gen_movi_tl(e2k_cs.pc, dc->npc); + gen_helper_call(cpu_env, e2k_cs.ctprs[dc->call_ctpr], dc->jmp.cond); tcg_gen_exit_tb(NULL, 0); break; + } + case DISAS_NORETURN: { + /* exception */ + tcg_gen_exit_tb(NULL, 0); + break; + } case STATIC_JUMP: tcg_gen_mov_i64(e2k_cs.pc, dc->jmp.dest); tcg_gen_exit_tb(NULL, 0); break; case DYNAMIC_JUMP: { TCGv_i64 one = tcg_const_i64(1); + TCGv_i64 npc = tcg_const_i64(dc->npc); tcg_gen_movcond_i64(TCG_COND_EQ, e2k_cs.pc, dc->jmp.cond, one, - dc->jmp.dest, e2k_cs.pc + dc->jmp.dest, npc ); + tcg_temp_free_i64(npc); tcg_temp_free_i64(one); tcg_gen_exit_tb(NULL, 0); break; @@ -347,6 +356,7 @@ void e2k_tcg_initialize(void) { { &e2k_cs.rsz, offsetof(CPUE2KState, rsz), "rsz" }, { &e2k_cs.rcur, offsetof(CPUE2KState, rcur), "rcur" }, { &e2k_cs.psz, offsetof(CPUE2KState, psz), "psz" }, + { &e2k_cs.syscall_wbs, offsetof(CPUE2KState, syscall_wbs), "syscall_wbs" }, }; static const struct { TCGv_i64 *ptr; int off; const char *name; } r64[] = { diff --git a/target/e2k/translate.h b/target/e2k/translate.h index 24b6c79538..87eb4f77ae 100644 --- a/target/e2k/translate.h +++ b/target/e2k/translate.h @@ -6,6 +6,7 @@ #define STATIC_JUMP DISAS_TARGET_0 #define DYNAMIC_JUMP DISAS_TARGET_1 +#define DISAS_CALL DISAS_TARGET_2 #define GEN_MASK(type, start, end) \ ((((type) 1 << ((end) - (start) + 1)) - 1) << start) @@ -68,6 +69,7 @@ typedef struct CPUE2KStateTCG { TCGv_i32 rsz; TCGv_i32 rcur; TCGv_i32 psz; + TCGv_i32 syscall_wbs; TCGv_ptr win_ptr; TCGv_i64 wregs[WREGS_SIZE]; TCGv_i64 gregs[32]; @@ -121,12 +123,15 @@ typedef struct DisasContext { DisasContextBase base; UnpackedBundle bundle; target_ulong pc; + target_ulong npc; + bool is_call; + int call_ctpr; int version; // Temporary values. TCGv_i32 t32[16]; - TCGv_i64 t64[16]; + TCGv_i64 t64[32]; TCGv ttl[8]; // Allocated temporary values count. int t32_len; diff --git a/target/e2k/translate/alc.c b/target/e2k/translate/alc.c index af58b63b83..7e73f42bb6 100644 --- a/target/e2k/translate/alc.c +++ b/target/e2k/translate/alc.c @@ -262,7 +262,7 @@ static void gen_channel(DisasContext *dc, int chan) break; } case 0x40: // TODO: udivs used as temporary UD - e2k_gen_exception(dc, 1); + e2k_gen_exception(dc, E2K_EXCP_UNIMPL); break; default: qemu_log_mask(LOG_UNIMP, "gen_alc: undefined instruction 0x%x %s\n", opc, sm ? "(speculative)" : ""); diff --git a/target/e2k/translate/control.c b/target/e2k/translate/control.c index 6ce4475a3c..42141b19bd 100644 --- a/target/e2k/translate/control.c +++ b/target/e2k/translate/control.c @@ -263,7 +263,8 @@ static void gen_cs1(DisasContext *dc) unsigned int wbs = cs1 & 0x7f; if (ctop) { - tcg_gen_movi_i32(e2k_cs.wbs, wbs); + dc->is_call = true; + tcg_gen_movi_i32(e2k_cs.syscall_wbs, wbs * 2); // my_printf ("call %%ctpr%d, wbs = 0x%x", ctop, wbs); // print_ctcond (info, instr->ss & 0x1ff); } else { @@ -324,116 +325,118 @@ 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); + if (cond_type == 1) { + dc->base.is_jmp = STATIC_JUMP; + tcg_gen_movi_i64(dc->jmp.cond, 1); + } else { + dc->base.is_jmp = DYNAMIC_JUMP; + + if (cond_type == 2 || cond_type == 6 || cond_type == 0xf) { + /* if pred is true */ + tcg_gen_mov_i64(dc->jmp.cond, e2k_get_preg(dc, psrc)); + } else if (cond_type == 3 || cond_type == 7 || cond_type == 0xe) { + /* if pred is false */ + TCGv_i64 one = tcg_const_i64(1); + TCGv_i64 zero = tcg_const_i64(0); + tcg_gen_movcond_i64(TCG_COND_EQ, dc->jmp.cond, + e2k_get_preg(dc, psrc), zero, + one, zero); + tcg_temp_free_i64(zero); + tcg_temp_free_i64(one); + } + + /* TODO: other kinds of conditions */ + + if (cond_type == 4 + || cond_type == 6 + || cond_type == 0xe) + { + if (cond_type == 6 || cond_type == 0xe) { + // or + } + + // %LOOP_END + } + + if (cond_type == 5 + || cond_type == 7 + || cond_type == 0xf) + { + if(cond_type == 7 + || cond_type == 0xf) + { + // AND + } + // %NOT_LOOP_END + } + + if (cond_type == 8) { + // %MLOCK + /* It's not clearly said in C.17.1.2 of iset-vX.single if the uppermost + fourth bit in `psrc' has any meaning at all. */ + if (psrc & 0xf) { + // static const int conv[] = {0, 1, 3, 4}; + int i; + + // %dt_al + for (i = 0; i < 4; i++) { + if (psrc & (1 << i)) { + // i + } + } + } + } + + /* `lock_cond || pl_cond' control transfer conditions. */ + if (cond_type == 9) { + 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]); + } 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); + } else if (type == 2) { + // unsigned int clp_num = (psrc & 0x6) >> 1; + // unsigned int neg = psrc & 0x1; + + // "%%MLOCK || %s%%clp%d", neg ? "~" : "", clp_num + } + } + + if (cond_type >= 0xa && cond_type <= 0xd) { + // reserved condition type + qemu_log_mask(LOG_UNIMP, "Undefined control transfer type %#x\n", cond_type); + abort(); + } + } + /* TODO: check CPU behavior if present ibranch and ctpr is not zero */ /* TODO: different kinds of ct */ if (ctpr != 0) { + if (dc->is_call) { + /* TODO: call save state */ + dc->call_ctpr = ctpr; + dc->base.is_jmp = DISAS_CALL; + return; + } TCGv_i64 t0 = tcg_temp_new_i64(); - /* TODO: use save_state */ - tcg_gen_movi_i64(e2k_cs.pc, dc->pc); - gen_helper_check_syscall_ctpr(cpu_env, e2k_cs.ctprs[ctpr]); tcg_gen_andi_i64(t0, e2k_cs.ctprs[ctpr], GEN_MASK(uint64_t, 0, 47)); tcg_gen_mov_tl(dc->jmp.dest, t0); tcg_temp_free_i64(t0); } - - if (cond_type == 1) { - dc->base.is_jmp = STATIC_JUMP; - tcg_gen_movi_i64(dc->jmp.cond, 1); - return; - } - - dc->base.is_jmp = DYNAMIC_JUMP; - - if (cond_type == 2 || cond_type == 6 || cond_type == 0xf) { - /* if pred is true */ - tcg_gen_mov_i64(dc->jmp.cond, e2k_get_preg(dc, psrc)); - } else if (cond_type == 3 || cond_type == 7 || cond_type == 0xe) { - /* if pred is false */ - TCGv_i64 one = tcg_const_i64(1); - TCGv_i64 zero = tcg_const_i64(0); - tcg_gen_movcond_i64(TCG_COND_EQ, dc->jmp.cond, - e2k_get_preg(dc, psrc), zero, - one, zero); - tcg_temp_free_i64(zero); - tcg_temp_free_i64(one); - } - - /* TODO: other kinds of conditions */ - - if (cond_type == 4 - || cond_type == 6 - || cond_type == 0xe) - { - if (cond_type == 6 || cond_type == 0xe) { - // or - } - - // %LOOP_END - } - - if (cond_type == 5 - || cond_type == 7 - || cond_type == 0xf) - { - if(cond_type == 7 - || cond_type == 0xf) - { - // AND - } - // %NOT_LOOP_END - } - - if (cond_type == 8) { - // %MLOCK - /* It's not clearly said in C.17.1.2 of iset-vX.single if the uppermost - fourth bit in `psrc' has any meaning at all. */ - if (psrc & 0xf) { -// static const int conv[] = {0, 1, 3, 4}; - int i; - - // %dt_al - for (i = 0; i < 4; i++) { - if (psrc & (1 << i)) { - // i - } - } - } - } - - /* `lock_cond || pl_cond' control transfer conditions. */ - if (cond_type == 9) { - 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]); - } 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); - } else if (type == 2) { -// unsigned int clp_num = (psrc & 0x6) >> 1; -// unsigned int neg = psrc & 0x1; - - // "%%MLOCK || %s%%clp%d", neg ? "~" : "", clp_num - } - } - - if (cond_type >= 0xa && cond_type <= 0xd) { - // reserved condition type - qemu_log_mask(LOG_UNIMP, "Undefined control transfer type %#x\n", cond_type); - abort(); - } } void e2k_control_gen(DisasContext *dc)