Commit a7ac06fd authored by Max Filippov's avatar Max Filippov
Browse files

target/xtensa: clean up gdbstub register handling



- move register counting to xtensa/gdbstub.c
- add symbolic names for register types and flags from GDB and use them
  in register counting and access functions.

Signed-off-by: default avatarMax Filippov <jcmvbkbc@gmail.com>
parent 2becc8fd
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -503,6 +503,8 @@ void xtensa_cpu_do_unassigned_access(CPUState *cpu, hwaddr addr,
void xtensa_cpu_dump_state(CPUState *cpu, FILE *f,
                           fprintf_function cpu_fprintf, int flags);
hwaddr xtensa_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
void xtensa_count_regs(const XtensaConfig *config,
                       unsigned *n_regs, unsigned *n_core_regs);
int xtensa_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
int xtensa_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
void xtensa_cpu_do_unaligned_access(CPUState *cpu, vaddr addr,
+48 −12
Original line number Diff line number Diff line
@@ -23,6 +23,42 @@
#include "exec/gdbstub.h"
#include "qemu/log.h"

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;

    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 ((config->gdb_regmap.reg[i].flags &
                 XTENSA_REGISTER_FLAGS_PRIVILEGED) == 0) {
                ++*n_core_regs;
            }
        }
    }
}

int xtensa_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
{
    XtensaCPU *cpu = XTENSA_CPU(cs);
@@ -40,21 +76,21 @@ int xtensa_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
    }

    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:
@@ -69,7 +105,7 @@ int xtensa_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
            return reg->size;
        }

    case 8: /*a*/
    case xtRegisterTypeWindow: /*a*/
        return gdb_get_reg32(mem_buf, env->regs[reg->targno & 0x0f]);

    default:
@@ -99,24 +135,24 @@ int xtensa_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
    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);
@@ -130,7 +166,7 @@ int xtensa_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
            return reg->size;
        }

    case 8: /*a*/
    case xtRegisterTypeWindow: /*a*/
        env->regs[reg->targno & 0x0f] = tmp;
        break;

+1 −11
Original line number Diff line number Diff line
@@ -95,20 +95,10 @@ void xtensa_finalize_config(XtensaConfig *config)

    if (config->gdb_regmap.num_regs == 0 ||
        config->gdb_regmap.num_core_regs == 0) {
        unsigned i;
        unsigned n_regs = 0;
        unsigned n_core_regs = 0;

        for (i = 0; config->gdb_regmap.reg[i].targno >= 0; ++i) {
            if (config->gdb_regmap.reg[i].type != 5 &&
                config->gdb_regmap.reg[i].type != 6 &&
                config->gdb_regmap.reg[i].type != 7) {
                ++n_regs;
                if ((config->gdb_regmap.reg[i].flags & 0x1) == 0) {
                    ++n_core_regs;
                }
            }
        }
        xtensa_count_regs(config, &n_regs, &n_core_regs);
        if (config->gdb_regmap.num_regs == 0) {
            config->gdb_regmap.num_regs = n_regs;
        }