e2k: Check address before MOVA memory read.
This commit is contained in:
parent
cf04412feb
commit
65675ac1cf
@ -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
|
||||
|
@ -292,6 +292,7 @@ typedef struct {
|
||||
bool is_set;
|
||||
uint8_t dst;
|
||||
TCGv_i32 index;
|
||||
TCGv_i32 tag;
|
||||
TCGv_i64 value;
|
||||
} AauResult;
|
||||
|
||||
|
@ -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];
|
||||
|
Loading…
Reference in New Issue
Block a user