]> Git Repo - qemu.git/blobdiff - target/xtensa/gdbstub.c
*: Use fprintf between qemu_log_trylock/unlock
[qemu.git] / target / xtensa / gdbstub.c
index fa5469a4ef5f5b6053ea377b379f48ac0770d02d..b6696063e5e6793b0e1d161966a0412375d59e29 100644 (file)
@@ -7,7 +7,7 @@
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * version 2.1 of the License, or (at your option) any later version.
  *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 #include "qemu/osdep.h"
-#include "qemu-common.h"
 #include "cpu.h"
 #include "exec/gdbstub.h"
 #include "qemu/log.h"
 
-int xtensa_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
+enum {
+  xtRegisterTypeArRegfile = 1,  /* Register File ar0..arXX.  */
+  xtRegisterTypeSpecialReg,     /* CPU states, such as PS, Booleans, (rsr).  */
+  xtRegisterTypeUserReg,        /* User defined registers (rur).  */
+  xtRegisterTypeTieRegfile,     /* User define register files.  */
+  xtRegisterTypeTieState,       /* TIE States (mapped on user regs).  */
+  xtRegisterTypeMapped,         /* Mapped on Special Registers.  */
+  xtRegisterTypeUnmapped,       /* Special case of masked registers.  */
+  xtRegisterTypeWindow,         /* Live window registers (a0..a15).  */
+  xtRegisterTypeVirtual,        /* PC, FP.  */
+  xtRegisterTypeUnknown
+};
+
+#define XTENSA_REGISTER_FLAGS_PRIVILEGED        0x0001
+#define XTENSA_REGISTER_FLAGS_READABLE          0x0002
+#define XTENSA_REGISTER_FLAGS_WRITABLE          0x0004
+#define XTENSA_REGISTER_FLAGS_VOLATILE          0x0008
+
+void xtensa_count_regs(const XtensaConfig *config,
+                       unsigned *n_regs, unsigned *n_core_regs)
+{
+    unsigned i;
+    bool count_core_regs = true;
+
+    for (i = 0; config->gdb_regmap.reg[i].targno >= 0; ++i) {
+        if (config->gdb_regmap.reg[i].type != xtRegisterTypeTieState &&
+            config->gdb_regmap.reg[i].type != xtRegisterTypeMapped &&
+            config->gdb_regmap.reg[i].type != xtRegisterTypeUnmapped) {
+            ++*n_regs;
+            if (count_core_regs) {
+                if ((config->gdb_regmap.reg[i].flags &
+                     XTENSA_REGISTER_FLAGS_PRIVILEGED) == 0) {
+                    ++*n_core_regs;
+                } else {
+                    count_core_regs = false;
+                }
+            }
+        }
+    }
+}
+
+int xtensa_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
 {
     XtensaCPU *cpu = XTENSA_CPU(cs);
     CPUXtensaState *env = &cpu->env;
     const XtensaGdbReg *reg = env->config->gdb_regmap.reg + n;
+#ifdef CONFIG_USER_ONLY
+    int num_regs = env->config->gdb_regmap.num_core_regs;
+#else
+    int num_regs = env->config->gdb_regmap.num_regs;
+#endif
     unsigned i;
 
-    if (n < 0 || n >= env->config->gdb_regmap.num_regs) {
+    if (n < 0 || n >= num_regs) {
         return 0;
     }
 
     switch (reg->type) {
-    case 9: /*pc*/
+    case xtRegisterTypeVirtual: /*pc*/
         return gdb_get_reg32(mem_buf, env->pc);
 
-    case 1: /*ar*/
+    case xtRegisterTypeArRegfile: /*ar*/
         xtensa_sync_phys_from_window(env);
         return gdb_get_reg32(mem_buf, env->phys_regs[(reg->targno & 0xff)
                                                      % env->config->nareg]);
 
-    case 2: /*SR*/
+    case xtRegisterTypeSpecialReg: /*SR*/
         return gdb_get_reg32(mem_buf, env->sregs[reg->targno & 0xff]);
 
-    case 3: /*UR*/
+    case xtRegisterTypeUserReg: /*UR*/
         return gdb_get_reg32(mem_buf, env->uregs[reg->targno & 0xff]);
 
-    case 4: /*f*/
+    case xtRegisterTypeTieRegfile: /*f*/
         i = reg->targno & 0x0f;
         switch (reg->size) {
         case 4:
@@ -58,16 +103,18 @@ int xtensa_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
         case 8:
             return gdb_get_reg64(mem_buf, float64_val(env->fregs[i].f64));
         default:
-            return 0;
+            qemu_log_mask(LOG_UNIMP, "%s from reg %d of unsupported size %d\n",
+                          __func__, n, reg->size);
+            return gdb_get_zeroes(mem_buf, reg->size);
         }
 
-    case 8: /*a*/
+    case xtRegisterTypeWindow: /*a*/
         return gdb_get_reg32(mem_buf, env->regs[reg->targno & 0x0f]);
 
     default:
         qemu_log_mask(LOG_UNIMP, "%s from reg %d of unsupported type %d\n",
                       __func__, n, reg->type);
-        return 0;
+        return gdb_get_zeroes(mem_buf, reg->size);
     }
 }
 
@@ -77,32 +124,37 @@ int xtensa_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
     CPUXtensaState *env = &cpu->env;
     uint32_t tmp;
     const XtensaGdbReg *reg = env->config->gdb_regmap.reg + n;
+#ifdef CONFIG_USER_ONLY
+    int num_regs = env->config->gdb_regmap.num_core_regs;
+#else
+    int num_regs = env->config->gdb_regmap.num_regs;
+#endif
 
-    if (n < 0 || n >= env->config->gdb_regmap.num_regs) {
+    if (n < 0 || n >= num_regs) {
         return 0;
     }
 
     tmp = ldl_p(mem_buf);
 
     switch (reg->type) {
-    case 9: /*pc*/
+    case xtRegisterTypeVirtual: /*pc*/
         env->pc = tmp;
         break;
 
-    case 1: /*ar*/
+    case xtRegisterTypeArRegfile: /*ar*/
         env->phys_regs[(reg->targno & 0xff) % env->config->nareg] = tmp;
         xtensa_sync_window_from_phys(env);
         break;
 
-    case 2: /*SR*/
+    case xtRegisterTypeSpecialReg: /*SR*/
         env->sregs[reg->targno & 0xff] = tmp;
         break;
 
-    case 3: /*UR*/
+    case xtRegisterTypeUserReg: /*UR*/
         env->uregs[reg->targno & 0xff] = tmp;
         break;
 
-    case 4: /*f*/
+    case xtRegisterTypeTieRegfile: /*f*/
         switch (reg->size) {
         case 4:
             env->fregs[reg->targno & 0x0f].f32[FP_F32_LOW] = make_float32(tmp);
@@ -111,17 +163,19 @@ int xtensa_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
             env->fregs[reg->targno & 0x0f].f64 = make_float64(tmp);
             return 8;
         default:
-            return 0;
+            qemu_log_mask(LOG_UNIMP, "%s to reg %d of unsupported size %d\n",
+                          __func__, n, reg->size);
+            return reg->size;
         }
 
-    case 8: /*a*/
+    case xtRegisterTypeWindow: /*a*/
         env->regs[reg->targno & 0x0f] = tmp;
         break;
 
     default:
         qemu_log_mask(LOG_UNIMP, "%s to reg %d of unsupported type %d\n",
                       __func__, n, reg->type);
-        return 0;
+        return reg->size;
     }
 
     return 4;
This page took 0.028555 seconds and 4 git commands to generate.