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
		
			
				
	
	
		
			212 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			212 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * ARM gdb server stub: AArch64 specific functions.
 | 
						|
 *
 | 
						|
 * Copyright (c) 2013 SUSE LINUX Products GmbH
 | 
						|
 *
 | 
						|
 * 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.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
 | 
						|
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
						|
 * Lesser General Public License for more details.
 | 
						|
 *
 | 
						|
 * You should have received a copy of the GNU Lesser General Public
 | 
						|
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
 | 
						|
 */
 | 
						|
#include "qemu/osdep.h"
 | 
						|
#include "qemu/log.h"
 | 
						|
#include "cpu.h"
 | 
						|
#include "internals.h"
 | 
						|
#include "exec/gdbstub.h"
 | 
						|
 | 
						|
int aarch64_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
 | 
						|
{
 | 
						|
    ARMCPU *cpu = ARM_CPU(cs);
 | 
						|
    CPUARMState *env = &cpu->env;
 | 
						|
 | 
						|
    if (n < 31) {
 | 
						|
        /* Core integer register.  */
 | 
						|
        return gdb_get_reg64(mem_buf, env->xregs[n]);
 | 
						|
    }
 | 
						|
    switch (n) {
 | 
						|
    case 31:
 | 
						|
        return gdb_get_reg64(mem_buf, env->xregs[31]);
 | 
						|
    case 32:
 | 
						|
        return gdb_get_reg64(mem_buf, env->pc);
 | 
						|
    case 33:
 | 
						|
        return gdb_get_reg32(mem_buf, pstate_read(env));
 | 
						|
    }
 | 
						|
    /* Unknown register.  */
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
int aarch64_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
 | 
						|
{
 | 
						|
    ARMCPU *cpu = ARM_CPU(cs);
 | 
						|
    CPUARMState *env = &cpu->env;
 | 
						|
    uint64_t tmp;
 | 
						|
 | 
						|
    tmp = ldq_p(mem_buf);
 | 
						|
 | 
						|
    if (n < 31) {
 | 
						|
        /* Core integer register.  */
 | 
						|
        env->xregs[n] = tmp;
 | 
						|
        return 8;
 | 
						|
    }
 | 
						|
    switch (n) {
 | 
						|
    case 31:
 | 
						|
        env->xregs[31] = tmp;
 | 
						|
        return 8;
 | 
						|
    case 32:
 | 
						|
        env->pc = tmp;
 | 
						|
        return 8;
 | 
						|
    case 33:
 | 
						|
        /* CPSR */
 | 
						|
        pstate_write(env, tmp);
 | 
						|
        return 4;
 | 
						|
    }
 | 
						|
    /* Unknown register.  */
 | 
						|
    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;
 | 
						|
}
 |