mirror of https://github.com/xemu-project/xemu.git
target/riscv: gdb: support vector registers for rv64 & rv32
Signed-off-by: Hsiangkai Wang <kai.wang@sifive.com> Signed-off-by: Greentime Hu <greentime.hu@sifive.com> Signed-off-by: Frank Chang <frank.chang@sifive.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-Id: <20211210075704.23951-69-frank.chang@sifive.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
This commit is contained in:
parent
d6c4d3f2a6
commit
719d3561b2
|
@ -675,6 +675,8 @@ static const char *riscv_gdb_get_dynamic_xml(CPUState *cs, const char *xmlname)
|
||||||
|
|
||||||
if (strcmp(xmlname, "riscv-csr.xml") == 0) {
|
if (strcmp(xmlname, "riscv-csr.xml") == 0) {
|
||||||
return cpu->dyn_csr_xml;
|
return cpu->dyn_csr_xml;
|
||||||
|
} else if (strcmp(xmlname, "riscv-vector.xml") == 0) {
|
||||||
|
return cpu->dyn_vreg_xml;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -291,6 +291,7 @@ struct RISCVCPU {
|
||||||
CPURISCVState env;
|
CPURISCVState env;
|
||||||
|
|
||||||
char *dyn_csr_xml;
|
char *dyn_csr_xml;
|
||||||
|
char *dyn_vreg_xml;
|
||||||
|
|
||||||
/* Configuration Settings */
|
/* Configuration Settings */
|
||||||
struct {
|
struct {
|
||||||
|
|
|
@ -20,6 +20,32 @@
|
||||||
#include "exec/gdbstub.h"
|
#include "exec/gdbstub.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
|
|
||||||
|
struct TypeSize {
|
||||||
|
const char *gdb_type;
|
||||||
|
const char *id;
|
||||||
|
int size;
|
||||||
|
const char suffix;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct TypeSize vec_lanes[] = {
|
||||||
|
/* quads */
|
||||||
|
{ "uint128", "quads", 128, 'q' },
|
||||||
|
/* 64 bit */
|
||||||
|
{ "uint64", "longs", 64, 'l' },
|
||||||
|
/* 32 bit */
|
||||||
|
{ "uint32", "words", 32, 'w' },
|
||||||
|
/* 16 bit */
|
||||||
|
{ "uint16", "shorts", 16, 's' },
|
||||||
|
/*
|
||||||
|
* TODO: currently there is no reliable way of telling
|
||||||
|
* if the remote gdb actually understands ieee_half so
|
||||||
|
* we don't expose it in the target description for now.
|
||||||
|
* { "ieee_half", 16, 'h', 'f' },
|
||||||
|
*/
|
||||||
|
/* bytes */
|
||||||
|
{ "uint8", "bytes", 8, 'b' },
|
||||||
|
};
|
||||||
|
|
||||||
int riscv_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
|
int riscv_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
|
||||||
{
|
{
|
||||||
RISCVCPU *cpu = RISCV_CPU(cs);
|
RISCVCPU *cpu = RISCV_CPU(cs);
|
||||||
|
@ -101,6 +127,96 @@ static int riscv_gdb_set_fpu(CPURISCVState *env, uint8_t *mem_buf, int n)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convert register index number passed by GDB to the correspond
|
||||||
|
* vector CSR number. Vector CSRs are defined after vector registers
|
||||||
|
* in dynamic generated riscv-vector.xml, thus the starting register index
|
||||||
|
* of vector CSRs is 32.
|
||||||
|
* Return 0 if register index number is out of range.
|
||||||
|
*/
|
||||||
|
static int riscv_gdb_vector_csrno(int num_regs)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* The order of vector CSRs in the switch case
|
||||||
|
* should match with the order defined in csr_ops[].
|
||||||
|
*/
|
||||||
|
switch (num_regs) {
|
||||||
|
case 32:
|
||||||
|
return CSR_VSTART;
|
||||||
|
case 33:
|
||||||
|
return CSR_VXSAT;
|
||||||
|
case 34:
|
||||||
|
return CSR_VXRM;
|
||||||
|
case 35:
|
||||||
|
return CSR_VCSR;
|
||||||
|
case 36:
|
||||||
|
return CSR_VL;
|
||||||
|
case 37:
|
||||||
|
return CSR_VTYPE;
|
||||||
|
case 38:
|
||||||
|
return CSR_VLENB;
|
||||||
|
default:
|
||||||
|
/* Unknown register. */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int riscv_gdb_get_vector(CPURISCVState *env, GByteArray *buf, int n)
|
||||||
|
{
|
||||||
|
uint16_t vlenb = env_archcpu(env)->cfg.vlen >> 3;
|
||||||
|
if (n < 32) {
|
||||||
|
int i;
|
||||||
|
int cnt = 0;
|
||||||
|
for (i = 0; i < vlenb; i += 8) {
|
||||||
|
cnt += gdb_get_reg64(buf,
|
||||||
|
env->vreg[(n * vlenb + i) / 8]);
|
||||||
|
}
|
||||||
|
return cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
int csrno = riscv_gdb_vector_csrno(n);
|
||||||
|
|
||||||
|
if (!csrno) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
target_ulong val = 0;
|
||||||
|
int result = riscv_csrrw_debug(env, csrno, &val, 0, 0);
|
||||||
|
|
||||||
|
if (result == 0) {
|
||||||
|
return gdb_get_regl(buf, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int riscv_gdb_set_vector(CPURISCVState *env, uint8_t *mem_buf, int n)
|
||||||
|
{
|
||||||
|
uint16_t vlenb = env_archcpu(env)->cfg.vlen >> 3;
|
||||||
|
if (n < 32) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < vlenb; i += 8) {
|
||||||
|
env->vreg[(n * vlenb + i) / 8] = ldq_p(mem_buf + i);
|
||||||
|
}
|
||||||
|
return vlenb;
|
||||||
|
}
|
||||||
|
|
||||||
|
int csrno = riscv_gdb_vector_csrno(n);
|
||||||
|
|
||||||
|
if (!csrno) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
target_ulong val = ldtul_p(mem_buf);
|
||||||
|
int result = riscv_csrrw_debug(env, csrno, NULL, val, -1);
|
||||||
|
|
||||||
|
if (result == 0) {
|
||||||
|
return sizeof(target_ulong);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int riscv_gdb_get_csr(CPURISCVState *env, GByteArray *buf, int n)
|
static int riscv_gdb_get_csr(CPURISCVState *env, GByteArray *buf, int n)
|
||||||
{
|
{
|
||||||
if (n < CSR_TABLE_SIZE) {
|
if (n < CSR_TABLE_SIZE) {
|
||||||
|
@ -187,6 +303,68 @@ static int riscv_gen_dynamic_csr_xml(CPUState *cs, int base_reg)
|
||||||
return CSR_TABLE_SIZE;
|
return CSR_TABLE_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ricsv_gen_dynamic_vector_xml(CPUState *cs, int base_reg)
|
||||||
|
{
|
||||||
|
RISCVCPU *cpu = RISCV_CPU(cs);
|
||||||
|
GString *s = g_string_new(NULL);
|
||||||
|
g_autoptr(GString) ts = g_string_new("");
|
||||||
|
int reg_width = cpu->cfg.vlen;
|
||||||
|
int num_regs = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
g_string_printf(s, "<?xml version=\"1.0\"?>");
|
||||||
|
g_string_append_printf(s, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">");
|
||||||
|
g_string_append_printf(s, "<feature name=\"org.gnu.gdb.riscv.vector\">");
|
||||||
|
|
||||||
|
/* First define types and totals in a whole VL */
|
||||||
|
for (i = 0; i < ARRAY_SIZE(vec_lanes); i++) {
|
||||||
|
int count = reg_width / vec_lanes[i].size;
|
||||||
|
g_string_printf(ts, "%s", vec_lanes[i].id);
|
||||||
|
g_string_append_printf(s,
|
||||||
|
"<vector id=\"%s\" type=\"%s\" count=\"%d\"/>",
|
||||||
|
ts->str, vec_lanes[i].gdb_type, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Define unions */
|
||||||
|
g_string_append_printf(s, "<union id=\"riscv_vector\">");
|
||||||
|
for (i = 0; i < ARRAY_SIZE(vec_lanes); i++) {
|
||||||
|
g_string_append_printf(s, "<field name=\"%c\" type=\"%s\"/>",
|
||||||
|
vec_lanes[i].suffix,
|
||||||
|
vec_lanes[i].id);
|
||||||
|
}
|
||||||
|
g_string_append(s, "</union>");
|
||||||
|
|
||||||
|
/* Define vector registers */
|
||||||
|
for (i = 0; i < 32; i++) {
|
||||||
|
g_string_append_printf(s,
|
||||||
|
"<reg name=\"v%d\" bitsize=\"%d\""
|
||||||
|
" regnum=\"%d\" group=\"vector\""
|
||||||
|
" type=\"riscv_vector\"/>",
|
||||||
|
i, reg_width, base_reg++);
|
||||||
|
num_regs++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Define vector CSRs */
|
||||||
|
const char *vector_csrs[7] = {
|
||||||
|
"vstart", "vxsat", "vxrm", "vcsr",
|
||||||
|
"vl", "vtype", "vlenb"
|
||||||
|
};
|
||||||
|
|
||||||
|
for (i = 0; i < 7; i++) {
|
||||||
|
g_string_append_printf(s,
|
||||||
|
"<reg name=\"%s\" bitsize=\"%d\""
|
||||||
|
" regnum=\"%d\" group=\"vector\""
|
||||||
|
" type=\"int\"/>",
|
||||||
|
vector_csrs[i], TARGET_LONG_BITS, base_reg++);
|
||||||
|
num_regs++;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_string_append_printf(s, "</feature>");
|
||||||
|
|
||||||
|
cpu->dyn_vreg_xml = g_string_free(s, false);
|
||||||
|
return num_regs;
|
||||||
|
}
|
||||||
|
|
||||||
void riscv_cpu_register_gdb_regs_for_features(CPUState *cs)
|
void riscv_cpu_register_gdb_regs_for_features(CPUState *cs)
|
||||||
{
|
{
|
||||||
RISCVCPU *cpu = RISCV_CPU(cs);
|
RISCVCPU *cpu = RISCV_CPU(cs);
|
||||||
|
@ -198,6 +376,12 @@ void riscv_cpu_register_gdb_regs_for_features(CPUState *cs)
|
||||||
gdb_register_coprocessor(cs, riscv_gdb_get_fpu, riscv_gdb_set_fpu,
|
gdb_register_coprocessor(cs, riscv_gdb_get_fpu, riscv_gdb_set_fpu,
|
||||||
36, "riscv-32bit-fpu.xml", 0);
|
36, "riscv-32bit-fpu.xml", 0);
|
||||||
}
|
}
|
||||||
|
if (env->misa_ext & RVV) {
|
||||||
|
gdb_register_coprocessor(cs, riscv_gdb_get_vector, riscv_gdb_set_vector,
|
||||||
|
ricsv_gen_dynamic_vector_xml(cs,
|
||||||
|
cs->gdb_num_regs),
|
||||||
|
"riscv-vector.xml", 0);
|
||||||
|
}
|
||||||
#if defined(TARGET_RISCV32)
|
#if defined(TARGET_RISCV32)
|
||||||
gdb_register_coprocessor(cs, riscv_gdb_get_virtual, riscv_gdb_set_virtual,
|
gdb_register_coprocessor(cs, riscv_gdb_get_virtual, riscv_gdb_set_virtual,
|
||||||
1, "riscv-32bit-virtual.xml", 0);
|
1, "riscv-32bit-virtual.xml", 0);
|
||||||
|
|
Loading…
Reference in New Issue