diff options
Diffstat (limited to 'gdb')
-rw-r--r-- | gdb/csky-tdep.c | 261 | ||||
-rw-r--r-- | gdb/csky-tdep.h | 7 |
2 files changed, 268 insertions, 0 deletions
diff --git a/gdb/csky-tdep.c b/gdb/csky-tdep.c index 7a9c38c0064..b63ff7ccd44 100644 --- a/gdb/csky-tdep.c +++ b/gdb/csky-tdep.c @@ -59,6 +59,7 @@ #include <vector> /* Control debugging information emitted in this file. */ + static bool csky_debug = false; static const reggroup *cr_reggroup; @@ -363,7 +364,13 @@ static const struct csky_supported_tdesc_register csky_supported_alias_regs[] = {"t_pcr", 230}, }; +/* Functions declaration. */ + +static const char * +csky_pseudo_register_name (struct gdbarch *gdbarch, int regno); + /* Get csky supported registers's count for tdesc xml. */ + static int csky_get_supported_tdesc_registers_count() { @@ -381,6 +388,7 @@ csky_get_supported_tdesc_registers_count() } /* Return a supported register according to index. */ + static const struct csky_supported_tdesc_register * csky_get_supported_register_by_index (int index) { @@ -652,6 +660,15 @@ static const char * const csky_register_names[] = static const char * csky_register_name (struct gdbarch *gdbarch, int reg_nr) { + int num_regs = gdbarch_num_regs (gdbarch); + int num_pseudo_regs = gdbarch_num_pseudo_regs (gdbarch); + + if ((reg_nr >= num_regs) && (reg_nr < (num_regs + num_pseudo_regs))) + return csky_pseudo_register_name (gdbarch, reg_nr); + + if (tdesc_has_registers (gdbarch_target_desc (gdbarch))) + return tdesc_register_name (gdbarch, reg_nr); + if (reg_nr < 0) return NULL; @@ -2569,6 +2586,7 @@ csky_print_registers_info (struct gdbarch *gdbarch, struct ui_file *file, } /* Check whether xml has discribled the essential regs. */ + static int csky_essential_reg_check (const struct csky_supported_tdesc_register *reg) { @@ -2585,6 +2603,200 @@ csky_essential_reg_check (const struct csky_supported_tdesc_register *reg) return 0; } +/* Check whether xml has discribled the fr0~fr15 regs. */ + +static int +csky_fr0_fr15_reg_check (const struct csky_supported_tdesc_register *reg) { + int i = 0; + for (i = 0; i < 16; i++) + { + if ((strcmp (reg->name, csky_supported_fpu_regs[i].name) == 0) + && (csky_supported_fpu_regs[i].num == reg->num)) + return (1 << i); + } + + return 0; +}; + +/* Check whether xml has discribled the fr16~fr31 regs. */ + +static int +csky_fr16_fr31_reg_check (const struct csky_supported_tdesc_register *reg) { + int i = 0; + for (i = 0; i < 16; i++) + { + if ((strcmp (reg->name, csky_supported_fpu_regs[i + 16].name) == 0) + && (csky_supported_fpu_regs[i + 16].num == reg->num)) + return (1 << i); + } + + return 0; +}; + +/* Check whether xml has discribled the vr0~vr15 regs. */ + +static int +csky_vr0_vr15_reg_check (const struct csky_supported_tdesc_register *reg) { + int i = 0; + for (i = 0; i < 16; i++) + { + if ((strcmp (reg->name, csky_supported_fpu_regs[i + 32].name) == 0) + && (csky_supported_fpu_regs[i + 32].num == reg->num)) + return (1 << i); + } + + return 0; +}; + +/* Return pseudo reg's name. */ + +static const char * +csky_pseudo_register_name (struct gdbarch *gdbarch, int regno) +{ + int num_regs = gdbarch_num_regs (gdbarch); + csky_gdbarch_tdep *tdep + = (csky_gdbarch_tdep *) gdbarch_tdep (gdbarch); + + regno -= num_regs; + + if (tdep->fv_pseudo_registers_count) + { + static const char *const fv_pseudo_names[] = { + "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", + "s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15", + "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23", + "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31", + "s32", "s33", "s34", "s35", "s36", "s37", "s38", "s39", + "s40", "s41", "s42", "s43", "s44", "s45", "s46", "s47", + "s48", "s49", "s50", "s51", "s52", "s53", "s54", "s55", + "s56", "s57", "s58", "s59", "s60", "s61", "s62", "s63", + "s64", "s65", "s66", "s67", "s68", "s69", "s70", "s71", + "s72", "s73", "s74", "s75", "s76", "s77", "s78", "s79", + "s80", "s81", "s82", "s83", "s84", "s85", "s86", "s87", + "s88", "s89", "s90", "s91", "s92", "s93", "s94", "s95", + "s96", "s97", "s98", "s99", "s100", "s101", "s102", "s103", + "s104", "s105", "s106", "s107", "s108", "s109", "s110", "s111", + "s112", "s113", "s114", "s115", "s116", "s117", "s118", "s119", + "s120", "s121", "s122", "s123", "s124", "s125", "s126", "s127", + }; + + if (regno < tdep->fv_pseudo_registers_count) + { + if ((regno < 64) && ((regno % 4) >= 2) && !tdep->has_vr0) + return NULL; + else if ((regno >= 64) && ((regno % 4) >= 2)) + return NULL; + else + return fv_pseudo_names[regno]; + } + } + + return NULL; +} + +/* Read for csky pseudo regs. */ + +static enum register_status +csky_pseudo_register_read (struct gdbarch *gdbarch, + struct readable_regcache *regcache, + int regnum, gdb_byte *buf) +{ + int num_regs = gdbarch_num_regs (gdbarch); + csky_gdbarch_tdep *tdep + = (csky_gdbarch_tdep *) gdbarch_tdep (gdbarch); + + regnum -= num_regs; + + if (regnum < tdep->fv_pseudo_registers_count) + { + enum register_status status; + int gdb_regnum = 0; + int offset = 0; + gdb_byte reg_buf[16]; + + /* Ensure getting s0~s63 from vrx if tdep->has_vr0 is ture. */ + if (tdep->has_vr0) + { + if (regnum < 64) + { + gdb_regnum = CSKY_VR0_REGNUM + (regnum / 4); + offset = (regnum % 4) * 4; + } + else + { + gdb_regnum = CSKY_FR16_REGNUM + ((regnum - 64) / 4); + if ((regnum % 4) >= 2) + return REG_UNAVAILABLE; + offset = (regnum % 2) * 4; + } + } + else + { + gdb_regnum = CSKY_FR0_REGNUM + (regnum / 4); + if ((regnum % 4) >= 2) + return REG_UNAVAILABLE; + offset = (regnum % 2) * 4; + } + + status = regcache->raw_read (gdb_regnum, reg_buf); + if (status == REG_VALID) + memcpy (buf, reg_buf + offset, 4); + return status; + } + + return REG_UNKNOWN; +} + +/* Write for csky pseudo regs. */ + +static void +csky_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache, + int regnum, const gdb_byte *buf) +{ + int num_regs = gdbarch_num_regs (gdbarch); + csky_gdbarch_tdep *tdep + = (csky_gdbarch_tdep *) gdbarch_tdep (gdbarch); + + regnum -= num_regs; + + if (regnum < tdep->fv_pseudo_registers_count) + { + gdb_byte reg_buf[16]; + int gdb_regnum = 0; + int offset = 0; + + if (tdep->has_vr0) + { + if (regnum < 64) + { + gdb_regnum = CSKY_VR0_REGNUM + (regnum / 4); + offset = (regnum % 4) * 4; + } + else + { + gdb_regnum = CSKY_FR16_REGNUM + ((regnum - 64) / 4); + if ((regnum % 4) >= 2) + return; + offset = (regnum % 2) * 4; + } + } + else + { + gdb_regnum = CSKY_FR0_REGNUM + (regnum / 4); + if ((regnum % 4) >= 2) + return; + offset = (regnum % 2) * 4; + } + + regcache->raw_read (gdb_regnum, reg_buf); + memcpy (reg_buf + offset, buf, 4); + regcache->raw_write (gdb_regnum, reg_buf); + return; + } + + return; +} + /* Initialize the current architecture based on INFO. If possible, re-use an architecture from ARCHES, which is a list of architectures already created during this debugging session. @@ -2602,6 +2814,9 @@ csky_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) unsigned int fpu_hardfp = 0; /* Analyze info.target_desc */ int num_regs = 0; + int has_fr0 = 0; + int has_fr16 = 0; + int has_vr0 = 0; tdesc_arch_data_up tdesc_data; if (tdesc_has_registers (info.target_desc)) @@ -2633,6 +2848,9 @@ csky_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) tdesc_reg->name); if (numbered) { valid_p |= csky_essential_reg_check (tdesc_reg); + has_fr0 |= csky_fr0_fr15_reg_check (tdesc_reg); + has_fr16 |= csky_fr16_fr31_reg_check (tdesc_reg); + has_vr0 |= csky_vr0_vr15_reg_check (tdesc_reg); if (num_regs < tdesc_reg->num) num_regs = tdesc_reg->num; } @@ -2685,6 +2903,38 @@ csky_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) tdep->vdsp_version = vdsp_version; tdep->fpu_hardfp = fpu_hardfp; + if (tdesc_data != NULL) + { + if ((has_vr0 == CSKY_FULL16_ONEHOT_VALUE) + && (has_fr16 == CSKY_FULL16_ONEHOT_VALUE)) + { + tdep->has_vr0 = 1; + tdep->fv_pseudo_registers_count = 128; + } + else if ((has_vr0 == CSKY_FULL16_ONEHOT_VALUE) + && (has_fr16 != CSKY_FULL16_ONEHOT_VALUE)) + { + tdep->has_vr0 = 1; + tdep->fv_pseudo_registers_count = 64; + } + else if ((has_fr0 == CSKY_FULL16_ONEHOT_VALUE) + && (has_vr0 != CSKY_FULL16_ONEHOT_VALUE)) + { + tdep->has_vr0 = 0; + tdep->fv_pseudo_registers_count = 64; + } + else + { + tdep->has_vr0 = 0; + tdep->fv_pseudo_registers_count = 0; + } + } + else + { + tdep->has_vr0 = 1; + tdep->fv_pseudo_registers_count = 64; + } + /* Target data types. */ set_gdbarch_ptr_bit (gdbarch, 32); set_gdbarch_addr_bit (gdbarch, 32); @@ -2753,6 +3003,17 @@ csky_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_register_type (gdbarch, csky_register_type); } + if (tdep->fv_pseudo_registers_count) + { + set_gdbarch_num_pseudo_regs (gdbarch, + tdep->fv_pseudo_registers_count); + set_gdbarch_pseudo_register_read (gdbarch, + csky_pseudo_register_read); + set_gdbarch_pseudo_register_write (gdbarch, + csky_pseudo_register_write); + set_tdesc_pseudo_register_name (gdbarch, csky_pseudo_register_name); + } + return gdbarch; } diff --git a/gdb/csky-tdep.h b/gdb/csky-tdep.h index adfe9faaa0c..4ff8a6b8613 100644 --- a/gdb/csky-tdep.h +++ b/gdb/csky-tdep.h @@ -37,6 +37,10 @@ struct csky_gdbarch_tdep : gdbarch_tdep unsigned int fpu_abi; unsigned int fpu_hardfp; unsigned int vdsp_version; + + /* Save fv_pseudo_registers_count. */ + unsigned int has_vr0; + unsigned int fv_pseudo_registers_count; }; /* Instruction sizes. */ @@ -101,6 +105,9 @@ enum csky_regnum #define CSKY_TDESC_REGS_LR_NUMBERED (1 << 2) #define CSKY_TDESC_REGS_ESSENTIAL_VALUE (7) +/* For fr0~fr15, fr16~fr31, vr0~vr15 check. */ +#define CSKY_FULL16_ONEHOT_VALUE 0xffff + /* Number of processor registers w/o ICE registers. */ #define CSKY_NUM_REGS (CSKY_MAX_REGS - CSKY_CRBANK_NUM_REGS) |