diff --git a/linux-user/e2k/cpu_loop.c b/linux-user/e2k/cpu_loop.c index 5c71a5f36f..174d7fe2cc 100644 --- a/linux-user/e2k/cpu_loop.c +++ b/linux-user/e2k/cpu_loop.c @@ -42,14 +42,20 @@ void cpu_loop(CPUE2KState *env) switch (trapnr) { case E2K_EXCP_SYSCALL: { /* TODO: wrap register indices */ - uint64_t *regs = &env->wregs[env->wbs + env->syscall_wbs]; + int offset = (env->wbs + env->syscall_wbs) * 2; + uint64_t *regs = &env->wregs[offset]; abi_ulong ret = do_syscall(env, regs[0], regs[1], regs[2], regs[3], regs[4], regs[5], regs[6], regs[7], regs[8]); if (ret == -TARGET_ERESTARTSYS) { /* TODO: restart syscall */ } else if (ret != -TARGET_QEMU_ESIGRETURN) { + unsigned int i; + regs[0] = ret; + for (i = 1; i < 8; i++) { + regs[i] = 0; + } } break; } diff --git a/target/e2k/cpu.c b/target/e2k/cpu.c index 2c0880a6db..f4d77ed80d 100644 --- a/target/e2k/cpu.c +++ b/target/e2k/cpu.c @@ -83,6 +83,9 @@ void e2k_cpu_dump_state(CPUState *cs, FILE *f, int flags) qemu_fprintf(f, "pregs: %016lx\n", env->pregs); qemu_fprintf(f, "usd_hi: %016lx, usd_lo: %016lx\n", env->usd_hi, env->usd_lo); + qemu_fprintf(f, "wbs: %d, wsz: %d\n", (int) env->wbs, (int) env->wsz); + qemu_fprintf(f, "rbs: %d, rsz: %d, rcur: %d\n", + (int) env->rbs, (int) env->rsz, (int) env->rcur); qemu_fprintf(f, "psz: %d, pcur: %d\n", (int) env->psz, (int) env->pcur); qemu_fprintf(f, "lsr: %016lx\n", env->lsr); diff --git a/target/e2k/cpu.h b/target/e2k/cpu.h index 20d6106b98..41e65440d9 100644 --- a/target/e2k/cpu.h +++ b/target/e2k/cpu.h @@ -60,15 +60,15 @@ typedef struct CPUArchState { target_ulong *win_ptr; uint64_t pregs; - 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 wbs; // window regs offset + uint32_t wsz; // window regs size uint32_t nfx; // TODO uint32_t dbl; // TODO /* TODO: move them to %br? */ - 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 offset, in bundle it comes divided by 2 + uint32_t rbs; // based regs offset + uint32_t rsz; // based regs size + uint32_t rcur; // based regs current offset uint64_t psz; // pred regs window size uint64_t pcur; // pred regs current offset diff --git a/target/e2k/translate.h b/target/e2k/translate.h index ad3f94c52c..5a8598f670 100644 --- a/target/e2k/translate.h +++ b/target/e2k/translate.h @@ -172,6 +172,19 @@ static inline void e2k_gen_wrap_i32(TCGv_i32 ret, TCGv_i32 x, TCGv_i32 y) tcg_temp_free_i32(t0); } +// FIXME: x must not be greater than y * 2 +static inline void e2k_gen_wrapi_i32(TCGv_i32 ret, TCGv_i32 x, uint32_t y) +{ + TCGv_i32 t0 = tcg_temp_new_i32(); + TCGv_i32 t1 = tcg_const_i32(y); + + tcg_gen_sub_i32(t0, x, t1); + tcg_gen_movcond_i32(TCG_COND_LTU, ret, x, t1, x, t0); + + tcg_temp_free_i32(t1); + tcg_temp_free_i32(t0); +} + // FIXME: x must not be greater than y * 2 static inline void e2k_gen_wrap_i64(TCGv_i64 ret, TCGv_i64 x, TCGv_i64 y) { diff --git a/target/e2k/translate/alc.c b/target/e2k/translate/alc.c index fcca1d0bdf..043863d99d 100644 --- a/target/e2k/translate/alc.c +++ b/target/e2k/translate/alc.c @@ -359,6 +359,17 @@ static void gen_getsp(DisasContext *dc, int chan) tcg_temp_free_i64(t0); } +/* FIXME: movtd: don't know what it does */ +static void gen_movtd(DisasContext *dc, int chan) +{ + uint32_t als = dc->bundle.als[chan]; + TCGv_i64 src2 = get_src2(dc, als); + TCGv_i64 t0 = e2k_get_temp_i64(dc); + + tcg_gen_mov_i64(t0, src2); + store_reg_alc_result(dc, chan, t0); +} + static void gen_ld(DisasContext *dc, int chan, MemOp memop) { uint32_t als = dc->bundle.als[chan]; @@ -462,7 +473,6 @@ static void gen_alopf_simple(DisasContext *dc, int chan) uint32_t als = dc->bundle.als[chan]; int opc = GET_FIELD(als, 24, 30); int sm = GET_BIT(als, 31); - Result res = { 0 }; switch(opc) { case 0x00: /* ands */ gen_alopf1_i32(dc, chan, tcg_gen_and_i32); break; @@ -500,21 +510,25 @@ static void gen_alopf_simple(DisasContext *dc, int chan) TCGv_i64 cpu_src1 = get_src1(dc, als); TCGv_i64 cpu_src2 = get_src2(dc, als); TCGv_i64 tmp_dst = e2k_get_temp_i64(dc); + TCGCond cond = TCG_COND_NEVER; + Result res = { 0 }; unsigned int cmp_op = GET_FIELD(als, 5, 7); // TODO: move to separate function switch(cmp_op) { - case 1: // unsigned less - tcg_gen_setcond_i64(TCG_COND_LEU, tmp_dst, cpu_src1, cpu_src2); - break; - case 2: // equal - tcg_gen_setcond_i64(TCG_COND_EQ, tmp_dst, cpu_src1, cpu_src2); - break; - default: - abort(); - break; + case 0: abort(); break; + case 1: cond = TCG_COND_LTU; break; + case 2: cond = TCG_COND_EQ; break; + case 3: cond = TCG_COND_LEU; break; + case 4: abort(); break; + case 5: abort(); break; + case 6: cond = TCG_COND_LT; break; + case 7: cond = TCG_COND_LE; break; + default: g_assert_not_reached(); break; } + tcg_gen_setcond_i64(cond, tmp_dst, cpu_src1, cpu_src2); + res.tag = RESULT_PREG; res.u.reg.i = als & 0x1f; res.u.reg.v = tmp_dst; @@ -561,6 +575,14 @@ static void gen_alopf_simple(DisasContext *dc, int chan) case 0x40: // TODO: udivs used as temporary UD e2k_gen_exception(dc, E2K_EXCP_UNIMPL); break; + case 0x61: + if (chan == 2 || chan == 5) { + /* TODO: exception */ + abort(); + } else { + gen_movtd(dc, chan); + } + break; case 0x64: { /* ldb */ if (chan == 2 || chan == 5) { /* TODO: exception */ diff --git a/target/e2k/translate/control.c b/target/e2k/translate/control.c index cbbfd78f8d..f3597c3679 100644 --- a/target/e2k/translate/control.c +++ b/target/e2k/translate/control.c @@ -59,18 +59,20 @@ static inline void gen_abn_inc(DisasContext *dc, TCGCond cond) { 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(); TCGv_i32 one = tcg_const_i32(1); - TCGv_i32 jmp_cond = tcg_temp_new_i32(); - tcg_gen_addi_i32(t0, e2k_cs.rcur, 2); - e2k_gen_wrap_i32(t1, t0, e2k_cs.rsz); - tcg_gen_extrl_i64_i32(jmp_cond, dc->jmp.cond); + tcg_gen_subi_i32(t0, e2k_cs.rcur, 1); + tcg_gen_umin_i32(t2, t0, e2k_cs.rsz); + tcg_gen_extrl_i64_i32(t3, dc->jmp.cond); tcg_gen_movcond_i32(cond, e2k_cs.rcur, - jmp_cond, one, - t1, e2k_cs.rcur); + t3, one, + t2, e2k_cs.rcur); - tcg_temp_free_i32(jmp_cond); tcg_temp_free_i32(one); + tcg_temp_free_i32(t3); + tcg_temp_free_i32(t2); tcg_temp_free_i32(t1); tcg_temp_free_i32(t0); } @@ -322,7 +324,7 @@ static void gen_cs1(DisasContext *dc) abort(); } else { uint32_t lts0 = bundle->lts[0]; - tcg_gen_movi_i32(e2k_cs.wsz, GET_FIELD(lts0, 5, 11) * 2); + tcg_gen_movi_i32(e2k_cs.wsz, GET_FIELD(lts0, 5, 11)); tcg_gen_movi_i32(e2k_cs.nfx, GET_BIT(lts0, 4)); if (dc->version >= 3) { @@ -336,9 +338,9 @@ static void gen_cs1(DisasContext *dc) unsigned int rsz = (cs1 & 0x00000fc0) >> 6; unsigned int rbs = cs1 & 0x0000003f; - tcg_gen_movi_i32(e2k_cs.rcur, rcur * 2); - tcg_gen_movi_i32(e2k_cs.rsz, rsz * 2 + 2); - tcg_gen_movi_i32(e2k_cs.rbs, rbs * 2); + tcg_gen_movi_i32(e2k_cs.rcur, rcur); + tcg_gen_movi_i32(e2k_cs.rsz, rsz); + tcg_gen_movi_i32(e2k_cs.rbs, rbs); } if (setbp) { @@ -393,7 +395,7 @@ static void gen_cs1(DisasContext *dc) if (ctop) { dc->is_call = true; - tcg_gen_movi_i32(e2k_cs.syscall_wbs, wbs * 2); + tcg_gen_movi_i32(e2k_cs.syscall_wbs, wbs); // my_printf ("call %%ctpr%d, wbs = 0x%x", ctop, wbs); // print_ctcond (info, instr->ss & 0x1ff); } else { diff --git a/target/e2k/translate/state.c b/target/e2k/translate/state.c index c847bacc6f..40b6eb45e7 100644 --- a/target/e2k/translate/state.c +++ b/target/e2k/translate/state.c @@ -9,14 +9,11 @@ static void gen_preg_offset(TCGv_i64 ret, int reg) TCGv_i64 t0 = tcg_temp_new_i64(); TCGv_i64 t1 = tcg_temp_new_i64(); - TCGv_i64 t2 = tcg_temp_new_i64(); tcg_gen_addi_i64(t0, e2k_cs.pcur, reg); - tcg_gen_addi_i64(t1, e2k_cs.psz, 1); - e2k_gen_wrap_i64(t2, t0, t1); - tcg_gen_shli_i64(ret, t2, 1); + e2k_gen_wrap_i64(t1, t0, e2k_cs.psz); + tcg_gen_shli_i64(ret, t1, 1); - tcg_temp_free_i64(t2); tcg_temp_free_i64(t1); tcg_temp_free_i64(t0); } @@ -27,7 +24,7 @@ static void gen_preg_clear(TCGv_i64 ret, TCGv_i64 offset) TCGv_i64 t1 = tcg_temp_new_i64(); TCGv_i64 t2 = tcg_temp_new_i64(); - tcg_gen_shr_i64(t1, t0, offset); + tcg_gen_shl_i64(t1, t0, offset); tcg_gen_not_i64(t2, t1); tcg_gen_and_i64(ret, t2, e2k_cs.pregs); @@ -81,12 +78,15 @@ static inline void gen_wreg_offset(TCGv_i32 ret, int reg) TCGv_i32 t0 = tcg_temp_new_i32(); TCGv_i32 t1 = tcg_temp_new_i32(); - TCGv_i32 t2 = tcg_const_i32(WREGS_SIZE); + TCGv_i32 t2 = tcg_temp_new_i32(); + TCGv_i32 t3 = tcg_const_i32(WREGS_SIZE); - tcg_gen_addi_i32(t0, e2k_cs.wbs, reg); // t = win_start + reg_index - e2k_gen_wrap_i32(t1, t0, t2); // t = t % WIN_REGS_COUNT - tcg_gen_muli_i32(ret, t1, REG_SIZE); // t = t * REG_SIZE_IN_BYTES + tcg_gen_shli_i32(t0, e2k_cs.wbs, 1); // t = wbs * 2 + tcg_gen_addi_i32(t1, t0, reg); // t = t + reg_index + e2k_gen_wrap_i32(t2, t1, t3); // t = t % WIN_REGS_COUNT + tcg_gen_muli_i32(ret, t2, REG_SIZE); // t = t * REG_SIZE_IN_BYTES + tcg_temp_free_i32(t3); tcg_temp_free_i32(t2); tcg_temp_free_i32(t1); tcg_temp_free_i32(t0); @@ -121,31 +121,45 @@ void e2k_gen_store_wreg(int reg, TCGv_i64 val) tcg_temp_free_ptr(ptr); } +static inline void gen_breg_start(TCGv_i32 ret) +{ + TCGv_i32 t0 = tcg_temp_new_i32(); + + tcg_gen_add_i32(t0, e2k_cs.wbs, e2k_cs.rbs); + tcg_gen_shli_i32(ret, t0, 1); + + tcg_temp_free_i32(t0); +} + static inline void gen_breg_offset(TCGv_i32 ret, int reg) { - assert(reg < 128); - // TODO: exception cpu_wsz <= reg || cpu_rsz <= reg 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(); TCGv_i32 t4 = tcg_temp_new_i32(); - TCGv_i32 t5 = tcg_const_i32(WREGS_SIZE); + TCGv_i32 t5 = tcg_temp_new_i32(); TCGv_i32 t6 = tcg_temp_new_i32(); + TCGv_i32 t7 = tcg_temp_new_i32(); - // t2 = (index + rsz + rcur) % rsz - tcg_gen_sub_i32(t0, e2k_cs.rsz, e2k_cs.rcur); + /* TODO: exception: reg > (rsz * 2 + 2) */ + /* t = (reg + rcur * 2) % (rsz * 2 + 2) */ + tcg_gen_shli_i32(t0, e2k_cs.rcur, 1); tcg_gen_addi_i32(t1, t0, reg); - e2k_gen_wrap_i32(t2, t1, e2k_cs.rsz); + tcg_gen_addi_i32(t2, e2k_cs.rsz, 1); + tcg_gen_shli_i32(t3, t2, 1); + e2k_gen_wrap_i32(t4, t1, t3); - // (t2 + wbs + rbs) % WIN_REGS_COUNT - tcg_gen_add_i32(t3, e2k_cs.wbs, e2k_cs.rbs); - tcg_gen_add_i32(t4, t2, t3); - e2k_gen_wrap_i32(t6, t4, t5); + /* TODO: exceptioon: (reg + rbs * 2) > (wsz * 2) */ + /* t = (t + wbs * 2 + rbs * 2) % 192 */ + gen_breg_start(t5); + tcg_gen_add_i32(t6, t4, t5); + e2k_gen_wrapi_i32(t7, t6, WREGS_SIZE); - // (t6 * REG_SIZE_IN_BYTES - tcg_gen_muli_i32(ret, t6, REG_SIZE); + /* ret = t * 8 */ + tcg_gen_muli_i32(ret, t7, REG_SIZE); + tcg_temp_free_i32(t7); tcg_temp_free_i32(t6); tcg_temp_free_i32(t5); tcg_temp_free_i32(t4);