target: e2k: alc: Conditional execution.

This commit is contained in:
Denis Drakhnia 2020-11-24 11:12:01 +02:00
parent a10190535e
commit 8f060b59f0
4 changed files with 85 additions and 20 deletions

View File

@ -310,10 +310,17 @@ static inline void do_commit(DisasContext *ctx)
unsigned int i; unsigned int i;
for (i = 0; i < 6; i++) { for (i = 0; i < 6; i++) {
TCGLabel *l0 = gen_new_label();
Result *res = &ctx->alc[i]; Result *res = &ctx->alc[i];
if (!ctx->bundle.als_present[i]) { if (!ctx->bundle.als_present[i]) {
continue; continue;
} }
if (res->has_cond) {
tcg_gen_brcondi_i64(TCG_COND_EQ, res->cond, 0, l0);
}
switch(res->tag) { switch(res->tag) {
case RESULT_BASED_REG: case RESULT_BASED_REG:
e2k_gen_store_breg(res->u.reg.i, res->u.reg.v); e2k_gen_store_breg(res->u.reg.i, res->u.reg.v);
@ -330,6 +337,8 @@ static inline void do_commit(DisasContext *ctx)
default: default:
break; break;
} }
gen_set_label(l0);
} }
e2k_plu_commit(ctx); e2k_plu_commit(ctx);

View File

@ -110,6 +110,8 @@ enum ResultType {
typedef struct { typedef struct {
enum ResultType tag; enum ResultType tag;
bool has_cond;
TCGv_i64 cond;
union { union {
struct { struct {
unsigned int i; unsigned int i;
@ -158,6 +160,7 @@ typedef struct DisasContext {
int t64_len; int t64_len;
int ttl_len; int ttl_len;
TCGv_i64 cond[6];
Result alc[6]; Result alc[6];
PluResult plu[3]; PluResult plu[3];
ControlTransfer ct; ControlTransfer ct;
@ -220,6 +223,18 @@ TCGv_i64 e2k_get_breg(DisasContext *dc, int reg);
void e2k_gen_store_breg(int reg, TCGv_i64 val); void e2k_gen_store_breg(int reg, TCGv_i64 val);
TCGv_i64 e2k_get_greg(DisasContext *dc, int reg); TCGv_i64 e2k_get_greg(DisasContext *dc, int reg);
void e2k_gen_store_greg(int reg, TCGv_i64 val); void e2k_gen_store_greg(int reg, TCGv_i64 val);
void e2k_gen_cond_i32(DisasContext *ctx, TCGv_i32 ret, uint8_t psrc);
static inline void e2k_gen_cond_i64(DisasContext *ctx, TCGv_i64 ret,
uint8_t psrc)
{
TCGv_i32 t0 = tcg_temp_new_i32();
e2k_gen_cond_i32(ctx, t0, psrc);
tcg_gen_extu_i32_i64(ret, t0);
tcg_temp_free_i32(t0);
}
void e2k_gen_exception(DisasContext *dc, int which); void e2k_gen_exception(DisasContext *dc, int which);

View File

@ -454,14 +454,34 @@ static uint16_t find_mrgc(DisasContext *dc, int chan)
return 0; return 0;
} }
static inline void gen_cond_psrc(TCGv_i64 ret, uint8_t psrc) static inline bool is_cond(uint16_t rlp, int chan)
{ {
if ((psrc & 0xe0) == 0x60) { int is_mrgc = GET_BIT(rlp, 15);
e2k_gen_preg(ret, psrc & 0x1f); int cluster = GET_BIT(rlp, 14);
} else { int alc_mask = GET_FIELD(rlp, 10, 3);
/* TODO: lcntex, spred, pcnt */ int alc = GET_BIT(alc_mask, chan % 3);
abort();
return !is_mrgc && (cluster == (chan > 2)) && (alc != 0);
}
static uint16_t find_cond(DisasContext *ctx, int chan)
{
unsigned int i;
for (i = 0; ctx->bundle.cds_present[i]; i++) {
uint32_t cds = ctx->bundle.cds[i];
uint16_t rlp0 = cds >> 16;
uint16_t rlp1 = cds & 0xffff;
if (is_cond(rlp0, chan)) {
return rlp0;
}
if (is_cond(rlp1, chan)) {
return rlp1;
}
} }
return 0;
} }
static inline void gen_mrgc_i64(DisasContext *dc, int chan, TCGv_i64 ret) static inline void gen_mrgc_i64(DisasContext *dc, int chan, TCGv_i64 ret)
@ -480,7 +500,7 @@ static inline void gen_mrgc_i64(DisasContext *dc, int chan, TCGv_i64 ret)
t1 = tcg_temp_new_i64(); t1 = tcg_temp_new_i64();
inv = tcg_const_i64(GET_BIT(rlp, 7 + chan % 3)); inv = tcg_const_i64(GET_BIT(rlp, 7 + chan % 3));
gen_cond_psrc(t0, rlp & 0x7f); e2k_gen_cond_i64(dc, t0, rlp & 0x7f);
tcg_gen_not_i64(t1, t0); tcg_gen_not_i64(t1, t0);
tcg_gen_movcond_i64(TCG_COND_EQ, ret, t0, inv, t0, t1); tcg_gen_movcond_i64(TCG_COND_EQ, ret, t0, inv, t0, t1);
@ -848,22 +868,38 @@ static void execute_ext1(DisasContext *dc, int chan)
} }
} }
void e2k_execute_alc(DisasContext *ctx, int index) void e2k_execute_alc(DisasContext *ctx, int chan)
{ {
const UnpackedBundle *bundle = &ctx->bundle; const UnpackedBundle *bundle = &ctx->bundle;
uint16_t rlp = find_cond(ctx, chan);
TCGLabel *l0 = gen_new_label();
TCGv_i64 cond = NULL;
switch(bundle->ales_present[index]) { if (rlp != 0) {
TCGv_i64 t0 = tcg_temp_new_i64();
uint8_t psrc = GET_FIELD(rlp, 0, 7);
bool neg = GET_BIT(rlp, 7 + chan % 3);
e2k_gen_cond_i64(ctx, t0, psrc);
cond = e2k_get_temp_i64(ctx);
tcg_gen_xori_i64(cond, t0, neg);
tcg_gen_brcondi_i64(TCG_COND_EQ, cond, 0, l0);
tcg_temp_free_i64(t0);
}
switch(bundle->ales_present[chan]) {
case ALES_NONE: case ALES_NONE:
execute_alopf_simple(ctx, index); execute_alopf_simple(ctx, chan);
break; break;
case ALES_ALLOCATED: // 2 or 5 channel case ALES_ALLOCATED: // 2 or 5 channel
e2k_gen_exception(ctx, E2K_EXCP_ILLOPC); e2k_gen_exception(ctx, E2K_EXCP_ILLOPC);
break; break;
case ALES_PRESENT: { case ALES_PRESENT: {
uint8_t opc = GET_FIELD(bundle->ales[index], 8, 8); uint8_t opc = GET_FIELD(bundle->ales[chan], 8, 8);
switch (opc) { switch (opc) {
case 0x01: case 0x01:
execute_ext1(ctx, index); execute_ext1(ctx, chan);
break; break;
default: default:
e2k_gen_exception(ctx, E2K_EXCP_ILLOPC); e2k_gen_exception(ctx, E2K_EXCP_ILLOPC);
@ -875,4 +911,9 @@ void e2k_execute_alc(DisasContext *ctx, int index)
g_assert_not_reached(); g_assert_not_reached();
break; break;
} }
gen_set_label(l0);
ctx->alc[chan].has_cond = rlp != 0;
ctx->alc[chan].cond = cond;
} }

View File

@ -11,17 +11,17 @@ static void gen_get_lp(TCGv_i32 ret, uint16_t clp, int offset, TCGv_i32 lp[7])
tcg_gen_xori_i32(ret, lp[p], neg); tcg_gen_xori_i32(ret, lp[p], neg);
} }
static void gen_elp(DisasContext *ctx, TCGv_i32 ret, uint8_t elp) void e2k_gen_cond_i32(DisasContext *ctx, TCGv_i32 ret, uint8_t psrc)
{ {
if (!GET_BIT(elp, 6)) { if (!GET_BIT(psrc, 6)) {
if (GET_FIELD(elp, 0, 6) == 0) { if (GET_FIELD(psrc, 0, 6) == 0) {
e2k_gen_lcntex(ret); e2k_gen_lcntex(ret);
} else { } else {
// TODO: spred // TODO: spred
gen_helper_unimpl(cpu_env); gen_helper_unimpl(cpu_env);
} }
} else if (GET_FIELD(elp, 5, 2) == 0x40) { } else if (GET_FIELD(psrc, 5, 2) == 0x40) {
int val = GET_FIELD(elp, 0, 5); int val = GET_FIELD(psrc, 0, 5);
if (val == 0) { if (val == 0) {
// TODO: bgrpred // TODO: bgrpred
gen_helper_unimpl(cpu_env); gen_helper_unimpl(cpu_env);
@ -32,7 +32,7 @@ static void gen_elp(DisasContext *ctx, TCGv_i32 ret, uint8_t elp)
e2k_gen_exception(ctx, E2K_EXCP_ILLOPN); e2k_gen_exception(ctx, E2K_EXCP_ILLOPN);
} }
} else { } else {
int reg = GET_FIELD(elp, 0, 5); int reg = GET_FIELD(psrc, 0, 5);
TCGv_i64 t0 = tcg_temp_new_i64(); TCGv_i64 t0 = tcg_temp_new_i64();
e2k_gen_preg(t0, reg); e2k_gen_preg(t0, reg);
@ -111,12 +111,12 @@ void e2k_plu_execute(DisasContext *ctx)
if (i < 2) { if (i < 2) {
if (need[i * 2]) { if (need[i * 2]) {
int elp = GET_FIELD(bundle->pls[i], 24, 7); int elp = GET_FIELD(bundle->pls[i], 24, 7);
gen_elp(ctx, lp[i * 2], elp); e2k_gen_cond_i32(ctx, lp[i * 2], elp);
} }
if (need[i * 2 + 1]) { if (need[i * 2 + 1]) {
int elp = GET_FIELD(bundle->pls[i], 16, 7); int elp = GET_FIELD(bundle->pls[i], 16, 7);
gen_elp(ctx, lp[i * 2 + 1], elp); e2k_gen_cond_i32(ctx, lp[i * 2 + 1], elp);
} }
} }