qemu/target/loongarch/gdbstub.c
Alex Bennée 4ea5fe997d gdbstub: move register helpers into standalone include
These inline helpers are all used by target specific code so move them
out of the general header so we don't needlessly pollute the rest of
the API with target specific stuff.

Note we have to include cpu.h in semihosting as it was relying on a
side effect before.

Reviewed-by: Taylor Simpson <tsimpson@quicinc.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>

Message-Id: <20230302190846.2593720-21-alex.bennee@linaro.org>
Message-Id: <20230303025805.625589-21-richard.henderson@linaro.org>
2023-03-07 20:44:08 +00:00

106 lines
2.5 KiB
C

/*
* LOONGARCH gdb server stub
*
* Copyright (c) 2021 Loongson Technology Corporation Limited
*
* SPDX-License-Identifier: LGPL-2.1+
*/
#include "qemu/osdep.h"
#include "cpu.h"
#include "internals.h"
#include "exec/gdbstub.h"
#include "gdbstub/helpers.h"
uint64_t read_fcc(CPULoongArchState *env)
{
uint64_t ret = 0;
for (int i = 0; i < 8; ++i) {
ret |= (uint64_t)env->cf[i] << (i * 8);
}
return ret;
}
void write_fcc(CPULoongArchState *env, uint64_t val)
{
for (int i = 0; i < 8; ++i) {
env->cf[i] = (val >> (i * 8)) & 1;
}
}
int loongarch_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
{
LoongArchCPU *cpu = LOONGARCH_CPU(cs);
CPULoongArchState *env = &cpu->env;
if (0 <= n && n < 32) {
return gdb_get_regl(mem_buf, env->gpr[n]);
} else if (n == 32) {
/* orig_a0 */
return gdb_get_regl(mem_buf, 0);
} else if (n == 33) {
return gdb_get_regl(mem_buf, env->pc);
} else if (n == 34) {
return gdb_get_regl(mem_buf, env->CSR_BADV);
}
return 0;
}
int loongarch_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
{
LoongArchCPU *cpu = LOONGARCH_CPU(cs);
CPULoongArchState *env = &cpu->env;
target_ulong tmp = ldtul_p(mem_buf);
int length = 0;
if (0 <= n && n < 32) {
env->gpr[n] = tmp;
length = sizeof(target_ulong);
} else if (n == 33) {
env->pc = tmp;
length = sizeof(target_ulong);
}
return length;
}
static int loongarch_gdb_get_fpu(CPULoongArchState *env,
GByteArray *mem_buf, int n)
{
if (0 <= n && n < 32) {
return gdb_get_reg64(mem_buf, env->fpr[n]);
} else if (n == 32) {
uint64_t val = read_fcc(env);
return gdb_get_reg64(mem_buf, val);
} else if (n == 33) {
return gdb_get_reg32(mem_buf, env->fcsr0);
}
return 0;
}
static int loongarch_gdb_set_fpu(CPULoongArchState *env,
uint8_t *mem_buf, int n)
{
int length = 0;
if (0 <= n && n < 32) {
env->fpr[n] = ldq_p(mem_buf);
length = 8;
} else if (n == 32) {
uint64_t val = ldq_p(mem_buf);
write_fcc(env, val);
length = 8;
} else if (n == 33) {
env->fcsr0 = ldl_p(mem_buf);
length = 4;
}
return length;
}
void loongarch_cpu_register_gdb_regs_for_features(CPUState *cs)
{
gdb_register_coprocessor(cs, loongarch_gdb_get_fpu, loongarch_gdb_set_fpu,
41, "loongarch-fpu.xml", 0);
}