diff options
author | Max Filippov <jcmvbkbc@gmail.com> | 2014-02-07 15:57:22 +0400 |
---|---|---|
committer | Max Filippov <jcmvbkbc@gmail.com> | 2014-02-24 04:47:01 +0400 |
commit | 7c84259019a945e4ff275994b96c0de4496d2a5e (patch) | |
tree | 0cea28c24e6656e3fa4ba1cdd2ab16140a86e2cf /target-xtensa | |
parent | 6502668237a27985dd386c6e42b46e8977b4f2c0 (diff) | |
download | qemu-7c84259019a945e4ff275994b96c0de4496d2a5e.zip qemu-7c84259019a945e4ff275994b96c0de4496d2a5e.tar.gz qemu-7c84259019a945e4ff275994b96c0de4496d2a5e.tar.bz2 |
target-xtensa: add basic checks to dcache opcodes
Check privilege level for privileged instructions (DHI, DHU, DII, DIU, DIWB,
DIWBI, DPFL are privileged), memory accessibility for instructions that
reference memory (all DH* and DPFL) and windowed register validity for all
data cache instructions.
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Diffstat (limited to 'target-xtensa')
-rw-r--r-- | target-xtensa/translate.c | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c index 355e75e..5ad900f 100644 --- a/target-xtensa/translate.c +++ b/target-xtensa/translate.c @@ -2235,6 +2235,20 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc) gen_load_store(st32, 2); break; +#define gen_dcache_hit_test(w, shift) do { \ + TCGv_i32 addr = tcg_temp_new_i32(); \ + TCGv_i32 res = tcg_temp_new_i32(); \ + gen_window_check1(dc, RRI##w##_S); \ + tcg_gen_addi_i32(addr, cpu_R[RRI##w##_S], \ + RRI##w##_IMM##w << shift); \ + tcg_gen_qemu_ld8u(res, addr, dc->cring); \ + tcg_temp_free(addr); \ + tcg_temp_free(res); \ + } while (0) + +#define gen_dcache_hit_test4() gen_dcache_hit_test(4, 4) +#define gen_dcache_hit_test8() gen_dcache_hit_test(8, 2) + case 7: /*CACHEc*/ if (RRI8_T < 8) { HAS_OPTION(XTENSA_OPTION_DCACHE); @@ -2242,49 +2256,69 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc) switch (RRI8_T) { case 0: /*DPFRc*/ + gen_window_check1(dc, RRI8_S); break; case 1: /*DPFWc*/ + gen_window_check1(dc, RRI8_S); break; case 2: /*DPFROc*/ + gen_window_check1(dc, RRI8_S); break; case 3: /*DPFWOc*/ + gen_window_check1(dc, RRI8_S); break; case 4: /*DHWBc*/ + gen_dcache_hit_test8(); break; case 5: /*DHWBIc*/ + gen_dcache_hit_test8(); break; case 6: /*DHIc*/ + gen_check_privilege(dc); + gen_dcache_hit_test8(); break; case 7: /*DIIc*/ + gen_check_privilege(dc); + gen_window_check1(dc, RRI8_S); break; case 8: /*DCEc*/ switch (OP1) { case 0: /*DPFLl*/ HAS_OPTION(XTENSA_OPTION_DCACHE_INDEX_LOCK); + gen_check_privilege(dc); + gen_dcache_hit_test4(); break; case 2: /*DHUl*/ HAS_OPTION(XTENSA_OPTION_DCACHE_INDEX_LOCK); + gen_check_privilege(dc); + gen_dcache_hit_test4(); break; case 3: /*DIUl*/ HAS_OPTION(XTENSA_OPTION_DCACHE_INDEX_LOCK); + gen_check_privilege(dc); + gen_window_check1(dc, RRI4_S); break; case 4: /*DIWBc*/ HAS_OPTION(XTENSA_OPTION_DCACHE); + gen_check_privilege(dc); + gen_window_check1(dc, RRI4_S); break; case 5: /*DIWBIc*/ HAS_OPTION(XTENSA_OPTION_DCACHE); + gen_check_privilege(dc); + gen_window_check1(dc, RRI4_S); break; default: /*reserved*/ @@ -2294,6 +2328,10 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc) } break; +#undef gen_dcache_hit_test +#undef gen_dcache_hit_test4 +#undef gen_dcache_hit_test8 + case 12: /*IPFc*/ HAS_OPTION(XTENSA_OPTION_ICACHE); break; |