qemu/target/xtensa/gdbstub.c
<<
>>
Prefs
   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 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 "qemu-common.h"
  22#include "cpu.h"
  23#include "exec/gdbstub.h"
  24#include "qemu/log.h"
  25
  26int xtensa_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
  27{
  28    XtensaCPU *cpu = XTENSA_CPU(cs);
  29    CPUXtensaState *env = &cpu->env;
  30    const XtensaGdbReg *reg = env->config->gdb_regmap.reg + n;
  31#ifdef CONFIG_USER_ONLY
  32    int num_regs = env->config->gdb_regmap.num_core_regs;
  33#else
  34    int num_regs = env->config->gdb_regmap.num_regs;
  35#endif
  36    unsigned i;
  37
  38    if (n < 0 || n >= num_regs) {
  39        return 0;
  40    }
  41
  42    switch (reg->type) {
  43    case 9: /*pc*/
  44        return gdb_get_reg32(mem_buf, env->pc);
  45
  46    case 1: /*ar*/
  47        xtensa_sync_phys_from_window(env);
  48        return gdb_get_reg32(mem_buf, env->phys_regs[(reg->targno & 0xff)
  49                                                     % env->config->nareg]);
  50
  51    case 2: /*SR*/
  52        return gdb_get_reg32(mem_buf, env->sregs[reg->targno & 0xff]);
  53
  54    case 3: /*UR*/
  55        return gdb_get_reg32(mem_buf, env->uregs[reg->targno & 0xff]);
  56
  57    case 4: /*f*/
  58        i = reg->targno & 0x0f;
  59        switch (reg->size) {
  60        case 4:
  61            return gdb_get_reg32(mem_buf,
  62                                 float32_val(env->fregs[i].f32[FP_F32_LOW]));
  63        case 8:
  64            return gdb_get_reg64(mem_buf, float64_val(env->fregs[i].f64));
  65        default:
  66            qemu_log_mask(LOG_UNIMP, "%s from reg %d of unsupported size %d\n",
  67                          __func__, n, reg->size);
  68            memset(mem_buf, 0, reg->size);
  69            return reg->size;
  70        }
  71
  72    case 8: /*a*/
  73        return gdb_get_reg32(mem_buf, env->regs[reg->targno & 0x0f]);
  74
  75    default:
  76        qemu_log_mask(LOG_UNIMP, "%s from reg %d of unsupported type %d\n",
  77                      __func__, n, reg->type);
  78        memset(mem_buf, 0, reg->size);
  79        return reg->size;
  80    }
  81}
  82
  83int xtensa_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
  84{
  85    XtensaCPU *cpu = XTENSA_CPU(cs);
  86    CPUXtensaState *env = &cpu->env;
  87    uint32_t tmp;
  88    const XtensaGdbReg *reg = env->config->gdb_regmap.reg + n;
  89#ifdef CONFIG_USER_ONLY
  90    int num_regs = env->config->gdb_regmap.num_core_regs;
  91#else
  92    int num_regs = env->config->gdb_regmap.num_regs;
  93#endif
  94
  95    if (n < 0 || n >= num_regs) {
  96        return 0;
  97    }
  98
  99    tmp = ldl_p(mem_buf);
 100
 101    switch (reg->type) {
 102    case 9: /*pc*/
 103        env->pc = tmp;
 104        break;
 105
 106    case 1: /*ar*/
 107        env->phys_regs[(reg->targno & 0xff) % env->config->nareg] = tmp;
 108        xtensa_sync_window_from_phys(env);
 109        break;
 110
 111    case 2: /*SR*/
 112        env->sregs[reg->targno & 0xff] = tmp;
 113        break;
 114
 115    case 3: /*UR*/
 116        env->uregs[reg->targno & 0xff] = tmp;
 117        break;
 118
 119    case 4: /*f*/
 120        switch (reg->size) {
 121        case 4:
 122            env->fregs[reg->targno & 0x0f].f32[FP_F32_LOW] = make_float32(tmp);
 123            return 4;
 124        case 8:
 125            env->fregs[reg->targno & 0x0f].f64 = make_float64(tmp);
 126            return 8;
 127        default:
 128            qemu_log_mask(LOG_UNIMP, "%s to reg %d of unsupported size %d\n",
 129                          __func__, n, reg->size);
 130            return reg->size;
 131        }
 132
 133    case 8: /*a*/
 134        env->regs[reg->targno & 0x0f] = tmp;
 135        break;
 136
 137    default:
 138        qemu_log_mask(LOG_UNIMP, "%s to reg %d of unsupported type %d\n",
 139                      __func__, n, reg->type);
 140        return reg->size;
 141    }
 142
 143    return 4;
 144}
 145