Message ID | CABtrw+ORds75FyUH+E0k2dqQuDfFXvhi8Fobmf=V+Qa_Xo0WtQ@mail.gmail.com |
---|---|
State | New |
Headers | show |
On 17 April 2012 10:53, Alexey Starikovskiy <aystarik@gmail.com> wrote: > I was wondering how to implement disabling of SWP/SWPB execution if > they are not enabled in SCTLR.SW bit. > One way to do this is to intercept writes to SCTLR, do tb_flush and > make SWP [un]defined for any following translations depending on the > c1_sys state during the translation. This is the right way to do this. The standard use case is that this SCTLR bit will never be touched by anybody and will retain its reset value. The less common case is that the OS will set it once on startup. Changing the value more often than that is basically vanishingly unlikely, and so trying to dynamically emit code that looks at the SCTLR is needless complication and slows down the case where you actually are using SWP. -- PMM
diff --git a/target-arm/translate.c b/target-arm/translate.c index 7a3c7d6..a54b436 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -7415,7 +7415,12 @@ static void disas_arm_insn(CPUARMState * env, DisasContex } tcg_temp_free(addr); } else { - /* SWP instruction */ + /* SWP/SWPB instruction */ + TCGv sctlr = load_cpu_field(cp15.c1_sys); + int fail_label = gen_new_label(); + int done_label = gen_new_label(); + tcg_gen_andi_i32(sctlr, sctlr, 1 << 10); /* Check if SW + tcg_gen_brcondi_i32(TCG_COND_EQ, sctlr, 0, fail_label); rm = (insn) & 0xf; /* ??? This is not really atomic. However we know @@ -7432,6 +7437,11 @@ static void disas_arm_insn(CPUARMState * env, DisasContex } tcg_temp_free_i32(addr); store_reg(s, rd, tmp2); + tcg_gen_br(done_label); + gen_set_label(fail_label); + gen_exception(EXCP_UDEF); + gen_set_label(done_label); + tcg_temp_free_i32(sctlr); } } } else {