e2k: Check address before MOVA memory read.

This commit is contained in:
Denis Drakhnia 2021-02-03 01:57:42 +02:00 committed by Denis Drakhnia
parent cf04412feb
commit 65675ac1cf
3 changed files with 32 additions and 10 deletions

View File

@ -36,6 +36,8 @@ typedef enum {
E2K_TAG_NON_NUMBER64 = 5,
} E2kRegisterTag;
#define E2K_MOVA_RESULT_INVALID 0xeaed0f70eaed0f70
#define CRS_SIZE (sizeof(E2KCrs))
#define CTPR_BASE_OFF 0

View File

@ -292,6 +292,7 @@ typedef struct {
bool is_set;
uint8_t dst;
TCGv_i32 index;
TCGv_i32 tag;
TCGv_i64 value;
} AauResult;

View File

@ -23,13 +23,14 @@ static void gen_load_prefetch_program(DisasContext *ctx)
gen_helper_aau_load_program(cpu_env);
}
static void gen_aau_result(DisasContext *ctx, Mova *instr, TCGv_i64 dst)
static void gen_aau_result(DisasContext *ctx, Mova *instr, TCGv_i64 dst,
TCGv_i32 tag)
{
AauResult *res = &ctx->aau_results[instr->chan];
res->is_set = true;
res->dst = instr->dst;
res->index = e2k_get_temp_i32(ctx);
res->value = dst;
res->tag = tag;
if (IS_REGULAR(instr->dst)) {
res->dst = instr->dst;
} else {
@ -38,10 +39,14 @@ static void gen_aau_result(DisasContext *ctx, Mova *instr, TCGv_i64 dst)
}
}
static void gen_ld(DisasContext *ctx, Mova *instr, TCGv ptr)
static void gen_checked_ld(DisasContext *ctx, Mova *instr, TCGv ptr)
{
MemOp memop = instr->be ? MO_BE : MO_LE;
TCGLabel *l0 = gen_new_label();
TCGLabel *l1 = gen_new_label();
TCGv_i32 tag = e2k_get_temp_i32(ctx);
TCGv_i64 dst = e2k_get_temp_i64(ctx);
TCGv_i32 t0 = tcg_temp_new_i32();
MemOp memop = instr->be ? MO_BE : MO_LE;
switch(instr->opc) {
case 1: memop |= MO_8; break; /* movab */
@ -53,8 +58,23 @@ static void gen_ld(DisasContext *ctx, Mova *instr, TCGv ptr)
break;
}
/* MOVA can try to read inaccessible memory */
gen_helper_probe_read_access(t0, cpu_env, ptr);
tcg_gen_brcondi_i32(TCG_COND_NE, t0, 0, l0);
tcg_temp_free_i32(t0);
/* if address is invalid */
tcg_gen_movi_i32(tag, E2K_TAG_NON_NUMBER64);
tcg_gen_movi_i64(dst, E2K_MOVA_RESULT_INVALID);
tcg_gen_br(l1);
/* if address is valid */
gen_set_label(l0);
tcg_gen_movi_i32(tag, E2K_TAG_NUMBER64);
tcg_gen_qemu_ld_i64(dst, ptr, 0, memop);
gen_aau_result(ctx, instr, dst);
gen_set_label(l1);
gen_aau_result(ctx, instr, dst, tag);
}
static inline void gen_mova_ptr(TCGv ret, Mova *instr)
@ -73,7 +93,8 @@ static inline void gen_mova_ptr(TCGv ret, Mova *instr)
static void gen_mova(DisasContext *ctx, Mova *instr)
{
TCGv t5 = tcg_temp_new();
/* branch in gen_checked_ld */
TCGv t5 = tcg_temp_local_new();
ctx->aau_am[instr->chan] = instr->am ? instr->area : -1;
// TODO: check ind has proper alignment
@ -85,7 +106,7 @@ static void gen_mova(DisasContext *ctx, Mova *instr)
case 2: /* movah */
case 3: /* movaw */
case 4: /* movad */
gen_ld(ctx, instr, t5);
gen_checked_ld(ctx, instr, t5);
break;
case 5: /* movaq */
e2k_todo_illop(ctx, "movaq");
@ -154,17 +175,15 @@ void e2k_aau_commit(DisasContext *ctx)
}
}
TCGv_i32 zero = tcg_const_i32(0);
for (i = 0; i < 4; i++) {
AauResult *res = &ctx->aau_results[i];
// TODO: aau.tags
if (res->is_set) {
e2k_gen_reg_tag_write_i64(zero, res->index);
e2k_gen_reg_tag_write_i64(res->tag, res->index);
e2k_gen_reg_write_i64(res->value, res->index);
}
}
tcg_temp_free_i32(zero);
for (i = 0; i < 4; i++) {
int area = ctx->aau_am[i];