mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-09 10:34:58 -06:00
target/arm: Move gdbstub related code out of helper.c
Currently helper.c includes some code which is part of the arm target's gdbstub support. This code has a better home: in gdbstub.c and gdbstub64.c. Move it there. Because aarch64_fpu_gdb_get_reg() and aarch64_fpu_gdb_set_reg() move into gdbstub64.c, this means that they're now compiled only for TARGET_AARCH64 rather than always. That is the only case when they would ever be used, but it does mean that the ifdef in arm_cpu_register_gdb_regs_for_features() needs to be adjusted to match. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20210921162901.17508-4-peter.maydell@linaro.org
This commit is contained in:
parent
d59b7cdccc
commit
89f4f20e27
4 changed files with 277 additions and 271 deletions
|
@ -19,6 +19,7 @@
|
||||||
*/
|
*/
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
|
#include "internals.h"
|
||||||
#include "exec/gdbstub.h"
|
#include "exec/gdbstub.h"
|
||||||
|
|
||||||
typedef struct RegisterSysregXmlParam {
|
typedef struct RegisterSysregXmlParam {
|
||||||
|
@ -124,6 +125,98 @@ int arm_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int vfp_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg)
|
||||||
|
{
|
||||||
|
ARMCPU *cpu = env_archcpu(env);
|
||||||
|
int nregs = cpu_isar_feature(aa32_simd_r32, cpu) ? 32 : 16;
|
||||||
|
|
||||||
|
/* VFP data registers are always little-endian. */
|
||||||
|
if (reg < nregs) {
|
||||||
|
return gdb_get_reg64(buf, *aa32_vfp_dreg(env, reg));
|
||||||
|
}
|
||||||
|
if (arm_feature(env, ARM_FEATURE_NEON)) {
|
||||||
|
/* Aliases for Q regs. */
|
||||||
|
nregs += 16;
|
||||||
|
if (reg < nregs) {
|
||||||
|
uint64_t *q = aa32_vfp_qreg(env, reg - 32);
|
||||||
|
return gdb_get_reg128(buf, q[0], q[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch (reg - nregs) {
|
||||||
|
case 0:
|
||||||
|
return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPSID]);
|
||||||
|
case 1:
|
||||||
|
return gdb_get_reg32(buf, vfp_get_fpscr(env));
|
||||||
|
case 2:
|
||||||
|
return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPEXC]);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int vfp_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
|
||||||
|
{
|
||||||
|
ARMCPU *cpu = env_archcpu(env);
|
||||||
|
int nregs = cpu_isar_feature(aa32_simd_r32, cpu) ? 32 : 16;
|
||||||
|
|
||||||
|
if (reg < nregs) {
|
||||||
|
*aa32_vfp_dreg(env, reg) = ldq_le_p(buf);
|
||||||
|
return 8;
|
||||||
|
}
|
||||||
|
if (arm_feature(env, ARM_FEATURE_NEON)) {
|
||||||
|
nregs += 16;
|
||||||
|
if (reg < nregs) {
|
||||||
|
uint64_t *q = aa32_vfp_qreg(env, reg - 32);
|
||||||
|
q[0] = ldq_le_p(buf);
|
||||||
|
q[1] = ldq_le_p(buf + 8);
|
||||||
|
return 16;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch (reg - nregs) {
|
||||||
|
case 0:
|
||||||
|
env->vfp.xregs[ARM_VFP_FPSID] = ldl_p(buf);
|
||||||
|
return 4;
|
||||||
|
case 1:
|
||||||
|
vfp_set_fpscr(env, ldl_p(buf));
|
||||||
|
return 4;
|
||||||
|
case 2:
|
||||||
|
env->vfp.xregs[ARM_VFP_FPEXC] = ldl_p(buf) & (1 << 30);
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* arm_get/set_gdb_*: get/set a gdb register
|
||||||
|
* @env: the CPU state
|
||||||
|
* @buf: a buffer to copy to/from
|
||||||
|
* @reg: register number (offset from start of group)
|
||||||
|
*
|
||||||
|
* We return the number of bytes copied
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int arm_gdb_get_sysreg(CPUARMState *env, GByteArray *buf, int reg)
|
||||||
|
{
|
||||||
|
ARMCPU *cpu = env_archcpu(env);
|
||||||
|
const ARMCPRegInfo *ri;
|
||||||
|
uint32_t key;
|
||||||
|
|
||||||
|
key = cpu->dyn_sysreg_xml.data.cpregs.keys[reg];
|
||||||
|
ri = get_arm_cp_reginfo(cpu->cp_regs, key);
|
||||||
|
if (ri) {
|
||||||
|
if (cpreg_field_is_64bit(ri)) {
|
||||||
|
return gdb_get_reg64(buf, (uint64_t)read_raw_cp_reg(env, ri));
|
||||||
|
} else {
|
||||||
|
return gdb_get_reg32(buf, (uint32_t)read_raw_cp_reg(env, ri));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int arm_gdb_set_sysreg(CPUARMState *env, uint8_t *buf, int reg)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void arm_gen_one_xml_sysreg_tag(GString *s, DynamicGDBXMLInfo *dyn_xml,
|
static void arm_gen_one_xml_sysreg_tag(GString *s, DynamicGDBXMLInfo *dyn_xml,
|
||||||
ARMCPRegInfo *ri, uint32_t ri_key,
|
ARMCPRegInfo *ri, uint32_t ri_key,
|
||||||
int bitsize, int regnum)
|
int bitsize, int regnum)
|
||||||
|
@ -319,3 +412,40 @@ const char *arm_gdb_get_dynamic_xml(CPUState *cs, const char *xmlname)
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
|
||||||
|
{
|
||||||
|
CPUState *cs = CPU(cpu);
|
||||||
|
CPUARMState *env = &cpu->env;
|
||||||
|
|
||||||
|
if (arm_feature(env, ARM_FEATURE_AARCH64)) {
|
||||||
|
/*
|
||||||
|
* The lower part of each SVE register aliases to the FPU
|
||||||
|
* registers so we don't need to include both.
|
||||||
|
*/
|
||||||
|
#ifdef TARGET_AARCH64
|
||||||
|
if (isar_feature_aa64_sve(&cpu->isar)) {
|
||||||
|
gdb_register_coprocessor(cs, arm_gdb_get_svereg, arm_gdb_set_svereg,
|
||||||
|
arm_gen_dynamic_svereg_xml(cs, cs->gdb_num_regs),
|
||||||
|
"sve-registers.xml", 0);
|
||||||
|
} else {
|
||||||
|
gdb_register_coprocessor(cs, aarch64_fpu_gdb_get_reg,
|
||||||
|
aarch64_fpu_gdb_set_reg,
|
||||||
|
34, "aarch64-fpu.xml", 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} else if (arm_feature(env, ARM_FEATURE_NEON)) {
|
||||||
|
gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
|
||||||
|
51, "arm-neon.xml", 0);
|
||||||
|
} else if (cpu_isar_feature(aa32_simd_r32, cpu)) {
|
||||||
|
gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
|
||||||
|
35, "arm-vfp3.xml", 0);
|
||||||
|
} else if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
|
||||||
|
gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
|
||||||
|
19, "arm-vfp.xml", 0);
|
||||||
|
}
|
||||||
|
gdb_register_coprocessor(cs, arm_gdb_get_sysreg, arm_gdb_set_sysreg,
|
||||||
|
arm_gen_dynamic_sysreg_xml(cs, cs->gdb_num_regs),
|
||||||
|
"system-registers.xml", 0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -17,7 +17,9 @@
|
||||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
|
#include "qemu/log.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
|
#include "internals.h"
|
||||||
#include "exec/gdbstub.h"
|
#include "exec/gdbstub.h"
|
||||||
|
|
||||||
int aarch64_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
|
int aarch64_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
|
||||||
|
@ -69,3 +71,141 @@ int aarch64_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
|
||||||
/* Unknown register. */
|
/* Unknown register. */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int aarch64_fpu_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg)
|
||||||
|
{
|
||||||
|
switch (reg) {
|
||||||
|
case 0 ... 31:
|
||||||
|
{
|
||||||
|
/* 128 bit FP register - quads are in LE order */
|
||||||
|
uint64_t *q = aa64_vfp_qreg(env, reg);
|
||||||
|
return gdb_get_reg128(buf, q[1], q[0]);
|
||||||
|
}
|
||||||
|
case 32:
|
||||||
|
/* FPSR */
|
||||||
|
return gdb_get_reg32(buf, vfp_get_fpsr(env));
|
||||||
|
case 33:
|
||||||
|
/* FPCR */
|
||||||
|
return gdb_get_reg32(buf, vfp_get_fpcr(env));
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int aarch64_fpu_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
|
||||||
|
{
|
||||||
|
switch (reg) {
|
||||||
|
case 0 ... 31:
|
||||||
|
/* 128 bit FP register */
|
||||||
|
{
|
||||||
|
uint64_t *q = aa64_vfp_qreg(env, reg);
|
||||||
|
q[0] = ldq_le_p(buf);
|
||||||
|
q[1] = ldq_le_p(buf + 8);
|
||||||
|
return 16;
|
||||||
|
}
|
||||||
|
case 32:
|
||||||
|
/* FPSR */
|
||||||
|
vfp_set_fpsr(env, ldl_p(buf));
|
||||||
|
return 4;
|
||||||
|
case 33:
|
||||||
|
/* FPCR */
|
||||||
|
vfp_set_fpcr(env, ldl_p(buf));
|
||||||
|
return 4;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int arm_gdb_get_svereg(CPUARMState *env, GByteArray *buf, int reg)
|
||||||
|
{
|
||||||
|
ARMCPU *cpu = env_archcpu(env);
|
||||||
|
|
||||||
|
switch (reg) {
|
||||||
|
/* The first 32 registers are the zregs */
|
||||||
|
case 0 ... 31:
|
||||||
|
{
|
||||||
|
int vq, len = 0;
|
||||||
|
for (vq = 0; vq < cpu->sve_max_vq; vq++) {
|
||||||
|
len += gdb_get_reg128(buf,
|
||||||
|
env->vfp.zregs[reg].d[vq * 2 + 1],
|
||||||
|
env->vfp.zregs[reg].d[vq * 2]);
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
case 32:
|
||||||
|
return gdb_get_reg32(buf, vfp_get_fpsr(env));
|
||||||
|
case 33:
|
||||||
|
return gdb_get_reg32(buf, vfp_get_fpcr(env));
|
||||||
|
/* then 16 predicates and the ffr */
|
||||||
|
case 34 ... 50:
|
||||||
|
{
|
||||||
|
int preg = reg - 34;
|
||||||
|
int vq, len = 0;
|
||||||
|
for (vq = 0; vq < cpu->sve_max_vq; vq = vq + 4) {
|
||||||
|
len += gdb_get_reg64(buf, env->vfp.pregs[preg].p[vq / 4]);
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
case 51:
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* We report in Vector Granules (VG) which is 64bit in a Z reg
|
||||||
|
* while the ZCR works in Vector Quads (VQ) which is 128bit chunks.
|
||||||
|
*/
|
||||||
|
int vq = sve_zcr_len_for_el(env, arm_current_el(env)) + 1;
|
||||||
|
return gdb_get_reg64(buf, vq * 2);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
/* gdbstub asked for something out our range */
|
||||||
|
qemu_log_mask(LOG_UNIMP, "%s: out of range register %d", __func__, reg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int arm_gdb_set_svereg(CPUARMState *env, uint8_t *buf, int reg)
|
||||||
|
{
|
||||||
|
ARMCPU *cpu = env_archcpu(env);
|
||||||
|
|
||||||
|
/* The first 32 registers are the zregs */
|
||||||
|
switch (reg) {
|
||||||
|
/* The first 32 registers are the zregs */
|
||||||
|
case 0 ... 31:
|
||||||
|
{
|
||||||
|
int vq, len = 0;
|
||||||
|
uint64_t *p = (uint64_t *) buf;
|
||||||
|
for (vq = 0; vq < cpu->sve_max_vq; vq++) {
|
||||||
|
env->vfp.zregs[reg].d[vq * 2 + 1] = *p++;
|
||||||
|
env->vfp.zregs[reg].d[vq * 2] = *p++;
|
||||||
|
len += 16;
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
case 32:
|
||||||
|
vfp_set_fpsr(env, *(uint32_t *)buf);
|
||||||
|
return 4;
|
||||||
|
case 33:
|
||||||
|
vfp_set_fpcr(env, *(uint32_t *)buf);
|
||||||
|
return 4;
|
||||||
|
case 34 ... 50:
|
||||||
|
{
|
||||||
|
int preg = reg - 34;
|
||||||
|
int vq, len = 0;
|
||||||
|
uint64_t *p = (uint64_t *) buf;
|
||||||
|
for (vq = 0; vq < cpu->sve_max_vq; vq = vq + 4) {
|
||||||
|
env->vfp.pregs[preg].p[vq / 4] = *p++;
|
||||||
|
len += 8;
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
case 51:
|
||||||
|
/* cannot set vg via gdbstub */
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
/* gdbstub asked for something out our range */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "internals.h"
|
#include "internals.h"
|
||||||
#include "exec/gdbstub.h"
|
|
||||||
#include "exec/helper-proto.h"
|
#include "exec/helper-proto.h"
|
||||||
#include "qemu/host-utils.h"
|
#include "qemu/host-utils.h"
|
||||||
#include "qemu/main-loop.h"
|
#include "qemu/main-loop.h"
|
||||||
|
@ -54,110 +53,6 @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address,
|
||||||
static void switch_mode(CPUARMState *env, int mode);
|
static void switch_mode(CPUARMState *env, int mode);
|
||||||
static int aa64_va_parameter_tbi(uint64_t tcr, ARMMMUIdx mmu_idx);
|
static int aa64_va_parameter_tbi(uint64_t tcr, ARMMMUIdx mmu_idx);
|
||||||
|
|
||||||
static int vfp_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg)
|
|
||||||
{
|
|
||||||
ARMCPU *cpu = env_archcpu(env);
|
|
||||||
int nregs = cpu_isar_feature(aa32_simd_r32, cpu) ? 32 : 16;
|
|
||||||
|
|
||||||
/* VFP data registers are always little-endian. */
|
|
||||||
if (reg < nregs) {
|
|
||||||
return gdb_get_reg64(buf, *aa32_vfp_dreg(env, reg));
|
|
||||||
}
|
|
||||||
if (arm_feature(env, ARM_FEATURE_NEON)) {
|
|
||||||
/* Aliases for Q regs. */
|
|
||||||
nregs += 16;
|
|
||||||
if (reg < nregs) {
|
|
||||||
uint64_t *q = aa32_vfp_qreg(env, reg - 32);
|
|
||||||
return gdb_get_reg128(buf, q[0], q[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
switch (reg - nregs) {
|
|
||||||
case 0:
|
|
||||||
return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPSID]);
|
|
||||||
case 1:
|
|
||||||
return gdb_get_reg32(buf, vfp_get_fpscr(env));
|
|
||||||
case 2:
|
|
||||||
return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPEXC]);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int vfp_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
|
|
||||||
{
|
|
||||||
ARMCPU *cpu = env_archcpu(env);
|
|
||||||
int nregs = cpu_isar_feature(aa32_simd_r32, cpu) ? 32 : 16;
|
|
||||||
|
|
||||||
if (reg < nregs) {
|
|
||||||
*aa32_vfp_dreg(env, reg) = ldq_le_p(buf);
|
|
||||||
return 8;
|
|
||||||
}
|
|
||||||
if (arm_feature(env, ARM_FEATURE_NEON)) {
|
|
||||||
nregs += 16;
|
|
||||||
if (reg < nregs) {
|
|
||||||
uint64_t *q = aa32_vfp_qreg(env, reg - 32);
|
|
||||||
q[0] = ldq_le_p(buf);
|
|
||||||
q[1] = ldq_le_p(buf + 8);
|
|
||||||
return 16;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
switch (reg - nregs) {
|
|
||||||
case 0:
|
|
||||||
env->vfp.xregs[ARM_VFP_FPSID] = ldl_p(buf);
|
|
||||||
return 4;
|
|
||||||
case 1:
|
|
||||||
vfp_set_fpscr(env, ldl_p(buf));
|
|
||||||
return 4;
|
|
||||||
case 2:
|
|
||||||
env->vfp.xregs[ARM_VFP_FPEXC] = ldl_p(buf) & (1 << 30);
|
|
||||||
return 4;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int aarch64_fpu_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg)
|
|
||||||
{
|
|
||||||
switch (reg) {
|
|
||||||
case 0 ... 31:
|
|
||||||
{
|
|
||||||
/* 128 bit FP register - quads are in LE order */
|
|
||||||
uint64_t *q = aa64_vfp_qreg(env, reg);
|
|
||||||
return gdb_get_reg128(buf, q[1], q[0]);
|
|
||||||
}
|
|
||||||
case 32:
|
|
||||||
/* FPSR */
|
|
||||||
return gdb_get_reg32(buf, vfp_get_fpsr(env));
|
|
||||||
case 33:
|
|
||||||
/* FPCR */
|
|
||||||
return gdb_get_reg32(buf, vfp_get_fpcr(env));
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int aarch64_fpu_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
|
|
||||||
{
|
|
||||||
switch (reg) {
|
|
||||||
case 0 ... 31:
|
|
||||||
/* 128 bit FP register */
|
|
||||||
{
|
|
||||||
uint64_t *q = aa64_vfp_qreg(env, reg);
|
|
||||||
q[0] = ldq_le_p(buf);
|
|
||||||
q[1] = ldq_le_p(buf + 8);
|
|
||||||
return 16;
|
|
||||||
}
|
|
||||||
case 32:
|
|
||||||
/* FPSR */
|
|
||||||
vfp_set_fpsr(env, ldl_p(buf));
|
|
||||||
return 4;
|
|
||||||
case 33:
|
|
||||||
/* FPCR */
|
|
||||||
vfp_set_fpcr(env, ldl_p(buf));
|
|
||||||
return 4;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint64_t raw_read(CPUARMState *env, const ARMCPRegInfo *ri)
|
static uint64_t raw_read(CPUARMState *env, const ARMCPRegInfo *ri)
|
||||||
{
|
{
|
||||||
assert(ri->fieldoffset);
|
assert(ri->fieldoffset);
|
||||||
|
@ -217,134 +112,6 @@ static void write_raw_cp_reg(CPUARMState *env, const ARMCPRegInfo *ri,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* arm_get/set_gdb_*: get/set a gdb register
|
|
||||||
* @env: the CPU state
|
|
||||||
* @buf: a buffer to copy to/from
|
|
||||||
* @reg: register number (offset from start of group)
|
|
||||||
*
|
|
||||||
* We return the number of bytes copied
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int arm_gdb_get_sysreg(CPUARMState *env, GByteArray *buf, int reg)
|
|
||||||
{
|
|
||||||
ARMCPU *cpu = env_archcpu(env);
|
|
||||||
const ARMCPRegInfo *ri;
|
|
||||||
uint32_t key;
|
|
||||||
|
|
||||||
key = cpu->dyn_sysreg_xml.data.cpregs.keys[reg];
|
|
||||||
ri = get_arm_cp_reginfo(cpu->cp_regs, key);
|
|
||||||
if (ri) {
|
|
||||||
if (cpreg_field_is_64bit(ri)) {
|
|
||||||
return gdb_get_reg64(buf, (uint64_t)read_raw_cp_reg(env, ri));
|
|
||||||
} else {
|
|
||||||
return gdb_get_reg32(buf, (uint32_t)read_raw_cp_reg(env, ri));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int arm_gdb_set_sysreg(CPUARMState *env, uint8_t *buf, int reg)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef TARGET_AARCH64
|
|
||||||
static int arm_gdb_get_svereg(CPUARMState *env, GByteArray *buf, int reg)
|
|
||||||
{
|
|
||||||
ARMCPU *cpu = env_archcpu(env);
|
|
||||||
|
|
||||||
switch (reg) {
|
|
||||||
/* The first 32 registers are the zregs */
|
|
||||||
case 0 ... 31:
|
|
||||||
{
|
|
||||||
int vq, len = 0;
|
|
||||||
for (vq = 0; vq < cpu->sve_max_vq; vq++) {
|
|
||||||
len += gdb_get_reg128(buf,
|
|
||||||
env->vfp.zregs[reg].d[vq * 2 + 1],
|
|
||||||
env->vfp.zregs[reg].d[vq * 2]);
|
|
||||||
}
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
case 32:
|
|
||||||
return gdb_get_reg32(buf, vfp_get_fpsr(env));
|
|
||||||
case 33:
|
|
||||||
return gdb_get_reg32(buf, vfp_get_fpcr(env));
|
|
||||||
/* then 16 predicates and the ffr */
|
|
||||||
case 34 ... 50:
|
|
||||||
{
|
|
||||||
int preg = reg - 34;
|
|
||||||
int vq, len = 0;
|
|
||||||
for (vq = 0; vq < cpu->sve_max_vq; vq = vq + 4) {
|
|
||||||
len += gdb_get_reg64(buf, env->vfp.pregs[preg].p[vq / 4]);
|
|
||||||
}
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
case 51:
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* We report in Vector Granules (VG) which is 64bit in a Z reg
|
|
||||||
* while the ZCR works in Vector Quads (VQ) which is 128bit chunks.
|
|
||||||
*/
|
|
||||||
int vq = sve_zcr_len_for_el(env, arm_current_el(env)) + 1;
|
|
||||||
return gdb_get_reg64(buf, vq * 2);
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
/* gdbstub asked for something out our range */
|
|
||||||
qemu_log_mask(LOG_UNIMP, "%s: out of range register %d", __func__, reg);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int arm_gdb_set_svereg(CPUARMState *env, uint8_t *buf, int reg)
|
|
||||||
{
|
|
||||||
ARMCPU *cpu = env_archcpu(env);
|
|
||||||
|
|
||||||
/* The first 32 registers are the zregs */
|
|
||||||
switch (reg) {
|
|
||||||
/* The first 32 registers are the zregs */
|
|
||||||
case 0 ... 31:
|
|
||||||
{
|
|
||||||
int vq, len = 0;
|
|
||||||
uint64_t *p = (uint64_t *) buf;
|
|
||||||
for (vq = 0; vq < cpu->sve_max_vq; vq++) {
|
|
||||||
env->vfp.zregs[reg].d[vq * 2 + 1] = *p++;
|
|
||||||
env->vfp.zregs[reg].d[vq * 2] = *p++;
|
|
||||||
len += 16;
|
|
||||||
}
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
case 32:
|
|
||||||
vfp_set_fpsr(env, *(uint32_t *)buf);
|
|
||||||
return 4;
|
|
||||||
case 33:
|
|
||||||
vfp_set_fpcr(env, *(uint32_t *)buf);
|
|
||||||
return 4;
|
|
||||||
case 34 ... 50:
|
|
||||||
{
|
|
||||||
int preg = reg - 34;
|
|
||||||
int vq, len = 0;
|
|
||||||
uint64_t *p = (uint64_t *) buf;
|
|
||||||
for (vq = 0; vq < cpu->sve_max_vq; vq = vq + 4) {
|
|
||||||
env->vfp.pregs[preg].p[vq / 4] = *p++;
|
|
||||||
len += 8;
|
|
||||||
}
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
case 51:
|
|
||||||
/* cannot set vg via gdbstub */
|
|
||||||
return 0;
|
|
||||||
default:
|
|
||||||
/* gdbstub asked for something out our range */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif /* TARGET_AARCH64 */
|
|
||||||
|
|
||||||
static bool raw_accessors_invalid(const ARMCPRegInfo *ri)
|
static bool raw_accessors_invalid(const ARMCPRegInfo *ri)
|
||||||
{
|
{
|
||||||
/* Return true if the regdef would cause an assertion if you called
|
/* Return true if the regdef would cause an assertion if you called
|
||||||
|
@ -8667,44 +8434,6 @@ void register_cp_regs_for_features(ARMCPU *cpu)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
|
|
||||||
{
|
|
||||||
CPUState *cs = CPU(cpu);
|
|
||||||
CPUARMState *env = &cpu->env;
|
|
||||||
|
|
||||||
if (arm_feature(env, ARM_FEATURE_AARCH64)) {
|
|
||||||
/*
|
|
||||||
* The lower part of each SVE register aliases to the FPU
|
|
||||||
* registers so we don't need to include both.
|
|
||||||
*/
|
|
||||||
#ifdef TARGET_AARCH64
|
|
||||||
if (isar_feature_aa64_sve(&cpu->isar)) {
|
|
||||||
gdb_register_coprocessor(cs, arm_gdb_get_svereg, arm_gdb_set_svereg,
|
|
||||||
arm_gen_dynamic_svereg_xml(cs, cs->gdb_num_regs),
|
|
||||||
"sve-registers.xml", 0);
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
gdb_register_coprocessor(cs, aarch64_fpu_gdb_get_reg,
|
|
||||||
aarch64_fpu_gdb_set_reg,
|
|
||||||
34, "aarch64-fpu.xml", 0);
|
|
||||||
}
|
|
||||||
} else if (arm_feature(env, ARM_FEATURE_NEON)) {
|
|
||||||
gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
|
|
||||||
51, "arm-neon.xml", 0);
|
|
||||||
} else if (cpu_isar_feature(aa32_simd_r32, cpu)) {
|
|
||||||
gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
|
|
||||||
35, "arm-vfp3.xml", 0);
|
|
||||||
} else if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
|
|
||||||
gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
|
|
||||||
19, "arm-vfp.xml", 0);
|
|
||||||
}
|
|
||||||
gdb_register_coprocessor(cs, arm_gdb_get_sysreg, arm_gdb_set_sysreg,
|
|
||||||
arm_gen_dynamic_sysreg_xml(cs, cs->gdb_num_regs),
|
|
||||||
"system-registers.xml", 0);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Sort alphabetically by type name, except for "any". */
|
/* Sort alphabetically by type name, except for "any". */
|
||||||
static gint arm_cpu_list_compare(gconstpointer a, gconstpointer b)
|
static gint arm_cpu_list_compare(gconstpointer a, gconstpointer b)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1270,4 +1270,11 @@ static inline uint64_t pmu_counter_mask(CPUARMState *env)
|
||||||
return (1 << 31) | ((1 << pmu_num_counters(env)) - 1);
|
return (1 << 31) | ((1 << pmu_num_counters(env)) - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef TARGET_AARCH64
|
||||||
|
int arm_gdb_get_svereg(CPUARMState *env, GByteArray *buf, int reg);
|
||||||
|
int arm_gdb_set_svereg(CPUARMState *env, uint8_t *buf, int reg);
|
||||||
|
int aarch64_fpu_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg);
|
||||||
|
int aarch64_fpu_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue