qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

gdbstub.c (6099B)


      1 /*
      2  * Xtensa gdb server stub
      3  *
      4  * Copyright (c) 2003-2005 Fabrice Bellard
      5  * Copyright (c) 2013 SUSE LINUX Products GmbH
      6  *
      7  * This library is free software; you can redistribute it and/or
      8  * modify it under the terms of the GNU Lesser General Public
      9  * License as published by the Free Software Foundation; either
     10  * version 2.1 of the License, or (at your option) any later version.
     11  *
     12  * This library is distributed in the hope that it will be useful,
     13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     15  * Lesser General Public License for more details.
     16  *
     17  * You should have received a copy of the GNU Lesser General Public
     18  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
     19  */
     20 #include "qemu/osdep.h"
     21 #include "cpu.h"
     22 #include "exec/gdbstub.h"
     23 #include "qemu/log.h"
     24 
     25 enum {
     26   xtRegisterTypeArRegfile = 1,  /* Register File ar0..arXX.  */
     27   xtRegisterTypeSpecialReg,     /* CPU states, such as PS, Booleans, (rsr).  */
     28   xtRegisterTypeUserReg,        /* User defined registers (rur).  */
     29   xtRegisterTypeTieRegfile,     /* User define register files.  */
     30   xtRegisterTypeTieState,       /* TIE States (mapped on user regs).  */
     31   xtRegisterTypeMapped,         /* Mapped on Special Registers.  */
     32   xtRegisterTypeUnmapped,       /* Special case of masked registers.  */
     33   xtRegisterTypeWindow,         /* Live window registers (a0..a15).  */
     34   xtRegisterTypeVirtual,        /* PC, FP.  */
     35   xtRegisterTypeUnknown
     36 };
     37 
     38 #define XTENSA_REGISTER_FLAGS_PRIVILEGED        0x0001
     39 #define XTENSA_REGISTER_FLAGS_READABLE          0x0002
     40 #define XTENSA_REGISTER_FLAGS_WRITABLE          0x0004
     41 #define XTENSA_REGISTER_FLAGS_VOLATILE          0x0008
     42 
     43 void xtensa_count_regs(const XtensaConfig *config,
     44                        unsigned *n_regs, unsigned *n_core_regs)
     45 {
     46     unsigned i;
     47     bool count_core_regs = true;
     48 
     49     for (i = 0; config->gdb_regmap.reg[i].targno >= 0; ++i) {
     50         if (config->gdb_regmap.reg[i].type != xtRegisterTypeTieState &&
     51             config->gdb_regmap.reg[i].type != xtRegisterTypeMapped &&
     52             config->gdb_regmap.reg[i].type != xtRegisterTypeUnmapped) {
     53             ++*n_regs;
     54             if (count_core_regs) {
     55                 if ((config->gdb_regmap.reg[i].flags &
     56                      XTENSA_REGISTER_FLAGS_PRIVILEGED) == 0) {
     57                     ++*n_core_regs;
     58                 } else {
     59                     count_core_regs = false;
     60                 }
     61             }
     62         }
     63     }
     64 }
     65 
     66 int xtensa_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
     67 {
     68     XtensaCPU *cpu = XTENSA_CPU(cs);
     69     CPUXtensaState *env = &cpu->env;
     70     const XtensaGdbReg *reg = env->config->gdb_regmap.reg + n;
     71 #ifdef CONFIG_USER_ONLY
     72     int num_regs = env->config->gdb_regmap.num_core_regs;
     73 #else
     74     int num_regs = env->config->gdb_regmap.num_regs;
     75 #endif
     76     unsigned i;
     77 
     78     if (n < 0 || n >= num_regs) {
     79         return 0;
     80     }
     81 
     82     switch (reg->type) {
     83     case xtRegisterTypeVirtual: /*pc*/
     84         return gdb_get_reg32(mem_buf, env->pc);
     85 
     86     case xtRegisterTypeArRegfile: /*ar*/
     87         xtensa_sync_phys_from_window(env);
     88         return gdb_get_reg32(mem_buf, env->phys_regs[(reg->targno & 0xff)
     89                                                      % env->config->nareg]);
     90 
     91     case xtRegisterTypeSpecialReg: /*SR*/
     92         return gdb_get_reg32(mem_buf, env->sregs[reg->targno & 0xff]);
     93 
     94     case xtRegisterTypeUserReg: /*UR*/
     95         return gdb_get_reg32(mem_buf, env->uregs[reg->targno & 0xff]);
     96 
     97     case xtRegisterTypeTieRegfile: /*f*/
     98         i = reg->targno & 0x0f;
     99         switch (reg->size) {
    100         case 4:
    101             return gdb_get_reg32(mem_buf,
    102                                  float32_val(env->fregs[i].f32[FP_F32_LOW]));
    103         case 8:
    104             return gdb_get_reg64(mem_buf, float64_val(env->fregs[i].f64));
    105         default:
    106             qemu_log_mask(LOG_UNIMP, "%s from reg %d of unsupported size %d\n",
    107                           __func__, n, reg->size);
    108             return gdb_get_zeroes(mem_buf, reg->size);
    109         }
    110 
    111     case xtRegisterTypeWindow: /*a*/
    112         return gdb_get_reg32(mem_buf, env->regs[reg->targno & 0x0f]);
    113 
    114     default:
    115         qemu_log_mask(LOG_UNIMP, "%s from reg %d of unsupported type %d\n",
    116                       __func__, n, reg->type);
    117         return gdb_get_zeroes(mem_buf, reg->size);
    118     }
    119 }
    120 
    121 int xtensa_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
    122 {
    123     XtensaCPU *cpu = XTENSA_CPU(cs);
    124     CPUXtensaState *env = &cpu->env;
    125     uint32_t tmp;
    126     const XtensaGdbReg *reg = env->config->gdb_regmap.reg + n;
    127 #ifdef CONFIG_USER_ONLY
    128     int num_regs = env->config->gdb_regmap.num_core_regs;
    129 #else
    130     int num_regs = env->config->gdb_regmap.num_regs;
    131 #endif
    132 
    133     if (n < 0 || n >= num_regs) {
    134         return 0;
    135     }
    136 
    137     tmp = ldl_p(mem_buf);
    138 
    139     switch (reg->type) {
    140     case xtRegisterTypeVirtual: /*pc*/
    141         env->pc = tmp;
    142         break;
    143 
    144     case xtRegisterTypeArRegfile: /*ar*/
    145         env->phys_regs[(reg->targno & 0xff) % env->config->nareg] = tmp;
    146         xtensa_sync_window_from_phys(env);
    147         break;
    148 
    149     case xtRegisterTypeSpecialReg: /*SR*/
    150         env->sregs[reg->targno & 0xff] = tmp;
    151         break;
    152 
    153     case xtRegisterTypeUserReg: /*UR*/
    154         env->uregs[reg->targno & 0xff] = tmp;
    155         break;
    156 
    157     case xtRegisterTypeTieRegfile: /*f*/
    158         switch (reg->size) {
    159         case 4:
    160             env->fregs[reg->targno & 0x0f].f32[FP_F32_LOW] = make_float32(tmp);
    161             return 4;
    162         case 8:
    163             env->fregs[reg->targno & 0x0f].f64 = make_float64(tmp);
    164             return 8;
    165         default:
    166             qemu_log_mask(LOG_UNIMP, "%s to reg %d of unsupported size %d\n",
    167                           __func__, n, reg->size);
    168             return reg->size;
    169         }
    170 
    171     case xtRegisterTypeWindow: /*a*/
    172         env->regs[reg->targno & 0x0f] = tmp;
    173         break;
    174 
    175     default:
    176         qemu_log_mask(LOG_UNIMP, "%s to reg %d of unsupported type %d\n",
    177                       __func__, n, reg->type);
    178         return reg->size;
    179     }
    180 
    181     return 4;
    182 }