target: e2k: Fix bugs.
This commit is contained in:
parent
24b5d5c7fb
commit
54feb6fbe3
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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 */
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user