diff options
author | Alexander Graf <agraf@suse.de> | 2014-06-23 15:23:08 +0200 |
---|---|---|
committer | Alexander Graf <agraf@suse.de> | 2014-06-27 13:48:22 +0200 |
commit | b3cad3abf6df07db165091343b912c2a5de63c26 (patch) | |
tree | d010a10efa2e67806871326459b79fd4206ad98d /target-ppc/gdbstub.c | |
parent | 294d1292893867894992e810a01cfcfa451f1885 (diff) | |
download | hqemu-b3cad3abf6df07db165091343b912c2a5de63c26.zip hqemu-b3cad3abf6df07db165091343b912c2a5de63c26.tar.gz |
PPC: Add support for Apple gdb in gdbstub
The Apple gdbstub protocol is different from the normal gdbstub protocol
used on PowerPC. Add support for the different variant, so that we can use
Apple's gdb to debug guest code.
Keep in mind that the switch is a compile time option. We can't detect
during runtime whether a gdb connecting to us is an upstream gdb or an
Apple gdb.
Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'target-ppc/gdbstub.c')
-rw-r--r-- | target-ppc/gdbstub.c | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/target-ppc/gdbstub.c b/target-ppc/gdbstub.c index 381a3c7..694d303 100644 --- a/target-ppc/gdbstub.c +++ b/target-ppc/gdbstub.c @@ -21,6 +21,31 @@ #include "qemu-common.h" #include "exec/gdbstub.h" +static int ppc_gdb_register_len_apple(int n) +{ + switch (n) { + case 0 ... 31: + /* gprs */ + return 8; + case 32 ... 63: + /* fprs */ + return 8; + case 64 ... 95: + return 16; + case 64+32: /* nip */ + case 65+32: /* msr */ + case 67+32: /* lr */ + case 68+32: /* ctr */ + case 69+32: /* xer */ + case 70+32: /* fpscr */ + return 8; + case 66+32: /* cr */ + return 4; + default: + return 0; + } +} + static int ppc_gdb_register_len(int n) { switch (n) { @@ -132,6 +157,65 @@ int ppc_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n) return r; } +int ppc_cpu_gdb_read_register_apple(CPUState *cs, uint8_t *mem_buf, int n) +{ + PowerPCCPU *cpu = POWERPC_CPU(cs); + CPUPPCState *env = &cpu->env; + int r = ppc_gdb_register_len_apple(n); + + if (!r) { + return r; + } + + if (n < 32) { + /* gprs */ + gdb_get_reg64(mem_buf, env->gpr[n]); + } else if (n < 64) { + /* fprs */ + stfq_p(mem_buf, env->fpr[n-32]); + } else if (n < 96) { + /* Altivec */ + stq_p(mem_buf, n - 64); + stq_p(mem_buf + 8, 0); + } else { + switch (n) { + case 64 + 32: + gdb_get_reg64(mem_buf, env->nip); + break; + case 65 + 32: + gdb_get_reg64(mem_buf, env->msr); + break; + case 66 + 32: + { + uint32_t cr = 0; + int i; + for (i = 0; i < 8; i++) { + cr |= env->crf[i] << (32 - ((i + 1) * 4)); + } + gdb_get_reg32(mem_buf, cr); + break; + } + case 67 + 32: + gdb_get_reg64(mem_buf, env->lr); + break; + case 68 + 32: + gdb_get_reg64(mem_buf, env->ctr); + break; + case 69 + 32: + gdb_get_reg64(mem_buf, env->xer); + break; + case 70 + 32: + gdb_get_reg64(mem_buf, env->fpscr); + break; + } + } + if (msr_le) { + /* If cpu is in LE mode, convert memory contents to LE. */ + ppc_gdb_swap_register(mem_buf, n, r); + } + return r; +} + int ppc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) { PowerPCCPU *cpu = POWERPC_CPU(cs); @@ -185,3 +269,56 @@ int ppc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) } return r; } +int ppc_cpu_gdb_write_register_apple(CPUState *cs, uint8_t *mem_buf, int n) +{ + PowerPCCPU *cpu = POWERPC_CPU(cs); + CPUPPCState *env = &cpu->env; + int r = ppc_gdb_register_len_apple(n); + + if (!r) { + return r; + } + if (msr_le) { + /* If cpu is in LE mode, convert memory contents to LE. */ + ppc_gdb_swap_register(mem_buf, n, r); + } + if (n < 32) { + /* gprs */ + env->gpr[n] = ldq_p(mem_buf); + } else if (n < 64) { + /* fprs */ + env->fpr[n-32] = ldfq_p(mem_buf); + } else { + switch (n) { + case 64 + 32: + env->nip = ldq_p(mem_buf); + break; + case 65 + 32: + ppc_store_msr(env, ldq_p(mem_buf)); + break; + case 66 + 32: + { + uint32_t cr = ldl_p(mem_buf); + int i; + for (i = 0; i < 8; i++) { + env->crf[i] = (cr >> (32 - ((i + 1) * 4))) & 0xF; + } + break; + } + case 67 + 32: + env->lr = ldq_p(mem_buf); + break; + case 68 + 32: + env->ctr = ldq_p(mem_buf); + break; + case 69 + 32: + env->xer = ldq_p(mem_buf); + break; + case 70 + 32: + /* fpscr */ + store_fpscr(env, ldq_p(mem_buf), 0xffffffff); + break; + } + } + return r; +} |