diff options
-rw-r--r-- | gdb/csky-linux-tdep.c | 149 | ||||
-rw-r--r-- | gdb/csky-tdep.h | 3 |
2 files changed, 140 insertions, 12 deletions
diff --git a/gdb/csky-linux-tdep.c b/gdb/csky-linux-tdep.c index 440045e..106f629 100644 --- a/gdb/csky-linux-tdep.c +++ b/gdb/csky-linux-tdep.c @@ -36,6 +36,8 @@ #define SIZEOF_CSKY_GREGSET 34*4 /* Float regset fesr fsr fr0-fr31 for CK810. */ #define SIZEOF_CSKY_FREGSET 34*4 +/* Float regset vr0~vr15 fr15~fr31, reserved for CK810 when kernel 4.x. */ +#define SIZEOF_CSKY_FREGSET_K4X 400 /* Offset mapping table from core_section to regcache of general registers for ck810. */ @@ -118,16 +120,80 @@ csky_supply_fregset (const struct regset *regset, int fregset_num = ARRAY_SIZE (csky_fregset_offset); gdb_assert (len >= SIZEOF_CSKY_FREGSET); - for (i = 0; i < fregset_num; i++) + if (len == SIZEOF_CSKY_FREGSET) { - if ((regnum == csky_fregset_offset[i] || regnum == -1) - && csky_fregset_offset[i] != -1) + for (i = 0; i < fregset_num; i++) { - int num = csky_fregset_offset[i]; - offset += register_size (gdbarch, num); - regcache->raw_supply (csky_fregset_offset[i], fregs + offset); + if ((regnum == csky_fregset_offset[i] || regnum == -1) + && csky_fregset_offset[i] != -1) + { + int num = csky_fregset_offset[i]; + offset += register_size (gdbarch, num); + regcache->raw_supply (csky_fregset_offset[i], fregs + offset); + } } } + else if (len == SIZEOF_CSKY_FREGSET_K4X) + { + /* When kernel version >= 4.x, .reg2 size will be 400. + Contents is { + unsigned long vr[96]; + unsigned long fcr; + unsigned long fesr; + unsigned long fid; + unsigned long reserved; + } + VR[96] means: (vr0~vr15) + (fr16~fr31), each Vector register is + 128-bits, each Float register is 64 bits, the total size is + (4*96). + + In addition, for fr0~fr15, each FRx is the lower 64 bits of the + corresponding VRx. So fr0~fr15 and vr0~vr15 regisetrs use the same + offset. */ + int fcr_regno[] = {122, 123, 121}; /* fcr, fesr, fid. */ + + /* Supply vr0~vr15. */ + for (i = 0; i < 16; i ++) + { + if (gdbarch_register_name (gdbarch, (CSKY_VR0_REGNUM + i))) + { + offset = 16 * i; + regcache->raw_supply (CSKY_VR0_REGNUM + i, fregs + offset); + } + } + /* Supply fr0~fr15. */ + for (i = 0; i < 16; i ++) + { + if (gdbarch_register_name (gdbarch, (CSKY_FR0_REGNUM + i))) + { + offset = 16 * i; + regcache->raw_supply (CSKY_FR0_REGNUM + i, fregs + offset); + } + } + /* Supply fr16~fr31. */ + for (i = 0; i < 16; i ++) + { + if (gdbarch_register_name (gdbarch, (CSKY_FR16_REGNUM + i))) + { + offset = (16 * 16) + (8 * i); + regcache->raw_supply (CSKY_FR16_REGNUM + i, fregs + offset); + } + } + /* Supply fcr, fesr, fid. */ + for (i = 0; i < 3; i ++) + { + if (gdbarch_register_name (gdbarch, fcr_regno[i])) + { + offset = (16 * 16) + (16 * 8) + (4 * i); + regcache->raw_supply (fcr_regno[i], fregs + offset); + } + } + } + else + { + warning (_("Unknow size %ld of section .reg2, can not get value" + " of float registers."), len); + } } /* Implement the collect_regset hook for FP registers in core files. */ @@ -144,14 +210,70 @@ csky_collect_fregset (const struct regset *regset, int offset = 0; gdb_assert (len >= SIZEOF_CSKY_FREGSET); - for (regno = 0; regno < fregset_num; regno++) + if (len == SIZEOF_CSKY_FREGSET) + { + for (regno = 0; regno < fregset_num; regno++) + { + if ((regnum == csky_fregset_offset[regno] || regnum == -1) + && csky_fregset_offset[regno] != -1) + { + offset += register_size (gdbarch, csky_fregset_offset[regno]); + regcache->raw_collect (regno, fregs + offset); + } + } + } + else if (len == SIZEOF_CSKY_FREGSET_K4X) { - if ((regnum == csky_fregset_offset[regno] || regnum == -1) - && csky_fregset_offset[regno] != -1) + /* When kernel version >= 4.x, .reg2 size will be 400. + Contents is { + unsigned long vr[96]; + unsigned long fcr; + unsigned long fesr; + unsigned long fid; + unsigned long reserved; + } + VR[96] means: (vr0~vr15) + (fr16~fr31), each Vector register is$ + 128-bits, each Float register is 64 bits, the total size is$ + (4*96).$ + + In addition, for fr0~fr15, each FRx is the lower 64 bits of the$ + corresponding VRx. So fr0~fr15 and vr0~vr15 regisetrs use the same$ + offset. */ + int i = 0; + int fcr_regno[] = {122, 123, 121}; /* fcr, fesr, fid. */ + + /* Supply vr0~vr15. */ + for (i = 0; i < 16; i ++) { - offset += register_size (gdbarch, csky_fregset_offset[regno]); - regcache->raw_collect (regno, fregs + offset); + if (gdbarch_register_name (gdbarch, (CSKY_VR0_REGNUM + i))) + { + offset = 16 * i; + regcache ->raw_collect (CSKY_VR0_REGNUM + i, fregs + offset); + } } + /* Supply fr16~fr31. */ + for (i = 0; i < 16; i ++) + { + if (gdbarch_register_name (gdbarch, (CSKY_FR16_REGNUM + i))) + { + offset = (16 * 16) + (8 * i); + regcache ->raw_collect (CSKY_FR16_REGNUM + i, fregs + offset); + } + } + /* Supply fcr, fesr, fid. */ + for (i = 0; i < 3; i ++) + { + if (gdbarch_register_name (gdbarch, fcr_regno[i])) + { + offset = (16 * 16) + (16 * 8) + (4 * i); + regcache ->raw_collect (fcr_regno[i], fregs + offset); + } + } + } + else + { + warning (_("Unknow size %ld of section .reg2, will not set value" + " of float registers."), len); } } @@ -166,7 +288,10 @@ static const struct regset csky_regset_float = { NULL, csky_supply_fregset, - csky_collect_fregset + csky_collect_fregset, + /* Allow .reg2 to have a different size, and the size of .reg2 should + always be bigger than SIZEOF_CSKY_FREGSET. */ + 1 }; /* Iterate over core file register note sections. */ diff --git a/gdb/csky-tdep.h b/gdb/csky-tdep.h index 54000ab..3ee50fc 100644 --- a/gdb/csky-tdep.h +++ b/gdb/csky-tdep.h @@ -93,6 +93,9 @@ enum csky_regnum CSKY_PSR_REGNUM = CSKY_CR0_REGNUM, CSKY_MAX_REGISTER_SIZE = 16, + + /* Actually, the max regs number should be 1187. But if the + gdb stub does not send a tdesc-xml file to gdb, 253 works. */ CSKY_MAX_REGS = 253 }; |