From 57b3469cda8770fa3df26b96ab13e95e983905d6 Mon Sep 17 00:00:00 2001 From: Denis Drakhnya Date: Wed, 2 Dec 2020 15:06:50 +0200 Subject: [PATCH] target: e2k: Impl speculative execution. --- linux-user/e2k/cpu_loop.c | 2 +- target/e2k/cpu.c | 2 +- target/e2k/helper.h | 2 + target/e2k/helper_sm.c | 27 +++ target/e2k/meson.build | 1 + target/e2k/translate.h | 3 +- target/e2k/translate/alc.c | 389 ++++++++++++++++++++++++++++------- target/e2k/translate/state.c | 36 +--- 8 files changed, 363 insertions(+), 99 deletions(-) create mode 100644 target/e2k/helper_sm.c diff --git a/linux-user/e2k/cpu_loop.c b/linux-user/e2k/cpu_loop.c index 6a19ae6d3b..b1c7a47214 100644 --- a/linux-user/e2k/cpu_loop.c +++ b/linux-user/e2k/cpu_loop.c @@ -58,7 +58,7 @@ void cpu_loop(CPUE2KState *env) } else if (ret != -TARGET_QEMU_ESIGRETURN) { unsigned int i; - regs[0] = ret; + regs[offset % E2K_NR_COUNT] = ret; for (i = 1; i < 8; i++) { regs[(i + offset) % E2K_NR_COUNT] = 0; } diff --git a/target/e2k/cpu.c b/target/e2k/cpu.c index 7557d435de..fa95f4a4b5 100644 --- a/target/e2k/cpu.c +++ b/target/e2k/cpu.c @@ -141,7 +141,7 @@ void e2k_cpu_dump_state(CPUState *cs, FILE *f, int flags) for (i = 0; i < E2K_REG_COUNT; i++) { char name = i < E2K_NR_COUNT ? 'r' : 'g'; int tag = extract_tag(env->tags, i); - qemu_fprintf(f, "%%%c%d\t<%d%d> 0x%lx\n", name, i, tag & 3, tag >> 2, + qemu_fprintf(f, "%%%c%d\t<%d%d> 0x%lx\n", name, i, tag >> 2, tag & 3, env->regs[i]); } diff --git a/target/e2k/helper.h b/target/e2k/helper.h index 744523cd53..b1f45103bb 100644 --- a/target/e2k/helper.h +++ b/target/e2k/helper.h @@ -13,3 +13,5 @@ DEF_HELPER_3(state_reg_write_i32, void, env, int, i32) DEF_HELPER_2(getsp, i64, env, i64) /* FIXME: return tl? */ DEF_HELPER_1(break_restore_state, void, env) DEF_HELPER_2(setwd, void, env, i32) +DEF_HELPER_2(probe_read_access, int, env, tl) +DEF_HELPER_2(probe_write_access, int, env, tl) diff --git a/target/e2k/helper_sm.c b/target/e2k/helper_sm.c new file mode 100644 index 0000000000..ae1c1c2221 --- /dev/null +++ b/target/e2k/helper_sm.c @@ -0,0 +1,27 @@ +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "cpu.h" +#include "exec/exec-all.h" +#include "qemu/host-utils.h" +#include "exec/helper-proto.h" +#include "translate.h" + +int HELPER(probe_read_access)(CPUE2KState *env, target_ulong addr) +{ + int flags; + void *ignore; + + flags = probe_access_flags(env, addr, MMU_DATA_LOAD, 0, true, &ignore, 0); + + return (flags & TLB_INVALID_MASK) == 0; +} + +int HELPER(probe_write_access)(CPUE2KState *env, target_ulong addr) +{ + int flags; + void *ignore; + + flags = probe_access_flags(env, addr, MMU_DATA_STORE, 0, true, &ignore, 0); + + return (flags & TLB_INVALID_MASK) == 0; +} diff --git a/target/e2k/meson.build b/target/e2k/meson.build index 9daefbdceb..2cd476164c 100644 --- a/target/e2k/meson.build +++ b/target/e2k/meson.build @@ -4,6 +4,7 @@ e2k_ss.add(files( 'gdbstub.c', 'helper.c', 'helper_int.c', + 'helper_sm.c', 'translate.c', 'translate/state.c', 'translate/control.c', diff --git a/target/e2k/translate.h b/target/e2k/translate.h index acc500ac2a..8505cc62b3 100644 --- a/target/e2k/translate.h +++ b/target/e2k/translate.h @@ -299,8 +299,7 @@ static inline void e2k_gen_lcntex(TCGv_i32 ret) void e2k_gen_store_preg(int idx, TCGv_i64 val); -void e2k_gen_reg_tag_read_i64(TCGv_i32 ret, TCGv_i32 idx); -void e2k_gen_reg_tag_read_i32(TCGv_i32 ret, TCGv_i32 idx); +void e2k_gen_reg_tag_read(TCGv_i32 ret, TCGv_i32 idx); void e2k_gen_reg_tag_write_i64(TCGv_i32 value, TCGv_i32 idx); void e2k_gen_reg_tag_write_i32(TCGv_i32 value, TCGv_i32 idx); diff --git a/target/e2k/translate/alc.c b/target/e2k/translate/alc.c index 193f4ecd2b..56702efa95 100644 --- a/target/e2k/translate/alc.c +++ b/target/e2k/translate/alc.c @@ -33,7 +33,7 @@ static inline void gen_reg_i64(DisasContext *ctx, Src64 *ret, uint8_t arg) gen_reg_index(t0, arg); ret->tag = e2k_get_temp_i32(ctx); ret->value = e2k_get_temp_i64(ctx); - e2k_gen_reg_tag_read_i32(ret->tag, t0); + e2k_gen_reg_tag_read(ret->tag, t0); e2k_gen_reg_read_i64(ret->value, t0); tcg_temp_free_i32(t0); @@ -46,7 +46,7 @@ static inline void gen_reg_i32(DisasContext *ctx, Src32 *ret, uint8_t arg) gen_reg_index(t0, arg); ret->tag = e2k_get_temp_i32(ctx); ret->value = e2k_get_temp_i32(ctx); - e2k_gen_reg_tag_read_i32(ret->tag, t0); + e2k_gen_reg_tag_read(ret->tag, t0); e2k_gen_reg_read_i32(ret->value, t0); tcg_temp_free_i32(t0); @@ -247,51 +247,107 @@ static inline void set_al_result_preg(DisasContext *ctx, int chan, int index, res->preg.value = value; } -static inline void gen_andn_i32(TCGv_i32 ret, TCGv_i32 x, TCGv_i32 y) +static void gen_tag_check_i64(bool sm, TCGv_i64 dst, TCGv_i32 dst_tag, + TCGv_i32 src_tag, TCGLabel *l) +{ + if (src_tag != NULL) { + TCGLabel *l0 = gen_new_label(); + TCGv_i32 t0 = tcg_temp_new_i32(); + + e2k_gen_reg_tag_check_i64(t0, src_tag); + tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l0); + if (sm) { + if (dst_tag != NULL) { + tcg_gen_movi_i32(dst_tag, 5); + } + if (dst != NULL) { + tcg_gen_ori_i64(dst, dst, (1UL << 62) | (1UL << 30)); + } + } else { + e2k_gen_exception(E2K_EXCP_ILLOPN); + } + if (l != NULL) { + tcg_gen_br(l); + } + gen_set_label(l0); + + tcg_temp_free_i32(t0); + } +} + +static void gen_tag_check_i32(bool sm, TCGv_i32 dst, TCGv_i32 dst_tag, + TCGv_i32 tag, TCGLabel *l) +{ + if (tag != NULL) { + TCGLabel *l0 = gen_new_label(); + TCGv_i32 t0 = tcg_temp_new_i32(); + + e2k_gen_reg_tag_check_i32(t0, tag); + tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l0); + if (sm) { + if (dst_tag != NULL) { + tcg_gen_movi_i32(dst_tag, 1); + } + if (dst != NULL) { + tcg_gen_ori_i32(dst, dst, 1 << 30); + } + } else { + e2k_gen_exception(E2K_EXCP_ILLOPN); + } + if (l != NULL) { + tcg_gen_br(l); + } + gen_set_label(l0); + + tcg_temp_free_i32(t0); + } +} + +static inline void gen_andn_i32(TCGv_i32 ret, TCGv_i32 src1, TCGv_i32 src2) { TCGv_i32 t0 = tcg_temp_new_i32(); - tcg_gen_and_i32(t0, x, y); - tcg_gen_not_i32(ret, t0); + tcg_gen_not_i32(t0, src2); + tcg_gen_and_i32(ret, src1, t0); tcg_temp_free_i32(t0); } -static inline void gen_andn_i64(TCGv_i64 ret, TCGv_i64 x, TCGv_i64 y) +static inline void gen_andn_i64(TCGv_i64 ret, TCGv_i64 src1, TCGv_i64 src2) { TCGv_i64 t0 = tcg_temp_new_i64(); - tcg_gen_and_i64(t0, x, y); - tcg_gen_not_i64(ret, t0); + tcg_gen_not_i64(t0, src2); + tcg_gen_and_i64(ret, src1, t0); tcg_temp_free_i64(t0); } -static inline void gen_orn_i32(TCGv_i32 ret, TCGv_i32 x, TCGv_i32 y) +static inline void gen_orn_i32(TCGv_i32 ret, TCGv_i32 src1, TCGv_i32 src2) { TCGv_i32 t0 = tcg_temp_new_i32(); - tcg_gen_or_i32(t0, x, y); - tcg_gen_not_i32(ret, t0); + tcg_gen_not_i32(t0, src2); + tcg_gen_or_i32(ret, src1, t0); tcg_temp_free_i32(t0); } -static inline void gen_orn_i64(TCGv_i64 ret, TCGv_i64 x, TCGv_i64 y) +static inline void gen_orn_i64(TCGv_i64 ret, TCGv_i64 src1, TCGv_i64 src2) { TCGv_i64 t0 = tcg_temp_new_i64(); - tcg_gen_or_i64(t0, x, y); - tcg_gen_not_i64(ret, t0); + tcg_gen_not_i64(t0, src2); + tcg_gen_or_i64(ret, src1, t0); tcg_temp_free_i64(t0); } -static inline void gen_xorn_i32(TCGv_i32 ret, TCGv_i32 x, TCGv_i32 y) +static inline void gen_xorn_i32(TCGv_i32 ret, TCGv_i32 src1, TCGv_i32 src2) { TCGv_i32 t0 = tcg_temp_new_i32(); - tcg_gen_xor_i32(t0, x, y); - tcg_gen_not_i32(ret, t0); + tcg_gen_not_i32(t0, src2); + tcg_gen_xor_i32(ret, src1, t0); tcg_temp_free_i32(t0); } -static inline void gen_xorn_i64(TCGv_i64 ret, TCGv_i64 x, TCGv_i64 y) +static inline void gen_xorn_i64(TCGv_i64 ret, TCGv_i64 src1, TCGv_i64 src2) { TCGv_i64 t0 = tcg_temp_new_i64(); - tcg_gen_xor_i64(t0, x, y); - tcg_gen_not_i64(ret, t0); + tcg_gen_not_i64(t0, src2); + tcg_gen_xor_i64(ret, src1, t0); tcg_temp_free_i64(t0); } @@ -515,16 +571,16 @@ static inline void gen_movehl_i64(TCGv_i64 ret, TCGv_i64 x, TCGv_i64 y) static inline void gen_merge_i32(TCGv_i32 ret, TCGv_i32 x, TCGv_i32 y, TCGv_i32 cond) { - TCGv_i32 one = tcg_const_i32(1); - tcg_gen_movcond_i32(TCG_COND_EQ, ret, cond, one, x, y); - tcg_temp_free_i32(one); + TCGv_i32 zero = tcg_const_i32(0); + tcg_gen_movcond_i32(TCG_COND_EQ, ret, cond, zero, x, y); + tcg_temp_free_i32(zero); } static inline void gen_merge_i64(TCGv_i64 ret, TCGv_i64 x, TCGv_i64 y, TCGv_i64 cond) { - TCGv_i64 one = tcg_const_i64(1); - tcg_gen_movcond_i64(TCG_COND_EQ, ret, cond, one, x, y); - tcg_temp_free_i64(one); + TCGv_i64 zero = tcg_const_i64(0); + tcg_gen_movcond_i64(TCG_COND_EQ, ret, cond, zero, x, y); + tcg_temp_free_i64(zero); } static inline bool is_mrgc(uint16_t rlp, int chan) @@ -590,17 +646,12 @@ static uint16_t find_cond(DisasContext *ctx, int chan) static inline void gen_mrgc_i64(DisasContext *ctx, int chan, TCGv_i64 ret) { uint16_t rlp = find_mrgc(ctx, chan); - TCGv_i64 inv = tcg_const_i64(GET_BIT(rlp, 7 + chan % 3)); TCGv_i64 t0 = tcg_temp_new_i64(); - TCGv_i64 t1 = tcg_temp_new_i64(); e2k_gen_cond_i64(ctx, t0, rlp & 0x7f); - tcg_gen_not_i64(t1, t0); - tcg_gen_movcond_i64(TCG_COND_EQ, ret, t0, inv, t0, t1); + tcg_gen_xori_i64(ret, t0, GET_BIT(rlp, 7 + chan % 3)); - tcg_temp_free_i64(t1); tcg_temp_free_i64(t0); - tcg_temp_free_i64(inv); } static inline void gen_mrgc_i32(DisasContext *dc, int chan, TCGv_i32 ret) @@ -611,6 +662,78 @@ static inline void gen_mrgc_i32(DisasContext *dc, int chan, TCGv_i32 ret) tcg_temp_free(t0); } +static inline void gen_udivd(TCGv_i64 ret, TCGv_i32 ret_tag, bool sm, + TCGv_i64 src1, TCGv_i64 src2) +{ + TCGLabel *l0 = gen_new_label(); + + if (sm) { + TCGLabel *l1 = gen_new_label(); + tcg_gen_brcondi_i64(TCG_COND_NE, src2, 0, l1); + tcg_gen_movi_i32(ret_tag, 5); + tcg_gen_movi_i64(ret, 0); + tcg_gen_br(l0); + gen_set_label(l1); + } + tcg_gen_movi_i32(ret_tag, 0); + tcg_gen_divu_i64(ret, src1, src2); + gen_set_label(l0); +} + +static inline void gen_udivs(TCGv_i32 ret, TCGv_i32 ret_tag, bool sm, + TCGv_i32 src1, TCGv_i32 src2) +{ + TCGLabel *l0 = gen_new_label(); + + if (sm) { + TCGLabel *l1 = gen_new_label(); + tcg_gen_brcondi_i32(TCG_COND_NE, src2, 0, l1); + tcg_gen_movi_i32(ret_tag, 5); + tcg_gen_movi_i32(ret, 0); + tcg_gen_br(l0); + gen_set_label(l1); + } + tcg_gen_movi_i32(ret_tag, 0); + tcg_gen_divu_i32(ret, src1, src2); + gen_set_label(l0); +} + +static inline void gen_sdivd(TCGv_i64 ret, TCGv_i32 ret_tag, bool sm, + TCGv_i64 src1, TCGv_i64 src2) +{ + TCGLabel *l0 = gen_new_label(); + + if (sm) { + TCGLabel *l1 = gen_new_label(); + tcg_gen_brcondi_i64(TCG_COND_NE, src2, 0, l1); + tcg_gen_movi_i32(ret_tag, 5); + tcg_gen_movi_i64(ret, 0); + tcg_gen_br(l0); + gen_set_label(l1); + } + tcg_gen_movi_i32(ret_tag, 0); + tcg_gen_div_i64(ret, src1, src2); + gen_set_label(l0); +} + +static inline void gen_sdivs(TCGv_i32 ret, TCGv_i32 ret_tag, bool sm, + TCGv_i32 src1, TCGv_i32 src2) +{ + TCGLabel *l0 = gen_new_label(); + + if (sm) { + TCGLabel *l1 = gen_new_label(); + tcg_gen_brcondi_i32(TCG_COND_NE, src2, 0, l1); + tcg_gen_movi_i32(ret_tag, 5); + tcg_gen_movi_i32(ret, 0); + tcg_gen_br(l0); + gen_set_label(l1); + } + tcg_gen_movi_i32(ret_tag, 0); + tcg_gen_div_i32(ret, src1, src2); + gen_set_label(l0); +} + static inline void gen_rr_i64(DisasContext *ctx, int chan) { uint32_t als = ctx->bundle.als[chan]; @@ -639,9 +762,10 @@ static inline void gen_rw_i64(DisasContext *ctx, int chan) { uint32_t als = ctx->bundle.als[chan]; Src64 s2 = get_src2_i64(ctx, chan); - TCGv_i32 t0 = tcg_const_i32(als & 0xff); + TCGv_i32 t0; - // TODO: check tags + gen_tag_check_i64(false, NULL, NULL, s2.tag, NULL); + t0 = tcg_const_i32(als & 0xff); gen_helper_state_reg_write_i64(cpu_env, t0, s2.value); tcg_temp_free_i32(t0); } @@ -650,9 +774,10 @@ static inline void gen_rw_i32(DisasContext *ctx, int chan) { uint32_t als = ctx->bundle.als[chan]; Src32 s2 = get_src2_i32(ctx, chan); - TCGv_i32 t0 = tcg_const_i32(als & 0xff); + TCGv_i32 t0; - // TODO: check tags + gen_tag_check_i32(false, NULL, NULL, s2.tag, NULL); + t0 = tcg_const_i32(als & 0xff); gen_helper_state_reg_write_i32(cpu_env, t0, s2.value); tcg_temp_free_i32(t0); } @@ -667,14 +792,10 @@ static void gen_getsp(DisasContext *ctx, int chan) set_al_result_reg64(ctx, chan, dst); } -/* FIXME: movtd: don't know what it does */ static void gen_movtd(DisasContext *ctx, int chan) { Src64 s2 = get_src2_i64(ctx, chan); - TCGv_i64 dst = e2k_get_temp_i64(ctx); - - tcg_gen_mov_i64(dst, s2.value); - set_al_result_reg64(ctx, chan, dst); + set_al_result_reg64_tag(ctx, chan, s2.value, s2.tag); } static MemOp gen_mas(DisasContext *ctx, int chan, MemOp memop, TCGv_i64 addr) @@ -704,31 +825,71 @@ static MemOp gen_mas(DisasContext *ctx, int chan, MemOp memop, TCGv_i64 addr) static void gen_ld(DisasContext *ctx, int chan, MemOp memop) { + bool sm = GET_BIT(ctx->bundle.als[chan], 31); + TCGLabel *l0 = gen_new_label(); + TCGLabel *l1 = gen_new_label(); Src64 s1 = get_src1_i64(ctx, chan); Src64 s2 = get_src2_i64(ctx, chan); - TCGv_i64 t0 = tcg_temp_new_i64(); + TCGv_i64 t0 = tcg_temp_local_new_i64(); + TCGv_i32 tag = e2k_get_temp_i32(ctx); TCGv_i64 dst = e2k_get_temp_i64(ctx); - // TODO: check tags + tcg_gen_movi_i64(dst, 0); + gen_tag_check_i64(sm, dst, tag, s1.tag, l1); + gen_tag_check_i64(sm, dst, tag, s2.tag, l1); + tcg_gen_add_i64(t0, s1.value, s2.value); memop = gen_mas(ctx, chan, memop, t0); + + if (sm) { + TCGv_i32 t1 = tcg_temp_new_i32(); + + gen_helper_probe_read_access(t1, cpu_env, t0); + tcg_gen_brcondi_i32(TCG_COND_EQ, t1, 1, l0); + tcg_temp_free_i32(t1); + tcg_gen_movi_i32(tag, 5); + tcg_gen_movi_i64(dst, 0x4afafafa4afafafa); + tcg_gen_br(l1); + } + + gen_set_label(l0); + tcg_gen_movi_i32(tag, 0); tcg_gen_qemu_ld_i64(dst, t0, ctx->mmuidx, memop); - set_al_result_reg64(ctx, chan, dst); + + gen_set_label(l1); + set_al_result_reg64_tag(ctx, chan, dst, tag); tcg_temp_free_i64(t0); } static void gen_st(DisasContext *ctx, int chan, MemOp memop) { + bool sm = GET_BIT(ctx->bundle.als[chan], 31); + TCGLabel *l0 = gen_new_label(); + TCGLabel *l1 = gen_new_label(); Src64 s1 = get_src1_i64(ctx, chan); Src64 s2 = get_src2_i64(ctx, chan); Src64 s4 = get_src4_i64(ctx, chan); - TCGv_i64 t0 = tcg_temp_new_i64(); + TCGv_i64 t0 = tcg_temp_local_new_i64(); + + gen_tag_check_i64(sm, NULL, NULL, s1.tag, l1); + gen_tag_check_i64(sm, NULL, NULL, s2.tag, l1); + gen_tag_check_i64(sm, NULL, NULL, s4.tag, l1); - // TODO: check tags tcg_gen_add_i64(t0, s1.value, s2.value); memop = gen_mas(ctx, chan, memop, t0); + + if (sm) { + TCGv_i32 t1 = tcg_temp_new_i32(); + + gen_helper_probe_write_access(t1, cpu_env, t0); + tcg_gen_brcondi_i32(TCG_COND_EQ, t1, 0, l1); + tcg_temp_free_i32(t1); + } + + gen_set_label(l0); tcg_gen_qemu_st_i64(s4.value, t0, ctx->mmuidx, memop); + gen_set_label(l1); tcg_temp_free_i64(t0); } @@ -736,39 +897,112 @@ static void gen_st(DisasContext *ctx, int chan, MemOp memop) static void gen_alopf1_i32(DisasContext *ctx, int chan, void (*op)(TCGv_i32, TCGv_i32, TCGv_i32)) { + bool sm = GET_BIT(ctx->bundle.als[chan], 31); Src32 s1 = get_src1_i32(ctx, chan); Src32 s2 = get_src2_i32(ctx, chan); + TCGv_i32 tag = e2k_get_temp_i32(ctx); TCGv_i32 dst = e2k_get_temp_i32(ctx); - // TODO: check tags + tcg_gen_movi_i32(tag, 0); (*op)(dst, s1.value, s2.value); - set_al_result_reg32(ctx, chan, dst); + + gen_tag_check_i32(sm, dst, tag, s1.tag, NULL); + gen_tag_check_i32(sm, dst, tag, s2.tag, NULL); + + set_al_result_reg32_tag(ctx, chan, dst, tag); } static void gen_alopf1_i64(DisasContext *ctx, int chan, void (*op)(TCGv_i64, TCGv_i64, TCGv_i64)) { + bool sm = GET_BIT(ctx->bundle.als[chan], 31); Src64 s1 = get_src1_i64(ctx, chan); Src64 s2 = get_src2_i64(ctx, chan); + TCGv_i32 tag = e2k_get_temp_i32(ctx); TCGv_i64 dst = e2k_get_temp_i64(ctx); - // TODO: check tags + tcg_gen_movi_i32(tag, 0); (*op)(dst, s1.value, s2.value); - set_al_result_reg64(ctx, chan, dst); + + gen_tag_check_i64(sm, dst, tag, s1.tag, NULL); + gen_tag_check_i64(sm, dst, tag, s2.tag, NULL); + + set_al_result_reg64_tag(ctx, chan, dst, tag); +} + +static void gen_alopf1_tag_i64(DisasContext *ctx, int chan, + void (*op)(TCGv_i64, TCGv_i32, bool, TCGv_i64, TCGv_i64)) +{ + bool sm = GET_BIT(ctx->bundle.als[chan], 31); + TCGLabel *l0 = gen_new_label(); + TCGLabel *l1 = gen_new_label(); + Src64 s1 = get_src1_i64(ctx, chan); + Src64 s2 = get_src2_i64(ctx, chan); + TCGv_i32 tag = e2k_get_temp_i32(ctx); + TCGv_i64 dst = e2k_get_temp_i64(ctx); + + tcg_gen_movi_i32(tag, 0); + (*op)(dst, tag, sm, s1.value, s2.value); + tcg_gen_brcondi_i32(TCG_COND_EQ, tag, 0, l0); + tcg_gen_ori_i64(dst, dst, (1UL << 62) | (1UL << 30)); + tcg_gen_br(l1); + + gen_set_label(l0); + gen_tag_check_i64(sm, dst, tag, s1.tag, NULL); + gen_tag_check_i64(sm, dst, tag, s2.tag, NULL); + + gen_set_label(l1); + set_al_result_reg64_tag(ctx, chan, dst, tag); +} + +static void gen_alopf1_tag_i32(DisasContext *ctx, int chan, + void (*op)(TCGv_i32, TCGv_i32, bool, TCGv_i32, TCGv_i32)) +{ + bool sm = GET_BIT(ctx->bundle.als[chan], 31); + TCGLabel *l0 = gen_new_label(); + TCGLabel *l1 = gen_new_label(); + Src32 s1 = get_src1_i32(ctx, chan); + Src32 s2 = get_src2_i32(ctx, chan); + TCGv_i32 tag = e2k_get_temp_i32(ctx); + TCGv_i32 dst = e2k_get_temp_i32(ctx); + + tcg_gen_movi_i32(tag, 0); + (*op)(dst, tag, sm, s1.value, s2.value); + tcg_gen_brcondi_i32(TCG_COND_EQ, tag, 0, l0); + tcg_gen_ori_i32(dst, dst, 1UL << 30); + tcg_gen_br(l1); + + gen_set_label(l0); + gen_tag_check_i32(sm, dst, tag, s1.tag, NULL); + gen_tag_check_i32(sm, dst, tag, s2.tag, NULL); + + gen_set_label(l1); + set_al_result_reg32_tag(ctx, chan, dst, tag); } static void gen_alopf1_cmp_i64(DisasContext *ctx, int chan, void (*op)(TCGv_i64, int, TCGv_i64, TCGv_i64)) { uint32_t als = ctx->bundle.als[chan]; + bool sm = extract32(als, 31, 1); int opc = extract32(als, 5, 3); int idx = extract32(als, 0, 5); + TCGLabel *l0 = gen_new_label(); + TCGLabel *l1 = gen_new_label(); Src64 s1 = get_src1_i64(ctx, chan); Src64 s2 = get_src2_i64(ctx, chan); TCGv_i64 dst = e2k_get_temp_i64(ctx); - // TODO: check tags + gen_tag_check_i32(sm, NULL, NULL, s1.tag, l0); + gen_tag_check_i32(sm, NULL, NULL, s2.tag, l0); + (*op)(dst, opc, s1.value, s2.value); + tcg_gen_br(l1); + + gen_set_label(l0); + tcg_gen_movi_i64(dst, 2); + + gen_set_label(l1); set_al_result_preg(ctx, chan, idx, dst); } @@ -776,49 +1010,65 @@ static void gen_alopf1_cmp_i32(DisasContext *ctx, int chan, void (*op)(TCGv_i32, int, TCGv_i32, TCGv_i32)) { uint32_t als = ctx->bundle.als[chan]; + bool sm = extract32(als, 31, 1); int opc = extract32(als, 5, 3); int idx = extract32(als, 0, 5); + TCGLabel *l0 = gen_new_label(); + TCGLabel *l1 = gen_new_label(); Src32 s1 = get_src1_i32(ctx, chan); Src32 s2 = get_src2_i32(ctx, chan); TCGv_i64 dst = e2k_get_temp_i64(ctx); TCGv_i32 t0 = tcg_temp_new_i32(); - // TODO: check tags + gen_tag_check_i32(sm, NULL, NULL, s1.tag, l0); + gen_tag_check_i32(sm, NULL, NULL, s2.tag, l0); + (*op)(t0, opc, s1.value, s2.value); tcg_gen_extu_i32_i64(dst, t0); + tcg_gen_br(l1); tcg_temp_free_i32(t0); + + gen_set_label(l0); + tcg_gen_movi_i64(dst, 2); + + gen_set_label(l1); set_al_result_preg(ctx, chan, idx, dst); } static void gen_alopf1_mrgc_i32(DisasContext *ctx, int chan) { - Src64 s1 = get_src1_i64(ctx, chan); - Src64 s2 = get_src2_i64(ctx, chan); + bool sm = extract32(ctx->bundle.als[chan], 31, 1); + Src32 s1 = get_src1_i32(ctx, chan); + Src32 s2 = get_src2_i32(ctx, chan); + TCGv_i32 tag = e2k_get_temp_i32(ctx); TCGv_i32 dst = e2k_get_temp_i32(ctx); - TCGv_i64 cond = tcg_temp_new_i64(); - TCGv_i64 t0 = tcg_temp_new_i64(); + TCGv_i32 cond = tcg_temp_new_i32(); - // TODO: check tags - gen_mrgc_i64(ctx, chan, cond); - gen_merge_i64(t0, s1.value, s2.value, cond); - tcg_gen_extrl_i64_i32(dst, t0); - set_al_result_reg32(ctx, chan, dst); + gen_mrgc_i32(ctx, chan, cond); + gen_merge_i32(dst, s1.value, s2.value, cond); + tcg_gen_movi_i32(tag, 0); + gen_tag_check_i32(sm, dst, tag, s1.tag, NULL); + gen_tag_check_i32(sm, dst, tag, s2.tag, NULL); + set_al_result_reg32_tag(ctx, chan, dst, tag); - tcg_temp_free_i64(t0); - tcg_temp_free_i64(cond); + tcg_temp_free_i32(cond); } static void gen_alopf1_mrgc_i64(DisasContext *ctx, int chan) { + bool sm = extract32(ctx->bundle.als[chan], 31, 1); Src64 s1 = get_src1_i64(ctx, chan); Src64 s2 = get_src2_i64(ctx, chan); TCGv_i64 cond = tcg_temp_new_i64(); + TCGv_i32 tag = e2k_get_temp_i32(ctx); TCGv_i64 dst = e2k_get_temp_i64(ctx); - // TODO: check tags gen_mrgc_i64(ctx, chan, cond); gen_merge_i64(dst, s1.value, s2.value, cond); - set_al_result_reg64(ctx, chan, dst); + tcg_gen_movi_i32(tag, 0); + gen_tag_check_i64(sm, dst, tag, s1.tag, NULL); + gen_tag_check_i64(sm, dst, tag, s2.tag, NULL); + set_al_result_reg64_tag(ctx, chan, dst, tag); tcg_temp_free_i64(cond); } @@ -929,28 +1179,28 @@ static void execute_alopf_simple(DisasContext *dc, int chan) e2k_gen_exception(0); gen_set_label(l0); - gen_alopf1_i32(dc, chan, tcg_gen_divu_i32); + gen_alopf1_tag_i32(dc, chan, gen_udivs); /* udivs */ } else { abort(); } break; case 0x41: if (is_div_chan(chan)) { - gen_alopf1_i64(dc, chan, tcg_gen_divu_i64); + gen_alopf1_tag_i64(dc, chan, gen_udivd); /* udivd */ } else { abort(); } break; case 0x42: if (is_div_chan(chan)) { - gen_alopf1_i32(dc, chan, tcg_gen_div_i32); + gen_alopf1_tag_i32(dc, chan, gen_sdivs); /* sdivs */ } else { abort(); } break; case 0x43: if (is_div_chan(chan)) { - gen_alopf1_i64(dc, chan, tcg_gen_div_i64); + gen_alopf1_tag_i64(dc, chan, gen_sdivd); /* sdivd */ } else { abort(); } @@ -1100,7 +1350,6 @@ void e2k_alc_commit(DisasContext *ctx) e2k_gen_reg_write_i64(res->reg.v64, res->reg.index); break; case AL_RESULT_PREG: - // TODO: write predicate register tag e2k_gen_store_preg(res->preg.index, res->preg.value); break; default: diff --git a/target/e2k/translate/state.c b/target/e2k/translate/state.c index fc9223bca0..ec1b177138 100644 --- a/target/e2k/translate/state.c +++ b/target/e2k/translate/state.c @@ -78,8 +78,8 @@ void e2k_gen_store_preg(int idx, TCGv_i64 val) gen_preg_offset(t0, idx); gen_preg_clear(t1, t0); - tcg_gen_setcondi_i64(TCG_COND_NE, t2, val, 0); - tcg_gen_shl_i64(t3, t2, t0); + tcg_gen_andi_i64(t2, val, 3); + tcg_gen_shl_i64(t3, val, t0); tcg_gen_or_i64(e2k_cs.pregs, t1, t3); tcg_temp_free_i64(t3); @@ -137,43 +137,29 @@ static inline void gen_reg_tags_read(TCGv_i32 ret, TCGv_i32 idx, int len) tcg_temp_free_i64(t4); } -void e2k_gen_reg_tag_read_i64(TCGv_i32 ret, TCGv_i32 idx) +void e2k_gen_reg_tag_read(TCGv_i32 ret, TCGv_i32 idx) { gen_reg_tags_read(ret, idx, E2K_REG_TAGS_SIZE); } -void e2k_gen_reg_tag_read_i32(TCGv_i32 ret, TCGv_i32 idx) -{ - gen_reg_tags_read(ret, idx, E2K_TAG_SIZE); -} - static inline void gen_tag_check(TCGv_i32 ret, TCGv_i32 tag) { // FIXME: what CPU does if tag is greater than 1? - tcg_gen_setcondi_i32(TCG_COND_GTU, ret, tag, 0); + tcg_gen_setcondi_i32(TCG_COND_NE, ret, tag, 0); } void e2k_gen_reg_tag_check_i64(TCGv_i32 ret, TCGv_i32 tag) { - 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(); - - e2k_gen_reg_tag_extract_lo(t0, tag); - gen_tag_check(t1, t0); - tcg_temp_free_i32(t0); - e2k_gen_reg_tag_extract_hi(t2, tag); - gen_tag_check(t3, t2); - tcg_temp_free_i32(t2); - tcg_gen_or_i32(ret, t1, t3); - tcg_temp_free_i32(t1); - tcg_temp_free_i32(t3); + gen_tag_check(ret, tag); } void e2k_gen_reg_tag_check_i32(TCGv_i32 ret, TCGv_i32 tag) { - gen_tag_check(ret, tag); + TCGv_i32 t0 = tcg_temp_new_i32(); + + e2k_gen_reg_tag_extract_lo(t0, tag); + gen_tag_check(ret, t0); + tcg_temp_free_i32(t0); } static inline void gen_reg_tags_write(TCGv_i32 value, TCGv_i32 idx, int len) @@ -184,7 +170,7 @@ static inline void gen_reg_tags_write(TCGv_i32 value, TCGv_i32 idx, int len) TCGv_i64 t3 = tcg_temp_new_i64(); TCGv_i64 t4 = tcg_const_i64(len); TCGv_i64 t5 = tcg_temp_new_i64(); - + gen_reg_tags_group_ptr(t0, idx); tcg_gen_ld_i64(t1, t0, 0); tcg_gen_extu_i32_i64(t2, value);