summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorGreg Kurz <gkurz@linux.vnet.ibm.com>2016-01-15 16:00:38 +0100
committerDavid Gibson <david@gibson.dropbear.id.au>2016-01-30 23:37:38 +1100
commitea499e71506c91aa259a7fdccf1d6b2022f5b530 (patch)
treeb5a89a908f90ff3977feb5b093d33b4cf35f010b
parent87601e2d5c22d9c1fef0e09978d377f46336c1db (diff)
downloadfocaccia-qemu-ea499e71506c91aa259a7fdccf1d6b2022f5b530.tar.gz
focaccia-qemu-ea499e71506c91aa259a7fdccf1d6b2022f5b530.zip
target-ppc: gdbstub: fix altivec registers for little-endian guests
Altivec registers are 128-bit wide. They are stored in memory as two
64-bit values that must be byteswapped when the guest is little-endian.
Let's reuse the ppc_maybe_bswap_register() helper for this.

We also need to fix the ordering of the 64-bit elements according to
the target endianness, for both system and user mode.

Signed-off-by: Greg Kurz <gkurz@linux.vnet.ibm.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
-rw-r--r--target-ppc/translate_init.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 0d6d1154c5..11741413e5 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -8753,9 +8753,9 @@ static void dump_ppc_insns (CPUPPCState *env)
 static bool avr_need_swap(CPUPPCState *env)
 {
 #ifdef HOST_WORDS_BIGENDIAN
-    return false;
+    return msr_le;
 #else
-    return true;
+    return !msr_le;
 #endif
 }
 
@@ -8799,14 +8799,18 @@ static int gdb_get_avr_reg(CPUPPCState *env, uint8_t *mem_buf, int n)
             stq_p(mem_buf, env->avr[n].u64[1]);
             stq_p(mem_buf+8, env->avr[n].u64[0]);
         }
+        ppc_maybe_bswap_register(env, mem_buf, 8);
+        ppc_maybe_bswap_register(env, mem_buf + 8, 8);
         return 16;
     }
     if (n == 32) {
         stl_p(mem_buf, env->vscr);
+        ppc_maybe_bswap_register(env, mem_buf, 4);
         return 4;
     }
     if (n == 33) {
         stl_p(mem_buf, (uint32_t)env->spr[SPR_VRSAVE]);
+        ppc_maybe_bswap_register(env, mem_buf, 4);
         return 4;
     }
     return 0;
@@ -8815,6 +8819,8 @@ static int gdb_get_avr_reg(CPUPPCState *env, uint8_t *mem_buf, int n)
 static int gdb_set_avr_reg(CPUPPCState *env, uint8_t *mem_buf, int n)
 {
     if (n < 32) {
+        ppc_maybe_bswap_register(env, mem_buf, 8);
+        ppc_maybe_bswap_register(env, mem_buf + 8, 8);
         if (!avr_need_swap(env)) {
             env->avr[n].u64[0] = ldq_p(mem_buf);
             env->avr[n].u64[1] = ldq_p(mem_buf+8);
@@ -8825,10 +8831,12 @@ static int gdb_set_avr_reg(CPUPPCState *env, uint8_t *mem_buf, int n)
         return 16;
     }
     if (n == 32) {
+        ppc_maybe_bswap_register(env, mem_buf, 4);
         env->vscr = ldl_p(mem_buf);
         return 4;
     }
     if (n == 33) {
+        ppc_maybe_bswap_register(env, mem_buf, 4);
         env->spr[SPR_VRSAVE] = (target_ulong)ldl_p(mem_buf);
         return 4;
     }