forked from Imagelibrary/binutils-gdb
gdb/gdbserver: LoongArch: Improve implementation of fcc registers
The current implementation of the fcc register is referenced to the
user_fp_state structure of the kernel uapi [1].
struct user_fp_state {
uint64_t fpr[32];
uint64_t fcc;
uint32_t fcsr;
};
But it is mistakenly defined as a 64-bit fputype register, resulting
in a confusing output of "info register".
(gdb) info register
...
fcc {f = 0x0, d = 0x0} {f = 0, d = 0}
...
According to "Condition Flag Register" in "LoongArch Reference Manual"
[2], there are 8 condition flag registers of size 1. Use 8 registers of
uint8 to make it easier for users to view the fcc register groups.
(gdb) info register
...
fcc0 0x1 1
fcc1 0x0 0
fcc2 0x0 0
fcc3 0x0 0
fcc4 0x0 0
fcc5 0x0 0
fcc6 0x0 0
fcc7 0x0 0
...
[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/loongarch/include/uapi/asm/ptrace.h
[2] https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html#_condition_flag_register
Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
This commit is contained in:
committed by
Tiezhu Yang
parent
a88c79b770
commit
ea3352172e
@@ -37,9 +37,10 @@ enum loongarch_regnum
|
||||
LOONGARCH_ARG_REGNUM = 8, /* r4-r11: general-purpose argument registers.
|
||||
f0-f7: floating-point argument registers. */
|
||||
LOONGARCH_FIRST_FP_REGNUM = LOONGARCH_LINUX_NUM_GREGSET,
|
||||
LOONGARCH_FCC_REGNUM = LOONGARCH_FIRST_FP_REGNUM + 32,
|
||||
LOONGARCH_FCSR_REGNUM = LOONGARCH_FCC_REGNUM + 1,
|
||||
LOONGARCH_LINUX_NUM_FPREGSET = 34,
|
||||
LOONGARCH_LINUX_NUM_FPREGSET = 32,
|
||||
LOONGARCH_FIRST_FCC_REGNUM = LOONGARCH_FIRST_FP_REGNUM + LOONGARCH_LINUX_NUM_FPREGSET,
|
||||
LOONGARCH_LINUX_NUM_FCC = 8,
|
||||
LOONGARCH_FCSR_REGNUM = LOONGARCH_FIRST_FCC_REGNUM + LOONGARCH_LINUX_NUM_FCC,
|
||||
};
|
||||
|
||||
enum loongarch_fputype
|
||||
|
||||
@@ -49,7 +49,14 @@ create_feature_loongarch_fpu (struct target_desc *result, long regnum)
|
||||
tdesc_create_reg (feature, "f29", regnum++, 1, "float", 64, "fputype");
|
||||
tdesc_create_reg (feature, "f30", regnum++, 1, "float", 64, "fputype");
|
||||
tdesc_create_reg (feature, "f31", regnum++, 1, "float", 64, "fputype");
|
||||
tdesc_create_reg (feature, "fcc", regnum++, 1, "float", 64, "fputype");
|
||||
tdesc_create_reg (feature, "fcc0", regnum++, 1, "float", 8, "uint8");
|
||||
tdesc_create_reg (feature, "fcc1", regnum++, 1, "float", 8, "uint8");
|
||||
tdesc_create_reg (feature, "fcc2", regnum++, 1, "float", 8, "uint8");
|
||||
tdesc_create_reg (feature, "fcc3", regnum++, 1, "float", 8, "uint8");
|
||||
tdesc_create_reg (feature, "fcc4", regnum++, 1, "float", 8, "uint8");
|
||||
tdesc_create_reg (feature, "fcc5", regnum++, 1, "float", 8, "uint8");
|
||||
tdesc_create_reg (feature, "fcc6", regnum++, 1, "float", 8, "uint8");
|
||||
tdesc_create_reg (feature, "fcc7", regnum++, 1, "float", 8, "uint8");
|
||||
tdesc_create_reg (feature, "fcsr", regnum++, 1, "float", 32, "uint32");
|
||||
return regnum;
|
||||
}
|
||||
|
||||
@@ -45,6 +45,13 @@
|
||||
<reg name="f29" bitsize="64" type="fputype" group="float"/>
|
||||
<reg name="f30" bitsize="64" type="fputype" group="float"/>
|
||||
<reg name="f31" bitsize="64" type="fputype" group="float"/>
|
||||
<reg name="fcc" bitsize="64" type="fputype" group="float"/>
|
||||
<reg name="fcc0" bitsize="8" type="uint8" group="float"/>
|
||||
<reg name="fcc1" bitsize="8" type="uint8" group="float"/>
|
||||
<reg name="fcc2" bitsize="8" type="uint8" group="float"/>
|
||||
<reg name="fcc3" bitsize="8" type="uint8" group="float"/>
|
||||
<reg name="fcc4" bitsize="8" type="uint8" group="float"/>
|
||||
<reg name="fcc5" bitsize="8" type="uint8" group="float"/>
|
||||
<reg name="fcc6" bitsize="8" type="uint8" group="float"/>
|
||||
<reg name="fcc7" bitsize="8" type="uint8" group="float"/>
|
||||
<reg name="fcsr" bitsize="32" type="uint32" group="float"/>
|
||||
</feature>
|
||||
|
||||
@@ -123,6 +123,7 @@ loongarch_supply_fpregset (const struct regset *r,
|
||||
{
|
||||
const gdb_byte *buf = nullptr;
|
||||
int fprsize = register_size (regcache->arch (), LOONGARCH_FIRST_FP_REGNUM);
|
||||
int fccsize = register_size (regcache->arch (), LOONGARCH_FIRST_FCC_REGNUM);
|
||||
|
||||
if (regnum == -1)
|
||||
{
|
||||
@@ -131,12 +132,33 @@ loongarch_supply_fpregset (const struct regset *r,
|
||||
buf = (const gdb_byte *)fprs + fprsize * i;
|
||||
regcache->raw_supply (LOONGARCH_FIRST_FP_REGNUM + i, (const void *)buf);
|
||||
}
|
||||
for (int i = 0; i < LOONGARCH_LINUX_NUM_FCC; i++)
|
||||
{
|
||||
buf = (const gdb_byte *)fprs + fprsize * LOONGARCH_LINUX_NUM_FPREGSET +
|
||||
fccsize * i;
|
||||
regcache->raw_supply (LOONGARCH_FIRST_FCC_REGNUM + i, (const void *)buf);
|
||||
}
|
||||
buf = (const gdb_byte *)fprs + fprsize * LOONGARCH_LINUX_NUM_FPREGSET +
|
||||
fccsize * LOONGARCH_LINUX_NUM_FCC;
|
||||
regcache->raw_supply (LOONGARCH_FCSR_REGNUM, (const void *)buf);
|
||||
}
|
||||
else if (regnum >= LOONGARCH_FIRST_FP_REGNUM && regnum <= LOONGARCH_FCSR_REGNUM)
|
||||
else if (regnum >= LOONGARCH_FIRST_FP_REGNUM && regnum < LOONGARCH_FIRST_FCC_REGNUM)
|
||||
{
|
||||
buf = (const gdb_byte *)fprs + fprsize * (regnum - LOONGARCH_FIRST_FP_REGNUM);
|
||||
regcache->raw_supply (regnum, (const void *)buf);
|
||||
}
|
||||
else if (regnum >= LOONGARCH_FIRST_FCC_REGNUM && regnum < LOONGARCH_FCSR_REGNUM)
|
||||
{
|
||||
buf = (const gdb_byte *)fprs + fprsize * LOONGARCH_LINUX_NUM_FPREGSET +
|
||||
fccsize * (regnum - LOONGARCH_FIRST_FCC_REGNUM);
|
||||
regcache->raw_supply (regnum, (const void *)buf);
|
||||
}
|
||||
else if (regnum == LOONGARCH_FCSR_REGNUM)
|
||||
{
|
||||
buf = (const gdb_byte *)fprs + fprsize * LOONGARCH_LINUX_NUM_FPREGSET +
|
||||
fccsize * LOONGARCH_LINUX_NUM_FCC;
|
||||
regcache->raw_supply (regnum, (const void *)buf);
|
||||
}
|
||||
}
|
||||
|
||||
/* Pack the GDB's register cache value into an elf_fpregset_t. */
|
||||
@@ -147,6 +169,7 @@ loongarch_fill_fpregset (const struct regset *r,
|
||||
{
|
||||
gdb_byte *buf = nullptr;
|
||||
int fprsize = register_size (regcache->arch (), LOONGARCH_FIRST_FP_REGNUM);
|
||||
int fccsize = register_size (regcache->arch (), LOONGARCH_FIRST_FCC_REGNUM);
|
||||
|
||||
if (regnum == -1)
|
||||
{
|
||||
@@ -155,12 +178,33 @@ loongarch_fill_fpregset (const struct regset *r,
|
||||
buf = (gdb_byte *)fprs + fprsize * i;
|
||||
regcache->raw_collect (LOONGARCH_FIRST_FP_REGNUM + i, (void *)buf);
|
||||
}
|
||||
for (int i = 0; i < LOONGARCH_LINUX_NUM_FCC; i++)
|
||||
{
|
||||
buf = (gdb_byte *)fprs + fprsize * LOONGARCH_LINUX_NUM_FPREGSET +
|
||||
fccsize * i;
|
||||
regcache->raw_collect (LOONGARCH_FIRST_FCC_REGNUM + i, (void *)buf);
|
||||
}
|
||||
buf = (gdb_byte *)fprs + fprsize * LOONGARCH_LINUX_NUM_FPREGSET +
|
||||
fccsize * LOONGARCH_LINUX_NUM_FCC;
|
||||
regcache->raw_collect (LOONGARCH_FCSR_REGNUM, (void *)buf);
|
||||
}
|
||||
else if (regnum >= LOONGARCH_FIRST_FP_REGNUM && regnum <= LOONGARCH_FCSR_REGNUM)
|
||||
else if (regnum >= LOONGARCH_FIRST_FP_REGNUM && regnum < LOONGARCH_FIRST_FCC_REGNUM)
|
||||
{
|
||||
buf = (gdb_byte *)fprs + fprsize * (regnum - LOONGARCH_FIRST_FP_REGNUM);
|
||||
regcache->raw_collect (regnum, (void *)buf);
|
||||
}
|
||||
else if (regnum >= LOONGARCH_FIRST_FCC_REGNUM && regnum < LOONGARCH_FCSR_REGNUM)
|
||||
{
|
||||
buf = (gdb_byte *)fprs + fprsize * LOONGARCH_LINUX_NUM_FPREGSET +
|
||||
fccsize * (regnum - LOONGARCH_FIRST_FCC_REGNUM);
|
||||
regcache->raw_collect (regnum, (void *)buf);
|
||||
}
|
||||
else if (regnum == LOONGARCH_FCSR_REGNUM)
|
||||
{
|
||||
buf = (gdb_byte *)fprs + fprsize * LOONGARCH_LINUX_NUM_FPREGSET +
|
||||
fccsize * LOONGARCH_LINUX_NUM_FCC;
|
||||
regcache->raw_collect (regnum, (void *)buf);
|
||||
}
|
||||
}
|
||||
|
||||
/* Define the FP register regset. */
|
||||
@@ -221,11 +265,14 @@ loongarch_iterate_over_regset_sections (struct gdbarch *gdbarch,
|
||||
{
|
||||
int gprsize = register_size (gdbarch, 0);
|
||||
int fprsize = register_size (gdbarch, LOONGARCH_FIRST_FP_REGNUM);
|
||||
int fccsize = register_size (gdbarch, LOONGARCH_FIRST_FCC_REGNUM);
|
||||
int fcsrsize = register_size (gdbarch, LOONGARCH_FCSR_REGNUM);
|
||||
int fpsize = fprsize * LOONGARCH_LINUX_NUM_FPREGSET +
|
||||
fccsize * LOONGARCH_LINUX_NUM_FCC + fcsrsize;
|
||||
|
||||
cb (".reg", LOONGARCH_LINUX_NUM_GREGSET * gprsize,
|
||||
LOONGARCH_LINUX_NUM_GREGSET * gprsize, &loongarch_gregset, nullptr, cb_data);
|
||||
cb (".reg2", LOONGARCH_LINUX_NUM_FPREGSET * fprsize,
|
||||
LOONGARCH_LINUX_NUM_FPREGSET * fprsize, &loongarch_fpregset, nullptr, cb_data);
|
||||
cb (".reg2", fpsize, fpsize, &loongarch_fpregset, nullptr, cb_data);
|
||||
}
|
||||
|
||||
/* The following value is derived from __NR_rt_sigreturn in
|
||||
|
||||
@@ -1428,10 +1428,12 @@ loongarch_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
||||
/* Validate the description provides the fpu registers and
|
||||
allocate their numbers. */
|
||||
regnum = LOONGARCH_FIRST_FP_REGNUM;
|
||||
for (int i = 0; i < 32; i++)
|
||||
for (int i = 0; i < LOONGARCH_LINUX_NUM_FPREGSET; i++)
|
||||
valid_p &= tdesc_numbered_register (feature_fpu, tdesc_data.get (), regnum++,
|
||||
loongarch_f_normal_name[i] + 1);
|
||||
valid_p &= tdesc_numbered_register (feature_fpu, tdesc_data.get (), regnum++, "fcc");
|
||||
for (int i = 0; i < LOONGARCH_LINUX_NUM_FCC; i++)
|
||||
valid_p &= tdesc_numbered_register (feature_fpu, tdesc_data.get (), regnum++,
|
||||
loongarch_c_normal_name[i] + 1);
|
||||
valid_p &= tdesc_numbered_register (feature_fpu, tdesc_data.get (), regnum++, "fcsr");
|
||||
if (!valid_p)
|
||||
return nullptr;
|
||||
|
||||
@@ -127,12 +127,24 @@ loongarch_fill_fpregset (struct regcache *regcache, void *buf)
|
||||
{
|
||||
gdb_byte *regbuf = nullptr;
|
||||
int fprsize = register_size (regcache->tdesc, LOONGARCH_FIRST_FP_REGNUM);
|
||||
int fccsize = register_size (regcache->tdesc, LOONGARCH_FIRST_FCC_REGNUM);
|
||||
|
||||
for (int i = 0; i < LOONGARCH_LINUX_NUM_FPREGSET; i++)
|
||||
{
|
||||
regbuf = (gdb_byte *)buf + fprsize * i;
|
||||
collect_register (regcache, LOONGARCH_FIRST_FP_REGNUM + i, regbuf);
|
||||
}
|
||||
|
||||
for (int i = 0; i < LOONGARCH_LINUX_NUM_FCC; i++)
|
||||
{
|
||||
regbuf = (gdb_byte *)buf + fprsize * LOONGARCH_LINUX_NUM_FPREGSET +
|
||||
fccsize * i;
|
||||
collect_register (regcache, LOONGARCH_FIRST_FCC_REGNUM + i, regbuf);
|
||||
}
|
||||
|
||||
regbuf = (gdb_byte *)buf + fprsize * LOONGARCH_LINUX_NUM_FPREGSET +
|
||||
fccsize * LOONGARCH_LINUX_NUM_FCC;
|
||||
collect_register (regcache, LOONGARCH_FCSR_REGNUM, regbuf);
|
||||
}
|
||||
|
||||
/* Supply FPRs from BUF into REGCACHE. */
|
||||
@@ -142,12 +154,24 @@ loongarch_store_fpregset (struct regcache *regcache, const void *buf)
|
||||
{
|
||||
const gdb_byte *regbuf = nullptr;
|
||||
int fprsize = register_size (regcache->tdesc, LOONGARCH_FIRST_FP_REGNUM);
|
||||
int fccsize = register_size (regcache->tdesc, LOONGARCH_FIRST_FCC_REGNUM);
|
||||
|
||||
for (int i = 0; i < LOONGARCH_LINUX_NUM_FPREGSET; i++)
|
||||
{
|
||||
regbuf = (const gdb_byte *)buf + fprsize * i;
|
||||
supply_register (regcache, LOONGARCH_FIRST_FP_REGNUM + i, regbuf);
|
||||
}
|
||||
|
||||
for (int i = 0; i < LOONGARCH_LINUX_NUM_FCC; i++)
|
||||
{
|
||||
regbuf = (const gdb_byte *)buf + fprsize * LOONGARCH_LINUX_NUM_FPREGSET +
|
||||
fccsize * i;
|
||||
supply_register (regcache, LOONGARCH_FIRST_FCC_REGNUM + i, regbuf);
|
||||
}
|
||||
|
||||
regbuf = (const gdb_byte *)buf + fprsize * LOONGARCH_LINUX_NUM_FPREGSET +
|
||||
fccsize * LOONGARCH_LINUX_NUM_FCC;
|
||||
supply_register (regcache, LOONGARCH_FCSR_REGNUM, regbuf);
|
||||
}
|
||||
|
||||
/* LoongArch/Linux regsets. */
|
||||
|
||||
Reference in New Issue
Block a user