target: e2k: Fix bugs.

This commit is contained in:
Denis Drakhnia 2020-11-13 22:47:31 +02:00 committed by Denis Drakhnia
parent 24b5d5c7fb
commit 54feb6fbe3
7 changed files with 110 additions and 50 deletions

View File

@ -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;
}

View File

@ -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);

View File

@ -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

View File

@ -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)
{

View File

@ -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 */

View File

@ -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 {

View File

@ -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);