X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fscore-tdep.c;h=5ca763c40f42735bbe402c57c76f7744e09ce2ec;hb=98f9338a584c5f68595fc97e692e83f700c8da3d;hp=4ef620024668ffa8add0a18df43a7bfdc409d533;hpb=be8626e05a1d01d9467d67dead4d3b176d0a9cb6;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/score-tdep.c b/gdb/score-tdep.c index 4ef6200246..5ca763c40f 100644 --- a/gdb/score-tdep.c +++ b/gdb/score-tdep.c @@ -1,7 +1,7 @@ /* Target-dependent code for the S+core architecture, for GDB, the GNU Debugger. - Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc. + Copyright (C) 2006-2019 Free Software Foundation, Inc. Contributed by Qinwei (qinwei@sunnorth.com.cn) Contributed by Ching-Peng Lin (cplin@sunplus.com) @@ -22,7 +22,6 @@ along with this program. If not, see . */ #include "defs.h" -#include "gdb_assert.h" #include "inferior.h" #include "symtab.h" #include "objfiles.h" @@ -30,6 +29,7 @@ #include "target.h" #include "arch-utils.h" #include "regcache.h" +#include "regset.h" #include "dis-asm.h" #include "frame-unwind.h" #include "frame-base.h" @@ -37,13 +37,13 @@ #include "dwarf2-frame.h" #include "score-tdep.h" -#define G_FLD(_i,_ms,_ls) (((_i) << (31 - (_ms))) >> (31 - (_ms) + (_ls))) -#define RM_PBITS(_raw) ((G_FLD(_raw, 31, 16) << 15) | G_FLD(_raw, 14, 0)) +#define G_FLD(_i,_ms,_ls) \ + ((unsigned)((_i) << (31 - (_ms))) >> (31 - (_ms) + (_ls))) typedef struct{ - unsigned int v; - unsigned int raw; - char is15; + unsigned long long v; + unsigned long long raw; + unsigned int len; }inst_t; struct score_frame_cache @@ -53,326 +53,348 @@ struct score_frame_cache struct trad_frame_saved_reg *saved_regs; }; -#if 0 -/* If S+core GCC will generate these instructions in the prologue: +static int target_mach = bfd_mach_score7; - lw rx, imm1 - addi rx, -imm2 - mv! r2, rx - - then .pdr section is used. */ - -#define P_SIZE 8 -#define PI_SYM 0 -#define PI_R_MSK 1 -#define PI_R_OFF 2 -#define PI_R_LEF 4 -#define PI_F_OFF 5 -#define PI_F_REG 6 -#define PI_RAREG 7 - -typedef struct frame_extra_info +static struct type * +score_register_type (struct gdbarch *gdbarch, int regnum) { - CORE_ADDR p_frame; - unsigned int pdr[P_SIZE]; -} extra_info_t; + gdb_assert (regnum >= 0 + && regnum < ((target_mach == bfd_mach_score7) + ? SCORE7_NUM_REGS : SCORE3_NUM_REGS)); + return builtin_type (gdbarch)->builtin_uint32; +} -struct obj_priv +static const char * +score7_register_name (struct gdbarch *gdbarch, int regnum) { - bfd_size_type size; - char *contents; -}; + const char *score_register_names[] = { + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", + "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", + "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", -static bfd *the_bfd; + "PSR", "COND", "ECR", "EXCPVEC", "CCR", + "EPC", "EMA", "TLBLOCK", "TLBPT", "PEADDR", + "TLBRPT", "PEVN", "PECTX", "LIMPFN", "LDMPFN", + "PREV", "DREG", "PC", "DSAVE", "COUNTER", + "LDCR", "STCR", "CEH", "CEL", + }; -static int -score_compare_pdr_entries (const void *a, const void *b) -{ - CORE_ADDR lhs = bfd_get_32 (the_bfd, (bfd_byte *) a); - CORE_ADDR rhs = bfd_get_32 (the_bfd, (bfd_byte *) b); - if (lhs < rhs) - return -1; - else if (lhs == rhs) - return 0; - else - return 1; + gdb_assert (regnum >= 0 && regnum < SCORE7_NUM_REGS); + return score_register_names[regnum]; } -static void -score_analyze_pdr_section (CORE_ADDR startaddr, CORE_ADDR pc, - struct frame_info *next_frame, - struct score_frame_cache *this_cache) +static const char * +score3_register_name (struct gdbarch *gdbarch, int regnum) { - struct symbol *sym; - struct obj_section *sec; - extra_info_t *fci_ext; - CORE_ADDR leaf_ra_stack_addr = -1; + const char *score_register_names[] = { + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", + "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", + "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", - gdb_assert (startaddr <= pc); - gdb_assert (this_cache != NULL); + "PSR", "COND", "ECR", "EXCPVEC", "CCR", + "EPC", "EMA", "PREV", "DREG", "DSAVE", + "COUNTER", "LDCR", "STCR", "CEH", "CEL", + "", "", "PC", + }; - fci_ext = frame_obstack_zalloc (sizeof (extra_info_t)); - if ((sec = find_pc_section (pc)) == NULL) - { - error ("Error: Can't find section in file:%s, line:%d!", - __FILE__, __LINE__); - return; - } + gdb_assert (regnum >= 0 && regnum < SCORE3_NUM_REGS); + return score_register_names[regnum]; +} - /* Anylyze .pdr section and get coresponding fields. */ - { - static struct obj_priv *priv = NULL; - - if (priv == NULL) - { - asection *bfdsec; - priv = obstack_alloc (&sec->objfile->objfile_obstack, - sizeof (struct obj_priv)); - if ((bfdsec = bfd_get_section_by_name (sec->objfile->obfd, ".pdr"))) - { - priv->size = bfd_section_size (sec->objfile->obfd, bfdsec); - priv->contents = obstack_alloc (&sec->objfile->objfile_obstack, - priv->size); - bfd_get_section_contents (sec->objfile->obfd, bfdsec, - priv->contents, 0, priv->size); - the_bfd = sec->objfile->obfd; - qsort (priv->contents, priv->size / 32, 32, - score_compare_pdr_entries); - the_bfd = NULL; - } - else - priv->size = 0; - } - if (priv->size != 0) - { - int low = 0, mid, high = priv->size / 32; - char *ptr; - do - { - CORE_ADDR pdr_pc; - mid = (low + high) / 2; - ptr = priv->contents + mid * 32; - pdr_pc = bfd_get_signed_32 (sec->objfile->obfd, ptr); - pdr_pc += ANOFFSET (sec->objfile->section_offsets, - SECT_OFF_TEXT (sec->objfile)); - if (pdr_pc == startaddr) - break; - if (pdr_pc > startaddr) - high = mid; - else - low = mid + 1; - } - while (low != high); - - if (low != high) - { - gdb_assert (bfd_get_32 (sec->objfile->obfd, ptr) == startaddr); -#define EXT_PDR(_pi) bfd_get_32(sec->objfile->obfd, ptr+((_pi)<<2)) - fci_ext->pdr[PI_SYM] = EXT_PDR (PI_SYM); - fci_ext->pdr[PI_R_MSK] = EXT_PDR (PI_R_MSK); - fci_ext->pdr[PI_R_OFF] = EXT_PDR (PI_R_OFF); - fci_ext->pdr[PI_R_LEF] = EXT_PDR (PI_R_LEF); - fci_ext->pdr[PI_F_OFF] = EXT_PDR (PI_F_OFF); - fci_ext->pdr[PI_F_REG] = EXT_PDR (PI_F_REG); - fci_ext->pdr[PI_RAREG] = EXT_PDR (PI_RAREG); -#undef EXT_PDR - } - } - } +#if WITH_SIM +static int +score_register_sim_regno (struct gdbarch *gdbarch, int regnum) +{ + gdb_assert (regnum >= 0 + && regnum < ((target_mach == bfd_mach_score7) + ? SCORE7_NUM_REGS : SCORE3_NUM_REGS)); + return regnum; } #endif -#if 0 -/* Open these functions if build with simulator. */ - -int -score_target_can_use_watch (int type, int cnt, int othertype) +static inst_t * +score7_fetch_inst (struct gdbarch *gdbarch, CORE_ADDR addr, gdb_byte *memblock) { - if (strcmp (current_target.to_shortname, "sim") == 0) - { - return soc_gh_can_use_watch (type, cnt); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + static inst_t inst = { 0, 0, 0 }; + gdb_byte buf[SCORE_INSTLEN] = { 0 }; + int big; + int ret; + + if (target_has_execution && memblock != NULL) + { + /* Fetch instruction from local MEMBLOCK. */ + memcpy (buf, memblock, SCORE_INSTLEN); } else { - return (*current_target.to_can_use_hw_breakpoint) (type, cnt, othertype); + /* Fetch instruction from target. */ + ret = target_read_memory (addr & ~0x3, buf, SCORE_INSTLEN); + if (ret) + { + error (_("Error: target_read_memory in file:%s, line:%d!"), + __FILE__, __LINE__); + return 0; + } } -} -int -score_stopped_by_watch (void) -{ - if (strcmp (current_target.to_shortname, "sim") == 0) - { - return soc_gh_stopped_by_watch (); - } - else + inst.raw = extract_unsigned_integer (buf, SCORE_INSTLEN, byte_order); + inst.len = (inst.raw & 0x80008000) ? 4 : 2; + inst.v = ((inst.raw >> 16 & 0x7FFF) << 15) | (inst.raw & 0x7FFF); + big = (byte_order == BFD_ENDIAN_BIG); + if (inst.len == 2) { - return (*current_target.to_stopped_by_watchpoint) (); + if (big ^ ((addr & 0x2) == 2)) + inst.v = G_FLD (inst.v, 29, 15); + else + inst.v = G_FLD (inst.v, 14, 0); } + return &inst; } -int -score_target_insert_watchpoint (CORE_ADDR addr, int len, int type) +static inst_t * +score3_adjust_pc_and_fetch_inst (CORE_ADDR *pcptr, int *lenptr, + enum bfd_endian byte_order) { - if (strcmp (current_target.to_shortname, "sim") == 0) - { - return soc_gh_add_watch (addr, len, type); - } - else + static inst_t inst = { 0, 0, 0 }; + + struct breakplace + { + int break_offset; + int inst_len; + }; + /* raw table 1 (column 2, 3, 4) + * 0 1 0 * # 2 + * 0 1 1 0 # 3 + 0 1 1 0 * # 6 + table 2 (column 1, 2, 3) + * 0 0 * * # 0, 4 + 0 1 0 * * # 2 + 1 1 0 * * # 6 + */ + + static const struct breakplace bk_table[16] = { - return (*current_target.to_insert_watchpoint) (addr, len, type); + /* table 1 */ + {0, 0}, + {0, 0}, + {0, 4}, + {0, 6}, + {0, 0}, + {0, 0}, + {-2, 6}, + {0, 0}, + /* table 2 */ + {0, 2}, + {0, 0}, + {-2, 4}, + {0, 0}, + {0, 2}, + {0, 0}, + {-4, 6}, + {0, 0} + }; + +#define EXTRACT_LEN 2 + CORE_ADDR adjust_pc = *pcptr & ~0x1; + gdb_byte buf[5][EXTRACT_LEN] = + { + {'\0', '\0'}, + {'\0', '\0'}, + {'\0', '\0'}, + {'\0', '\0'}, + {'\0', '\0'} + }; + int ret; + unsigned int raw; + unsigned int cbits = 0; + int bk_index; + int i, count; + + inst.v = 0; + inst.raw = 0; + inst.len = 0; + + adjust_pc -= 4; + for (i = 0; i < 5; i++) + { + ret = target_read_memory (adjust_pc + 2 * i, buf[i], EXTRACT_LEN); + if (ret != 0) + { + buf[i][0] = '\0'; + buf[i][1] = '\0'; + if (i == 2) + error (_("Error: target_read_memory in file:%s, line:%d!"), + __FILE__, __LINE__); + } + + raw = extract_unsigned_integer (buf[i], EXTRACT_LEN, byte_order); + cbits = (cbits << 1) | (raw >> 15); } -} + adjust_pc += 4; -int -score_target_remove_watchpoint (CORE_ADDR addr, int len, int type) -{ - if (strcmp (current_target.to_shortname, "sim") == 0) - { - return soc_gh_del_watch (addr, len, type); + if (cbits & 0x4) + { + /* table 1 */ + cbits = (cbits >> 1) & 0x7; + bk_index = cbits; } else { - return (*current_target.to_remove_watchpoint) (addr, len, type); + /* table 2 */ + cbits = (cbits >> 2) & 0x7; + bk_index = cbits + 8; } -} -int -score_target_insert_hw_breakpoint (struct bp_target_info * bp_tgt) -{ - if (strcmp (current_target.to_shortname, "sim") == 0) - { - return soc_gh_add_hardbp (bp_tgt->placed_address); + gdb_assert (!((bk_table[bk_index].break_offset == 0) + && (bk_table[bk_index].inst_len == 0))); + + inst.len = bk_table[bk_index].inst_len; + + i = (bk_table[bk_index].break_offset + 4) / 2; + count = inst.len / 2; + for (; count > 0; i++, count--) + { + inst.raw = (inst.raw << 16) + | extract_unsigned_integer (buf[i], EXTRACT_LEN, byte_order); } - else + + switch (inst.len) { - return (*current_target.to_insert_hw_breakpoint) (bp_tgt); + case 2: + inst.v = inst.raw & 0x7FFF; + break; + case 4: + inst.v = ((inst.raw >> 16 & 0x7FFF) << 15) | (inst.raw & 0x7FFF); + break; + case 6: + inst.v = ((inst.raw >> 32 & 0x7FFF) << 30) + | ((inst.raw >> 16 & 0x7FFF) << 15) | (inst.raw & 0x7FFF); + break; } + + if (pcptr) + *pcptr = adjust_pc + bk_table[bk_index].break_offset; + if (lenptr) + *lenptr = bk_table[bk_index].inst_len; + +#undef EXTRACT_LEN + + return &inst; } -int -score_target_remove_hw_breakpoint (struct bp_target_info * bp_tgt) +/* Implement the breakpoint_kind_from_pc gdbarch method. */ + +static int +score7_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr) { - if (strcmp (current_target.to_shortname, "sim") == 0) - { - return soc_gh_del_hardbp (bp_tgt->placed_address); + int ret; + unsigned int raw; + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + gdb_byte buf[SCORE_INSTLEN] = { 0 }; + + if ((ret = target_read_memory (*pcptr & ~0x3, buf, SCORE_INSTLEN)) != 0) + { + error (_("Error: target_read_memory in file:%s, line:%d!"), + __FILE__, __LINE__); + } + raw = extract_unsigned_integer (buf, SCORE_INSTLEN, byte_order); + + if (!(raw & 0x80008000)) + { + /* 16bits instruction. */ + *pcptr &= ~0x1; + return 2; } else { - return (*current_target.to_remove_hw_breakpoint) (bp_tgt); + /* 32bits instruction. */ + *pcptr &= ~0x3; + return 4; } } -#endif -static struct type * -score_register_type (struct gdbarch *gdbarch, int regnum) -{ - gdb_assert (regnum >= 0 && regnum < SCORE_NUM_REGS); - return builtin_type_uint32; -} +/* Implement the sw_breakpoint_from_kind gdbarch method. */ -static CORE_ADDR -score_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame) +static const gdb_byte * +score7_sw_breakpoint_from_kind (struct gdbarch *gdbarch, int kind, int *size) { - return frame_unwind_register_unsigned (next_frame, SCORE_PC_REGNUM); -} + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); -static CORE_ADDR -score_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame) -{ - return frame_unwind_register_unsigned (next_frame, SCORE_SP_REGNUM); -} + *size = kind; -static const char * -score_register_name (struct gdbarch *gdbarch, int regnum) -{ - const char *score_register_names[] = { - "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", - "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", - "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", - "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", + if (kind == 4) + { + static gdb_byte big_breakpoint32[] = { 0x80, 0x00, 0x80, 0x06 }; + static gdb_byte little_breakpoint32[] = { 0x06, 0x80, 0x00, 0x80 }; - "PSR", "COND", "ECR", "EXCPVEC", - "CCR", "EPC", "EMA", "TLBLOCK", - "TLBPT", "PEADDR", "TLBRPT", "PEVN", - "PECTX", "LIMPFN", "LDMPFN", "PREV", - "DREG", "PC", "DSAVE", "COUNTER", - "LDCR", "STCR", "CEH", "CEL", - }; + if (byte_order == BFD_ENDIAN_BIG) + return big_breakpoint32; + else + return little_breakpoint32; + } + else + { + static gdb_byte big_breakpoint16[] = { 0x60, 0x02 }; + static gdb_byte little_breakpoint16[] = { 0x02, 0x60 }; - gdb_assert (regnum >= 0 && regnum < SCORE_NUM_REGS); - return score_register_names[regnum]; + if (byte_order == BFD_ENDIAN_BIG) + return big_breakpoint16; + else + return little_breakpoint16; + } } -static int -score_register_sim_regno (struct gdbarch *gdbarch, int regnum) -{ - gdb_assert (regnum >= 0 && regnum < SCORE_NUM_REGS); - return regnum; -} +/* Implement the breakpoint_kind_from_pc gdbarch method. */ static int -score_print_insn (bfd_vma memaddr, struct disassemble_info *info) +score3_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr) { - if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG) - return print_insn_big_score (memaddr, info); - else - return print_insn_little_score (memaddr, info); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + int len; + + score3_adjust_pc_and_fetch_inst (pcptr, &len, byte_order); + + return len; } +/* Implement the sw_breakpoint_from_kind gdbarch method. */ + static const gdb_byte * -score_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr, - int *lenptr) +score3_sw_breakpoint_from_kind (struct gdbarch *gdbarch, int kind, int *size) { - gdb_byte buf[SCORE_INSTLEN] = { 0 }; - int ret; - unsigned int raw; + int index = 0; + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + static gdb_byte score_break_insns[6][6] = { + /* The following three instructions are big endian. */ + { 0x00, 0x20 }, + { 0x80, 0x00, 0x00, 0x06 }, + { 0x80, 0x00, 0x80, 0x00, 0x00, 0x00 }, + /* The following three instructions are little endian. */ + { 0x20, 0x00 }, + { 0x00, 0x80, 0x06, 0x00 }, + { 0x00, 0x80, 0x00, 0x80, 0x00, 0x00 }}; + + *size = kind; + + index = ((byte_order == BFD_ENDIAN_BIG) ? 0 : 3) + (kind / 2 - 1); + return score_break_insns[index]; +} - if ((ret = target_read_memory (*pcptr & ~0x3, buf, SCORE_INSTLEN)) != 0) - { - error ("Error: target_read_memory in file:%s, line:%d!", - __FILE__, __LINE__); - } - raw = extract_unsigned_integer (buf, SCORE_INSTLEN); +static CORE_ADDR +score_adjust_breakpoint_address (struct gdbarch *gdbarch, CORE_ADDR bpaddr) +{ + CORE_ADDR adjust_pc = bpaddr; - if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) - { - if (!(raw & 0x80008000)) - { - /* 16bits instruction. */ - static gdb_byte big_breakpoint16[] = { 0x60, 0x02 }; - *pcptr &= ~0x1; - *lenptr = sizeof (big_breakpoint16); - return big_breakpoint16; - } - else - { - /* 32bits instruction. */ - static gdb_byte big_breakpoint32[] = { 0x80, 0x00, 0x80, 0x06 }; - *pcptr &= ~0x3; - *lenptr = sizeof (big_breakpoint32); - return big_breakpoint32; - } - } + if (target_mach == bfd_mach_score3) + score3_adjust_pc_and_fetch_inst (&adjust_pc, NULL, + gdbarch_byte_order (gdbarch)); else - { - if (!(raw & 0x80008000)) - { - /* 16bits instruction. */ - static gdb_byte little_breakpoint16[] = { 0x02, 0x60 }; - *pcptr &= ~0x1; - *lenptr = sizeof (little_breakpoint16); - return little_breakpoint16; - } - else - { - /* 32bits instruction. */ - static gdb_byte little_breakpoint32[] = { 0x06, 0x80, 0x00, 0x80 }; - *pcptr &= ~0x3; - *lenptr = sizeof (little_breakpoint32); - return little_breakpoint32; - } - } + adjust_pc = align_down (adjust_pc, 2); + + return adjust_pc; } static CORE_ADDR @@ -387,7 +409,9 @@ score_xfer_register (struct regcache *regcache, int regnum, int length, const gdb_byte *writebuf, int buf_offset) { int reg_offset = 0; - gdb_assert (regnum >= 0 && regnum < SCORE_NUM_REGS); + gdb_assert (regnum >= 0 + && regnum < ((target_mach == bfd_mach_score7) + ? SCORE7_NUM_REGS : SCORE3_NUM_REGS)); switch (endian) { @@ -401,21 +425,21 @@ score_xfer_register (struct regcache *regcache, int regnum, int length, reg_offset = 0; break; default: - error ("Error: score_xfer_register in file:%s, line:%d!", + error (_("Error: score_xfer_register in file:%s, line:%d!"), __FILE__, __LINE__); } if (readbuf != NULL) - regcache_cooked_read_part (regcache, regnum, reg_offset, length, - readbuf + buf_offset); + regcache->cooked_read_part (regnum, reg_offset, length, + readbuf + buf_offset); if (writebuf != NULL) - regcache_cooked_write_part (regcache, regnum, reg_offset, length, - writebuf + buf_offset); + regcache->cooked_write_part (regnum, reg_offset, length, + writebuf + buf_offset); } static enum return_value_convention -score_return_value (struct gdbarch *gdbarch, struct type *type, - struct regcache *regcache, +score_return_value (struct gdbarch *gdbarch, struct value *function, + struct type *type, struct regcache *regcache, gdb_byte * readbuf, const gdb_byte * writebuf) { if (TYPE_CODE (type) == TYPE_CODE_STRUCT @@ -431,25 +455,17 @@ score_return_value (struct gdbarch *gdbarch, struct type *type, offset += SCORE_REGSIZE, regnum++) { int xfer = SCORE_REGSIZE; + if (offset + xfer > TYPE_LENGTH (type)) xfer = TYPE_LENGTH (type) - offset; score_xfer_register (regcache, regnum, xfer, - gdbarch_byte_order (gdbarch), + gdbarch_byte_order(gdbarch), readbuf, writebuf, offset); } return RETURN_VALUE_REGISTER_CONVENTION; } } -static struct frame_id -score_unwind_dummy_id (struct gdbarch *gdbarch, - struct frame_info *next_frame) -{ - return frame_id_build ( - frame_unwind_register_unsigned (next_frame, SCORE_SP_REGNUM), - frame_pc_unwind (next_frame)); -} - static int score_type_needs_double_align (struct type *type) { @@ -475,8 +491,10 @@ static CORE_ADDR score_push_dummy_call (struct gdbarch *gdbarch, struct value *function, struct regcache *regcache, CORE_ADDR bp_addr, int nargs, struct value **args, CORE_ADDR sp, - int struct_return, CORE_ADDR struct_addr) + function_call_return_method return_method, + CORE_ADDR struct_addr) { + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); int argnum; int argreg; int arglen = 0; @@ -498,7 +516,7 @@ score_push_dummy_call (struct gdbarch *gdbarch, struct value *function, /* Step 3, Check if struct return then save the struct address to r4 and increase the stack_offset by 4. */ - if (struct_return) + if (return_method == return_method_struct) { regcache_cooked_write_unsigned (regcache, argreg++, struct_addr); stack_offset += SCORE_REGSIZE; @@ -514,12 +532,9 @@ score_push_dummy_call (struct gdbarch *gdbarch, struct value *function, enum type_code typecode = TYPE_CODE (arg_type); const gdb_byte *val = value_contents (arg); int downward_offset = 0; - int odd_sized_struct_p; int arg_last_part_p = 0; arglen = TYPE_LENGTH (arg_type); - odd_sized_struct_p = (arglen > SCORE_REGSIZE - && arglen % SCORE_REGSIZE != 0); /* If a arg should be aligned to 8 bytes (long long or double), the value should be put to even register numbers. */ @@ -544,7 +559,7 @@ score_push_dummy_call (struct gdbarch *gdbarch, struct value *function, Where X is a hole. */ - if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG + if (gdbarch_byte_order(gdbarch) == BFD_ENDIAN_BIG && (typecode == TYPE_CODE_STRUCT || typecode == TYPE_CODE_UNION) && argreg > SCORE_LAST_ARG_REGNUM @@ -554,11 +569,12 @@ score_push_dummy_call (struct gdbarch *gdbarch, struct value *function, while (arglen > 0) { int partial_len = arglen < SCORE_REGSIZE ? arglen : SCORE_REGSIZE; - ULONGEST regval = extract_unsigned_integer (val, partial_len); + ULONGEST regval = extract_unsigned_integer (val, partial_len, + byte_order); /* The last part of a arg should shift left when gdbarch_byte_order is BFD_ENDIAN_BIG. */ - if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG + if (byte_order == BFD_ENDIAN_BIG && arg_last_part_p == 1 && (typecode == TYPE_CODE_STRUCT || typecode == TYPE_CODE_UNION)) @@ -587,151 +603,126 @@ score_push_dummy_call (struct gdbarch *gdbarch, struct value *function, return sp; } -static char * -score_malloc_and_get_memblock (CORE_ADDR addr, CORE_ADDR size) -{ - int ret; - char *memblock = NULL; - - if (size < 0) - { - error ("Error: malloc size < 0 in file:%s, line:%d!", - __FILE__, __LINE__); - return NULL; - } - else if (size == 0) - return NULL; - - memblock = (char *) xmalloc (size); - memset (memblock, 0, size); - ret = target_read_memory (addr & ~0x3, memblock, size); - if (ret) - { - error ("Error: target_read_memory in file:%s, line:%d!", - __FILE__, __LINE__); - return NULL; - } - return memblock; -} - -static void -score_free_memblock (char *memblock) -{ - xfree (memblock); -} - -static void -score_adjust_memblock_ptr (char **memblock, CORE_ADDR prev_pc, - CORE_ADDR cur_pc) -{ - if (prev_pc == -1) - { - /* First time call this function, do nothing. */ - } - else if (cur_pc - prev_pc == 2 && (cur_pc & 0x3) == 0) - { - /* First 16-bit instruction, then 32-bit instruction. */ - *memblock += SCORE_INSTLEN; - } - else if (cur_pc - prev_pc == 4) - { - /* Is 32-bit instruction, increase MEMBLOCK by 4. */ - *memblock += SCORE_INSTLEN; - } -} - -static inst_t * -score_fetch_inst (struct gdbarch *gdbarch, CORE_ADDR addr, char *memblock) -{ - static inst_t inst = { 0, 0 }; - char buf[SCORE_INSTLEN] = { 0 }; - int big; - int ret; - - if (target_has_execution && memblock != NULL) - { - /* Fetch instruction from local MEMBLOCK. */ - memcpy (buf, memblock, SCORE_INSTLEN); - } - else - { - /* Fetch instruction from target. */ - ret = target_read_memory (addr & ~0x3, buf, SCORE_INSTLEN); - if (ret) - { - error ("Error: target_read_memory in file:%s, line:%d!", - __FILE__, __LINE__); - return 0; - } - } - - inst.raw = extract_unsigned_integer (buf, SCORE_INSTLEN); - inst.is15 = !(inst.raw & 0x80008000); - inst.v = RM_PBITS (inst.raw); - big = (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG); - if (inst.is15) - { - if (big ^ ((addr & 0x2) == 2)) - inst.v = G_FLD (inst.v, 29, 15); - else - inst.v = G_FLD (inst.v, 14, 0); - } - return &inst; -} - static CORE_ADDR -score_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc) +score7_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc) { CORE_ADDR cpc = pc; int iscan = 32, stack_sub = 0; while (iscan-- > 0) { - inst_t *inst = score_fetch_inst (gdbarch, cpc, NULL); + inst_t *inst = score7_fetch_inst (gdbarch, cpc, NULL); if (!inst) break; - if (!inst->is15 && !stack_sub + if ((inst->len == 4) && !stack_sub && (G_FLD (inst->v, 29, 25) == 0x1 && G_FLD (inst->v, 24, 20) == 0x0)) { /* addi r0, offset */ - pc = stack_sub = cpc + SCORE_INSTLEN; + stack_sub = cpc + SCORE_INSTLEN; + pc = cpc + SCORE_INSTLEN; } - else if (!inst->is15 - && inst->v == RM_PBITS (0x8040bc56)) + else if ((inst->len == 4) + && (G_FLD (inst->v, 29, 25) == 0x0) + && (G_FLD (inst->v, 24, 20) == 0x2) + && (G_FLD (inst->v, 19, 15) == 0x0) + && (G_FLD (inst->v, 14, 10) == 0xF) + && (G_FLD (inst->v, 9, 0) == 0x56)) { /* mv r2, r0 */ pc = cpc + SCORE_INSTLEN; break; } - else if (inst->is15 - && inst->v == RM_PBITS (0x0203)) + else if ((inst->len == 2) + && (G_FLD (inst->v, 14, 12) == 0x0) + && (G_FLD (inst->v, 11, 8) == 0x2) + && (G_FLD (inst->v, 7, 4) == 0x0) + && (G_FLD (inst->v, 3, 0) == 0x3)) { /* mv! r2, r0 */ pc = cpc + SCORE16_INSTLEN; break; } - else if (inst->is15 + else if ((inst->len == 2) && ((G_FLD (inst->v, 14, 12) == 3) /* j15 form */ || (G_FLD (inst->v, 14, 12) == 4) /* b15 form */ || (G_FLD (inst->v, 14, 12) == 0x0 && G_FLD (inst->v, 3, 0) == 0x4))) /* br! */ break; - else if (!inst->is15 + else if ((inst->len == 4) && ((G_FLD (inst->v, 29, 25) == 2) /* j32 form */ || (G_FLD (inst->v, 29, 25) == 4) /* b32 form */ || (G_FLD (inst->v, 29, 25) == 0x0 && G_FLD (inst->v, 6, 1) == 0x4))) /* br */ break; - cpc += inst->is15 ? SCORE16_INSTLEN : SCORE_INSTLEN; + cpc += (inst->len == 2) ? SCORE16_INSTLEN : SCORE_INSTLEN; + } + return pc; +} + +static CORE_ADDR +score3_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc) +{ + CORE_ADDR cpc = pc; + int iscan = 32, stack_sub = 0; + while (iscan-- > 0) + { + inst_t *inst + = score3_adjust_pc_and_fetch_inst (&cpc, NULL, + gdbarch_byte_order (gdbarch)); + + if (!inst) + break; + if (inst->len == 4 && !stack_sub + && (G_FLD (inst->v, 29, 25) == 0x1) + && (G_FLD (inst->v, 19, 17) == 0x0) + && (G_FLD (inst->v, 24, 20) == 0x0)) + { + /* addi r0, offset */ + stack_sub = cpc + inst->len; + pc = cpc + inst->len; + } + else if (inst->len == 4 + && (G_FLD (inst->v, 29, 25) == 0x0) + && (G_FLD (inst->v, 24, 20) == 0x2) + && (G_FLD (inst->v, 19, 15) == 0x0) + && (G_FLD (inst->v, 14, 10) == 0xF) + && (G_FLD (inst->v, 9, 0) == 0x56)) + { + /* mv r2, r0 */ + pc = cpc + inst->len; + break; + } + else if ((inst->len == 2) + && (G_FLD (inst->v, 14, 10) == 0x10) + && (G_FLD (inst->v, 9, 5) == 0x2) + && (G_FLD (inst->v, 4, 0) == 0x0)) + { + /* mv! r2, r0 */ + pc = cpc + inst->len; + break; + } + else if (inst->len == 2 + && ((G_FLD (inst->v, 14, 12) == 3) /* b15 form */ + || (G_FLD (inst->v, 14, 12) == 0x0 + && G_FLD (inst->v, 11, 5) == 0x4))) /* br! */ + break; + else if (inst->len == 4 + && ((G_FLD (inst->v, 29, 25) == 2) /* j32 form */ + || (G_FLD (inst->v, 29, 25) == 4))) /* b32 form */ + break; + + cpc += inst->len; } return pc; } +/* Implement the stack_frame_destroyed_p gdbarch method. */ + static int -score_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR cur_pc) +score7_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR cur_pc) { - inst_t *inst = score_fetch_inst (gdbarch, cur_pc, NULL); + inst_t *inst = score7_fetch_inst (gdbarch, cur_pc, NULL); if (inst->v == 0x23) return 1; /* mv! r0, r2 */ @@ -752,12 +743,106 @@ score_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR cur_pc) return 0; } +/* Implement the stack_frame_destroyed_p gdbarch method. */ + +static int +score3_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR cur_pc) +{ + CORE_ADDR pc = cur_pc; + inst_t *inst + = score3_adjust_pc_and_fetch_inst (&pc, NULL, + gdbarch_byte_order (gdbarch)); + + if (inst->len == 2 + && (G_FLD (inst->v, 14, 10) == 0x10) + && (G_FLD (inst->v, 9, 5) == 0x0) + && (G_FLD (inst->v, 4, 0) == 0x2)) + return 1; /* mv! r0, r2 */ + else if (inst->len == 4 + && (G_FLD (inst->v, 29, 25) == 0x0) + && (G_FLD (inst->v, 24, 20) == 0x2) + && (G_FLD (inst->v, 19, 15) == 0x0) + && (G_FLD (inst->v, 14, 10) == 0xF) + && (G_FLD (inst->v, 9, 0) == 0x56)) + return 1; /* mv r0, r2 */ + else if (inst->len == 2 + && (G_FLD (inst->v, 14, 12) == 0x0) + && (G_FLD (inst->v, 11, 5) == 0x2)) + return 1; /* pop! */ + else if (inst->len == 2 + && (G_FLD (inst->v, 14, 12) == 0x0) + && (G_FLD (inst->v, 11, 7) == 0x0) + && (G_FLD (inst->v, 6, 5) == 0x2)) + return 1; /* rpop! */ + else if (inst->len == 2 + && (G_FLD (inst->v, 14, 12) == 0x0) + && (G_FLD (inst->v, 11, 5) == 0x4) + && (G_FLD (inst->v, 4, 0) == 0x3)) + return 1; /* br! r3 */ + else if (inst->len == 4 + && (G_FLD (inst->v, 29, 25) == 0x0) + && (G_FLD (inst->v, 24, 20) == 0x0) + && (G_FLD (inst->v, 19, 15) == 0x3) + && (G_FLD (inst->v, 14, 10) == 0xF) + && (G_FLD (inst->v, 9, 0) == 0x8)) + return 1; /* br r3 */ + else + return 0; +} + +static gdb_byte * +score7_malloc_and_get_memblock (CORE_ADDR addr, CORE_ADDR size) +{ + int ret; + gdb_byte *memblock = NULL; + + if (size == 0) + return NULL; + + memblock = (gdb_byte *) xmalloc (size); + memset (memblock, 0, size); + ret = target_read_memory (addr & ~0x3, memblock, size); + if (ret) + { + error (_("Error: target_read_memory in file:%s, line:%d!"), + __FILE__, __LINE__); + return NULL; + } + return memblock; +} + static void -score_analyze_prologue (CORE_ADDR startaddr, CORE_ADDR pc, - struct frame_info *next_frame, +score7_free_memblock (gdb_byte *memblock) +{ + xfree (memblock); +} + +static void +score7_adjust_memblock_ptr (gdb_byte **memblock, CORE_ADDR prev_pc, + CORE_ADDR cur_pc) +{ + if (prev_pc == -1) + { + /* First time call this function, do nothing. */ + } + else if (cur_pc - prev_pc == 2 && (cur_pc & 0x3) == 0) + { + /* First 16-bit instruction, then 32-bit instruction. */ + *memblock += SCORE_INSTLEN; + } + else if (cur_pc - prev_pc == 4) + { + /* Is 32-bit instruction, increase MEMBLOCK by 4. */ + *memblock += SCORE_INSTLEN; + } +} + +static void +score7_analyze_prologue (CORE_ADDR startaddr, CORE_ADDR pc, + struct frame_info *this_frame, struct score_frame_cache *this_cache) { - struct gdbarch *gdbarch = get_frame_arch (next_frame); + struct gdbarch *gdbarch = get_frame_arch (this_frame); CORE_ADDR sp; CORE_ADDR fp; CORE_ADDR cur_pc = startaddr; @@ -769,35 +854,36 @@ score_analyze_prologue (CORE_ADDR startaddr, CORE_ADDR pc, int fp_offset_p = 0; int inst_len = 0; - char *memblock = NULL; - char *memblock_ptr = NULL; + gdb_byte *memblock = NULL; + gdb_byte *memblock_ptr = NULL; CORE_ADDR prev_pc = -1; /* Allocate MEMBLOCK if PC - STARTADDR > 0. */ memblock_ptr = memblock = - score_malloc_and_get_memblock (startaddr, pc - startaddr); + score7_malloc_and_get_memblock (startaddr, pc - startaddr); - sp = frame_unwind_register_unsigned (next_frame, SCORE_SP_REGNUM); - fp = frame_unwind_register_unsigned (next_frame, SCORE_FP_REGNUM); + sp = get_frame_register_unsigned (this_frame, SCORE_SP_REGNUM); + fp = get_frame_register_unsigned (this_frame, SCORE_FP_REGNUM); for (; cur_pc < pc; prev_pc = cur_pc, cur_pc += inst_len) { inst_t *inst = NULL; if (memblock != NULL) { - /* Reading memory block from target succefully and got all + /* Reading memory block from target successfully and got all the instructions(from STARTADDR to PC) needed. */ - score_adjust_memblock_ptr (&memblock, prev_pc, cur_pc); - inst = score_fetch_inst (gdbarch, cur_pc, memblock); + score7_adjust_memblock_ptr (&memblock, prev_pc, cur_pc); + inst = score7_fetch_inst (gdbarch, cur_pc, memblock); } else { /* Otherwise, we fetch 4 bytes from target, and GDB also work correctly. */ - inst = score_fetch_inst (gdbarch, cur_pc, NULL); + inst = score7_fetch_inst (gdbarch, cur_pc, NULL); } - if (inst->is15 == 1) + /* FIXME: make a full-power prologue analyzer. */ + if (inst->len == 2) { inst_len = SCORE16_INSTLEN; @@ -845,27 +931,48 @@ score_analyze_prologue (CORE_ADDR startaddr, CORE_ADDR pc, { inst_len = SCORE_INSTLEN; - if (G_FLD (inst->v, 29, 15) == 0xc60 - && G_FLD (inst->v, 2, 0) == 0x4) + if (G_FLD(inst->v, 29, 25) == 0x3 + && G_FLD(inst->v, 2, 0) == 0x4 + && G_FLD(inst->v, 19, 15) == 0) { - /* sw r3, [r0, offset]+ */ - sp_offset += SCORE_INSTLEN; - if (ra_offset_p == 0) - { - ra_offset = sp_offset; - ra_offset_p = 1; - } + /* sw rD, [r0, offset]+ */ + sp_offset += SCORE_INSTLEN; + + if (G_FLD(inst->v, 24, 20) == 0x3) + { + /* rD = r3 */ + if (ra_offset_p == 0) + { + ra_offset = sp_offset; + ra_offset_p = 1; + } + } + else if (G_FLD(inst->v, 24, 20) == 0x2) + { + /* rD = r2 */ + if (fp_offset_p == 0) + { + fp_offset = sp_offset; + fp_offset_p = 1; + } + } } - if (G_FLD (inst->v, 29, 15) == 0xc40 - && G_FLD (inst->v, 2, 0) == 0x4) + else if (G_FLD(inst->v, 29, 25) == 0x14 + && G_FLD(inst->v, 19,15) == 0) { - /* sw r2, [r0, offset]+ */ - sp_offset += SCORE_INSTLEN; - if (fp_offset_p == 0) - { - fp_offset = sp_offset; - fp_offset_p = 1; - } + /* sw rD, [r0, offset] */ + if (G_FLD(inst->v, 24, 20) == 0x3) + { + /* rD = r3 */ + ra_offset = sp_offset - G_FLD(inst->v, 14, 0); + ra_offset_p = 1; + } + else if (G_FLD(inst->v, 24, 20) == 0x2) + { + /* rD = r2 */ + fp_offset = sp_offset - G_FLD(inst->v, 14, 0); + fp_offset_p = 1; + } } else if (G_FLD (inst->v, 29, 15) == 0x1c60 && G_FLD (inst->v, 2, 0) == 0x0) @@ -896,7 +1003,7 @@ score_analyze_prologue (CORE_ADDR startaddr, CORE_ADDR pc, { unsigned int save_v = inst->v; inst_t *inst2 = - score_fetch_inst (gdbarch, cur_pc + SCORE_INSTLEN, NULL); + score7_fetch_inst (gdbarch, cur_pc + SCORE_INSTLEN, NULL); if (inst2->v == 0x23) { /* mv! r0, r2 */ @@ -934,80 +1041,321 @@ score_analyze_prologue (CORE_ADDR startaddr, CORE_ADDR pc, /* Don't forget to free MEMBLOCK if we allocated it. */ if (memblock_ptr != NULL) - score_free_memblock (memblock_ptr); + score7_free_memblock (memblock_ptr); +} + +static void +score3_analyze_prologue (CORE_ADDR startaddr, CORE_ADDR pc, + struct frame_info *this_frame, + struct score_frame_cache *this_cache) +{ + CORE_ADDR sp; + CORE_ADDR fp; + CORE_ADDR cur_pc = startaddr; + enum bfd_endian byte_order + = gdbarch_byte_order (get_frame_arch (this_frame)); + + int sp_offset = 0; + int ra_offset = 0; + int fp_offset = 0; + int ra_offset_p = 0; + int fp_offset_p = 0; + int inst_len = 0; + + sp = get_frame_register_unsigned (this_frame, SCORE_SP_REGNUM); + fp = get_frame_register_unsigned (this_frame, SCORE_FP_REGNUM); + + for (; cur_pc < pc; cur_pc += inst_len) + { + inst_t *inst = NULL; + + inst = score3_adjust_pc_and_fetch_inst (&cur_pc, &inst_len, byte_order); + + /* FIXME: make a full-power prologue analyzer. */ + if (inst->len == 2) + { + if (G_FLD (inst->v, 14, 12) == 0x0 + && G_FLD (inst->v, 11, 7) == 0x0 + && G_FLD (inst->v, 6, 5) == 0x3) + { + /* push! */ + sp_offset += 4; + + if (G_FLD (inst->v, 4, 0) == 0x3 + && ra_offset_p == 0) + { + /* push! r3, [r0] */ + ra_offset = sp_offset; + ra_offset_p = 1; + } + else if (G_FLD (inst->v, 4, 0) == 0x2 + && fp_offset_p == 0) + { + /* push! r2, [r0] */ + fp_offset = sp_offset; + fp_offset_p = 1; + } + } + else if (G_FLD (inst->v, 14, 12) == 0x6 + && G_FLD (inst->v, 11, 10) == 0x3) + { + /* rpush! */ + int start_r = G_FLD (inst->v, 9, 5); + int cnt = G_FLD (inst->v, 4, 0); + + if ((ra_offset_p == 0) + && (start_r <= SCORE_RA_REGNUM) + && (SCORE_RA_REGNUM < start_r + cnt)) + { + /* rpush! contains r3 */ + ra_offset_p = 1; + ra_offset = sp_offset + 4 * (SCORE_RA_REGNUM - start_r) + 4; + } + + if ((fp_offset_p == 0) + && (start_r <= SCORE_FP_REGNUM) + && (SCORE_FP_REGNUM < start_r + cnt)) + { + /* rpush! contains r2 */ + fp_offset_p = 1; + fp_offset = sp_offset + 4 * (SCORE_FP_REGNUM - start_r) + 4; + } + + sp_offset += 4 * cnt; + } + else if (G_FLD (inst->v, 14, 12) == 0x0 + && G_FLD (inst->v, 11, 7) == 0x0 + && G_FLD (inst->v, 6, 5) == 0x2) + { + /* pop! */ + sp_offset -= 4; + } + else if (G_FLD (inst->v, 14, 12) == 0x6 + && G_FLD (inst->v, 11, 10) == 0x2) + { + /* rpop! */ + sp_offset -= 4 * G_FLD (inst->v, 4, 0); + } + else if (G_FLD (inst->v, 14, 12) == 0x5 + && G_FLD (inst->v, 11, 10) == 0x3 + && G_FLD (inst->v, 9, 6) == 0x0) + { + /* addi! r0, -offset */ + int imm = G_FLD (inst->v, 5, 0); + if (imm >> 5) + imm = -(0x3F - imm + 1); + sp_offset -= imm; + } + else if (G_FLD (inst->v, 14, 12) == 0x5 + && G_FLD (inst->v, 11, 10) == 0x3 + && G_FLD (inst->v, 9, 6) == 0x2) + { + /* addi! r2, offset */ + if (pc - cur_pc >= 2) + { + inst_t *inst2; + + cur_pc += inst->len; + inst2 = score3_adjust_pc_and_fetch_inst (&cur_pc, NULL, + byte_order); + + if (inst2->len == 2 + && G_FLD (inst2->v, 14, 10) == 0x10 + && G_FLD (inst2->v, 9, 5) == 0x0 + && G_FLD (inst2->v, 4, 0) == 0x2) + { + /* mv! r0, r2 */ + int imm = G_FLD (inst->v, 5, 0); + if (imm >> 5) + imm = -(0x3F - imm + 1); + sp_offset -= imm; + } + } + } + } + else if (inst->len == 4) + { + if (G_FLD (inst->v, 29, 25) == 0x3 + && G_FLD (inst->v, 2, 0) == 0x4 + && G_FLD (inst->v, 24, 20) == 0x3 + && G_FLD (inst->v, 19, 15) == 0x0) + { + /* sw r3, [r0, offset]+ */ + sp_offset += inst->len; + if (ra_offset_p == 0) + { + ra_offset = sp_offset; + ra_offset_p = 1; + } + } + else if (G_FLD (inst->v, 29, 25) == 0x3 + && G_FLD (inst->v, 2, 0) == 0x4 + && G_FLD (inst->v, 24, 20) == 0x2 + && G_FLD (inst->v, 19, 15) == 0x0) + { + /* sw r2, [r0, offset]+ */ + sp_offset += inst->len; + if (fp_offset_p == 0) + { + fp_offset = sp_offset; + fp_offset_p = 1; + } + } + else if (G_FLD (inst->v, 29, 25) == 0x7 + && G_FLD (inst->v, 2, 0) == 0x0 + && G_FLD (inst->v, 24, 20) == 0x3 + && G_FLD (inst->v, 19, 15) == 0x0) + { + /* lw r3, [r0]+, 4 */ + sp_offset -= inst->len; + ra_offset_p = 1; + } + else if (G_FLD (inst->v, 29, 25) == 0x7 + && G_FLD (inst->v, 2, 0) == 0x0 + && G_FLD (inst->v, 24, 20) == 0x2 + && G_FLD (inst->v, 19, 15) == 0x0) + { + /* lw r2, [r0]+, 4 */ + sp_offset -= inst->len; + fp_offset_p = 1; + } + else if (G_FLD (inst->v, 29, 25) == 0x1 + && G_FLD (inst->v, 19, 17) == 0x0 + && G_FLD (inst->v, 24, 20) == 0x0 + && G_FLD (inst->v, 0, 0) == 0x0) + { + /* addi r0, -offset */ + int imm = G_FLD (inst->v, 16, 1); + if (imm >> 15) + imm = -(0xFFFF - imm + 1); + sp_offset -= imm; + } + else if (G_FLD (inst->v, 29, 25) == 0x1 + && G_FLD (inst->v, 19, 17) == 0x0 + && G_FLD (inst->v, 24, 20) == 0x2 + && G_FLD (inst->v, 0, 0) == 0x0) + { + /* addi r2, offset */ + if (pc - cur_pc >= 2) + { + inst_t *inst2; + + cur_pc += inst->len; + inst2 = score3_adjust_pc_and_fetch_inst (&cur_pc, NULL, + byte_order); + + if (inst2->len == 2 + && G_FLD (inst2->v, 14, 10) == 0x10 + && G_FLD (inst2->v, 9, 5) == 0x0 + && G_FLD (inst2->v, 4, 0) == 0x2) + { + /* mv! r0, r2 */ + int imm = G_FLD (inst->v, 16, 1); + if (imm >> 15) + imm = -(0xFFFF - imm + 1); + sp_offset -= imm; + } + } + } + } + } + + /* Save RA. */ + if (ra_offset_p == 1) + { + if (this_cache->saved_regs[SCORE_PC_REGNUM].addr == -1) + this_cache->saved_regs[SCORE_PC_REGNUM].addr = + sp + sp_offset - ra_offset; + } + else + { + this_cache->saved_regs[SCORE_PC_REGNUM] = + this_cache->saved_regs[SCORE_RA_REGNUM]; + } + + /* Save FP. */ + if (fp_offset_p == 1) + { + if (this_cache->saved_regs[SCORE_FP_REGNUM].addr == -1) + this_cache->saved_regs[SCORE_FP_REGNUM].addr = + sp + sp_offset - fp_offset; + } + + /* Save SP and FP. */ + this_cache->base = sp + sp_offset; + this_cache->fp = fp; } static struct score_frame_cache * -score_make_prologue_cache (struct frame_info *next_frame, void **this_cache) +score_make_prologue_cache (struct frame_info *this_frame, void **this_cache) { struct score_frame_cache *cache; if ((*this_cache) != NULL) - return (*this_cache); + return (struct score_frame_cache *) (*this_cache); cache = FRAME_OBSTACK_ZALLOC (struct score_frame_cache); (*this_cache) = cache; - cache->saved_regs = trad_frame_alloc_saved_regs (next_frame); + cache->saved_regs = trad_frame_alloc_saved_regs (this_frame); /* Analyze the prologue. */ { - const CORE_ADDR pc = frame_pc_unwind (next_frame); + const CORE_ADDR pc = get_frame_pc (this_frame); CORE_ADDR start_addr; find_pc_partial_function (pc, NULL, &start_addr, NULL); if (start_addr == 0) return cache; - score_analyze_prologue (start_addr, pc, next_frame, *this_cache); + + if (target_mach == bfd_mach_score3) + score3_analyze_prologue (start_addr, pc, this_frame, + (struct score_frame_cache *) *this_cache); + else + score7_analyze_prologue (start_addr, pc, this_frame, + (struct score_frame_cache *) *this_cache); } /* Save SP. */ trad_frame_set_value (cache->saved_regs, SCORE_SP_REGNUM, cache->base); - return (*this_cache); + return (struct score_frame_cache *) (*this_cache); } static void -score_prologue_this_id (struct frame_info *next_frame, void **this_cache, +score_prologue_this_id (struct frame_info *this_frame, void **this_cache, struct frame_id *this_id) { - struct score_frame_cache *info = score_make_prologue_cache (next_frame, + struct score_frame_cache *info = score_make_prologue_cache (this_frame, this_cache); - (*this_id) = frame_id_build (info->base, - frame_func_unwind (next_frame, NORMAL_FRAME)); + (*this_id) = frame_id_build (info->base, get_frame_func (this_frame)); } -static void -score_prologue_prev_register (struct frame_info *next_frame, - void **this_cache, - int regnum, int *optimizedp, - enum lval_type *lvalp, CORE_ADDR * addrp, - int *realnump, gdb_byte * valuep) +static struct value * +score_prologue_prev_register (struct frame_info *this_frame, + void **this_cache, int regnum) { - struct score_frame_cache *info = score_make_prologue_cache (next_frame, + struct score_frame_cache *info = score_make_prologue_cache (this_frame, this_cache); - trad_frame_get_prev_register (next_frame, info->saved_regs, regnum, - optimizedp, lvalp, addrp, realnump, valuep); + return trad_frame_get_prev_register (this_frame, info->saved_regs, regnum); } static const struct frame_unwind score_prologue_unwind = { NORMAL_FRAME, + default_frame_unwind_stop_reason, score_prologue_this_id, - score_prologue_prev_register + score_prologue_prev_register, + NULL, + default_frame_sniffer, + NULL }; -static const struct frame_unwind * -score_prologue_sniffer (struct frame_info *next_frame) -{ - return &score_prologue_unwind; -} - static CORE_ADDR -score_prologue_frame_base_address (struct frame_info *next_frame, +score_prologue_frame_base_address (struct frame_info *this_frame, void **this_cache) { struct score_frame_cache *info = - score_make_prologue_cache (next_frame, this_cache); + score_make_prologue_cache (this_frame, this_cache); return info->fp; } @@ -1020,42 +1368,128 @@ static const struct frame_base score_prologue_frame_base = }; static const struct frame_base * -score_prologue_frame_base_sniffer (struct frame_info *next_frame) +score_prologue_frame_base_sniffer (struct frame_info *this_frame) { return &score_prologue_frame_base; } +/* Core file support. */ + +static const struct regcache_map_entry score7_linux_gregmap[] = + { + /* FIXME: According to the current Linux kernel, r0 is preceded by + 9 rather than 7 words. */ + { 7, REGCACHE_MAP_SKIP, 4 }, + { 32, 0, 4 }, /* r0 ... r31 */ + { 1, 55, 4 }, /* CEL */ + { 1, 54, 4 }, /* CEH */ + { 1, 53, 4 }, /* sr0, i.e. cnt or COUNTER */ + { 1, 52, 4 }, /* sr1, i.e. lcr or LDCR */ + { 1, 51, 4 }, /* sr2, i.e. scr or STCR */ + { 1, 49, 4 }, /* PC (same slot as EPC) */ + { 1, 38, 4 }, /* EMA */ + { 1, 32, 4 }, /* PSR */ + { 1, 34, 4 }, /* ECR */ + { 1, 33, 4 }, /* COND */ + { 0 } + }; + +#define SCORE7_LINUX_EPC_OFFSET (44 * 4) +#define SCORE7_LINUX_SIZEOF_GREGSET (49 * 4) + +static void +score7_linux_supply_gregset(const struct regset *regset, + struct regcache *regcache, + int regnum, const void *buf, + size_t size) +{ + regcache_supply_regset (regset, regcache, regnum, buf, size); + + /* Supply the EPC from the same slot as the PC. Note that the + collect function will store the PC in that slot. */ + if ((regnum == -1 || regnum == SCORE_EPC_REGNUM) + && size >= SCORE7_LINUX_EPC_OFFSET + 4) + regcache->raw_supply + (SCORE_EPC_REGNUM, (const gdb_byte *) buf + SCORE7_LINUX_EPC_OFFSET); +} + +static const struct regset score7_linux_gregset = + { + score7_linux_gregmap, + score7_linux_supply_gregset, + regcache_collect_regset + }; + +/* Iterate over core file register note sections. */ + +static void +score7_linux_iterate_over_regset_sections (struct gdbarch *gdbarch, + iterate_over_regset_sections_cb *cb, + void *cb_data, + const struct regcache *regcache) +{ + cb (".reg", SCORE7_LINUX_SIZEOF_GREGSET, SCORE7_LINUX_SIZEOF_GREGSET, + &score7_linux_gregset, NULL, cb_data); +} + static struct gdbarch * score_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) { struct gdbarch *gdbarch; + target_mach = info.bfd_arch_info->mach; arches = gdbarch_list_lookup_by_info (arches, &info); if (arches != NULL) { return (arches->gdbarch); } - gdbarch = gdbarch_alloc (&info, 0); + gdbarch = gdbarch_alloc (&info, NULL); set_gdbarch_short_bit (gdbarch, 16); set_gdbarch_int_bit (gdbarch, 32); set_gdbarch_float_bit (gdbarch, 32); set_gdbarch_double_bit (gdbarch, 64); set_gdbarch_long_double_bit (gdbarch, 64); +#if WITH_SIM set_gdbarch_register_sim_regno (gdbarch, score_register_sim_regno); +#endif set_gdbarch_pc_regnum (gdbarch, SCORE_PC_REGNUM); set_gdbarch_sp_regnum (gdbarch, SCORE_SP_REGNUM); - set_gdbarch_num_regs (gdbarch, SCORE_NUM_REGS); - set_gdbarch_register_name (gdbarch, score_register_name); - set_gdbarch_breakpoint_from_pc (gdbarch, score_breakpoint_from_pc); + set_gdbarch_adjust_breakpoint_address (gdbarch, + score_adjust_breakpoint_address); set_gdbarch_register_type (gdbarch, score_register_type); set_gdbarch_frame_align (gdbarch, score_frame_align); set_gdbarch_inner_than (gdbarch, core_addr_lessthan); - set_gdbarch_unwind_pc (gdbarch, score_unwind_pc); - set_gdbarch_unwind_sp (gdbarch, score_unwind_sp); - set_gdbarch_print_insn (gdbarch, score_print_insn); - set_gdbarch_skip_prologue (gdbarch, score_skip_prologue); - set_gdbarch_in_function_epilogue_p (gdbarch, score_in_function_epilogue_p); + + switch (target_mach) + { + case bfd_mach_score7: + set_gdbarch_breakpoint_kind_from_pc (gdbarch, + score7_breakpoint_kind_from_pc); + set_gdbarch_sw_breakpoint_from_kind (gdbarch, + score7_sw_breakpoint_from_kind); + set_gdbarch_skip_prologue (gdbarch, score7_skip_prologue); + set_gdbarch_stack_frame_destroyed_p (gdbarch, + score7_stack_frame_destroyed_p); + set_gdbarch_register_name (gdbarch, score7_register_name); + set_gdbarch_num_regs (gdbarch, SCORE7_NUM_REGS); + /* Core file support. */ + set_gdbarch_iterate_over_regset_sections + (gdbarch, score7_linux_iterate_over_regset_sections); + break; + + case bfd_mach_score3: + set_gdbarch_breakpoint_kind_from_pc (gdbarch, + score3_breakpoint_kind_from_pc); + set_gdbarch_sw_breakpoint_from_kind (gdbarch, + score3_sw_breakpoint_from_kind); + set_gdbarch_skip_prologue (gdbarch, score3_skip_prologue); + set_gdbarch_stack_frame_destroyed_p (gdbarch, + score3_stack_frame_destroyed_p); + set_gdbarch_register_name (gdbarch, score3_register_name); + set_gdbarch_num_regs (gdbarch, SCORE3_NUM_REGS); + break; + } /* Watchpoint hooks. */ set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1); @@ -1063,20 +1497,17 @@ score_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) /* Dummy frame hooks. */ set_gdbarch_return_value (gdbarch, score_return_value); set_gdbarch_call_dummy_location (gdbarch, AT_ENTRY_POINT); - set_gdbarch_unwind_dummy_id (gdbarch, score_unwind_dummy_id); set_gdbarch_push_dummy_call (gdbarch, score_push_dummy_call); /* Normal frame hooks. */ - frame_unwind_append_sniffer (gdbarch, dwarf2_frame_sniffer); + dwarf2_append_unwinders (gdbarch); frame_base_append_sniffer (gdbarch, dwarf2_frame_base_sniffer); - frame_unwind_append_sniffer (gdbarch, score_prologue_sniffer); + frame_unwind_append_unwinder (gdbarch, &score_prologue_unwind); frame_base_append_sniffer (gdbarch, score_prologue_frame_base_sniffer); return gdbarch; } -extern initialize_file_ftype _initialize_score_tdep; - void _initialize_score_tdep (void) {