gdb/sh-tdep.c - gdb
Global variables defined
Data types defined
Functions defined
Macros defined
Source code
- #include "defs.h"
- #include "frame.h"
- #include "frame-base.h"
- #include "frame-unwind.h"
- #include "dwarf2-frame.h"
- #include "symtab.h"
- #include "gdbtypes.h"
- #include "gdbcmd.h"
- #include "gdbcore.h"
- #include "value.h"
- #include "dis-asm.h"
- #include "inferior.h"
- #include "arch-utils.h"
- #include "floatformat.h"
- #include "regcache.h"
- #include "doublest.h"
- #include "osabi.h"
- #include "reggroups.h"
- #include "regset.h"
- #include "objfiles.h"
- #include "sh-tdep.h"
- #include "sh64-tdep.h"
- #include "elf-bfd.h"
- #include "solib-svr4.h"
- #include "elf/sh.h"
- #include "dwarf2.h"
- #include "gdb/sim-sh.h"
- static struct cmd_list_element *setshcmdlist = NULL;
- static struct cmd_list_element *showshcmdlist = NULL;
- static const char sh_cc_gcc[] = "gcc";
- static const char sh_cc_renesas[] = "renesas";
- static const char *const sh_cc_enum[] = {
- sh_cc_gcc,
- sh_cc_renesas,
- NULL
- };
- static const char *sh_active_calling_convention = sh_cc_gcc;
- #define SH_NUM_REGS 67
- struct sh_frame_cache
- {
-
- CORE_ADDR base;
- LONGEST sp_offset;
- CORE_ADDR pc;
-
- int uses_fp;
-
- CORE_ADDR saved_regs[SH_NUM_REGS];
- CORE_ADDR saved_sp;
- };
- static int
- sh_is_renesas_calling_convention (struct type *func_type)
- {
- int val = 0;
- if (func_type)
- {
- func_type = check_typedef (func_type);
- if (TYPE_CODE (func_type) == TYPE_CODE_PTR)
- func_type = check_typedef (TYPE_TARGET_TYPE (func_type));
- if (TYPE_CODE (func_type) == TYPE_CODE_FUNC
- && TYPE_CALLING_CONVENTION (func_type) == DW_CC_GNU_renesas_sh)
- val = 1;
- }
- if (sh_active_calling_convention == sh_cc_renesas)
- val = 1;
- return val;
- }
- static const char *
- sh_sh_register_name (struct gdbarch *gdbarch, int reg_nr)
- {
- static char *register_names[] = {
- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
- "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
- "pc", "pr", "gbr", "vbr", "mach", "macl", "sr",
- "", "",
- "", "", "", "", "", "", "", "",
- "", "", "", "", "", "", "", "",
- "", "",
- "", "", "", "", "", "", "", "",
- "", "", "", "", "", "", "", "",
- "", "", "", "", "", "", "", "",
- };
- if (reg_nr < 0)
- return NULL;
- if (reg_nr >= (sizeof (register_names) / sizeof (*register_names)))
- return NULL;
- return register_names[reg_nr];
- }
- static const char *
- sh_sh3_register_name (struct gdbarch *gdbarch, int reg_nr)
- {
- static char *register_names[] = {
- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
- "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
- "pc", "pr", "gbr", "vbr", "mach", "macl", "sr",
- "", "",
- "", "", "", "", "", "", "", "",
- "", "", "", "", "", "", "", "",
- "ssr", "spc",
- "r0b0", "r1b0", "r2b0", "r3b0", "r4b0", "r5b0", "r6b0", "r7b0",
- "r0b1", "r1b1", "r2b1", "r3b1", "r4b1", "r5b1", "r6b1", "r7b1"
- "", "", "", "", "", "", "", "",
- };
- if (reg_nr < 0)
- return NULL;
- if (reg_nr >= (sizeof (register_names) / sizeof (*register_names)))
- return NULL;
- return register_names[reg_nr];
- }
- static const char *
- sh_sh3e_register_name (struct gdbarch *gdbarch, int reg_nr)
- {
- static char *register_names[] = {
- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
- "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
- "pc", "pr", "gbr", "vbr", "mach", "macl", "sr",
- "fpul", "fpscr",
- "fr0", "fr1", "fr2", "fr3", "fr4", "fr5", "fr6", "fr7",
- "fr8", "fr9", "fr10", "fr11", "fr12", "fr13", "fr14", "fr15",
- "ssr", "spc",
- "r0b0", "r1b0", "r2b0", "r3b0", "r4b0", "r5b0", "r6b0", "r7b0",
- "r0b1", "r1b1", "r2b1", "r3b1", "r4b1", "r5b1", "r6b1", "r7b1",
- "", "", "", "", "", "", "", "",
- };
- if (reg_nr < 0)
- return NULL;
- if (reg_nr >= (sizeof (register_names) / sizeof (*register_names)))
- return NULL;
- return register_names[reg_nr];
- }
- static const char *
- sh_sh2e_register_name (struct gdbarch *gdbarch, int reg_nr)
- {
- static char *register_names[] = {
- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
- "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
- "pc", "pr", "gbr", "vbr", "mach", "macl", "sr",
- "fpul", "fpscr",
- "fr0", "fr1", "fr2", "fr3", "fr4", "fr5", "fr6", "fr7",
- "fr8", "fr9", "fr10", "fr11", "fr12", "fr13", "fr14", "fr15",
- "", "",
- "", "", "", "", "", "", "", "",
- "", "", "", "", "", "", "", "",
- "", "", "", "", "", "", "", "",
- };
- if (reg_nr < 0)
- return NULL;
- if (reg_nr >= (sizeof (register_names) / sizeof (*register_names)))
- return NULL;
- return register_names[reg_nr];
- }
- static const char *
- sh_sh2a_register_name (struct gdbarch *gdbarch, int reg_nr)
- {
- static char *register_names[] = {
-
- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
- "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
-
- "pc", "pr", "gbr", "vbr", "mach", "macl", "sr",
-
- "fpul", "fpscr",
-
- "fr0", "fr1", "fr2", "fr3", "fr4", "fr5", "fr6", "fr7",
- "fr8", "fr9", "fr10", "fr11", "fr12", "fr13", "fr14", "fr15",
-
- "", "",
-
- "r0b", "r1b", "r2b", "r3b", "r4b", "r5b", "r6b", "r7b",
- "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b",
- "machb", "ivnb", "prb", "gbrb", "maclb",
-
- "",
-
- "ibcr", "ibnr", "tbr",
-
- "bank",
-
- "dr0", "dr2", "dr4", "dr6", "dr8", "dr10", "dr12", "dr14",
- };
- if (reg_nr < 0)
- return NULL;
- if (reg_nr >= (sizeof (register_names) / sizeof (*register_names)))
- return NULL;
- return register_names[reg_nr];
- }
- static const char *
- sh_sh2a_nofpu_register_name (struct gdbarch *gdbarch, int reg_nr)
- {
- static char *register_names[] = {
-
- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
- "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
-
- "pc", "pr", "gbr", "vbr", "mach", "macl", "sr",
-
- "", "",
-
- "", "", "", "", "", "", "", "",
- "", "", "", "", "", "", "", "",
-
- "", "",
-
- "r0b", "r1b", "r2b", "r3b", "r4b", "r5b", "r6b", "r7b",
- "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b",
- "machb", "ivnb", "prb", "gbrb", "maclb",
-
- "",
-
- "ibcr", "ibnr", "tbr",
-
- "bank",
-
- "", "", "", "", "", "", "", "",
- };
- if (reg_nr < 0)
- return NULL;
- if (reg_nr >= (sizeof (register_names) / sizeof (*register_names)))
- return NULL;
- return register_names[reg_nr];
- }
- static const char *
- sh_sh_dsp_register_name (struct gdbarch *gdbarch, int reg_nr)
- {
- static char *register_names[] = {
- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
- "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
- "pc", "pr", "gbr", "vbr", "mach", "macl", "sr",
- "", "dsr",
- "a0g", "a0", "a1g", "a1", "m0", "m1", "x0", "x1",
- "y0", "y1", "", "", "", "", "", "mod",
- "", "",
- "rs", "re", "", "", "", "", "", "",
- "", "", "", "", "", "", "", "",
- "", "", "", "", "", "", "", "",
- };
- if (reg_nr < 0)
- return NULL;
- if (reg_nr >= (sizeof (register_names) / sizeof (*register_names)))
- return NULL;
- return register_names[reg_nr];
- }
- static const char *
- sh_sh3_dsp_register_name (struct gdbarch *gdbarch, int reg_nr)
- {
- static char *register_names[] = {
- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
- "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
- "pc", "pr", "gbr", "vbr", "mach", "macl", "sr",
- "", "dsr",
- "a0g", "a0", "a1g", "a1", "m0", "m1", "x0", "x1",
- "y0", "y1", "", "", "", "", "", "mod",
- "ssr", "spc",
- "rs", "re", "", "", "", "", "", "",
- "r0b", "r1b", "r2b", "r3b", "r4b", "r5b", "r6b", "r7b",
- "", "", "", "", "", "", "", "",
- "", "", "", "", "", "", "", "",
- };
- if (reg_nr < 0)
- return NULL;
- if (reg_nr >= (sizeof (register_names) / sizeof (*register_names)))
- return NULL;
- return register_names[reg_nr];
- }
- static const char *
- sh_sh4_register_name (struct gdbarch *gdbarch, int reg_nr)
- {
- static char *register_names[] = {
-
- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
- "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
-
- "pc", "pr", "gbr", "vbr", "mach", "macl", "sr",
-
- "fpul", "fpscr",
-
- "fr0", "fr1", "fr2", "fr3", "fr4", "fr5", "fr6", "fr7",
- "fr8", "fr9", "fr10", "fr11", "fr12", "fr13", "fr14", "fr15",
-
- "ssr", "spc",
-
- "r0b0", "r1b0", "r2b0", "r3b0", "r4b0", "r5b0", "r6b0", "r7b0",
-
- "r0b1", "r1b1", "r2b1", "r3b1", "r4b1", "r5b1", "r6b1", "r7b1",
-
- "", "", "", "", "", "", "", "",
-
- "",
-
- "dr0", "dr2", "dr4", "dr6", "dr8", "dr10", "dr12", "dr14",
-
- "fv0", "fv4", "fv8", "fv12",
- FIXME
- FIXME
- };
- if (reg_nr < 0)
- return NULL;
- if (reg_nr >= (sizeof (register_names) / sizeof (*register_names)))
- return NULL;
- return register_names[reg_nr];
- }
- static const char *
- sh_sh4_nofpu_register_name (struct gdbarch *gdbarch, int reg_nr)
- {
- static char *register_names[] = {
-
- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
- "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
-
- "pc", "pr", "gbr", "vbr", "mach", "macl", "sr",
-
- "", "",
-
- "", "", "", "", "", "", "", "",
- "", "", "", "", "", "", "", "",
-
- "ssr", "spc",
-
- "r0b0", "r1b0", "r2b0", "r3b0", "r4b0", "r5b0", "r6b0", "r7b0",
-
- "r0b1", "r1b1", "r2b1", "r3b1", "r4b1", "r5b1", "r6b1", "r7b1",
-
- "", "", "", "", "", "", "", "",
-
- "",
-
- "", "", "", "", "", "", "", "",
-
- "", "", "", "",
- };
- if (reg_nr < 0)
- return NULL;
- if (reg_nr >= (sizeof (register_names) / sizeof (*register_names)))
- return NULL;
- return register_names[reg_nr];
- }
- static const char *
- sh_sh4al_dsp_register_name (struct gdbarch *gdbarch, int reg_nr)
- {
- static char *register_names[] = {
- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
- "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
- "pc", "pr", "gbr", "vbr", "mach", "macl", "sr",
- "", "dsr",
- "a0g", "a0", "a1g", "a1", "m0", "m1", "x0", "x1",
- "y0", "y1", "", "", "", "", "", "mod",
- "ssr", "spc",
- "rs", "re", "", "", "", "", "", "",
- "r0b", "r1b", "r2b", "r3b", "r4b", "r5b", "r6b", "r7b",
- "", "", "", "", "", "", "", "",
- "", "", "", "", "", "", "", "",
- };
- if (reg_nr < 0)
- return NULL;
- if (reg_nr >= (sizeof (register_names) / sizeof (*register_names)))
- return NULL;
- return register_names[reg_nr];
- }
- static const unsigned char *
- sh_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr, int *lenptr)
- {
-
- static unsigned char breakpoint[] = { 0xc3, 0xc3 };
-
- if (strcmp (target_shortname, "remote") == 0)
- {
- static unsigned char big_remote_breakpoint[] = { 0xc3, 0x20 };
- static unsigned char little_remote_breakpoint[] = { 0x20, 0xc3 };
- if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
- {
- *lenptr = sizeof (big_remote_breakpoint);
- return big_remote_breakpoint;
- }
- else
- {
- *lenptr = sizeof (little_remote_breakpoint);
- return little_remote_breakpoint;
- }
- }
- *lenptr = sizeof (breakpoint);
- return breakpoint;
- }
- #define GET_SOURCE_REG(x) (((x) >> 4) & 0xf)
- #define GET_TARGET_REG(x) (((x) >> 8) & 0xf)
- #define IS_JSR(x) (((x) & 0xf0ff) == 0x400b)
- #define IS_STS(x) ((x) == 0x4f22)
- #define IS_MACL_STS(x) ((x) == 0x4f12)
- #define IS_PUSH(x) (((x) & 0xff0f) == 0x2f06)
- #define IS_MOV_SP_FP(x) ((x) == 0x6ef3)
- #define IS_ADD_IMM_SP(x) (((x) & 0xff00) == 0x7f00)
- #define IS_MOV_R3(x) (((x) & 0xff00) == 0x1a00)
- #define IS_SHLL_R3(x) ((x) == 0x4300)
- #define IS_ADD_R3SP(x) ((x) == 0x3f3c)
- #define IS_FPUSH(x) (((x) & 0xff0f) == 0xff0b)
- #define IS_MOV_ARG_TO_REG(x) \
- (((x) & 0xf00f) == 0x6003 && \
- ((x) & 0x00f0) >= 0x0040 && \
- ((x) & 0x00f0) <= 0x0070)
- #define IS_MOV_ARG_TO_IND_R14(x) \
- (((x) & 0xff0f) == 0x2e02 && \
- ((x) & 0x00f0) >= 0x0040 && \
- ((x) & 0x00f0) <= 0x0070)
- #define IS_MOV_ARG_TO_IND_R14_WITH_DISP(x) \
- (((x) & 0xff00) == 0x1e00 && \
- ((x) & 0x00f0) >= 0x0040 && \
- ((x) & 0x00f0) <= 0x0070)
- #define IS_MOVW_PCREL_TO_REG(x) (((x) & 0xf000) == 0x9000)
- #define IS_MOVL_PCREL_TO_REG(x) (((x) & 0xf000) == 0xd000)
- #define IS_MOVI20(x) (((x) & 0xf00f) == 0x0000)
- #define IS_SUB_REG_FROM_SP(x) (((x) & 0xff0f) == 0x3f08)
- #define FPSCR_SZ (1 << 20)
- #define IS_RESTORE_FP(x) ((x) == 0x6ef6)
- #define IS_RTS(x) ((x) == 0x000b)
- #define IS_LDS(x) ((x) == 0x4f26)
- #define IS_MACL_LDS(x) ((x) == 0x4f16)
- #define IS_MOV_FP_SP(x) ((x) == 0x6fe3)
- #define IS_ADD_REG_TO_FP(x) (((x) & 0xff0f) == 0x3e0c)
- #define IS_ADD_IMM_FP(x) (((x) & 0xff00) == 0x7e00)
- static CORE_ADDR
- sh_analyze_prologue (struct gdbarch *gdbarch,
- CORE_ADDR pc, CORE_ADDR limit_pc,
- struct sh_frame_cache *cache, ULONGEST fpscr)
- {
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- ULONGEST inst;
- int offset;
- int sav_offset = 0;
- int r3_val = 0;
- int reg, sav_reg = -1;
- cache->uses_fp = 0;
- for (; pc < limit_pc; pc += 2)
- {
- inst = read_memory_unsigned_integer (pc, 2, byte_order);
-
- if (IS_PUSH (inst))
- {
- cache->saved_regs[GET_SOURCE_REG (inst)] = cache->sp_offset;
- cache->sp_offset += 4;
- }
- else if (IS_STS (inst))
- {
- cache->saved_regs[PR_REGNUM] = cache->sp_offset;
- cache->sp_offset += 4;
- }
- else if (IS_MACL_STS (inst))
- {
- cache->saved_regs[MACL_REGNUM] = cache->sp_offset;
- cache->sp_offset += 4;
- }
- else if (IS_MOV_R3 (inst))
- {
- r3_val = ((inst & 0xff) ^ 0x80) - 0x80;
- }
- else if (IS_SHLL_R3 (inst))
- {
- r3_val <<= 1;
- }
- else if (IS_ADD_R3SP (inst))
- {
- cache->sp_offset += -r3_val;
- }
- else if (IS_ADD_IMM_SP (inst))
- {
- offset = ((inst & 0xff) ^ 0x80) - 0x80;
- cache->sp_offset -= offset;
- }
- else if (IS_MOVW_PCREL_TO_REG (inst))
- {
- if (sav_reg < 0)
- {
- reg = GET_TARGET_REG (inst);
- if (reg < 14)
- {
- sav_reg = reg;
- offset = (inst & 0xff) << 1;
- sav_offset =
- read_memory_integer ((pc + 4) + offset, 2, byte_order);
- }
- }
- }
- else if (IS_MOVL_PCREL_TO_REG (inst))
- {
- if (sav_reg < 0)
- {
- reg = GET_TARGET_REG (inst);
- if (reg < 14)
- {
- sav_reg = reg;
- offset = (inst & 0xff) << 2;
- sav_offset =
- read_memory_integer (((pc & 0xfffffffc) + 4) + offset,
- 4, byte_order);
- }
- }
- }
- else if (IS_MOVI20 (inst)
- && (pc + 2 < limit_pc))
- {
- if (sav_reg < 0)
- {
- reg = GET_TARGET_REG (inst);
- if (reg < 14)
- {
- sav_reg = reg;
- sav_offset = GET_SOURCE_REG (inst) << 16;
-
- pc += 2;
- sav_offset
- |= read_memory_unsigned_integer (pc, 2, byte_order);
-
- if (sav_offset & 0x00080000)
- sav_offset |= 0xfff00000;
- }
- }
- }
- else if (IS_SUB_REG_FROM_SP (inst))
- {
- reg = GET_SOURCE_REG (inst);
- if (sav_reg > 0 && reg == sav_reg)
- {
- sav_reg = -1;
- }
- cache->sp_offset += sav_offset;
- }
- else if (IS_FPUSH (inst))
- {
- if (fpscr & FPSCR_SZ)
- {
- cache->sp_offset += 8;
- }
- else
- {
- cache->sp_offset += 4;
- }
- }
- else if (IS_MOV_SP_FP (inst))
- {
- pc += 2;
-
- limit_pc = min (limit_pc, pc + (2 * 6));
- cache->uses_fp = 1;
-
- for (; pc < limit_pc; pc += 2)
- {
- inst = read_memory_integer (pc, 2, byte_order);
- if (IS_MOV_ARG_TO_IND_R14 (inst))
- {
- reg = GET_SOURCE_REG (inst);
- if (cache->sp_offset > 0)
- cache->saved_regs[reg] = cache->sp_offset;
- }
- else if (IS_MOV_ARG_TO_IND_R14_WITH_DISP (inst))
- {
- reg = GET_SOURCE_REG (inst);
- offset = (inst & 0xf) * 4;
- if (cache->sp_offset > offset)
- cache->saved_regs[reg] = cache->sp_offset - offset;
- }
- else if (IS_MOV_ARG_TO_REG (inst))
- continue;
- else
- break;
- }
- break;
- }
- else if (IS_JSR (inst))
- {
-
- if (pc + 2 < limit_pc)
- {
- inst = read_memory_integer (pc + 2, 2, byte_order);
- if (IS_MOV_SP_FP (inst))
- cache->uses_fp = 1;
- }
- break;
- }
- #if 0
- #endif
- }
- return pc;
- }
- static CORE_ADDR
- sh_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
- {
- CORE_ADDR post_prologue_pc, func_addr, func_end_addr, limit_pc;
- struct sh_frame_cache cache;
-
- if (find_pc_partial_function (pc, NULL, &func_addr, &func_end_addr))
- {
- post_prologue_pc = skip_prologue_using_sal (gdbarch, func_addr);
- if (post_prologue_pc != 0)
- return max (pc, post_prologue_pc);
- }
-
-
- limit_pc = skip_prologue_using_sal (gdbarch, pc);
- if (limit_pc == 0)
-
- limit_pc = pc + (2 * 28);
-
- if (func_end_addr != 0)
- limit_pc = min (limit_pc, func_end_addr);
- cache.sp_offset = -4;
- post_prologue_pc = sh_analyze_prologue (gdbarch, pc, limit_pc, &cache, 0);
- if (cache.uses_fp)
- pc = post_prologue_pc;
- return pc;
- }
- static int
- sh_use_struct_convention (int renesas_abi, struct type *type)
- {
- int len = TYPE_LENGTH (type);
- int nelem = TYPE_NFIELDS (type);
-
- if (renesas_abi && (TYPE_CODE (type) == TYPE_CODE_STRUCT
- || TYPE_CODE (type) == TYPE_CODE_UNION))
- return 1;
-
- if (len != 1 && len != 2 && len != 4 && len != 8)
- return 1;
-
- if (nelem <= 1)
- return 0;
-
- if (TYPE_LENGTH (TYPE_FIELD_TYPE (type, 0)) == len)
- return 0;
-
- if (len == 8 && TYPE_LENGTH (TYPE_FIELD_TYPE (type, 0)) == 4)
- return 0;
-
- return 1;
- }
- static int
- sh_use_struct_convention_nofpu (int renesas_abi, struct type *type)
- {
-
- if (renesas_abi && TYPE_NFIELDS (type) == 0 && TYPE_LENGTH (type) >= 8)
- return 1;
- return sh_use_struct_convention (renesas_abi, type);
- }
- static CORE_ADDR
- sh_frame_align (struct gdbarch *ignore, CORE_ADDR sp)
- {
- return sp & ~3;
- }
- static const gdb_byte *
- sh_justify_value_in_reg (struct gdbarch *gdbarch, struct value *val, int len)
- {
- static gdb_byte valbuf[4];
- memset (valbuf, 0, sizeof (valbuf));
- if (len < 4)
- {
-
- if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
- memcpy (valbuf + (4 - len), value_contents (val), len);
- else
- memcpy (valbuf, value_contents (val), len);
- return valbuf;
- }
- return value_contents (val);
- }
- static CORE_ADDR
- sh_stack_allocsize (int nargs, struct value **args)
- {
- int stack_alloc = 0;
- while (nargs-- > 0)
- stack_alloc += ((TYPE_LENGTH (value_type (args[nargs])) + 3) & ~3);
- return stack_alloc;
- }
- static int flt_argreg_array[FLOAT_ARGLAST_REGNUM - FLOAT_ARG0_REGNUM + 1];
- static void
- sh_init_flt_argreg (void)
- {
- memset (flt_argreg_array, 0, sizeof flt_argreg_array);
- }
- static int
- sh_next_flt_argreg (struct gdbarch *gdbarch, int len, struct type *func_type)
- {
- int argreg;
-
- for (argreg = 0; argreg <= FLOAT_ARGLAST_REGNUM - FLOAT_ARG0_REGNUM;
- ++argreg)
- if (!flt_argreg_array[argreg])
- break;
-
- if (argreg > FLOAT_ARGLAST_REGNUM - FLOAT_ARG0_REGNUM)
- return FLOAT_ARGLAST_REGNUM + 1;
- if (len == 8)
- {
-
- if (argreg & 1)
- {
-
- if (!sh_is_renesas_calling_convention (func_type))
- flt_argreg_array[argreg] = 1;
- ++argreg;
-
- if (argreg > FLOAT_ARGLAST_REGNUM - FLOAT_ARG0_REGNUM)
- return FLOAT_ARGLAST_REGNUM + 1;
- }
-
- flt_argreg_array[argreg + 1] = 1;
- }
- else if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_LITTLE
- && !sh_is_renesas_calling_convention (func_type))
- {
-
- if (!flt_argreg_array[argreg + 1])
- ++argreg;
- }
- flt_argreg_array[argreg] = 1;
- return FLOAT_ARG0_REGNUM + argreg;
- }
- static int
- sh_treat_as_flt_p (struct type *type)
- {
-
- if (TYPE_CODE (type) == TYPE_CODE_FLT)
- return 1;
-
- if (TYPE_CODE (type) != TYPE_CODE_STRUCT)
- return 0;
-
- if (TYPE_NFIELDS (type) != 1)
- return 0;
-
- if (TYPE_CODE (TYPE_FIELD_TYPE (type, 0)) == TYPE_CODE_FLT)
- return 1;
-
- return 0;
- }
- static CORE_ADDR
- sh_push_dummy_call_fpu (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)
- {
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- int stack_offset = 0;
- int argreg = ARG0_REGNUM;
- int flt_argreg = 0;
- int argnum;
- struct type *func_type = value_type (function);
- struct type *type;
- CORE_ADDR regval;
- const gdb_byte *val;
- int len, reg_size = 0;
- int pass_on_stack = 0;
- int treat_as_flt;
- int last_reg_arg = INT_MAX;
-
- if (sh_is_renesas_calling_convention (func_type)
- && TYPE_VARARGS (func_type))
- last_reg_arg = TYPE_NFIELDS (func_type) - 2;
-
- sp = sh_frame_align (gdbarch, sp);
-
- sp -= sh_stack_allocsize (nargs, args);
-
- sh_init_flt_argreg ();
-
- for (argnum = 0; argnum < nargs; argnum++)
- {
- type = value_type (args[argnum]);
- len = TYPE_LENGTH (type);
- val = sh_justify_value_in_reg (gdbarch, args[argnum], len);
-
- pass_on_stack = 0;
-
- treat_as_flt = sh_treat_as_flt_p (type);
- if (treat_as_flt)
- flt_argreg = sh_next_flt_argreg (gdbarch, len, func_type);
-
- else if (sh_is_renesas_calling_convention (func_type)
- && ((TYPE_CODE (type) == TYPE_CODE_INT && len == 8)
- || TYPE_CODE (type) == TYPE_CODE_STRUCT
- || TYPE_CODE (type) == TYPE_CODE_UNION))
- pass_on_stack = 1;
-
- else if (len > ((ARGLAST_REGNUM - argreg + 1) * 4))
- pass_on_stack = 1;
- while (len > 0)
- {
- if ((treat_as_flt && flt_argreg > FLOAT_ARGLAST_REGNUM)
- || (!treat_as_flt && (argreg > ARGLAST_REGNUM
- || pass_on_stack))
- || argnum > last_reg_arg)
- {
-
- reg_size = (len + 3) & ~3;
- write_memory (sp + stack_offset, val, reg_size);
- stack_offset += reg_size;
- }
- else if (treat_as_flt && flt_argreg <= FLOAT_ARGLAST_REGNUM)
- {
-
- reg_size = register_size (gdbarch, flt_argreg);
- regval = extract_unsigned_integer (val, reg_size, byte_order);
-
- if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_LITTLE
- && TYPE_LENGTH (type) == 2 * reg_size)
- {
- regcache_cooked_write_unsigned (regcache, flt_argreg + 1,
- regval);
- val += reg_size;
- len -= reg_size;
- regval = extract_unsigned_integer (val, reg_size,
- byte_order);
- }
- regcache_cooked_write_unsigned (regcache, flt_argreg++, regval);
- }
- else if (!treat_as_flt && argreg <= ARGLAST_REGNUM)
- {
-
- reg_size = register_size (gdbarch, argreg);
- regval = extract_unsigned_integer (val, reg_size, byte_order);
- regcache_cooked_write_unsigned (regcache, argreg++, regval);
- }
-
- len -= reg_size;
- val += reg_size;
- }
- }
- if (struct_return)
- {
- if (sh_is_renesas_calling_convention (func_type))
-
- write_memory_unsigned_integer (sp -= 4, 4, byte_order, struct_addr);
- else
-
- regcache_cooked_write_unsigned (regcache,
- STRUCT_RETURN_REGNUM, struct_addr);
- }
-
- regcache_cooked_write_unsigned (regcache, PR_REGNUM, bp_addr);
-
- regcache_cooked_write_unsigned (regcache,
- gdbarch_sp_regnum (gdbarch), sp);
- return sp;
- }
- static CORE_ADDR
- sh_push_dummy_call_nofpu (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)
- {
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- int stack_offset = 0;
- int argreg = ARG0_REGNUM;
- int argnum;
- struct type *func_type = value_type (function);
- struct type *type;
- CORE_ADDR regval;
- const gdb_byte *val;
- int len, reg_size = 0;
- int pass_on_stack = 0;
- int last_reg_arg = INT_MAX;
-
- if (sh_is_renesas_calling_convention (func_type)
- && TYPE_VARARGS (func_type))
- last_reg_arg = TYPE_NFIELDS (func_type) - 2;
-
- sp = sh_frame_align (gdbarch, sp);
-
- sp -= sh_stack_allocsize (nargs, args);
-
- for (argnum = 0; argnum < nargs; argnum++)
- {
- type = value_type (args[argnum]);
- len = TYPE_LENGTH (type);
- val = sh_justify_value_in_reg (gdbarch, args[argnum], len);
-
- pass_on_stack = 0;
-
- if (sh_is_renesas_calling_convention (func_type)
- && ((TYPE_CODE (type) == TYPE_CODE_INT && len >= 8)
- || (TYPE_CODE (type) == TYPE_CODE_FLT && len >= 8)
- || TYPE_CODE (type) == TYPE_CODE_STRUCT
- || TYPE_CODE (type) == TYPE_CODE_UNION))
- pass_on_stack = 1;
- while (len > 0)
- {
- if (argreg > ARGLAST_REGNUM || pass_on_stack
- || argnum > last_reg_arg)
- {
-
- reg_size = (len + 3) & ~3;
- write_memory (sp + stack_offset, val, reg_size);
- stack_offset += reg_size;
- }
- else if (argreg <= ARGLAST_REGNUM)
- {
-
- reg_size = register_size (gdbarch, argreg);
- regval = extract_unsigned_integer (val, reg_size, byte_order);
- regcache_cooked_write_unsigned (regcache, argreg++, regval);
- }
-
- len -= reg_size;
- val += reg_size;
- }
- }
- if (struct_return)
- {
- if (sh_is_renesas_calling_convention (func_type))
-
- write_memory_unsigned_integer (sp -= 4, 4, byte_order, struct_addr);
- else
-
- regcache_cooked_write_unsigned (regcache,
- STRUCT_RETURN_REGNUM, struct_addr);
- }
-
- regcache_cooked_write_unsigned (regcache, PR_REGNUM, bp_addr);
-
- regcache_cooked_write_unsigned (regcache,
- gdbarch_sp_regnum (gdbarch), sp);
- return sp;
- }
- static void
- sh_extract_return_value_nofpu (struct type *type, struct regcache *regcache,
- gdb_byte *valbuf)
- {
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- int len = TYPE_LENGTH (type);
- int return_register = R0_REGNUM;
- int offset;
- if (len <= 4)
- {
- ULONGEST c;
- regcache_cooked_read_unsigned (regcache, R0_REGNUM, &c);
- store_unsigned_integer (valbuf, len, byte_order, c);
- }
- else if (len == 8)
- {
- int i, regnum = R0_REGNUM;
- for (i = 0; i < len; i += 4)
- regcache_raw_read (regcache, regnum++, valbuf + i);
- }
- else
- error (_("bad size for return value"));
- }
- static void
- sh_extract_return_value_fpu (struct type *type, struct regcache *regcache,
- gdb_byte *valbuf)
- {
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
- if (sh_treat_as_flt_p (type))
- {
- int len = TYPE_LENGTH (type);
- int i, regnum = gdbarch_fp0_regnum (gdbarch);
- for (i = 0; i < len; i += 4)
- if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_LITTLE)
- regcache_raw_read (regcache, regnum++,
- valbuf + len - 4 - i);
- else
- regcache_raw_read (regcache, regnum++, valbuf + i);
- }
- else
- sh_extract_return_value_nofpu (type, regcache, valbuf);
- }
- static void
- sh_store_return_value_nofpu (struct type *type, struct regcache *regcache,
- const gdb_byte *valbuf)
- {
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- ULONGEST val;
- int len = TYPE_LENGTH (type);
- if (len <= 4)
- {
- val = extract_unsigned_integer (valbuf, len, byte_order);
- regcache_cooked_write_unsigned (regcache, R0_REGNUM, val);
- }
- else
- {
- int i, regnum = R0_REGNUM;
- for (i = 0; i < len; i += 4)
- regcache_raw_write (regcache, regnum++, valbuf + i);
- }
- }
- static void
- sh_store_return_value_fpu (struct type *type, struct regcache *regcache,
- const gdb_byte *valbuf)
- {
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
- if (sh_treat_as_flt_p (type))
- {
- int len = TYPE_LENGTH (type);
- int i, regnum = gdbarch_fp0_regnum (gdbarch);
- for (i = 0; i < len; i += 4)
- if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_LITTLE)
- regcache_raw_write (regcache, regnum++,
- valbuf + len - 4 - i);
- else
- regcache_raw_write (regcache, regnum++, valbuf + i);
- }
- else
- sh_store_return_value_nofpu (type, regcache, valbuf);
- }
- static enum return_value_convention
- sh_return_value_nofpu (struct gdbarch *gdbarch, struct value *function,
- struct type *type, struct regcache *regcache,
- gdb_byte *readbuf, const gdb_byte *writebuf)
- {
- struct type *func_type = function ? value_type (function) : NULL;
- if (sh_use_struct_convention_nofpu (
- sh_is_renesas_calling_convention (func_type), type))
- return RETURN_VALUE_STRUCT_CONVENTION;
- if (writebuf)
- sh_store_return_value_nofpu (type, regcache, writebuf);
- else if (readbuf)
- sh_extract_return_value_nofpu (type, regcache, readbuf);
- return RETURN_VALUE_REGISTER_CONVENTION;
- }
- static enum return_value_convention
- sh_return_value_fpu (struct gdbarch *gdbarch, struct value *function,
- struct type *type, struct regcache *regcache,
- gdb_byte *readbuf, const gdb_byte *writebuf)
- {
- struct type *func_type = function ? value_type (function) : NULL;
- if (sh_use_struct_convention (
- sh_is_renesas_calling_convention (func_type), type))
- return RETURN_VALUE_STRUCT_CONVENTION;
- if (writebuf)
- sh_store_return_value_fpu (type, regcache, writebuf);
- else if (readbuf)
- sh_extract_return_value_fpu (type, regcache, readbuf);
- return RETURN_VALUE_REGISTER_CONVENTION;
- }
- static struct type *
- sh_sh2a_register_type (struct gdbarch *gdbarch, int reg_nr)
- {
- if ((reg_nr >= gdbarch_fp0_regnum (gdbarch)
- && (reg_nr <= FP_LAST_REGNUM)) || (reg_nr == FPUL_REGNUM))
- return builtin_type (gdbarch)->builtin_float;
- else if (reg_nr >= DR0_REGNUM && reg_nr <= DR_LAST_REGNUM)
- return builtin_type (gdbarch)->builtin_double;
- else
- return builtin_type (gdbarch)->builtin_int;
- }
- static struct type *
- sh_sh3e_register_type (struct gdbarch *gdbarch, int reg_nr)
- {
- if ((reg_nr >= gdbarch_fp0_regnum (gdbarch)
- && (reg_nr <= FP_LAST_REGNUM)) || (reg_nr == FPUL_REGNUM))
- return builtin_type (gdbarch)->builtin_float;
- else
- return builtin_type (gdbarch)->builtin_int;
- }
- static struct type *
- sh_sh4_build_float_register_type (struct gdbarch *gdbarch, int high)
- {
- return lookup_array_range_type (builtin_type (gdbarch)->builtin_float,
- 0, high);
- }
- static struct type *
- sh_sh4_register_type (struct gdbarch *gdbarch, int reg_nr)
- {
- if ((reg_nr >= gdbarch_fp0_regnum (gdbarch)
- && (reg_nr <= FP_LAST_REGNUM)) || (reg_nr == FPUL_REGNUM))
- return builtin_type (gdbarch)->builtin_float;
- else if (reg_nr >= DR0_REGNUM && reg_nr <= DR_LAST_REGNUM)
- return builtin_type (gdbarch)->builtin_double;
- else if (reg_nr >= FV0_REGNUM && reg_nr <= FV_LAST_REGNUM)
- return sh_sh4_build_float_register_type (gdbarch, 3);
- else
- return builtin_type (gdbarch)->builtin_int;
- }
- static struct type *
- sh_default_register_type (struct gdbarch *gdbarch, int reg_nr)
- {
- return builtin_type (gdbarch)->builtin_int;
- }
- TODO
- static int
- sh_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
- struct reggroup *reggroup)
- {
- if (gdbarch_register_name (gdbarch, regnum) == NULL
- || *gdbarch_register_name (gdbarch, regnum) == '\0')
- return 0;
- if (reggroup == float_reggroup
- && (regnum == FPUL_REGNUM
- || regnum == FPSCR_REGNUM))
- return 1;
- if (regnum >= FV0_REGNUM && regnum <= FV_LAST_REGNUM)
- {
- if (reggroup == vector_reggroup || reggroup == float_reggroup)
- return 1;
- if (reggroup == general_reggroup)
- return 0;
- }
- if (regnum == VBR_REGNUM
- || regnum == SR_REGNUM
- || regnum == FPSCR_REGNUM
- || regnum == SSR_REGNUM
- || regnum == SPC_REGNUM)
- {
- if (reggroup == system_reggroup)
- return 1;
- if (reggroup == general_reggroup)
- return 0;
- }
-
- return default_register_reggroup_p (gdbarch, regnum, reggroup);
- }
- static void
- sh_register_convert_to_virtual (struct gdbarch *gdbarch, int regnum,
- struct type *type, gdb_byte *from, gdb_byte *to)
- {
- if (gdbarch_byte_order (gdbarch) != BFD_ENDIAN_LITTLE)
- {
-
- memcpy (to, from, register_size (gdbarch, regnum));
- return;
- }
- if (regnum >= DR0_REGNUM && regnum <= DR_LAST_REGNUM)
- {
- DOUBLEST val;
- floatformat_to_doublest (&floatformat_ieee_double_littlebyte_bigword,
- from, &val);
- store_typed_floating (to, type, val);
- }
- else
- error
- ("sh_register_convert_to_virtual called with non DR register number");
- }
- static void
- sh_register_convert_to_raw (struct gdbarch *gdbarch, struct type *type,
- int regnum, const gdb_byte *from, gdb_byte *to)
- {
- if (gdbarch_byte_order (gdbarch) != BFD_ENDIAN_LITTLE)
- {
-
- memcpy (to, from, register_size (gdbarch, regnum));
- return;
- }
- if (regnum >= DR0_REGNUM && regnum <= DR_LAST_REGNUM)
- {
- DOUBLEST val = extract_typed_floating (from, type);
- floatformat_from_doublest (&floatformat_ieee_double_littlebyte_bigword,
- &val, to);
- }
- else
- error (_("sh_register_convert_to_raw called with non DR register number"));
- }
- static int
- fv_reg_base_num (struct gdbarch *gdbarch, int fv_regnum)
- {
- int fp_regnum;
- fp_regnum = gdbarch_fp0_regnum (gdbarch)
- + (fv_regnum - FV0_REGNUM) * 4;
- return fp_regnum;
- }
- static int
- dr_reg_base_num (struct gdbarch *gdbarch, int dr_regnum)
- {
- int fp_regnum;
- fp_regnum = gdbarch_fp0_regnum (gdbarch)
- + (dr_regnum - DR0_REGNUM) * 2;
- return fp_regnum;
- }
- static enum register_status
- pseudo_register_read_portions (struct gdbarch *gdbarch,
- struct regcache *regcache,
- int portions,
- int base_regnum, gdb_byte *buffer)
- {
- int portion;
- for (portion = 0; portion < portions; portion++)
- {
- enum register_status status;
- gdb_byte *b;
- b = buffer + register_size (gdbarch, base_regnum) * portion;
- status = regcache_raw_read (regcache, base_regnum + portion, b);
- if (status != REG_VALID)
- return status;
- }
- return REG_VALID;
- }
- static enum register_status
- sh_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
- int reg_nr, gdb_byte *buffer)
- {
- int base_regnum;
- gdb_byte temp_buffer[MAX_REGISTER_SIZE];
- enum register_status status;
- if (reg_nr == PSEUDO_BANK_REGNUM)
- return regcache_raw_read (regcache, BANK_REGNUM, buffer);
- else if (reg_nr >= DR0_REGNUM && reg_nr <= DR_LAST_REGNUM)
- {
- base_regnum = dr_reg_base_num (gdbarch, reg_nr);
-
-
- status = pseudo_register_read_portions (gdbarch, regcache,
- 2, base_regnum, temp_buffer);
- if (status == REG_VALID)
- {
-
- sh_register_convert_to_virtual (gdbarch, reg_nr,
- register_type (gdbarch, reg_nr),
- temp_buffer, buffer);
- }
- return status;
- }
- else if (reg_nr >= FV0_REGNUM && reg_nr <= FV_LAST_REGNUM)
- {
- base_regnum = fv_reg_base_num (gdbarch, reg_nr);
-
- return pseudo_register_read_portions (gdbarch, regcache,
- 4, base_regnum, buffer);
- }
- else
- gdb_assert_not_reached ("invalid pseudo register number");
- }
- static void
- sh_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
- int reg_nr, const gdb_byte *buffer)
- {
- int base_regnum, portion;
- gdb_byte temp_buffer[MAX_REGISTER_SIZE];
- if (reg_nr == PSEUDO_BANK_REGNUM)
- {
-
- int bregnum;
- regcache_raw_write (regcache, BANK_REGNUM, buffer);
- for (bregnum = R0_BANK0_REGNUM; bregnum < MACLB_REGNUM; ++bregnum)
- regcache_invalidate (regcache, bregnum);
- }
- else if (reg_nr >= DR0_REGNUM && reg_nr <= DR_LAST_REGNUM)
- {
- base_regnum = dr_reg_base_num (gdbarch, reg_nr);
-
- sh_register_convert_to_raw (gdbarch, register_type (gdbarch, reg_nr),
- reg_nr, buffer, temp_buffer);
-
- for (portion = 0; portion < 2; portion++)
- regcache_raw_write (regcache, base_regnum + portion,
- (temp_buffer
- + register_size (gdbarch,
- base_regnum) * portion));
- }
- else if (reg_nr >= FV0_REGNUM && reg_nr <= FV_LAST_REGNUM)
- {
- base_regnum = fv_reg_base_num (gdbarch, reg_nr);
-
- for (portion = 0; portion < 4; portion++)
- regcache_raw_write (regcache, base_regnum + portion,
- (buffer
- + register_size (gdbarch,
- base_regnum) * portion));
- }
- }
- static int
- sh_dsp_register_sim_regno (struct gdbarch *gdbarch, int nr)
- {
- if (legacy_register_sim_regno (gdbarch, nr) < 0)
- return legacy_register_sim_regno (gdbarch, nr);
- if (nr >= DSR_REGNUM && nr <= Y1_REGNUM)
- return nr - DSR_REGNUM + SIM_SH_DSR_REGNUM;
- if (nr == MOD_REGNUM)
- return SIM_SH_MOD_REGNUM;
- if (nr == RS_REGNUM)
- return SIM_SH_RS_REGNUM;
- if (nr == RE_REGNUM)
- return SIM_SH_RE_REGNUM;
- if (nr >= DSP_R0_BANK_REGNUM && nr <= DSP_R7_BANK_REGNUM)
- return nr - DSP_R0_BANK_REGNUM + SIM_SH_R0_BANK_REGNUM;
- return nr;
- }
- static int
- sh_sh2a_register_sim_regno (struct gdbarch *gdbarch, int nr)
- {
- switch (nr)
- {
- case TBR_REGNUM:
- return SIM_SH_TBR_REGNUM;
- case IBNR_REGNUM:
- return SIM_SH_IBNR_REGNUM;
- case IBCR_REGNUM:
- return SIM_SH_IBCR_REGNUM;
- case BANK_REGNUM:
- return SIM_SH_BANK_REGNUM;
- case MACLB_REGNUM:
- return SIM_SH_BANK_MACL_REGNUM;
- case GBRB_REGNUM:
- return SIM_SH_BANK_GBR_REGNUM;
- case PRB_REGNUM:
- return SIM_SH_BANK_PR_REGNUM;
- case IVNB_REGNUM:
- return SIM_SH_BANK_IVN_REGNUM;
- case MACHB_REGNUM:
- return SIM_SH_BANK_MACH_REGNUM;
- default:
- break;
- }
- return legacy_register_sim_regno (gdbarch, nr);
- }
- static void
- sh_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum,
- struct dwarf2_frame_state_reg *reg,
- struct frame_info *this_frame)
- {
-
- if (regnum == gdbarch_pc_regnum (gdbarch))
- reg->how = DWARF2_FRAME_REG_RA;
-
- else if (regnum == gdbarch_sp_regnum (gdbarch))
- reg->how = DWARF2_FRAME_REG_CFA;
-
-
- else if ((regnum >= R0_REGNUM && regnum <= R0_REGNUM+7)
- || (regnum >= FR0_REGNUM && regnum <= FR0_REGNUM+11)
- || (regnum >= DR0_REGNUM && regnum <= DR0_REGNUM+5)
- || (regnum >= FV0_REGNUM && regnum <= FV0_REGNUM+2)
- || (regnum == MACH_REGNUM)
- || (regnum == MACL_REGNUM)
- || (regnum == FPUL_REGNUM)
- || (regnum == SR_REGNUM))
- reg->how = DWARF2_FRAME_REG_UNDEFINED;
-
- else if ((regnum >= R0_REGNUM+8 && regnum <= R0_REGNUM+15)
- || (regnum >= FR0_REGNUM+12 && regnum <= FR0_REGNUM+15)
- || (regnum >= DR0_REGNUM+6 && regnum <= DR0_REGNUM+8)
- || (regnum == FV0_REGNUM+3))
- reg->how = DWARF2_FRAME_REG_SAME_VALUE;
-
- else if ((regnum >= R0_BANK0_REGNUM && regnum <= R0_BANK0_REGNUM+15)
- || (regnum == GBR_REGNUM)
- || (regnum == VBR_REGNUM)
- || (regnum == FPSCR_REGNUM)
- || (regnum == SSR_REGNUM)
- || (regnum == SPC_REGNUM))
- reg->how = DWARF2_FRAME_REG_UNDEFINED;
- }
- static struct sh_frame_cache *
- sh_alloc_frame_cache (void)
- {
- struct sh_frame_cache *cache;
- int i;
- cache = FRAME_OBSTACK_ZALLOC (struct sh_frame_cache);
-
- cache->base = 0;
- cache->saved_sp = 0;
- cache->sp_offset = 0;
- cache->pc = 0;
-
- cache->uses_fp = 0;
-
- for (i = 0; i < SH_NUM_REGS; i++)
- {
- cache->saved_regs[i] = -1;
- }
- return cache;
- }
- static struct sh_frame_cache *
- sh_frame_cache (struct frame_info *this_frame, void **this_cache)
- {
- struct gdbarch *gdbarch = get_frame_arch (this_frame);
- struct sh_frame_cache *cache;
- CORE_ADDR current_pc;
- int i;
- if (*this_cache)
- return *this_cache;
- cache = sh_alloc_frame_cache ();
- *this_cache = cache;
-
- cache->base = get_frame_register_unsigned (this_frame, FP_REGNUM);
- if (cache->base == 0)
- return cache;
- cache->pc = get_frame_func (this_frame);
- current_pc = get_frame_pc (this_frame);
- if (cache->pc != 0)
- {
- ULONGEST fpscr;
-
- if (gdbarch_register_reggroup_p (gdbarch, FPSCR_REGNUM, all_reggroup))
- fpscr = get_frame_register_unsigned (this_frame, FPSCR_REGNUM);
- else
- fpscr = 0;
- sh_analyze_prologue (gdbarch, cache->pc, current_pc, cache, fpscr);
- }
- if (!cache->uses_fp)
- {
-
- cache->base = get_frame_register_unsigned
- (this_frame, gdbarch_sp_regnum (gdbarch));
- }
-
- cache->saved_sp = cache->base + cache->sp_offset;
-
- for (i = 0; i < SH_NUM_REGS; i++)
- if (cache->saved_regs[i] != -1)
- cache->saved_regs[i] = cache->saved_sp - cache->saved_regs[i] - 4;
- return cache;
- }
- static struct value *
- sh_frame_prev_register (struct frame_info *this_frame,
- void **this_cache, int regnum)
- {
- struct gdbarch *gdbarch = get_frame_arch (this_frame);
- struct sh_frame_cache *cache = sh_frame_cache (this_frame, this_cache);
- gdb_assert (regnum >= 0);
- if (regnum == gdbarch_sp_regnum (gdbarch) && cache->saved_sp)
- return frame_unwind_got_constant (this_frame, regnum, cache->saved_sp);
-
- if (regnum == gdbarch_pc_regnum (gdbarch))
- regnum = PR_REGNUM;
- if (regnum < SH_NUM_REGS && cache->saved_regs[regnum] != -1)
- return frame_unwind_got_memory (this_frame, regnum,
- cache->saved_regs[regnum]);
- return frame_unwind_got_register (this_frame, regnum, regnum);
- }
- static void
- sh_frame_this_id (struct frame_info *this_frame, void **this_cache,
- struct frame_id *this_id)
- {
- struct sh_frame_cache *cache = sh_frame_cache (this_frame, this_cache);
-
- if (cache->base == 0)
- return;
- *this_id = frame_id_build (cache->saved_sp, cache->pc);
- }
- static const struct frame_unwind sh_frame_unwind = {
- NORMAL_FRAME,
- default_frame_unwind_stop_reason,
- sh_frame_this_id,
- sh_frame_prev_register,
- NULL,
- default_frame_sniffer
- };
- static CORE_ADDR
- sh_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
- {
- return frame_unwind_register_unsigned (next_frame,
- gdbarch_sp_regnum (gdbarch));
- }
- static CORE_ADDR
- sh_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
- {
- return frame_unwind_register_unsigned (next_frame,
- gdbarch_pc_regnum (gdbarch));
- }
- static struct frame_id
- sh_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
- {
- CORE_ADDR sp = get_frame_register_unsigned (this_frame,
- gdbarch_sp_regnum (gdbarch));
- return frame_id_build (sp, get_frame_pc (this_frame));
- }
- static CORE_ADDR
- sh_frame_base_address (struct frame_info *this_frame, void **this_cache)
- {
- struct sh_frame_cache *cache = sh_frame_cache (this_frame, this_cache);
- return cache->base;
- }
- static const struct frame_base sh_frame_base = {
- &sh_frame_unwind,
- sh_frame_base_address,
- sh_frame_base_address,
- sh_frame_base_address
- };
- static struct sh_frame_cache *
- sh_make_stub_cache (struct frame_info *this_frame)
- {
- struct gdbarch *gdbarch = get_frame_arch (this_frame);
- struct sh_frame_cache *cache;
- cache = sh_alloc_frame_cache ();
- cache->saved_sp
- = get_frame_register_unsigned (this_frame, gdbarch_sp_regnum (gdbarch));
- return cache;
- }
- static void
- sh_stub_this_id (struct frame_info *this_frame, void **this_cache,
- struct frame_id *this_id)
- {
- struct sh_frame_cache *cache;
- if (*this_cache == NULL)
- *this_cache = sh_make_stub_cache (this_frame);
- cache = *this_cache;
- *this_id = frame_id_build (cache->saved_sp, get_frame_pc (this_frame));
- }
- static int
- sh_stub_unwind_sniffer (const struct frame_unwind *self,
- struct frame_info *this_frame,
- void **this_prologue_cache)
- {
- CORE_ADDR addr_in_block;
- addr_in_block = get_frame_address_in_block (this_frame);
- if (in_plt_section (addr_in_block))
- return 1;
- return 0;
- }
- static const struct frame_unwind sh_stub_unwind =
- {
- NORMAL_FRAME,
- default_frame_unwind_stop_reason,
- sh_stub_this_id,
- sh_frame_prev_register,
- NULL,
- sh_stub_unwind_sniffer
- };
- static int
- sh_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
- {
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- CORE_ADDR func_addr = 0, func_end = 0;
- if (find_pc_partial_function (pc, NULL, &func_addr, &func_end))
- {
- ULONGEST inst;
-
- CORE_ADDR addr = func_end - 28;
- if (addr < func_addr + 4)
- addr = func_addr + 4;
- if (pc < addr)
- return 0;
-
- while (addr < func_end
- && !IS_RTS (read_memory_unsigned_integer (addr, 2, byte_order)))
- addr += 2;
- if (addr >= func_end)
- return 0;
-
- inst = read_memory_unsigned_integer (addr - 2, 2, byte_order);
- if (IS_RESTORE_FP (read_memory_unsigned_integer (addr - 2, 2,
- byte_order)))
- addr -= 2;
- else if (!IS_RESTORE_FP (read_memory_unsigned_integer (addr + 2, 2,
- byte_order)))
- return 0;
- inst = read_memory_unsigned_integer (addr - 2, 2, byte_order);
-
- if (IS_MACL_LDS (inst))
- {
- addr -= 2;
- inst = read_memory_unsigned_integer (addr - 2, 2, byte_order);
- }
-
- if (IS_LDS (inst))
- {
- addr -= 2;
- inst = read_memory_unsigned_integer (addr - 2, 2, byte_order);
- }
-
- if (IS_MOV_FP_SP (inst))
- {
- addr -= 2;
- inst = read_memory_unsigned_integer (addr - 2, 2, byte_order);
- }
-
- while (addr > func_addr + 4
- && (IS_ADD_REG_TO_FP (inst) || IS_ADD_IMM_FP (inst)))
- {
- addr -= 2;
- inst = read_memory_unsigned_integer (addr - 2, 2, byte_order);
- }
-
- if ((gdbarch_bfd_arch_info (gdbarch)->mach == bfd_mach_sh2a
- || gdbarch_bfd_arch_info (gdbarch)->mach == bfd_mach_sh2a_nofpu)
- && addr > func_addr + 6
- && IS_MOVI20 (read_memory_unsigned_integer (addr - 4, 2,
- byte_order)))
- addr -= 4;
- if (pc >= addr)
- return 1;
- }
- return 0;
- }
- void
- sh_corefile_supply_regset (const struct regset *regset,
- struct regcache *regcache,
- int regnum, const void *regs, size_t len)
- {
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
- const struct sh_corefile_regmap *regmap = (regset == &sh_corefile_gregset
- ? tdep->core_gregmap
- : tdep->core_fpregmap);
- int i;
- for (i = 0; regmap[i].regnum != -1; i++)
- {
- if ((regnum == -1 || regnum == regmap[i].regnum)
- && regmap[i].offset + 4 <= len)
- regcache_raw_supply (regcache, regmap[i].regnum,
- (char *)regs + regmap[i].offset);
- }
- }
- void
- sh_corefile_collect_regset (const struct regset *regset,
- const struct regcache *regcache,
- int regnum, void *regs, size_t len)
- {
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
- const struct sh_corefile_regmap *regmap = (regset == &sh_corefile_gregset
- ? tdep->core_gregmap
- : tdep->core_fpregmap);
- int i;
- for (i = 0; regmap[i].regnum != -1; i++)
- {
- if ((regnum == -1 || regnum == regmap[i].regnum)
- && regmap[i].offset + 4 <= len)
- regcache_raw_collect (regcache, regmap[i].regnum,
- (char *)regs + regmap[i].offset);
- }
- }
- const struct regset sh_corefile_gregset =
- {
- NULL,
- sh_corefile_supply_regset,
- sh_corefile_collect_regset
- };
- static const struct regset sh_corefile_fpregset =
- {
- NULL,
- sh_corefile_supply_regset,
- sh_corefile_collect_regset
- };
- static void
- sh_iterate_over_regset_sections (struct gdbarch *gdbarch,
- iterate_over_regset_sections_cb *cb,
- void *cb_data,
- const struct regcache *regcache)
- {
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
- if (tdep->core_gregmap != NULL)
- cb (".reg", tdep->sizeof_gregset, &sh_corefile_gregset, NULL, cb_data);
- if (tdep->core_fpregmap != NULL)
- cb (".reg2", tdep->sizeof_fpregset, &sh_corefile_fpregset, NULL, cb_data);
- }
- static int
- sh_return_in_first_hidden_param_p (struct gdbarch *gdbarch,
- struct type *type)
- {
- return 0;
- }
- static struct gdbarch *
- sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
- {
- struct gdbarch *gdbarch;
- struct gdbarch_tdep *tdep;
-
- if (info.bfd_arch_info->mach == bfd_mach_sh5)
- return sh64_gdbarch_init (info, arches);
-
- arches = gdbarch_list_lookup_by_info (arches, &info);
- if (arches != NULL)
- return arches->gdbarch;
-
- tdep = XCNEW (struct gdbarch_tdep);
- gdbarch = gdbarch_alloc (&info, tdep);
- set_gdbarch_short_bit (gdbarch, 2 * TARGET_CHAR_BIT);
- set_gdbarch_int_bit (gdbarch, 4 * TARGET_CHAR_BIT);
- set_gdbarch_long_bit (gdbarch, 4 * TARGET_CHAR_BIT);
- set_gdbarch_long_long_bit (gdbarch, 8 * TARGET_CHAR_BIT);
- set_gdbarch_float_bit (gdbarch, 4 * TARGET_CHAR_BIT);
- set_gdbarch_double_bit (gdbarch, 8 * TARGET_CHAR_BIT);
- set_gdbarch_long_double_bit (gdbarch, 8 * TARGET_CHAR_BIT);
- set_gdbarch_ptr_bit (gdbarch, 4 * TARGET_CHAR_BIT);
- set_gdbarch_num_regs (gdbarch, SH_NUM_REGS);
- set_gdbarch_sp_regnum (gdbarch, 15);
- set_gdbarch_pc_regnum (gdbarch, 16);
- set_gdbarch_fp0_regnum (gdbarch, -1);
- set_gdbarch_num_pseudo_regs (gdbarch, 0);
- set_gdbarch_register_type (gdbarch, sh_default_register_type);
- set_gdbarch_register_reggroup_p (gdbarch, sh_register_reggroup_p);
- set_gdbarch_breakpoint_from_pc (gdbarch, sh_breakpoint_from_pc);
- set_gdbarch_print_insn (gdbarch, print_insn_sh);
- set_gdbarch_register_sim_regno (gdbarch, legacy_register_sim_regno);
- set_gdbarch_return_value (gdbarch, sh_return_value_nofpu);
- set_gdbarch_skip_prologue (gdbarch, sh_skip_prologue);
- set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
- set_gdbarch_push_dummy_call (gdbarch, sh_push_dummy_call_nofpu);
- set_gdbarch_return_in_first_hidden_param_p (gdbarch,
- sh_return_in_first_hidden_param_p);
- set_gdbarch_believe_pcc_promotion (gdbarch, 1);
- set_gdbarch_frame_align (gdbarch, sh_frame_align);
- set_gdbarch_unwind_sp (gdbarch, sh_unwind_sp);
- set_gdbarch_unwind_pc (gdbarch, sh_unwind_pc);
- set_gdbarch_dummy_id (gdbarch, sh_dummy_id);
- frame_base_set_default (gdbarch, &sh_frame_base);
- set_gdbarch_in_function_epilogue_p (gdbarch, sh_in_function_epilogue_p);
- dwarf2_frame_set_init_reg (gdbarch, sh_dwarf2_frame_init_reg);
- set_gdbarch_iterate_over_regset_sections
- (gdbarch, sh_iterate_over_regset_sections);
- switch (info.bfd_arch_info->mach)
- {
- case bfd_mach_sh:
- set_gdbarch_register_name (gdbarch, sh_sh_register_name);
- break;
- case bfd_mach_sh2:
- set_gdbarch_register_name (gdbarch, sh_sh_register_name);
- break;
- case bfd_mach_sh2e:
-
- set_gdbarch_double_bit (gdbarch, 4 * TARGET_CHAR_BIT);
- set_gdbarch_double_format (gdbarch, floatformats_ieee_single);
- set_gdbarch_register_name (gdbarch, sh_sh2e_register_name);
- set_gdbarch_register_type (gdbarch, sh_sh3e_register_type);
- set_gdbarch_fp0_regnum (gdbarch, 25);
- set_gdbarch_return_value (gdbarch, sh_return_value_fpu);
- set_gdbarch_push_dummy_call (gdbarch, sh_push_dummy_call_fpu);
- break;
- case bfd_mach_sh2a:
- set_gdbarch_register_name (gdbarch, sh_sh2a_register_name);
- set_gdbarch_register_type (gdbarch, sh_sh2a_register_type);
- set_gdbarch_register_sim_regno (gdbarch, sh_sh2a_register_sim_regno);
- set_gdbarch_fp0_regnum (gdbarch, 25);
- set_gdbarch_num_pseudo_regs (gdbarch, 9);
- set_gdbarch_pseudo_register_read (gdbarch, sh_pseudo_register_read);
- set_gdbarch_pseudo_register_write (gdbarch, sh_pseudo_register_write);
- set_gdbarch_return_value (gdbarch, sh_return_value_fpu);
- set_gdbarch_push_dummy_call (gdbarch, sh_push_dummy_call_fpu);
- break;
- case bfd_mach_sh2a_nofpu:
- set_gdbarch_register_name (gdbarch, sh_sh2a_nofpu_register_name);
- set_gdbarch_register_sim_regno (gdbarch, sh_sh2a_register_sim_regno);
- set_gdbarch_num_pseudo_regs (gdbarch, 1);
- set_gdbarch_pseudo_register_read (gdbarch, sh_pseudo_register_read);
- set_gdbarch_pseudo_register_write (gdbarch, sh_pseudo_register_write);
- break;
- case bfd_mach_sh_dsp:
- set_gdbarch_register_name (gdbarch, sh_sh_dsp_register_name);
- set_gdbarch_register_sim_regno (gdbarch, sh_dsp_register_sim_regno);
- break;
- case bfd_mach_sh3:
- case bfd_mach_sh3_nommu:
- case bfd_mach_sh2a_nofpu_or_sh3_nommu:
- set_gdbarch_register_name (gdbarch, sh_sh3_register_name);
- break;
- case bfd_mach_sh3e:
- case bfd_mach_sh2a_or_sh3e:
-
- set_gdbarch_double_bit (gdbarch, 4 * TARGET_CHAR_BIT);
- set_gdbarch_double_format (gdbarch, floatformats_ieee_single);
- set_gdbarch_register_name (gdbarch, sh_sh3e_register_name);
- set_gdbarch_register_type (gdbarch, sh_sh3e_register_type);
- set_gdbarch_fp0_regnum (gdbarch, 25);
- set_gdbarch_return_value (gdbarch, sh_return_value_fpu);
- set_gdbarch_push_dummy_call (gdbarch, sh_push_dummy_call_fpu);
- break;
- case bfd_mach_sh3_dsp:
- set_gdbarch_register_name (gdbarch, sh_sh3_dsp_register_name);
- set_gdbarch_register_sim_regno (gdbarch, sh_dsp_register_sim_regno);
- break;
- case bfd_mach_sh4:
- case bfd_mach_sh4a:
- case bfd_mach_sh2a_or_sh4:
- set_gdbarch_register_name (gdbarch, sh_sh4_register_name);
- set_gdbarch_register_type (gdbarch, sh_sh4_register_type);
- set_gdbarch_fp0_regnum (gdbarch, 25);
- set_gdbarch_num_pseudo_regs (gdbarch, 13);
- set_gdbarch_pseudo_register_read (gdbarch, sh_pseudo_register_read);
- set_gdbarch_pseudo_register_write (gdbarch, sh_pseudo_register_write);
- set_gdbarch_return_value (gdbarch, sh_return_value_fpu);
- set_gdbarch_push_dummy_call (gdbarch, sh_push_dummy_call_fpu);
- break;
- case bfd_mach_sh4_nofpu:
- case bfd_mach_sh4a_nofpu:
- case bfd_mach_sh4_nommu_nofpu:
- case bfd_mach_sh2a_nofpu_or_sh4_nommu_nofpu:
- set_gdbarch_register_name (gdbarch, sh_sh4_nofpu_register_name);
- break;
- case bfd_mach_sh4al_dsp:
- set_gdbarch_register_name (gdbarch, sh_sh4al_dsp_register_name);
- set_gdbarch_register_sim_regno (gdbarch, sh_dsp_register_sim_regno);
- break;
- default:
- set_gdbarch_register_name (gdbarch, sh_sh_register_name);
- break;
- }
-
- gdbarch_init_osabi (info, gdbarch);
- dwarf2_append_unwinders (gdbarch);
- frame_unwind_append_unwinder (gdbarch, &sh_stub_unwind);
- frame_unwind_append_unwinder (gdbarch, &sh_frame_unwind);
- return gdbarch;
- }
- static void
- show_sh_command (char *args, int from_tty)
- {
- help_list (showshcmdlist, "show sh ", all_commands, gdb_stdout);
- }
- static void
- set_sh_command (char *args, int from_tty)
- {
- printf_unfiltered
- ("\"set sh\" must be followed by an appropriate subcommand.\n");
- help_list (setshcmdlist, "set sh ", all_commands, gdb_stdout);
- }
- extern initialize_file_ftype _initialize_sh_tdep;
- void
- _initialize_sh_tdep (void)
- {
- gdbarch_register (bfd_arch_sh, sh_gdbarch_init, NULL);
- add_prefix_cmd ("sh", no_class, set_sh_command, "SH specific commands.",
- &setshcmdlist, "set sh ", 0, &setlist);
- add_prefix_cmd ("sh", no_class, show_sh_command, "SH specific commands.",
- &showshcmdlist, "show sh ", 0, &showlist);
- add_setshow_enum_cmd ("calling-convention", class_vars, sh_cc_enum,
- &sh_active_calling_convention,
- _("Set calling convention used when calling target "
- "functions from GDB."),
- _("Show calling convention used when calling target "
- "functions from GDB."),
- _("gcc - Use GCC calling convention (default).\n"
- "renesas - Enforce Renesas calling convention."),
- NULL, NULL,
- &setshcmdlist, &showshcmdlist);
- }