e2k: check predicate registers tags

This commit is contained in:
Denis Drakhnia 2024-01-03 17:10:23 +02:00
parent b7aa8589e9
commit 9044a3bb28

View File

@ -101,7 +101,7 @@ static TCGv_i32 cpu_bsize; /* holds rsz * 2 + 2 */
static TCGv_i32 cpu_bcur; /* holds rcur * 2 */
static TCGv_i64 cpu_pregs;
static TCGv_i32 cpu_psize; /* holds psz */
static TCGv_i32 cpu_pcur; /* holds pcur */
static TCGv_i32 cpu_pcur; /* holds pcur * 2 */
static TCGv_i64 cpu_last_val0;
static TCGv_i64 cpu_last_val1;
/* lsr */
@ -1108,36 +1108,27 @@ static void gen_preg_offset(DisasContext *ctx, TCGv_i64 ret, int preg)
{
TCGv_i32 t0 = tcg_temp_new_i32();
TCGv_i32 t1 = tcg_temp_new_i32();
TCGv_i32 p_size = tcg_constant_i32(ctx->p_size);
TCGv_i32 p_size = tcg_constant_i32(ctx->p_size * 2);
tcg_gen_addi_i32(t0, cpu_pcur, preg);
tcg_gen_addi_i32(t0, cpu_pcur, preg * 2);
tcg_gen_sub_i32(t1, t0, p_size);
tcg_gen_movcond_i32(TCG_COND_LEU, t0, p_size, t0, t1, t0);
tcg_gen_discard_i32(t1);
tcg_gen_shli_i32(t0, t0, 1);
tcg_gen_extu_i32_i64(ret, t0);
}
static void gen_preg_raw_i64(DisasContext *ctx, TCGv_i64 ret, int preg)
static void gen_preg_raw_i32(DisasContext *ctx, TCGv_i32 ret, int preg)
{
TCGv_i64 t0 = tcg_temp_new_i64();
// TODO: read preg tag
if (ctx->p_size > 1 && preg < ctx->p_size) {
gen_preg_offset(ctx, t0, preg);
tcg_gen_shr_i64(t0, cpu_pregs, t0);
} else {
tcg_gen_shri_i64(t0, cpu_pregs, preg * 2);
}
tcg_gen_andi_i64(ret, t0, 1);
}
static void gen_preg_raw_i32(DisasContext *ctx, TCGv_i32 ret, int reg)
{
TCGv_i64 t0 = tcg_temp_new_i64();
gen_preg_raw_i64(ctx, t0, reg);
tcg_gen_extrl_i64_i32(ret, t0);
tcg_gen_andi_i32(ret, ret, ctx->enable_tags ? 3 : 1);
}
static bool gen_saved_preg_i32(DisasContext *ctx, TCGv_i32 ret, int index)
@ -1179,6 +1170,18 @@ static void gen_preg_set_i32(DisasContext *ctx, int preg, TCGv_i32 val)
}
}
static void gen_preg_check_tag(DisasContext *ctx, TCGv_i32 val) {
if (ctx->enable_tags) {
TCGv_i32 t0 = tcg_temp_new_i32();
TCGLabel *l0 = gen_new_label();
tcg_gen_andi_i32(t0, val, 2);
tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l0);
gen_excp_illopc();
gen_set_label(l0);
}
}
static void gen_reg_ptr(TCGv_ptr ret, TCGv_i32 idx)
{
TCGv_ptr t0 = tcg_temp_new_ptr();
@ -1992,9 +1995,28 @@ static void gen_plu(DisasContext *ctx)
switch (opc) {
case 0: /* andp */
// FIXME: what is the difference between `andp` and `landp`?
case 1: /* landp */
tcg_gen_and_i32(lp[4 + i], p0, p1);
if (ctx->enable_tags) {
TCGv_i32 t0 = tcg_temp_new_i32();
uint32_t tbl;
tcg_gen_shli_i32(t0, p0, 2);
tcg_gen_or_i32(t0, t0, p1);
tcg_gen_shli_i32(t0, t0, 1);
// a=11 a=10 a=01 a=00
// andp: 0b10101010_10101010_10100100_10100000
// landp: 0b10101010_10101010_10100100_00000000
if (opc == 0) {
tbl = 0xaaaaa4a0;
} else {
tbl = 0xaaaaa400;
}
tcg_gen_shr_i32(t0, tcg_constant_i32(tbl), t0);
tcg_gen_andi_i32(lp[4 + i], t0, 3);
} else {
tcg_gen_and_i32(lp[4 + i], p0, p1);
}
if (vdst) {
gen_preg_set_i32(ctx, pdst, lp[4 + i]);
}
@ -2371,9 +2393,13 @@ static void gen_al_result_s(Alop *alop, Tagged_i32 arg)
}
}
static void gen_al_result_b(Alop *alop, Tagged_i32 arg)
static void gen_al_result_b(Alop *alop, Tagged_i32 v)
{
gen_preg_set_i32(alop->ctx, alop->als.dst_preg, arg.val);
if (alop->ctx->enable_tags) {
tcg_gen_movcond_i32(TCG_COND_EQ, v.val, v.tag, tcg_constant_i32(0),
v.val, tcg_constant_i32(2));
}
gen_preg_set_i32(alop->ctx, alop->als.dst_preg, v.val);
}
static inline bool check_qr(uint8_t src, int chan)
@ -6128,19 +6154,14 @@ static inline bool rlp_is_chan_pred(uint16_t rlp, int chan)
return !extract16(rlp, 15, 1) && rlp_check_chan(rlp, chan);
}
static void gen_alop_pred(Alop *alop, TCGLabel *l)
static TCGLabel *gen_alop_pred(Alop *alop)
{
DisasContext *ctx = alop->ctx;
bool has_pcnt = false;
bool has_preg = false;
TCGv_i32 t0 = tcg_temp_new_i32();
TCGv_i32 t1 = tcg_temp_new_i32();
TCGv_i32 t2 = tcg_temp_new_i32();
TCGv_i32 pcnt = NULL, preg = NULL, t2 = NULL;
TCGLabel *l0 = NULL;
bool has_pcnt = false, has_preg = false;
int i, j, chan = alop->chan;
tcg_gen_movi_i32(t0, 0);
tcg_gen_movi_i32(t1, 0);
for (i = 0; i < 3; i++) {
uint16_t *cds = (uint16_t *) &ctx->bundle.cds[i];
@ -6158,6 +6179,10 @@ static void gen_alop_pred(Alop *alop, TCGLabel *l)
continue;
}
if (!t2) {
t2 = tcg_temp_new_i32();
}
switch(kind) {
case 0x2: /* %pcntN */
has_pcnt = true;
@ -6165,7 +6190,11 @@ static void gen_alop_pred(Alop *alop, TCGLabel *l)
if (invert) {
tcg_gen_xori_i32(t2, t2, 1);
}
tcg_gen_or_i32(t0, t0, t2);
if (!pcnt) {
pcnt = tcg_temp_new_i32();
tcg_gen_movi_i32(pcnt, 0);
}
tcg_gen_or_i32(pcnt, pcnt, t2);
break;
case 0x3: /* %predN */
has_preg = true;
@ -6173,7 +6202,11 @@ static void gen_alop_pred(Alop *alop, TCGLabel *l)
if (invert) {
tcg_gen_xori_i32(t2, t2, 1);
}
tcg_gen_or_i32(t1, t1, t2);
if (!preg) {
preg = tcg_temp_new_i32();
tcg_gen_movi_i32(preg, 0);
}
tcg_gen_or_i32(preg, preg, t2);
break;
default:
if (ctx->strict) {
@ -6185,18 +6218,32 @@ static void gen_alop_pred(Alop *alop, TCGLabel *l)
}
if (has_preg || has_pcnt) {
TCGv_i32 cond = tcg_temp_new_i32();
TCGv_i32 cond = has_pcnt ? pcnt : preg;
l0 = gen_new_label();
if (has_preg && has_pcnt) {
tcg_gen_and_i32(cond, t0, t1);
} else if (has_preg) {
tcg_gen_mov_i32(cond, t1);
} else {
tcg_gen_mov_i32(cond, t0);
if (ctx->enable_tags) {
TCGv_i32 t0 = tcg_temp_new_i32();
TCGv_i32 t1 = tcg_temp_new_i32();
// invalid preg must be ignored in prologue
tcg_gen_shri_i32(t0, preg, 1);
tcg_gen_xori_i32(t1, pcnt, 1);
tcg_gen_and_i32(t0, t0, t1);
tcg_gen_brcondi_i32(TCG_COND_NE, t0, 0, l0);
}
tcg_gen_and_i32(cond, pcnt, preg);
}
tcg_gen_brcondi_i32(TCG_COND_EQ, cond, 0, l);
if (has_preg && !alop->als.sm) {
gen_preg_check_tag(ctx, preg);
}
tcg_gen_brcondi_i32(TCG_COND_EQ, cond, 0, l0);
}
return l0;
}
static void decode_alop(Alop *alop, AlesFlag ales_present)
@ -6447,7 +6494,6 @@ static void gen_alop(Alop *alop)
}
gen_alop_save_dst(alop);
l0 = gen_new_label();
l1 = gen_new_label();
if (ctx->loop_mode && is_alop_store(alop)) {
@ -6458,7 +6504,7 @@ static void gen_alop(Alop *alop)
gen_dec_lsr_strmd(ctx->loop_end);
}
gen_alop_pred(alop, l0);
l0 = gen_alop_pred(alop);
switch (alop->format) {
case ALOPF21_ICOMB:
@ -6478,7 +6524,9 @@ static void gen_alop(Alop *alop)
break;
}
gen_set_label(l0);
if (l0) {
gen_set_label(l0);
}
if (alop->format == ALOPF10 && (alop->als.aaopc & 1)
&& (alop->mas & 0x7) != 0x7)
@ -7299,7 +7347,7 @@ static void do_branch(DisasContext *ctx, target_ulong pc_next)
}
if (abp & ABPF) {
gen_dec_wrapi_i32(cpu_pcur, cpu_pcur, 1, ctx->p_size);
gen_dec_wrapi_i32(cpu_pcur, cpu_pcur, 2, ctx->p_size * 2);
}
if (abn & ABNF) {
@ -7319,7 +7367,7 @@ static void do_branch(DisasContext *ctx, target_ulong pc_next)
}
if (abp & ABPT) {
gen_dec_wrapi_i32(cpu_pcur, cpu_pcur, 1, ctx->p_size);
gen_dec_wrapi_i32(cpu_pcur, cpu_pcur, 2, ctx->p_size * 2);
}
if (abn & ABNT) {