mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-04 05:48:20 +08:00
2003-08-20 Michael Snyder <msnyder@redhat.com>
* sh-tdep.h (struct gdbarch_tdep): New member FLOAT_ARGLAST_REG. * sh-tdep.c (sh_gdbarch_init): For sh2e, sh3e, and sh4, set FLOAT_ARG0_REGNUM and FLOAT_ARGLAST_REGNUM, to be used for argument passing. (sh_push_dummy_call_fpu, sh_push_dummy_call_nofpu): New functions, replace sh_push_dummy_call. (sh_gdbarch_init): Set push_dummy_call to one of new methods.
This commit is contained in:
@ -1,3 +1,13 @@
|
||||
2003-08-20 Michael Snyder <msnyder@redhat.com>
|
||||
|
||||
* sh-tdep.h (struct gdbarch_tdep): New member FLOAT_ARGLAST_REG.
|
||||
* sh-tdep.c (sh_gdbarch_init): For sh2e, sh3e, and sh4, set
|
||||
FLOAT_ARG0_REGNUM and FLOAT_ARGLAST_REGNUM, to be used for
|
||||
argument passing.
|
||||
(sh_push_dummy_call_fpu, sh_push_dummy_call_nofpu): New
|
||||
functions, replace sh_push_dummy_call.
|
||||
(sh_gdbarch_init): Set push_dummy_call to one of new methods.
|
||||
|
||||
2003-08-20 Michael Chastain <mec@shout.net>
|
||||
|
||||
* gdbtypes.h (struct main_type): Rearrange to save space.
|
||||
|
161
gdb/sh-tdep.c
161
gdb/sh-tdep.c
@ -2034,7 +2034,7 @@ sh_frame_align (struct gdbarch *ignore, CORE_ADDR sp)
|
||||
return sp & ~3;
|
||||
}
|
||||
|
||||
/* Function: push_arguments
|
||||
/* Function: sh_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)
|
||||
@ -2042,6 +2042,10 @@ sh_frame_align (struct gdbarch *ignore, CORE_ADDR sp)
|
||||
four arguments (depending on size) may go into these registers.
|
||||
The rest go on the stack.
|
||||
|
||||
MVS: Except on SH variants that have floating point registers.
|
||||
In that case, float and double arguments are passed in the same
|
||||
manner, but using FP registers instead of GP registers.
|
||||
|
||||
Arguments that are smaller than 4 bytes will still take up a whole
|
||||
register or a whole 32-bit word on the stack, and will be
|
||||
right-justified in the register or the stack word. This includes
|
||||
@ -2055,6 +2059,11 @@ sh_frame_align (struct gdbarch *ignore, CORE_ADDR sp)
|
||||
that will be passed in this way; in other words, the convention of
|
||||
passing a pointer to a large aggregate instead of a copy is not used.
|
||||
|
||||
MVS: The above appears to be true for the SH variants that do not
|
||||
have an FPU, however those that have an FPU appear to copy the
|
||||
aggregate argument onto the stack (and not place it in registers)
|
||||
if it is larger than 16 bytes (four GP registers).
|
||||
|
||||
An exceptional case exists for struct arguments (and possibly other
|
||||
aggregates such as arrays) if the size is larger than 4 bytes but
|
||||
not a multiple of 4 bytes. In this case the argument is never split
|
||||
@ -2078,11 +2087,124 @@ sh_frame_align (struct gdbarch *ignore, CORE_ADDR sp)
|
||||
to R7. */
|
||||
|
||||
static CORE_ADDR
|
||||
sh_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
|
||||
struct regcache *regcache, CORE_ADDR bp_addr, int nargs,
|
||||
struct value **args, CORE_ADDR sp, int struct_return,
|
||||
CORE_ADDR struct_addr)
|
||||
sh_push_dummy_call_fpu (struct gdbarch *gdbarch,
|
||||
CORE_ADDR func_addr,
|
||||
struct regcache *regcache,
|
||||
CORE_ADDR bp_addr, int nargs,
|
||||
struct value **args,
|
||||
CORE_ADDR sp, int struct_return,
|
||||
CORE_ADDR struct_addr)
|
||||
{
|
||||
int stack_offset, stack_alloc;
|
||||
int argreg, flt_argreg;
|
||||
int argnum;
|
||||
struct type *type;
|
||||
CORE_ADDR regval;
|
||||
char *val;
|
||||
char valbuf[4];
|
||||
int len;
|
||||
int odd_sized_struct;
|
||||
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
||||
|
||||
/* first force sp to a 4-byte alignment */
|
||||
sp = sh_frame_align (gdbarch, sp);
|
||||
|
||||
/* The "struct return pointer" pseudo-argument has its own dedicated
|
||||
register */
|
||||
if (struct_return)
|
||||
regcache_cooked_write_unsigned (regcache,
|
||||
STRUCT_RETURN_REGNUM,
|
||||
struct_addr);
|
||||
|
||||
/* Now make sure there's space on the stack */
|
||||
for (argnum = 0, stack_alloc = 0; argnum < nargs; argnum++)
|
||||
stack_alloc += ((TYPE_LENGTH (VALUE_TYPE (args[argnum])) + 3) & ~3);
|
||||
sp -= stack_alloc; /* make room on stack for args */
|
||||
|
||||
/* Now load as many as possible of the first arguments into
|
||||
registers, and push the rest onto the stack. There are 16 bytes
|
||||
in four registers available. Loop thru args from first to last. */
|
||||
|
||||
argreg = tdep->ARG0_REGNUM;
|
||||
flt_argreg = tdep->FLOAT_ARG0_REGNUM;
|
||||
for (argnum = 0, stack_offset = 0; argnum < nargs; argnum++)
|
||||
{
|
||||
type = VALUE_TYPE (args[argnum]);
|
||||
len = TYPE_LENGTH (type);
|
||||
memset (valbuf, 0, sizeof (valbuf));
|
||||
if (len < 4)
|
||||
{
|
||||
/* value gets right-justified in the register or stack word */
|
||||
if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
|
||||
memcpy (valbuf + (4 - len),
|
||||
(char *) VALUE_CONTENTS (args[argnum]), len);
|
||||
else
|
||||
memcpy (valbuf, (char *) VALUE_CONTENTS (args[argnum]), len);
|
||||
val = valbuf;
|
||||
}
|
||||
else
|
||||
val = (char *) VALUE_CONTENTS (args[argnum]);
|
||||
|
||||
if (len > 4 && (len & 3) != 0)
|
||||
odd_sized_struct = 1; /* Such structs go entirely on stack. */
|
||||
else if (len > 16)
|
||||
odd_sized_struct = 1; /* So do aggregates bigger than 4 words. */
|
||||
else
|
||||
odd_sized_struct = 0;
|
||||
while (len > 0)
|
||||
{
|
||||
if ((TYPE_CODE (type) == TYPE_CODE_FLT
|
||||
&& flt_argreg > tdep->FLOAT_ARGLAST_REGNUM)
|
||||
|| argreg > tdep->ARGLAST_REGNUM
|
||||
|| odd_sized_struct)
|
||||
{
|
||||
/* must go on the stack */
|
||||
write_memory (sp + stack_offset, val, 4);
|
||||
stack_offset += 4;
|
||||
}
|
||||
/* NOTE WELL!!!!! This is not an "else if" clause!!!
|
||||
That's because some *&^%$ things get passed on the stack
|
||||
AND in the registers! */
|
||||
if (TYPE_CODE (type) == TYPE_CODE_FLT &&
|
||||
flt_argreg > 0 && flt_argreg <= tdep->FLOAT_ARGLAST_REGNUM)
|
||||
{
|
||||
/* Argument goes in a single-precision fp reg. */
|
||||
regval = extract_unsigned_integer (val, register_size (gdbarch,
|
||||
argreg));
|
||||
regcache_cooked_write_unsigned (regcache, flt_argreg++, regval);
|
||||
}
|
||||
else if (argreg <= tdep->ARGLAST_REGNUM)
|
||||
{
|
||||
/* there's room in a register */
|
||||
regval = extract_unsigned_integer (val, register_size (gdbarch,
|
||||
argreg));
|
||||
regcache_cooked_write_unsigned (regcache, argreg++, regval);
|
||||
}
|
||||
/* Store the value 4 bytes at a time. This means that things
|
||||
larger than 4 bytes may go partly in registers and partly
|
||||
on the stack. */
|
||||
len -= register_size (gdbarch, argreg);
|
||||
val += register_size (gdbarch, argreg);
|
||||
}
|
||||
}
|
||||
|
||||
/* Store return address. */
|
||||
regcache_cooked_write_unsigned (regcache, tdep->PR_REGNUM, bp_addr);
|
||||
|
||||
/* Update stack pointer. */
|
||||
regcache_cooked_write_unsigned (regcache, SP_REGNUM, sp);
|
||||
|
||||
return sp;
|
||||
}
|
||||
|
||||
static CORE_ADDR
|
||||
sh_push_dummy_call_nofpu (struct gdbarch *gdbarch,
|
||||
CORE_ADDR func_addr,
|
||||
struct regcache *regcache,
|
||||
CORE_ADDR bp_addr,
|
||||
int nargs, struct value **args,
|
||||
CORE_ADDR sp, int struct_return,
|
||||
CORE_ADDR struct_addr)
|
||||
{
|
||||
int stack_offset, stack_alloc;
|
||||
int argreg;
|
||||
@ -2101,7 +2223,9 @@ sh_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
|
||||
/* The "struct return pointer" pseudo-argument has its own dedicated
|
||||
register */
|
||||
if (struct_return)
|
||||
regcache_cooked_write_unsigned (regcache, STRUCT_RETURN_REGNUM, struct_addr);
|
||||
regcache_cooked_write_unsigned (regcache,
|
||||
STRUCT_RETURN_REGNUM,
|
||||
struct_addr);
|
||||
|
||||
/* Now make sure there's space on the stack */
|
||||
for (argnum = 0, stack_alloc = 0; argnum < nargs; argnum++)
|
||||
@ -4374,7 +4498,7 @@ sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
||||
set_gdbarch_push_dummy_code (gdbarch, sh_push_dummy_code);
|
||||
set_gdbarch_store_return_value (gdbarch, sh_default_store_return_value);
|
||||
set_gdbarch_extract_return_value (gdbarch, sh_default_extract_return_value);
|
||||
set_gdbarch_push_dummy_call (gdbarch, sh_push_dummy_call);
|
||||
set_gdbarch_push_dummy_call (gdbarch, sh_push_dummy_call_nofpu);
|
||||
set_gdbarch_extract_struct_value_address (gdbarch, sh_extract_struct_value_address);
|
||||
|
||||
set_gdbarch_deprecated_frame_init_saved_regs (gdbarch, sh_nofp_frame_init_saved_regs);
|
||||
@ -4387,7 +4511,7 @@ sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
||||
set_gdbarch_push_dummy_code (gdbarch, sh_push_dummy_code);
|
||||
set_gdbarch_store_return_value (gdbarch, sh_default_store_return_value);
|
||||
set_gdbarch_extract_return_value (gdbarch, sh_default_extract_return_value);
|
||||
set_gdbarch_push_dummy_call (gdbarch, sh_push_dummy_call);
|
||||
set_gdbarch_push_dummy_call (gdbarch, sh_push_dummy_call_nofpu);
|
||||
set_gdbarch_extract_struct_value_address (gdbarch, sh_extract_struct_value_address);
|
||||
|
||||
set_gdbarch_deprecated_frame_init_saved_regs (gdbarch, sh_nofp_frame_init_saved_regs);
|
||||
@ -4404,13 +4528,16 @@ sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
||||
set_gdbarch_fp0_regnum (gdbarch, 25);
|
||||
set_gdbarch_store_return_value (gdbarch, sh3e_sh4_store_return_value);
|
||||
set_gdbarch_extract_return_value (gdbarch, sh3e_sh4_extract_return_value);
|
||||
set_gdbarch_push_dummy_call (gdbarch, sh_push_dummy_call);
|
||||
set_gdbarch_push_dummy_call (gdbarch, sh_push_dummy_call_fpu);
|
||||
set_gdbarch_extract_struct_value_address (gdbarch, sh_extract_struct_value_address);
|
||||
tdep->FPUL_REGNUM = 23;
|
||||
tdep->FPSCR_REGNUM = 24;
|
||||
tdep->FP_LAST_REGNUM = 40;
|
||||
tdep->FLOAT_ARG0_REGNUM = 29; /* FIXME use constants! */
|
||||
tdep->FLOAT_ARGLAST_REGNUM = 36; /* FIXME use constants! */
|
||||
|
||||
set_gdbarch_deprecated_frame_init_saved_regs (gdbarch, sh_nofp_frame_init_saved_regs);
|
||||
set_gdbarch_deprecated_frame_init_saved_regs (gdbarch,
|
||||
sh_nofp_frame_init_saved_regs);
|
||||
break;
|
||||
case bfd_mach_sh_dsp:
|
||||
set_gdbarch_register_name (gdbarch, sh_sh_dsp_register_name);
|
||||
@ -4421,7 +4548,7 @@ sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
||||
set_gdbarch_register_sim_regno (gdbarch, sh_dsp_register_sim_regno);
|
||||
set_gdbarch_store_return_value (gdbarch, sh_default_store_return_value);
|
||||
set_gdbarch_extract_return_value (gdbarch, sh_default_extract_return_value);
|
||||
set_gdbarch_push_dummy_call (gdbarch, sh_push_dummy_call);
|
||||
set_gdbarch_push_dummy_call (gdbarch, sh_push_dummy_call_nofpu);
|
||||
set_gdbarch_extract_struct_value_address (gdbarch, sh_extract_struct_value_address);
|
||||
tdep->DSR_REGNUM = 24;
|
||||
tdep->A0G_REGNUM = 25;
|
||||
@ -4448,7 +4575,7 @@ sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
||||
set_gdbarch_push_dummy_code (gdbarch, sh_push_dummy_code);
|
||||
set_gdbarch_store_return_value (gdbarch, sh_default_store_return_value);
|
||||
set_gdbarch_extract_return_value (gdbarch, sh_default_extract_return_value);
|
||||
set_gdbarch_push_dummy_call (gdbarch, sh_push_dummy_call);
|
||||
set_gdbarch_push_dummy_call (gdbarch, sh_push_dummy_call_nofpu);
|
||||
set_gdbarch_extract_struct_value_address (gdbarch, sh_extract_struct_value_address);
|
||||
tdep->SSR_REGNUM = 41;
|
||||
tdep->SPC_REGNUM = 42;
|
||||
@ -4467,11 +4594,13 @@ sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
||||
set_gdbarch_fp0_regnum (gdbarch, 25);
|
||||
set_gdbarch_store_return_value (gdbarch, sh3e_sh4_store_return_value);
|
||||
set_gdbarch_extract_return_value (gdbarch, sh3e_sh4_extract_return_value);
|
||||
set_gdbarch_push_dummy_call (gdbarch, sh_push_dummy_call);
|
||||
set_gdbarch_push_dummy_call (gdbarch, sh_push_dummy_call_fpu);
|
||||
set_gdbarch_extract_struct_value_address (gdbarch, sh_extract_struct_value_address);
|
||||
tdep->FPUL_REGNUM = 23;
|
||||
tdep->FPSCR_REGNUM = 24;
|
||||
tdep->FP_LAST_REGNUM = 40;
|
||||
tdep->FLOAT_ARG0_REGNUM = 29; /* FIXME use constants! */
|
||||
tdep->FLOAT_ARGLAST_REGNUM = 36; /* FIXME use constants! */
|
||||
tdep->SSR_REGNUM = 41;
|
||||
tdep->SPC_REGNUM = 42;
|
||||
|
||||
@ -4486,7 +4615,7 @@ sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
||||
set_gdbarch_register_sim_regno (gdbarch, sh_dsp_register_sim_regno);
|
||||
set_gdbarch_store_return_value (gdbarch, sh_default_store_return_value);
|
||||
set_gdbarch_extract_return_value (gdbarch, sh_default_extract_return_value);
|
||||
set_gdbarch_push_dummy_call (gdbarch, sh_push_dummy_call);
|
||||
set_gdbarch_push_dummy_call (gdbarch, sh_push_dummy_call_nofpu);
|
||||
set_gdbarch_extract_struct_value_address (gdbarch, sh_extract_struct_value_address);
|
||||
tdep->DSR_REGNUM = 24;
|
||||
tdep->A0G_REGNUM = 25;
|
||||
@ -4519,7 +4648,7 @@ sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
||||
set_gdbarch_pseudo_register_write (gdbarch, sh_pseudo_register_write);
|
||||
set_gdbarch_store_return_value (gdbarch, sh3e_sh4_store_return_value);
|
||||
set_gdbarch_extract_return_value (gdbarch, sh3e_sh4_extract_return_value);
|
||||
set_gdbarch_push_dummy_call (gdbarch, sh_push_dummy_call);
|
||||
set_gdbarch_push_dummy_call (gdbarch, sh_push_dummy_call_fpu);
|
||||
set_gdbarch_extract_struct_value_address (gdbarch, sh_extract_struct_value_address);
|
||||
tdep->FPUL_REGNUM = 23;
|
||||
tdep->FPSCR_REGNUM = 24;
|
||||
@ -4530,6 +4659,8 @@ sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
||||
tdep->DR_LAST_REGNUM = 66;
|
||||
tdep->FV0_REGNUM = 67;
|
||||
tdep->FV_LAST_REGNUM = 70;
|
||||
tdep->FLOAT_ARG0_REGNUM = 29; /* FIXME use constants! */
|
||||
tdep->FLOAT_ARGLAST_REGNUM = 36; /* FIXME use constants! */
|
||||
|
||||
set_gdbarch_deprecated_frame_init_saved_regs (gdbarch, sh_fp_frame_init_saved_regs);
|
||||
break;
|
||||
|
@ -85,7 +85,8 @@ struct gdbarch_tdep
|
||||
int FV_LAST_C_REGNUM; /* sh5-compact*/
|
||||
int ARG0_REGNUM;
|
||||
int ARGLAST_REGNUM;
|
||||
int FLOAT_ARGLAST_REGNUM;
|
||||
int FLOAT_ARG0_REGNUM; /* sh4 */
|
||||
int FLOAT_ARGLAST_REGNUM; /* sh4, sh5 */
|
||||
int RETURN_REGNUM;
|
||||
enum sh_abi sh_abi;
|
||||
};
|
||||
|
Reference in New Issue
Block a user