e2k: Fix read and write probe access.
Signed-off-by: Denis Drakhnya <numas13@gmail.com>
This commit is contained in:
parent
6cbcdc4d5c
commit
c03d91b7c0
|
@ -19,11 +19,11 @@ DEF_HELPER_1(signal_return, void, env)
|
||||||
|
|
||||||
DEF_HELPER_4(setwd, void, env, int, int, int)
|
DEF_HELPER_4(setwd, void, env, int, int, int)
|
||||||
|
|
||||||
DEF_HELPER_FLAGS_2(probe_read_access, TCG_CALL_NO_RWG, int, env, tl)
|
DEF_HELPER_FLAGS_4(probe_read_access, TCG_CALL_NO_RWG, int, env, tl, int, int)
|
||||||
DEF_HELPER_FLAGS_2(probe_write_access, TCG_CALL_NO_RWG, int, env, tl)
|
DEF_HELPER_FLAGS_4(probe_write_access, TCG_CALL_NO_RWG, int, env, tl, int, int)
|
||||||
|
|
||||||
DEF_HELPER_1(aau_load_program, void, env)
|
DEF_HELPER_1(aau_load_program, void, env)
|
||||||
DEF_HELPER_4(mova_ptr, tl, env, int, int, int)
|
DEF_HELPER_6(mova_ptr, tl, env, int, int, int, int, int)
|
||||||
DEF_HELPER_3(aau_am, void, env, int, int)
|
DEF_HELPER_3(aau_am, void, env, int, int)
|
||||||
DEF_HELPER_4(dam_lock_addr, void, env, i64, int, int)
|
DEF_HELPER_4(dam_lock_addr, void, env, i64, int, int)
|
||||||
DEF_HELPER_4(dam_unlock_addr, int, env, i64, int, int)
|
DEF_HELPER_4(dam_unlock_addr, int, env, i64, int, int)
|
||||||
|
|
|
@ -45,7 +45,8 @@ void HELPER(aau_load_program)(CPUE2KState *env)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
target_ulong HELPER(mova_ptr)(CPUE2KState *env, int chan, int area, int ind)
|
target_ulong HELPER(mova_ptr)(CPUE2KState *env, int chan, int area, int ind,
|
||||||
|
int size, int mmu_idx)
|
||||||
{
|
{
|
||||||
E2KAauPrefState *ps = chan < 2 ? &env->aau.pl : &env->aau.pr;
|
E2KAauPrefState *ps = chan < 2 ? &env->aau.pl : &env->aau.pr;
|
||||||
E2KAauAreaState *as = &ps->area[area];
|
E2KAauAreaState *as = &ps->area[area];
|
||||||
|
@ -55,7 +56,7 @@ target_ulong HELPER(mova_ptr)(CPUE2KState *env, int chan, int area, int ind)
|
||||||
target_ulong page = ptr & ~(TARGET_PAGE_SIZE - 1);
|
target_ulong page = ptr & ~(TARGET_PAGE_SIZE - 1);
|
||||||
|
|
||||||
if (as->last_page == 0 || page != as->last_page) {
|
if (as->last_page == 0 || page != as->last_page) {
|
||||||
if (!helper_probe_read_access(env, page)) {
|
if (!helper_probe_read_access(env, ptr, size, mmu_idx)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
as->last_page = page;
|
as->last_page = page;
|
||||||
|
|
|
@ -5,22 +5,35 @@
|
||||||
#include "qemu/host-utils.h"
|
#include "qemu/host-utils.h"
|
||||||
#include "exec/helper-proto.h"
|
#include "exec/helper-proto.h"
|
||||||
|
|
||||||
int HELPER(probe_read_access)(CPUE2KState *env, target_ulong addr)
|
static int e2k_probe_access(CPUE2KState *env, target_ulong addr, int size,
|
||||||
|
MMUAccessType access_type, int mmu_idx)
|
||||||
{
|
{
|
||||||
|
target_ulong addr_end = addr + size;
|
||||||
int flags;
|
int flags;
|
||||||
void *ignore;
|
void *ignore;
|
||||||
|
|
||||||
flags = probe_access_flags(env, addr, MMU_DATA_LOAD, 0, true, &ignore, 0);
|
flags = probe_access_flags(env, addr, access_type, mmu_idx,
|
||||||
|
true, &ignore, 0);
|
||||||
|
|
||||||
return (flags & TLB_INVALID_MASK) == 0;
|
if (flags & TLB_INVALID_MASK) {
|
||||||
|
return 0;
|
||||||
|
} else if ((addr & ~TARGET_PAGE_MASK) != (addr_end & ~TARGET_PAGE_MASK)) {
|
||||||
|
flags = probe_access_flags(env, addr_end, access_type, mmu_idx,
|
||||||
|
true, &ignore, 0);
|
||||||
|
return !(flags & TLB_INVALID_MASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
int HELPER(probe_write_access)(CPUE2KState *env, target_ulong addr)
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int HELPER(probe_read_access)(CPUE2KState *env, target_ulong addr,
|
||||||
|
int size, int mmu_idx)
|
||||||
{
|
{
|
||||||
int flags;
|
return e2k_probe_access(env, addr, size, MMU_DATA_LOAD, mmu_idx);
|
||||||
void *ignore;
|
}
|
||||||
|
|
||||||
flags = probe_access_flags(env, addr, MMU_DATA_STORE, 0, true, &ignore, 0);
|
int HELPER(probe_write_access)(CPUE2KState *env, target_ulong addr,
|
||||||
|
int size, int mmu_idx)
|
||||||
return (flags & TLB_INVALID_MASK) == 0;
|
{
|
||||||
|
return e2k_probe_access(env, addr, size, MMU_DATA_STORE, mmu_idx);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3672,6 +3672,30 @@ static MemOp scan_st_mas(Instr *instr, MemOp memop, bool *skip, bool *check)
|
||||||
return memop;
|
return memop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void gen_probe_read_access(TCGv_i32 ret, TCGv addr, int size,
|
||||||
|
int mmu_idx)
|
||||||
|
{
|
||||||
|
TCGv_i32 t0 = tcg_const_i32(size);
|
||||||
|
TCGv_i32 t1 = tcg_const_i32(mmu_idx);
|
||||||
|
|
||||||
|
gen_helper_probe_read_access(ret, cpu_env, addr, t0, t1);
|
||||||
|
|
||||||
|
tcg_temp_free_i32(t1);
|
||||||
|
tcg_temp_free_i32(t0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gen_probe_write_access(TCGv_i32 ret, TCGv addr, int size,
|
||||||
|
int mmu_idx)
|
||||||
|
{
|
||||||
|
TCGv_i32 t0 = tcg_const_i32(size);
|
||||||
|
TCGv_i32 t1 = tcg_const_i32(mmu_idx);
|
||||||
|
|
||||||
|
gen_helper_probe_write_access(ret, cpu_env, addr, t0, t1);
|
||||||
|
|
||||||
|
tcg_temp_free_i32(t1);
|
||||||
|
tcg_temp_free_i32(t0);
|
||||||
|
}
|
||||||
|
|
||||||
static void gen_ld_raw_i64(Instr *instr, TCGv_i32 tag, TCGv addr,
|
static void gen_ld_raw_i64(Instr *instr, TCGv_i32 tag, TCGv addr,
|
||||||
MemOp memop, bool skip, bool save)
|
MemOp memop, bool skip, bool save)
|
||||||
{
|
{
|
||||||
|
@ -3682,7 +3706,7 @@ static void gen_ld_raw_i64(Instr *instr, TCGv_i32 tag, TCGv addr,
|
||||||
TCGLabel *l1 = gen_new_label();
|
TCGLabel *l1 = gen_new_label();
|
||||||
TCGv_i32 t0 = tcg_temp_new_i32();
|
TCGv_i32 t0 = tcg_temp_new_i32();
|
||||||
|
|
||||||
gen_helper_probe_read_access(t0, cpu_env, addr);
|
gen_probe_read_access(t0, addr, memop_size(memop), instr->ctx->mmuidx);
|
||||||
tcg_gen_brcondi_i32(TCG_COND_NE, t0, 0, l1);
|
tcg_gen_brcondi_i32(TCG_COND_NE, t0, 0, l1);
|
||||||
|
|
||||||
/* address is not available */
|
/* address is not available */
|
||||||
|
@ -3742,7 +3766,7 @@ static void gen_ld_raw_i128(Instr *instr, TCGv_i32 tag, TCGv addr,
|
||||||
TCGLabel *l1 = gen_new_label();
|
TCGLabel *l1 = gen_new_label();
|
||||||
TCGv_i32 t3 = tcg_temp_new_i32();
|
TCGv_i32 t3 = tcg_temp_new_i32();
|
||||||
|
|
||||||
gen_helper_probe_read_access(t3, cpu_env, addr);
|
gen_probe_read_access(t3, addr, 16, instr->ctx->mmuidx);
|
||||||
tcg_gen_brcondi_i32(TCG_COND_NE, t3, 0, l1);
|
tcg_gen_brcondi_i32(TCG_COND_NE, t3, 0, l1);
|
||||||
|
|
||||||
/* address is not available */
|
/* address is not available */
|
||||||
|
@ -3851,7 +3875,8 @@ static void gen_atomic_cmpxchg_i32(Instr *instr, TCGv_i32 value, TCGv addr,
|
||||||
if (instr->sm) { \
|
if (instr->sm) { \
|
||||||
TCGv_i32 t0 = tcg_temp_new_i32(); \
|
TCGv_i32 t0 = tcg_temp_new_i32(); \
|
||||||
\
|
\
|
||||||
gen_helper_probe_write_access(t0, cpu_env, addr); \
|
gen_probe_write_access(t0, addr, memop_size(memop), \
|
||||||
|
instr->ctx->mmuidx); \
|
||||||
tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l0); \
|
tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l0); \
|
||||||
\
|
\
|
||||||
tcg_temp_free_i32(t0); \
|
tcg_temp_free_i32(t0); \
|
||||||
|
@ -3904,7 +3929,7 @@ static void gen_st_raw_i128(Instr *instr, TCGv addr,
|
||||||
if (instr->sm) {
|
if (instr->sm) {
|
||||||
TCGv_i32 t0 = tcg_temp_new_i32();
|
TCGv_i32 t0 = tcg_temp_new_i32();
|
||||||
|
|
||||||
gen_helper_probe_write_access(t0, cpu_env, addr);
|
gen_probe_write_access(t0, addr, 16, instr->ctx->mmuidx);
|
||||||
tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l0);
|
tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l0);
|
||||||
|
|
||||||
tcg_temp_free_i32(t0);
|
tcg_temp_free_i32(t0);
|
||||||
|
@ -3985,7 +4010,7 @@ static void gen_stm_raw_i128(Instr *instr, TCGv addr,
|
||||||
if (instr->sm) {
|
if (instr->sm) {
|
||||||
TCGv_i32 t0 = tcg_temp_new_i32();
|
TCGv_i32 t0 = tcg_temp_new_i32();
|
||||||
|
|
||||||
gen_helper_probe_write_access(t0, cpu_env, addr);
|
gen_probe_write_access(t0, addr, 16, instr->ctx->mmuidx);
|
||||||
tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l0);
|
tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l0);
|
||||||
|
|
||||||
tcg_temp_free_i32(t0);
|
tcg_temp_free_i32(t0);
|
||||||
|
@ -4349,7 +4374,7 @@ static void gen_staaqp(Instr *instr)
|
||||||
|
|
||||||
if (instr->sm) {
|
if (instr->sm) {
|
||||||
TCGv_i32 t1 = tcg_temp_new_i32();
|
TCGv_i32 t1 = tcg_temp_new_i32();
|
||||||
gen_helper_probe_write_access(t1, cpu_env, t0);
|
gen_probe_write_access(t1, t0, 16, instr->ctx->mmuidx);
|
||||||
tcg_gen_brcondi_i32(TCG_COND_EQ, t1, 0, l0);
|
tcg_gen_brcondi_i32(TCG_COND_EQ, t1, 0, l0);
|
||||||
tcg_temp_free_i32(t1);
|
tcg_temp_free_i32(t1);
|
||||||
}
|
}
|
||||||
|
@ -4403,7 +4428,7 @@ static void gen_staa_i64(Instr *instr)
|
||||||
|
|
||||||
if (instr->sm) {
|
if (instr->sm) {
|
||||||
TCGv_i32 t1 = tcg_temp_new_i32();
|
TCGv_i32 t1 = tcg_temp_new_i32();
|
||||||
gen_helper_probe_write_access(t1, cpu_env, t0);
|
gen_probe_write_access(t1, t0, memop_size(memop), instr->ctx->mmuidx);
|
||||||
tcg_gen_brcondi_i32(TCG_COND_EQ, t1, 0, l0);
|
tcg_gen_brcondi_i32(TCG_COND_EQ, t1, 0, l0);
|
||||||
tcg_temp_free_i32(t1);
|
tcg_temp_free_i32(t1);
|
||||||
}
|
}
|
||||||
|
@ -4457,7 +4482,7 @@ static void gen_staa_i32(Instr *instr, MemOp memop)
|
||||||
|
|
||||||
if (instr->sm) {
|
if (instr->sm) {
|
||||||
TCGv_i32 t1 = tcg_temp_new_i32();
|
TCGv_i32 t1 = tcg_temp_new_i32();
|
||||||
gen_helper_probe_write_access(t1, cpu_env, t0);
|
gen_probe_write_access(t1, t0, memop_size(memop), instr->ctx->mmuidx);
|
||||||
tcg_gen_brcondi_i32(TCG_COND_EQ, t1, 0, l0);
|
tcg_gen_brcondi_i32(TCG_COND_EQ, t1, 0, l0);
|
||||||
tcg_temp_free_i32(t1);
|
tcg_temp_free_i32(t1);
|
||||||
}
|
}
|
||||||
|
@ -6784,12 +6809,17 @@ static void gen_checked_ld_qp(DisasContext *ctx, Mova *instr, TCGv addr)
|
||||||
tagged_free_ptr(r);
|
tagged_free_ptr(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void gen_mova_ptr(TCGv ret, Mova *instr)
|
static void gen_mova_ptr(TCGv ret, Mova *instr, int size, int mmu_idx)
|
||||||
{
|
{
|
||||||
TCGv_i32 t0 = tcg_const_i32(instr->chan);
|
TCGv_i32 t0 = tcg_const_i32(instr->chan);
|
||||||
TCGv_i32 t1 = tcg_const_i32(instr->area);
|
TCGv_i32 t1 = tcg_const_i32(instr->area);
|
||||||
TCGv_i32 t2 = tcg_const_i32(instr->ind);
|
TCGv_i32 t2 = tcg_const_i32(instr->ind);
|
||||||
gen_helper_mova_ptr(ret, cpu_env, t0, t1, t2);
|
TCGv_i32 t3 = tcg_const_i32(size);
|
||||||
|
TCGv_i32 t4 = tcg_const_i32(mmu_idx);
|
||||||
|
|
||||||
|
gen_helper_mova_ptr(ret, cpu_env, t0, t1, t2, t3, t4);
|
||||||
|
tcg_temp_free_i32(t4);
|
||||||
|
tcg_temp_free_i32(t3);
|
||||||
tcg_temp_free_i32(t2);
|
tcg_temp_free_i32(t2);
|
||||||
tcg_temp_free_i32(t1);
|
tcg_temp_free_i32(t1);
|
||||||
tcg_temp_free_i32(t0);
|
tcg_temp_free_i32(t0);
|
||||||
|
@ -6803,19 +6833,20 @@ static void gen_mova(DisasContext *ctx, Mova *instr)
|
||||||
ctx->aau_am[instr->chan] = instr->am ? instr->area : -1;
|
ctx->aau_am[instr->chan] = instr->am ? instr->area : -1;
|
||||||
// TODO: check ind has proper alignment
|
// TODO: check ind has proper alignment
|
||||||
// TODO: check ind is less than mrng
|
// TODO: check ind is less than mrng
|
||||||
gen_mova_ptr(t0, instr);
|
|
||||||
|
|
||||||
switch(instr->opc) {
|
switch(instr->opc) {
|
||||||
case 1: /* movab */
|
case 1: /* movab */
|
||||||
case 2: /* movah */
|
case 2: /* movah */
|
||||||
case 3: /* movaw */
|
case 3: /* movaw */
|
||||||
case 4: /* movad */
|
case 4: /* movad */
|
||||||
|
gen_mova_ptr(t0, instr, 1 << (instr->opc - 1), ctx->mmuidx);
|
||||||
gen_checked_ld(ctx, instr, t0);
|
gen_checked_ld(ctx, instr, t0);
|
||||||
break;
|
break;
|
||||||
case 5: /* movaq */
|
case 5: /* movaq */
|
||||||
e2k_todo_illop(ctx, "movaq");
|
e2k_todo_illop(ctx, "movaq");
|
||||||
break;
|
break;
|
||||||
case 7: /* movaqp */
|
case 7: /* movaqp */
|
||||||
|
gen_mova_ptr(t0, instr, 16, ctx->mmuidx);
|
||||||
gen_checked_ld_qp(ctx, instr, t0);
|
gen_checked_ld_qp(ctx, instr, t0);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
Loading…
Reference in New Issue