Re: [Qemu-devel] [PATCH v2 13/68] target/arm: Convert MRS/MSR (banked, register)

2019-08-23 Thread Peter Maydell
On Mon, 19 Aug 2019 at 22:38, Richard Henderson
 wrote:
>
> The m-profile and a-profile, decodings overlap.  Only return false
> for the case of wrong profile; handle UNDEFINED for permission failure
> directly.  This ensures that we don't accidentally pass an insn that
> applies to the wrong profile.
>
> Signed-off-by: Richard Henderson 
Reviewed-by: Peter Maydell 

thanks
-- PMM



[Qemu-devel] [PATCH v2 13/68] target/arm: Convert MRS/MSR (banked, register)

2019-08-19 Thread Richard Henderson
The m-profile and a-profile, decodings overlap.  Only return false
for the case of wrong profile; handle UNDEFINED for permission failure
directly.  This ensures that we don't accidentally pass an insn that
applies to the wrong profile.

Signed-off-by: Richard Henderson 
---
 target/arm/translate.c | 226 ++---
 target/arm/a32.decode  |  14 +++
 target/arm/t32.decode  |  40 ++--
 3 files changed, 142 insertions(+), 138 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index ee485b1cbd..026abcaa9c 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -8291,6 +8291,93 @@ static bool trans_MSR_imm(DisasContext *s, arg_MSR_imm 
*a)
 return true;
 }
 
+/*
+ * Miscellaneous instructions
+ */
+
+static bool trans_MRS_bank(DisasContext *s, arg_MRS_bank *a)
+{
+if (arm_dc_feature(s, ARM_FEATURE_M)) {
+return false;
+}
+gen_mrs_banked(s, a->r, a->sysm, a->rd);
+return true;
+}
+
+static bool trans_MSR_bank(DisasContext *s, arg_MSR_bank *a)
+{
+if (arm_dc_feature(s, ARM_FEATURE_M)) {
+return false;
+}
+gen_msr_banked(s, a->r, a->sysm, a->rn);
+return true;
+}
+
+static bool trans_MRS_reg(DisasContext *s, arg_MRS_reg *a)
+{
+TCGv_i32 tmp;
+
+if (arm_dc_feature(s, ARM_FEATURE_M)) {
+return false;
+}
+if (a->r) {
+if (IS_USER(s)) {
+unallocated_encoding(s);
+return true;
+}
+tmp = load_cpu_field(spsr);
+} else {
+tmp = tcg_temp_new_i32();
+gen_helper_cpsr_read(tmp, cpu_env);
+}
+store_reg(s, a->rd, tmp);
+return true;
+}
+
+static bool trans_MSR_reg(DisasContext *s, arg_MSR_reg *a)
+{
+TCGv_i32 tmp;
+uint32_t mask = msr_mask(s, a->mask, a->r);
+
+if (arm_dc_feature(s, ARM_FEATURE_M)) {
+return false;
+}
+tmp = load_reg(s, a->rn);
+if (gen_set_psr(s, mask, a->r, tmp)) {
+unallocated_encoding(s);
+}
+return true;
+}
+
+static bool trans_MRS_v7m(DisasContext *s, arg_MRS_v7m *a)
+{
+TCGv_i32 tmp;
+
+if (!arm_dc_feature(s, ARM_FEATURE_M)) {
+return false;
+}
+tmp = tcg_const_i32(a->sysm);
+gen_helper_v7m_mrs(tmp, cpu_env, tmp);
+store_reg(s, a->rd, tmp);
+return true;
+}
+
+static bool trans_MSR_v7m(DisasContext *s, arg_MSR_v7m *a)
+{
+TCGv_i32 addr, reg;
+
+if (!arm_dc_feature(s, ARM_FEATURE_M)) {
+return false;
+}
+addr = tcg_const_i32((a->mask << 10) | a->sysm);
+reg = load_reg(s, a->rn);
+gen_helper_v7m_msr(cpu_env, addr, reg);
+tcg_temp_free_i32(addr);
+tcg_temp_free_i32(reg);
+gen_lookup_tb(s);
+return true;
+}
+
 /*
  * Legacy decoder.
  */
@@ -8575,46 +8662,10 @@ static void disas_arm_insn(DisasContext *s, unsigned 
int insn)
 sh = (insn >> 4) & 0xf;
 rm = insn & 0xf;
 switch (sh) {
-case 0x0: /* MSR, MRS */
-if (insn & (1 << 9)) {
-/* MSR (banked) and MRS (banked) */
-int sysm = extract32(insn, 16, 4) |
-(extract32(insn, 8, 1) << 4);
-int r = extract32(insn, 22, 1);
-
-if (op1 & 1) {
-/* MSR (banked) */
-gen_msr_banked(s, r, sysm, rm);
-} else {
-/* MRS (banked) */
-int rd = extract32(insn, 12, 4);
-
-gen_mrs_banked(s, r, sysm, rd);
-}
-break;
-}
-
-/* MSR, MRS (for PSRs) */
-if (op1 & 1) {
-/* PSR = reg */
-tmp = load_reg(s, rm);
-i = ((op1 & 2) != 0);
-if (gen_set_psr(s, msr_mask(s, (insn >> 16) & 0xf, i), i, tmp))
-goto illegal_op;
-} else {
-/* reg = PSR */
-rd = (insn >> 12) & 0xf;
-if (op1 & 2) {
-if (IS_USER(s))
-goto illegal_op;
-tmp = load_cpu_field(spsr);
-} else {
-tmp = tcg_temp_new_i32();
-gen_helper_cpsr_read(tmp, cpu_env);
-}
-store_reg(s, rd, tmp);
-}
-break;
+case 0x0:
+/* MSR/MRS (banked/register) */
+/* All done in decodetree.  Illegal ops already signalled.  */
+g_assert_not_reached();
 case 0x1:
 if (op1 == 1) {
 /* branch/exchange thumb (bx).  */
@@ -10471,40 +10522,9 @@ static void disas_thumb2_insn(DisasContext *s, 
uint32_t insn)
 } else {
 op = (insn >> 20) & 7;
 switch (op) {
-case 0: /* msr cpsr.  */
-if (arm_dc_feature(s, ARM_FEATURE_M)) {
-tmp = load_reg(s, rn);
-/* the