summary refs log tree commit diff stats
path: root/target/microblaze/gdbstub.c
diff options
context:
space:
mode:
Diffstat (limited to 'target/microblaze/gdbstub.c')
-rw-r--r--target/microblaze/gdbstub.c91
1 files changed, 88 insertions, 3 deletions
diff --git a/target/microblaze/gdbstub.c b/target/microblaze/gdbstub.c
index f41ebf1f33..73e8973597 100644
--- a/target/microblaze/gdbstub.c
+++ b/target/microblaze/gdbstub.c
@@ -25,13 +25,54 @@ int mb_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
 {
     MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
     CPUMBState *env = &cpu->env;
+    /*
+     * GDB expects SREGs in the following order:
+     * PC, MSR, EAR, ESR, FSR, BTR, EDR, PID, ZPR, TLBX, TLBSX, TLBLO, TLBHI.
+     * They aren't stored in this order, so make a map.
+     * PID, ZPR, TLBx, TLBsx, TLBLO, and TLBHI aren't modeled, so we don't
+     * map them to anything and return a value of 0 instead.
+     */
+    static const uint8_t sreg_map[6] = {
+        SR_PC,
+        SR_MSR,
+        SR_EAR,
+        SR_ESR,
+        SR_FSR,
+        SR_BTR
+    };
 
+    /*
+     * GDB expects registers to be reported in this order:
+     * R0-R31
+     * PC-BTR
+     * PVR0-PVR11
+     * EDR-TLBHI
+     * SLR-SHR
+     */
     if (n < 32) {
         return gdb_get_reg32(mem_buf, env->regs[n]);
     } else {
-        return gdb_get_reg32(mem_buf, env->sregs[n - 32]);
+        n -= 32;
+        switch (n) {
+        case 0 ... 5:
+            return gdb_get_reg32(mem_buf, env->sregs[sreg_map[n]]);
+        /* PVR12 is intentionally skipped */
+        case 6 ... 17:
+            n -= 6;
+            return gdb_get_reg32(mem_buf, env->pvr.regs[n]);
+        case 18:
+            return gdb_get_reg32(mem_buf, env->sregs[SR_EDR]);
+        /* Other SRegs aren't modeled, so report a value of 0 */
+        case 19 ... 24:
+            return gdb_get_reg32(mem_buf, 0);
+        case 25:
+            return gdb_get_reg32(mem_buf, env->slr);
+        case 26:
+            return gdb_get_reg32(mem_buf, env->shr);
+        default:
+            return 0;
+        }
     }
-    return 0;
 }
 
 int mb_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
@@ -41,16 +82,60 @@ int mb_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
     CPUMBState *env = &cpu->env;
     uint32_t tmp;
 
+    /*
+     * GDB expects SREGs in the following order:
+     * PC, MSR, EAR, ESR, FSR, BTR, EDR, PID, ZPR, TLBX, TLBSX, TLBLO, TLBHI.
+     * They aren't stored in this order, so make a map.
+     * PID, ZPR, TLBx, TLBsx, TLBLO, and TLBHI aren't modeled, so we don't
+     * map them to anything.
+     */
+    static const uint8_t sreg_map[6] = {
+        SR_PC,
+        SR_MSR,
+        SR_EAR,
+        SR_ESR,
+        SR_FSR,
+        SR_BTR
+    };
+
     if (n > cc->gdb_num_core_regs) {
         return 0;
     }
 
     tmp = ldl_p(mem_buf);
 
+    /*
+     * GDB expects registers to be reported in this order:
+     * R0-R31
+     * PC-BTR
+     * PVR0-PVR11
+     * EDR-TLBHI
+     * SLR-SHR
+     */
     if (n < 32) {
         env->regs[n] = tmp;
     } else {
-        env->sregs[n - 32] = tmp;
+        n -= 32;
+        switch (n) {
+        case 0 ... 5:
+            env->sregs[sreg_map[n]] = tmp;
+            break;
+        /* PVR12 is intentionally skipped */
+        case 6 ... 17:
+            n -= 6;
+            env->pvr.regs[n] = tmp;
+            break;
+        /* Only EDR is modeled in these indeces, so ignore the rest */
+        case 18:
+            env->sregs[SR_EDR] = tmp;
+            break;
+        case 25:
+            env->slr = tmp;
+            break;
+        case 26:
+            env->shr = tmp;
+            break;
+        }
     }
     return 4;
 }