-/* Target-dependent code for Hitachi Super-H, for GDB.
- Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
- Free Software Foundation, Inc.
+/* Target-dependent code for Renesas Super-H, for GDB.
+ Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+ 2003, 2004 Free Software Foundation, Inc.
This file is part of GDB.
#include "frame-unwind.h"
#include "dwarf2-frame.h"
#include "symtab.h"
-#include "symfile.h"
#include "gdbtypes.h"
#include "gdbcmd.h"
#include "gdbcore.h"
};
static const char *
-sh_generic_register_name (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_sh_register_name (int reg_nr)
{
static char *register_names[] = {
"y0", "y1", "", "", "", "", "", "mod",
"ssr", "spc",
"rs", "re", "", "", "", "", "", "",
- "r0b", "r1b", "r2b", "r3b", "r4b", "r5b", "r6b", "r7b"
- "", "", "", "", "", "", "", "",
+ "r0b", "r1b", "r2b", "r3b", "r4b", "r5b", "r6b", "r7b",
+ "", "", "", "", "", "", "", "",
};
if (reg_nr < 0)
return NULL;
return register_names[reg_nr];
}
+static const char *
+sh_sh4_nofpu_register_name (int reg_nr)
+{
+ static char *register_names[] = {
+ /* general registers 0-15 */
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+ /* 16 - 22 */
+ "pc", "pr", "gbr", "vbr", "mach", "macl", "sr",
+ /* 23, 24 */
+ "", "",
+ /* floating point registers 25 - 40 -- not for nofpu target */
+ "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "",
+ /* 41, 42 */
+ "ssr", "spc",
+ /* bank 0 43 - 50 */
+ "r0b0", "r1b0", "r2b0", "r3b0", "r4b0", "r5b0", "r6b0", "r7b0",
+ /* bank 1 51 - 58 */
+ "r0b1", "r1b1", "r2b1", "r3b1", "r4b1", "r5b1", "r6b1", "r7b1",
+ /* double precision (pseudo) 59 - 66 -- not for nofpu target */
+ "", "", "", "", "", "", "", "",
+ /* vectors (pseudo) 67 - 70 -- not for nofpu target */
+ "", "", "", "",
+ };
+ 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 (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 (CORE_ADDR *pcptr, int *lenptr)
{
return breakpoint;
}
-static CORE_ADDR
-sh_push_dummy_code (struct gdbarch *gdbarch,
- CORE_ADDR sp, CORE_ADDR funaddr, int using_gcc,
- struct value **args, int nargs,
- struct type *value_type,
- CORE_ADDR *real_pc, CORE_ADDR *bp_addr)
-{
- /* Allocate space sufficient for a breakpoint. */
- sp = (sp - 2) & ~1;
- /* Store the address of that breakpoint */
- *bp_addr = sp;
- /* sh always starts the call at the callee's entry point. */
- *real_pc = funaddr;
- return sp;
-}
-
/* Prologue looks like
mov.l r14,@-r15
sts.l pr,@-r15
#define GET_SOURCE_REG(x) (((x) >> 4) & 0xf)
#define GET_TARGET_REG(x) (((x) >> 8) & 0xf)
+/* JSR @Rm 0100mmmm00001011 */
+#define IS_JSR(x) (((x) & 0xf0ff) == 0x400b)
+
/* STS.L PR,@-r15 0100111100100010
r15-4-->r15, PR-->(r15) */
#define IS_STS(x) ((x) == 0x4f22)
if (reg < 14)
{
sav_reg = reg;
- offset = (((inst & 0xff) ^ 0x80) - 0x80) << 1;
+ offset = (inst & 0xff) << 1;
sav_offset =
- read_memory_integer (((pc + 4) & ~3) + offset, 2);
+ read_memory_integer ((pc + 4) + offset, 2);
}
}
}
{
if (sav_reg < 0)
{
- reg = (inst & 0x0f00) >> 8;
+ reg = GET_TARGET_REG (inst);
if (reg < 14)
{
sav_reg = reg;
- offset = (((inst & 0xff) ^ 0x80) - 0x80) << 1;
+ offset = (inst & 0xff) << 2;
sav_offset =
- read_memory_integer (((pc + 4) & ~3) + offset, 4);
+ read_memory_integer (((pc & 0xfffffffc) + 4) + offset, 4);
}
}
}
}
else if (IS_MOV_SP_FP (inst))
{
- if (!cache->uses_fp)
- cache->uses_fp = 1;
+ cache->uses_fp = 1;
/* At this point, only allow argument register moves to other
registers or argument register moves to @(X,fp) which are
moving the register arguments onto the stack area allocated
}
break;
}
+ else if (IS_JSR (inst))
+ {
+ /* We have found a jsr that has been scheduled into the prologue.
+ If we continue the scan and return a pc someplace after this,
+ then setting a breakpoint on this function will cause it to
+ appear to be called after the function it is calling via the
+ jsr, which will be very confusing. Most likely the next
+ instruction is going to be IS_MOV_SP_FP in the delay slot. If
+ so, note that before returning the current pc. */
+ inst = read_memory_integer (pc + 2, 2);
+ if (IS_MOV_SP_FP (inst))
+ cache->uses_fp = 1;
+ break;
+ }
#if 0 /* This used to just stop when it found an instruction that
was not considered part of the prologue. Now, we just
keep going looking for likely instructions. */
return pc;
}
-/* Should call_function allocate stack space for a struct return? */
+/* The ABI says:
+
+ Aggregate types not bigger than 8 bytes that have the same size and
+ alignment as one of the integer scalar types are returned in the
+ same registers as the integer type they match.
+
+ For example, a 2-byte aligned structure with size 2 bytes has the
+ same size and alignment as a short int, and will be returned in R0.
+ A 4-byte aligned structure with size 8 bytes has the same size and
+ alignment as a long long int, and will be returned in R0 and R1.
+
+ When an aggregate type is returned in R0 and R1, R0 contains the
+ first four bytes of the aggregate, and R1 contains the
+ remainder. If the size of the aggregate type is not a multiple of 4
+ bytes, the aggregate is tail-padded up to a multiple of 4
+ bytes. The value of the padding is undefined. For little-endian
+ targets the padding will appear at the most significant end of the
+ last element, for big-endian targets the padding appears at the
+ least significant end of the last element.
+
+ All other aggregate types are returned by address. The caller
+ function passes the address of an area large enough to hold the
+ aggregate value in R2. The called function stores the result in
+ this location.
+
+ To reiterate, structs smaller than 8 bytes could also be returned
+ in memory, if they don't pass the "same size and alignment as an
+ integer type" rule.
+
+ For example, in
+
+ struct s { char c[3]; } wibble;
+ struct s foo(void) { return wibble; }
+
+ the return value from foo() will be in memory, not
+ in R0, because there is no 3-byte integer type.
+
+ Similarly, in
+
+ struct s { char c[2]; } wibble;
+ struct s foo(void) { return wibble; }
+
+ because a struct containing two chars has alignment 1, that matches
+ type char, but size 2, that matches type short. There's no integer
+ type that has alignment 1 and size 2, so the struct is returned in
+ memory.
+
+*/
+
static int
sh_use_struct_convention (int gcc_p, struct type *type)
{
int len = TYPE_LENGTH (type);
int nelem = TYPE_NFIELDS (type);
- return ((len != 1 && len != 2 && len != 4 && len != 8) || nelem != 1) &&
- (len != 8 || TYPE_LENGTH (TYPE_FIELD_TYPE (type, 0)) != 4);
+
+ /* Non-power of 2 length types and types bigger than 8 bytes (which don't
+ fit in two registers anyway) use struct convention. */
+ if (len != 1 && len != 2 && len != 4 && len != 8)
+ return 1;
+
+ /* Scalar types and aggregate types with exactly one field are aligned
+ by definition. They are returned in registers. */
+ if (nelem <= 1)
+ return 0;
+
+ /* If the first field in the aggregate has the same length as the entire
+ aggregate type, the type is returned in registers. */
+ if (TYPE_LENGTH (TYPE_FIELD_TYPE (type, 0)) == len)
+ return 0;
+
+ /* If the size of the aggregate is 8 bytes and the first field is
+ of size 4 bytes its alignment is equal to long long's alignment,
+ so it's returned in registers. */
+ if (len == 8 && TYPE_LENGTH (TYPE_FIELD_TYPE (type, 0)) == 4)
+ return 0;
+
+ /* Otherwise use struct convention. */
+ return 1;
}
/* Extract from an array REGBUF containing the (raw) register state
/* Function: push_dummy_call (formerly push_arguments)
Setup the function arguments for calling a function in the inferior.
- On the Hitachi SH architecture, there are four registers (R4 to R7)
+ On the Renesas SH architecture, there are four registers (R4 to R7)
which are dedicated for passing function arguments. Up to the first
four arguments (depending on size) may go into these registers.
The rest go on the stack.
return FLOAT_ARG0_REGNUM + argreg;
}
+/* Helper function which figures out, if a type is treated like a float type.
+
+ The FPU ABIs have a special way how to treat types as float types.
+ Structures with exactly one member, which is of type float or double, are
+ treated exactly as the base types float or double:
+
+ struct sf {
+ float f;
+ };
+
+ struct sd {
+ double d;
+ };
+
+ are handled the same way as just
+
+ float f;
+
+ double d;
+
+ As a result, arguments of these struct types are pushed into floating point
+ registers exactly as floats or doubles, using the same decision algorithm.
+
+ The same is valid if these types are used as function return types. The
+ above structs are returned in fr0 resp. fr0,fr1 instead of in r0, r0,r1
+ or even using struct convention as it is for other structs. */
+
+static int
+sh_treat_as_flt_p (struct type *type)
+{
+ int len = TYPE_LENGTH (type);
+
+ /* Ordinary float types are obviously treated as float. */
+ if (TYPE_CODE (type) == TYPE_CODE_FLT)
+ return 1;
+ /* Otherwise non-struct types are not treated as float. */
+ if (TYPE_CODE (type) != TYPE_CODE_STRUCT)
+ return 0;
+ /* Otherwise structs with more than one memeber are not treated as float. */
+ if (TYPE_NFIELDS (type) != 1)
+ return 0;
+ /* Otherwise if the type of that member is float, the whole type is
+ treated as float. */
+ if (TYPE_CODE (TYPE_FIELD_TYPE (type, 0)) == TYPE_CODE_FLT)
+ return 1;
+ /* Otherwise it's not treated as float. */
+ return 0;
+}
+
static CORE_ADDR
sh_push_dummy_call_fpu (struct gdbarch *gdbarch,
- CORE_ADDR func_addr,
+ struct value *function,
struct regcache *regcache,
CORE_ADDR bp_addr, int nargs,
struct value **args,
CORE_ADDR regval;
char *val;
int len, reg_size = 0;
- int pass_on_stack;
+ int pass_on_stack = 0;
+ int treat_as_flt;
/* first force sp to a 4-byte alignment */
sp = sh_frame_align (gdbarch, sp);
/* Some decisions have to be made how various types are handled.
This also differs in different ABIs. */
pass_on_stack = 0;
- if (len > 16)
- pass_on_stack = 1; /* Types bigger than 16 bytes are passed on stack. */
/* Find out the next register to use for a floating point value. */
- if (TYPE_CODE (type) == TYPE_CODE_FLT)
+ treat_as_flt = sh_treat_as_flt_p (type);
+ if (treat_as_flt)
flt_argreg = sh_next_flt_argreg (len);
+ /* In contrast to non-FPU CPUs, arguments are never split between
+ registers and stack. If an argument doesn't fit in the remaining
+ registers it's always pushed entirely on the stack. */
+ else if (len > ((ARGLAST_REGNUM - argreg + 1) * 4))
+ pass_on_stack = 1;
while (len > 0)
{
- if ((TYPE_CODE (type) == TYPE_CODE_FLT
- && flt_argreg > FLOAT_ARGLAST_REGNUM)
- || argreg > ARGLAST_REGNUM || pass_on_stack)
+ if ((treat_as_flt && flt_argreg > FLOAT_ARGLAST_REGNUM)
+ || (!treat_as_flt && (argreg > ARGLAST_REGNUM
+ || pass_on_stack)))
{
- /* The remainder of the data goes entirely on the stack,
- 4-byte aligned. */
+ /* The data goes entirely on the stack, 4-byte aligned. */
reg_size = (len + 3) & ~3;
write_memory (sp + stack_offset, val, reg_size);
stack_offset += reg_size;
}
- else if (TYPE_CODE (type) == TYPE_CODE_FLT
- && flt_argreg <= FLOAT_ARGLAST_REGNUM)
+ else if (treat_as_flt && flt_argreg <= FLOAT_ARGLAST_REGNUM)
{
/* Argument goes in a float argument register. */
reg_size = register_size (gdbarch, flt_argreg);
regval = extract_unsigned_integer (val, reg_size);
+ /* In little endian mode, float types taking two registers
+ (doubles on sh4, long doubles on sh2e, sh3e and sh4) must
+ be stored swapped in the argument registers. The below
+ code first writes the first 32 bits in the next but one
+ register, increments the val and len values accordingly
+ and then proceeds as normal by writing the second 32 bits
+ into the next register. */
+ if (TARGET_BYTE_ORDER == 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);
+ }
regcache_cooked_write_unsigned (regcache, flt_argreg++, regval);
}
- else if (argreg <= ARGLAST_REGNUM)
+ else if (!treat_as_flt && argreg <= ARGLAST_REGNUM)
{
/* there's room in a register */
reg_size = register_size (gdbarch, argreg);
regval = extract_unsigned_integer (val, reg_size);
regcache_cooked_write_unsigned (regcache, argreg++, regval);
}
- /* Store the value reg_size bytes at a time. This means that things
- larger than reg_size bytes may go partly in registers and partly
- on the stack. */
+ /* Store the value one register at a time or in one step on stack. */
len -= reg_size;
val += reg_size;
}
static CORE_ADDR
sh_push_dummy_call_nofpu (struct gdbarch *gdbarch,
- CORE_ADDR func_addr,
+ struct value *function,
struct regcache *regcache,
CORE_ADDR bp_addr,
int nargs, struct value **args,
sh3e_sh4_extract_return_value (struct type *type, struct regcache *regcache,
void *valbuf)
{
- if (TYPE_CODE (type) == TYPE_CODE_FLT)
+ if (sh_treat_as_flt_p (type))
{
int len = TYPE_LENGTH (type);
int i, regnum = FP0_REGNUM;
for (i = 0; i < len; i += 4)
- regcache_raw_read (regcache, regnum++, (char *) valbuf + i);
+ if (TARGET_BYTE_ORDER == BFD_ENDIAN_LITTLE)
+ regcache_raw_read (regcache, regnum++, (char *) valbuf + len - 4 - i);
+ else
+ regcache_raw_read (regcache, regnum++, (char *) valbuf + i);
}
else
sh_default_extract_return_value (type, regcache, valbuf);
sh3e_sh4_store_return_value (struct type *type, struct regcache *regcache,
const void *valbuf)
{
- if (TYPE_CODE (type) == TYPE_CODE_FLT)
+ if (sh_treat_as_flt_p (type))
{
int len = TYPE_LENGTH (type);
int i, regnum = FP0_REGNUM;
for (i = 0; i < len; i += 4)
- regcache_raw_write (regcache, regnum++, (char *) valbuf + i);
+ if (TARGET_BYTE_ORDER == BFD_ENDIAN_LITTLE)
+ regcache_raw_write (regcache, regnum++,
+ (char *) valbuf + len - 4 - i);
+ else
+ regcache_raw_write (regcache, regnum++, (char *) valbuf + i);
}
else
sh_default_store_return_value (type, regcache, valbuf);
}
static void
+sh4_nofpu_show_regs (void)
+{
+ printf_filtered ("PC=%s SR=%08lx PR=%08lx MACH=%08lx MACHL=%08lx\n",
+ paddr (read_register (PC_REGNUM)),
+ (long) read_register (SR_REGNUM),
+ (long) read_register (PR_REGNUM),
+ (long) read_register (MACH_REGNUM),
+ (long) read_register (MACL_REGNUM));
+
+ printf_filtered ("GBR=%08lx VBR=%08lx",
+ (long) read_register (GBR_REGNUM),
+ (long) read_register (VBR_REGNUM));
+ printf_filtered (" SSR=%08lx SPC=%08lx",
+ (long) read_register (SSR_REGNUM),
+ (long) read_register (SPC_REGNUM));
+
+ printf_filtered
+ ("\nR0-R7 %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+ (long) read_register (0), (long) read_register (1),
+ (long) read_register (2), (long) read_register (3),
+ (long) read_register (4), (long) read_register (5),
+ (long) read_register (6), (long) read_register (7));
+ printf_filtered ("R8-R15 %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+ (long) read_register (8), (long) read_register (9),
+ (long) read_register (10), (long) read_register (11),
+ (long) read_register (12), (long) read_register (13),
+ (long) read_register (14), (long) read_register (15));
+}
+
+static void
sh_dsp_show_regs (void)
{
printf_filtered ("PC=%s SR=%08lx PR=%08lx MACH=%08lx MACHL=%08lx\n",
because they are stored as 4 individual FP elements. */
static void
-sh_sh4_register_convert_to_virtual (int regnum, struct type *type,
- char *from, char *to)
+sh_register_convert_to_virtual (int regnum, struct type *type,
+ char *from, char *to)
{
if (regnum >= DR0_REGNUM && regnum <= DR_LAST_REGNUM)
{
}
static void
-sh_sh4_register_convert_to_raw (struct type *type, int regnum,
- const void *from, void *to)
+sh_register_convert_to_raw (struct type *type, int regnum,
+ const void *from, void *to)
{
if (regnum >= DR0_REGNUM && regnum <= DR_LAST_REGNUM)
{
+ register_size (gdbarch,
base_regnum) * portion));
/* We must pay attention to the endiannes. */
- sh_sh4_register_convert_to_virtual (reg_nr,
- gdbarch_register_type (gdbarch,
- reg_nr),
- temp_buffer, buffer);
+ sh_register_convert_to_virtual (reg_nr,
+ gdbarch_register_type (gdbarch, reg_nr),
+ temp_buffer, buffer);
}
else if (reg_nr >= FV0_REGNUM && reg_nr <= FV_LAST_REGNUM)
{
base_regnum = dr_reg_base_num (reg_nr);
/* We must pay attention to the endiannes. */
- sh_sh4_register_convert_to_raw (gdbarch_register_type (gdbarch, reg_nr),
- reg_nr, buffer, temp_buffer);
+ sh_register_convert_to_raw (gdbarch_register_type (gdbarch, reg_nr),
+ reg_nr, buffer, temp_buffer);
/* Write the real regs for which this one is an alias. */
for (portion = 0; portion < 2; portion++)
fprintf_filtered (file, "\t(raw 0x");
for (j = 0; j < register_size (gdbarch, regnum); j++)
{
- register int idx = TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? j
- : register_size (gdbarch, regnum) - 1 - j;
+ int idx = (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
+ ? j
+ : register_size (gdbarch, regnum) - 1 - j);
fprintf_filtered (file, "%02x", (unsigned char) raw_buffer[idx]);
}
fprintf_filtered (file, ")");
else
/* do all (or most) registers */
{
- regnum = 0;
- while (regnum < NUM_REGS)
+ for (regnum = 0; regnum < NUM_REGS; ++regnum)
{
/* If the register name is empty, it is undefined for this
processor, so don't display anything. */
if (REGISTER_NAME (regnum) == NULL
|| *(REGISTER_NAME (regnum)) == '\0')
- {
- regnum++;
- continue;
- }
+ continue;
if (TYPE_CODE (gdbarch_register_type (gdbarch, regnum)) ==
TYPE_CODE_FLT)
{
+ /* true for "INFO ALL-REGISTERS" command */
if (fpregs)
- {
- /* true for "INFO ALL-REGISTERS" command */
- sh_do_fp_register (gdbarch, file, regnum); /* FP regs */
- regnum++;
- }
- else
- regnum += (FP_LAST_REGNUM - FP0_REGNUM); /* skip FP regs */
+ sh_do_fp_register (gdbarch, file, regnum); /* FP regs */
}
else
- {
- sh_do_register (gdbarch, file, regnum); /* All other regs */
- regnum++;
- }
+ sh_do_register (gdbarch, file, regnum); /* All other regs */
}
if (fpregs)
return SIM_SH_RS_REGNUM;
if (nr == RE_REGNUM)
return SIM_SH_RE_REGNUM;
- if (nr >= R0_BANK_REGNUM && nr <= R7_BANK_REGNUM)
- return nr - R0_BANK_REGNUM + SIM_SH_R0_BANK_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;
}
break;
case bfd_mach_sh3_dsp:
+ case bfd_mach_sh4al_dsp:
sh_show_regs = sh3_dsp_show_regs;
break;
case bfd_mach_sh4:
+ case bfd_mach_sh4a:
sh_show_regs = sh4_show_regs;
break;
+ case bfd_mach_sh4_nofpu:
+ case bfd_mach_sh4a_nofpu:
+ sh_show_regs = sh4_nofpu_show_regs;
+ break;
+
case bfd_mach_sh5:
sh_show_regs = sh64_show_regs;
/* SH5 is handled entirely in sh64-tdep.c */
set_gdbarch_store_return_value (gdbarch, sh_default_store_return_value);
set_gdbarch_extract_return_value (gdbarch, sh_default_extract_return_value);
- set_gdbarch_extract_struct_value_address (gdbarch,
- sh_extract_struct_value_address);
+ set_gdbarch_deprecated_extract_struct_value_address (gdbarch, sh_extract_struct_value_address);
set_gdbarch_skip_prologue (gdbarch, sh_skip_prologue);
set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
- set_gdbarch_decr_pc_after_break (gdbarch, 0);
- set_gdbarch_function_start_offset (gdbarch, 0);
- set_gdbarch_push_dummy_code (gdbarch, sh_push_dummy_code);
set_gdbarch_push_dummy_call (gdbarch, sh_push_dummy_call_nofpu);
- set_gdbarch_frame_args_skip (gdbarch, 0);
- set_gdbarch_frameless_function_invocation (gdbarch,
- frameless_look_for_prologue);
+ set_gdbarch_deprecated_frameless_function_invocation (gdbarch, legacy_frameless_look_for_prologue);
set_gdbarch_believe_pcc_promotion (gdbarch, 1);
set_gdbarch_frame_align (gdbarch, sh_frame_align);
break;
case bfd_mach_sh4:
+ case bfd_mach_sh4a:
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_push_dummy_call (gdbarch, sh_push_dummy_call_fpu);
break;
+ case bfd_mach_sh4_nofpu:
+ case bfd_mach_sh4a_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_generic_register_name);
+ set_gdbarch_register_name (gdbarch, sh_sh_register_name);
break;
}