This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[ping] Re: [RFA] sh-tdep: multi-arch the push_dummy_call method.


Michael Snyder wrote:

Elena, this splits off two versions of push_dummy_call: one for sh2e,
sh3e, and sh4, and the other for all the others. There are two differences:
how they pass floats, and how they pass large structs.


This wins us 6 new passes in call-ar-st, one in call-rt-st, 13 in callfuncs,
and one in varargs.




------------------------------------------------------------------------

2003-07-30 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.


Index: sh-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/sh-tdep.c,v
retrieving revision 1.135
diff -p -r1.135 sh-tdep.c
*** sh-tdep.c 1 Aug 2003 19:52:49 -0000 1.135
--- sh-tdep.c 1 Aug 2003 22:00:40 -0000
*************** sh_frame_align (struct gdbarch *ignore, *** 2034,2040 ****
return sp & ~3;
}
! /* Function: 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)
--- 2034,2040 ----
return sp & ~3;
}
! /* 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)
*************** sh_frame_align (struct gdbarch *ignore, *** 2042,2047 ****
--- 2042,2051 ----
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
*************** sh_frame_align (struct gdbarch *ignore, *** 2055,2060 ****
--- 2059,2069 ----
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 *************** sh_frame_align (struct gdbarch *ignore, *** 2078,2088 ****
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)
{
int stack_offset, stack_alloc;
int argreg;
--- 2087,2210 ----
to R7. */
static CORE_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;
*************** sh_push_dummy_call (struct gdbarch *gdba
*** 2101,2107 ****
/* 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++)
--- 2223,2231 ----
/* 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++)
*************** sh_gdbarch_init (struct gdbarch_info inf
*** 4374,4380 ****
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_extract_struct_value_address (gdbarch, sh_extract_struct_value_address);
set_gdbarch_deprecated_frame_init_saved_regs (gdbarch, sh_nofp_frame_init_saved_regs);
--- 4498,4504 ----
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_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);
*************** sh_gdbarch_init (struct gdbarch_info inf
*** 4387,4393 ****
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_extract_struct_value_address (gdbarch, sh_extract_struct_value_address);
set_gdbarch_deprecated_frame_init_saved_regs (gdbarch, sh_nofp_frame_init_saved_regs);
--- 4511,4517 ----
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_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);
*************** sh_gdbarch_init (struct gdbarch_info inf
*** 4404,4416 ****
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_extract_struct_value_address (gdbarch, sh_extract_struct_value_address);
tdep->FPUL_REGNUM = 23;
tdep->FPSCR_REGNUM = 24;
tdep->FP_LAST_REGNUM = 40;
! 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);
--- 4528,4543 ----
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_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);
break;
case bfd_mach_sh_dsp:
set_gdbarch_register_name (gdbarch, sh_sh_dsp_register_name);
*************** sh_gdbarch_init (struct gdbarch_info inf
*** 4421,4427 ****
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_extract_struct_value_address (gdbarch, sh_extract_struct_value_address);
tdep->DSR_REGNUM = 24;
tdep->A0G_REGNUM = 25;
--- 4548,4554 ----
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_nofpu);
set_gdbarch_extract_struct_value_address (gdbarch, sh_extract_struct_value_address);
tdep->DSR_REGNUM = 24;
tdep->A0G_REGNUM = 25;
*************** sh_gdbarch_init (struct gdbarch_info inf
*** 4448,4454 ****
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_extract_struct_value_address (gdbarch, sh_extract_struct_value_address);
tdep->SSR_REGNUM = 41;
tdep->SPC_REGNUM = 42;
--- 4575,4581 ----
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_nofpu);
set_gdbarch_extract_struct_value_address (gdbarch, sh_extract_struct_value_address);
tdep->SSR_REGNUM = 41;
tdep->SPC_REGNUM = 42;
*************** sh_gdbarch_init (struct gdbarch_info inf
*** 4467,4477 ****
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_extract_struct_value_address (gdbarch, sh_extract_struct_value_address);
tdep->FPUL_REGNUM = 23;
tdep->FPSCR_REGNUM = 24;
tdep->FP_LAST_REGNUM = 40;
tdep->SSR_REGNUM = 41;
tdep->SPC_REGNUM = 42;
--- 4594,4606 ----
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_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;
*************** sh_gdbarch_init (struct gdbarch_info inf
*** 4486,4492 ****
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_extract_struct_value_address (gdbarch, sh_extract_struct_value_address);
tdep->DSR_REGNUM = 24;
tdep->A0G_REGNUM = 25;
--- 4615,4621 ----
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_nofpu);
set_gdbarch_extract_struct_value_address (gdbarch, sh_extract_struct_value_address);
tdep->DSR_REGNUM = 24;
tdep->A0G_REGNUM = 25;
*************** sh_gdbarch_init (struct gdbarch_info inf
*** 4519,4525 ****
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_extract_struct_value_address (gdbarch, sh_extract_struct_value_address);
tdep->FPUL_REGNUM = 23;
tdep->FPSCR_REGNUM = 24;
--- 4648,4654 ----
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_fpu);
set_gdbarch_extract_struct_value_address (gdbarch, sh_extract_struct_value_address);
tdep->FPUL_REGNUM = 23;
tdep->FPSCR_REGNUM = 24;
*************** sh_gdbarch_init (struct gdbarch_info inf
*** 4530,4535 ****
--- 4659,4666 ----
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;
Index: sh-tdep.h
===================================================================
RCS file: /cvs/src/src/gdb/sh-tdep.h,v
retrieving revision 1.3
diff -p -r1.3 sh-tdep.h
*** sh-tdep.h 4 Jan 2003 23:38:45 -0000 1.3
--- sh-tdep.h 1 Aug 2003 22:00:40 -0000
*************** struct gdbarch_tdep
*** 85,91 ****
int FV_LAST_C_REGNUM; /* sh5-compact*/
int ARG0_REGNUM;
int ARGLAST_REGNUM;
! int FLOAT_ARGLAST_REGNUM;
int RETURN_REGNUM;
enum sh_abi sh_abi;
};
--- 85,92 ----
int FV_LAST_C_REGNUM; /* sh5-compact*/
int ARG0_REGNUM;
int ARGLAST_REGNUM;
! int FLOAT_ARG0_REGNUM; /* sh4 */
! int FLOAT_ARGLAST_REGNUM; /* sh4, sh5 */
int RETURN_REGNUM;
enum sh_abi sh_abi;
};





Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]