diff mbox

[3/3] target-arm: implement setend

Message ID 1398102220-15714-4-git-send-email-pbonzini@redhat.com
State New
Headers show

Commit Message

Paolo Bonzini April 21, 2014, 5:43 p.m. UTC
Since this is not a high-performance path, just use a helper to
flip the E bit and force a lookup in the hash table since the
flags have changed.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 target-arm/helper.h    |  1 +
 target-arm/op_helper.c |  5 +++++
 target-arm/translate.c | 12 ++++++------
 3 files changed, 12 insertions(+), 6 deletions(-)

Comments

Peter Maydell April 21, 2014, 8:33 p.m. UTC | #1
On 21 April 2014 18:43, Paolo Bonzini <pbonzini@redhat.com> wrote:
> Since this is not a high-performance path, just use a helper to
> flip the E bit and force a lookup in the hash table since the
> flags have changed.

If we take an exception while the E bit is set we'll now incorrectly
start executing the exception handler in big-endian mode.
Minimally, we need to force "always little endian". Ideally, we
would implement SCTLR.EE correctly.

Also worth checking: in linux-user mode, if the guest executes
SETEND and then takes a signal, what does the Linux ABI say
should be the value of CPSR.E on entry to the signal handler,
and do we get it right?

thanks
-- PMM
diff mbox

Patch

diff --git a/target-arm/helper.h b/target-arm/helper.h
index 8923f8a..47d0194 100644
--- a/target-arm/helper.h
+++ b/target-arm/helper.h
@@ -49,6 +49,7 @@  DEF_HELPER_FLAGS_2(usad8, TCG_CALL_NO_RWG_SE, i32, i32, i32)
 DEF_HELPER_FLAGS_3(sel_flags, TCG_CALL_NO_RWG_SE,
                    i32, i32, i32, i32)
 DEF_HELPER_2(exception, void, env, i32)
+DEF_HELPER_1(setend, void, env)
 DEF_HELPER_1(wfi, void, env)
 DEF_HELPER_1(wfe, void, env)
 
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index 21ff58e..665a7a9 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -223,6 +223,11 @@  uint32_t HELPER(usat16)(CPUARMState *env, uint32_t x, uint32_t shift)
     return res;
 }
 
+void HELPER(setend)(CPUARMState *env)
+{
+    env->uncached_cpsr ^= CPSR_E;
+}
+
 void HELPER(wfi)(CPUARMState *env)
 {
     CPUState *cs = CPU(arm_env_get_cpu(env));
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 1b66798..e9633fe 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -7340,9 +7340,9 @@  static void disas_arm_insn(CPUARMState * env, DisasContext *s)
             ARCH(6);
             /* setend */
             if (((insn >> 9) & 1) != s->be8) {
-                /* Dynamic endianness switching not implemented. */
-                qemu_log_mask(LOG_UNIMP, "arm: unimplemented setend\n");
-                goto illegal_op;
+                gen_helper_setend(cpu_env);
+                gen_set_pc_im(s, s->pc);
+                s->is_jmp = DISAS_JUMP;
             }
             return;
         } else if ((insn & 0x0fffff00) == 0x057ff000) {
@@ -10473,9 +10473,9 @@  static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
                 /* setend */
                 ARCH(6);
                 if (((insn >> 3) & 1) != s->be8) {
-                    /* Dynamic endianness switching not implemented. */
-                    qemu_log_mask(LOG_UNIMP, "arm: unimplemented setend\n");
-                    goto illegal_op;
+                    gen_helper_setend(cpu_env);
+                    gen_set_pc_im(s, s->pc);
+                    s->is_jmp = DISAS_JUMP;
                 }
                 break;
             case 3: