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]

Re: [RFA] Fix sparc64 argument passing


"David S. Miller" wrote:
> 
> Instead of trying to fixup the code there, I reimplemented it using
> the Sparc GCC backend code for argument passing as a template.
> 
> Advantages:
> 
> 1) It works
> 
> 2) Sparc32 support can be folded into it
> 
> 3) Matching code means fixes in one can propagate (hopefully)
>    to the other. :-)
> 
> Regression update:
> 
>                 sparc32                 sparc64
> failures before 83                      110
> failures after  83                      105

If these test results apply on Solaris as well as Linux, 
then you can check this in.  Thanks.

> 
> 2002-04-20  David S. Miller  <davem@redhat.com>
> 
>         Fix sparc64 call dummy argument passing.
>         * sparc-tdep.c: Include gdb_assert.h
>         (sparc32_push_arguments): Allocate minimum of 6 arg slots so
>         that varargs doesn't write all over the stack.
>         (sparc_fix_call_dummy): Note that V9/ARCH64 do not have the
>         unimp after call convention.
>         (SPARC_INT_ARG_MAX, SPARC_FP_ARG_MAX, INTEGER_P): Define.
>         (sp64_compute_arg_slotno, sp64_arg_advance,
>         sp64_compute_arg_stack_space, sp64_struct_regs_analyze,
>         sp64_do_struct_regs_3, sp64_do_struct_regs_2,
>         sp64_push_one_struct_regs, sp64_push_one_arg): New functions.
>         (sparc64_push_arguments): Reimplement from scratch.
>         (sp64_extract_return_value): Handle TYPE_CODE_COMPLEX.
> 
> --- sparc-tdep.c.~1~    Sat Apr 20 02:13:23 2002
> +++ sparc-tdep.c        Sat Apr 20 02:22:28 2002
> @@ -32,6 +32,7 @@
>  #include "value.h"
>  #include "bfd.h"
>  #include "gdb_string.h"
> +#include "gdb_assert.h"
>  #include "regcache.h"
> 
>  #ifdef USE_PROC_FS
> @@ -2070,6 +2071,12 @@ sparc32_push_arguments (int nargs, struc
>        m_arg->contents = VALUE_CONTENTS (arg);
>      }
> 
> +  /* Make room for at least 6 integer arguments for the sake of
> +     varargs.  Otherwise a varargs function, once called via
> +     a CALL_DUMMY, can write over other parts of the stack.  */
> +  if (accumulate_size < (6 * 4))
> +    accumulate_size = (6 * 4);
> +
>    /* Make room for the arguments on the stack.  */
>    accumulate_size += CALL_DUMMY_STACK_ADJUST;
>    sp = ((sp - accumulate_size) & ~7) + CALL_DUMMY_STACK_ADJUST;
> @@ -2186,6 +2193,9 @@ sparc_fix_call_dummy (char *dummy, CORE_
>       which follows the call instruction.
>       For details see the SPARC Architecture Manual Version 8, Appendix D.3.
> 
> +     This does not happen on V9/ARCH64, such structure returns are passed
> +     by reference.
> +
>       Adjust the call_dummy_breakpoint_offset for the bp_call_dummy breakpoint
>       to the proper address in the call dummy, so that `finish' after a stop
>       in a call dummy works.
> @@ -2303,131 +2313,578 @@ sparc64_write_sp (CORE_ADDR val)
>      write_register (SP_REGNUM, val);
>  }
> 
> -/* The SPARC 64 ABI passes floating-point arguments in FP0 to FP31,
> -   and all other arguments in O0 to O5.  They are also copied onto
> -   the stack in the correct places.  Apparently (empirically),
> -   structs of less than 16 bytes are passed member-by-member in
> -   separate registers, but I am unable to figure out the algorithm.
> -   Some members go in floating point regs, but I don't know which.
> -
> -   FIXME: Handle small structs (less than 16 bytes containing floats).
> -
> -   The counting regimen for using both integer and FP registers
> -   for argument passing is rather odd -- a single counter is used
> -   for both; this means that if the arguments alternate between
> -   int and float, we will waste every other register of both types.  */
> +/* This is basically extracted from the Sparc backend of GCC.
> +   All errors introduced along the way are mine. -DaveM  */
> +
> +#define SPARC_INT_ARG_MAX      6
> +#define SPARC_FP_ARG_MAX       16
> +
> +#define INTEGER_P(TYPE)        \
> +       ((TYPE) == TYPE_CODE_INT || (TYPE) == TYPE_CODE_BOOL \
> +        || (TYPE) == TYPE_CODE_CHAR || (TYPE) == TYPE_CODE_RANGE \
> +        || (TYPE) == TYPE_CODE_ENUM || (TYPE) == TYPE_CODE_PTR \
> +        || (TYPE) == TYPE_CODE_REF)
> +
> +static int
> +sp64_compute_arg_slotno (int words, int *ppadding, int *pregno,
> +                        struct value *val, enum type_code type, int len)
> + {
> +  int regbase = O0_REGNUM;
> +  int slotno = words;
> +  int regno;
> +
> +  *ppadding = 0;
> +
> +  switch (type)
> +    {
> +    case TYPE_CODE_UNDEF:
> +    case TYPE_CODE_ARRAY:
> +    case TYPE_CODE_FUNC:
> +    case TYPE_CODE_VOID:
> +    case TYPE_CODE_ERROR:
> +    case TYPE_CODE_MEMBER:
> +    case TYPE_CODE_METHOD:
> +    case TYPE_CODE_SET:
> +    case TYPE_CODE_STRING:
> +    case TYPE_CODE_BITSTRING:
> +    case TYPE_CODE_TYPEDEF:
> +    case TYPE_CODE_TEMPLATE:
> +    case TYPE_CODE_TEMPLATE_ARG:
> +      /* If we see any of these, just bail... */
> +      error ("Type cannot be pushed into argument slot by GDB target code.\n");
> +
> +    default:
> +      break;
> +    };
> +
> +  if (INTEGER_P (type))
> +    {
> +      if (slotno >= SPARC_INT_ARG_MAX)
> +       {
> +         return -1;
> +       }
> +      regno = regbase + slotno;
> +    }
> +  else if (type == TYPE_CODE_FLT
> +          || type == TYPE_CODE_COMPLEX)
> +    {
> +      if (len == 16)
> +       {
> +         /* TFmode value.  */
> +         gdb_assert(SPARC_TARGET_LONG_DOUBLE_BYTES == 16
> +                    || type == TYPE_CODE_COMPLEX);
> +         if ((slotno & 1) != 0)
> +           {
> +             slotno++;
> +             *ppadding = 1;
> +           }
> +       }
> +      if (SPARC_HAS_FPU)
> +       {
> +         if (slotno >= SPARC_FP_ARG_MAX)
> +           {
> +             return -1;
> +           }
> +         regno = FP0_REGNUM + slotno * 2;
> +         if (len == 4)
> +           {
> +             /* SFmode value.  */
> +             regno++;
> +           }
> +       }
> +      else
> +       {
> +         /* Passed in integer registers, if possible.  */
> +         if (slotno >= SPARC_INT_ARG_MAX)
> +           {
> +             return -1;
> +           }
> +         regno = regbase + slotno;
> +       }
> +    }
> +  else
> +    {
> +      /* A structure or a union. */
> +
> +      /* ??? No way to get at required alignment of types.
> +        ??? We are supposed to give 16byte alignment to types
> +        ??? that require it (via attribute((align)) or similar)
> +        ??? but GDB appears to have no way to get at that information
> +        ??? currently.  */
> +#if 0
> +      if (TYPE_ALIGN (VALUE_TYPE (val)) == 128
> +         && (slotno & 1) != 0)
> +       {
> +         slotno++;
> +         *ppadding = 1;
> +       }
> +#endif
> +
> +      if (type == TYPE_CODE_UNION
> +         || len > 16)
> +       {
> +         if (slotno >= SPARC_INT_ARG_MAX)
> +           {
> +             return -1;
> +           }
> +         regno = regbase + slotno;
> +       }
> +      else
> +       {
> +         struct type *tp = VALUE_TYPE (val);
> +         int intregs_p = 0, fpregs_p = 0;
> +         int packed_p = 0;
> +         int field;
> +
> +         gdb_assert (type == TYPE_CODE_STRUCT);
> +
> +         for (field = 0; field < tp->nfields; field++)
> +           {
> +             struct field *fp = &tp->fields[field];
> +
> +             if ((TYPE_CODE (fp->type) == TYPE_CODE_FLT
> +                  || TYPE_CODE (fp->type) == TYPE_CODE_COMPLEX)
> +                 && SPARC_HAS_FPU)
> +               fpregs_p = 1;
> +             else
> +               intregs_p = 1;
> +
> +             /* ??? No way to get at this currently...  */
> +#if 0
> +             if (TYPE_PACKED (fp->type))
> +               packed_p = 1;
> +#endif
> +           }
> +
> +         if (packed_p)
> +           {
> +             fpregs_p = 0;
> +             intregs_p = 1;
> +           }
> +
> +         if (fpregs_p && slotno >= SPARC_FP_ARG_MAX)
> +           {
> +             return -1;
> +           }
> +
> +         if (!fpregs_p && intregs_p && slotno >= SPARC_INT_ARG_MAX)
> +           {
> +             return -1;
> +           }
> +
> +         return slotno;
> +       }
> +    }
> +
> +  *pregno = regno;
> +  return slotno;
> +}
> +
> +static void
> +sp64_arg_advance (int *p_arg_words, struct value *val)
> +{
> +  enum type_code type = TYPE_CODE (VALUE_TYPE (val));
> +  int len = TYPE_LENGTH (check_typedef (VALUE_TYPE (val)));
> +  int slotno, regno, padding;
> +
> +  slotno = sp64_compute_arg_slotno (*p_arg_words, &padding, &regno,
> +                                   val, type, len);
> +
> +  if (slotno != -1)
> +    *p_arg_words += padding;
> +
> +  if (type == TYPE_CODE_UNION
> +      || type == TYPE_CODE_STRUCT)
> +    {
> +      gdb_assert (len <= 16);
> +
> +      if (len <= 8)
> +       *p_arg_words += 1;
> +      else if (len <= 16)
> +       *p_arg_words += 2;
> +    }
> +#if 0 /* ??? How to do this */
> +  else if (type == TYPE_CODE_COMPLEX_INT)
> +    {
> +      *p_arg_words += 2;
> +    }
> +  else if (type == TYPE_CODE_COMPLEX_FLOAT)
> +    {
> +      *p_arg_words += len / SPARC_INTREG_SIZE;
> +    }
> +#endif
> +  else
> +    {
> +      *p_arg_words += ((len + (SPARC_INTREG_SIZE - 1))
> +                      / SPARC_INTREG_SIZE);
> +    }
> +}
> +
> +static void
> +sp64_compute_arg_stack_space (int *p_arg_words,
> +                             int nargs, struct value **args, int struct_return)
> +{
> +  int i;
> +
> +  *p_arg_words = 0;
> +
> +  /* This is true if USING_STRUCT_CONVENTION, in which case the function
> +     is returning a structure larger than 32 bytes and causes the first
> +     argument slot to be a pointer to the allocated space for it.  */
> +  if (struct_return)
> +    *p_arg_words += 1;
> +
> +  for (i = 0; i < nargs; i++)
> +    {
> +      struct value *val = args[i];
> +
> +      sp64_arg_advance (p_arg_words, val);
> +    }
> +}
> +
> +struct sp64_struct_regs_state
> +{
> +  int slotno;
> +  unsigned int nregs;
> +  int intoffset;
> +};
> +
> +static void
> +sp64_struct_regs_analyze (struct type *tp,
> +                         struct sp64_struct_regs_state *statep)
> +{
> +  int field;
> +
> +  for (field = 0; field < tp->nfields; field++)
> +    {
> +      struct field *fp = &tp->fields[field];
> +      int bitpos = fp->loc.bitpos;
> +      int this_len = TYPE_LENGTH (check_typedef (fp->type));
> +
> +      if (this_len == 0)
> +       bitpos = 0;
> +
> +      if (TYPE_CODE (fp->type) == TYPE_CODE_STRUCT)
> +       sp64_struct_regs_analyze (fp->type, statep);
> +      else if ((TYPE_CODE (fp->type) == TYPE_CODE_FLT
> +               || TYPE_CODE (fp->type) == TYPE_CODE_COMPLEX)
> +              && SPARC_HAS_FPU)
> +       {
> +         if (statep->intoffset != -1)
> +           {
> +             int intslots, this_slotno;
> +             int bits_per_word = SPARC_INTREG_SIZE * 8;
> +
> +             intslots = (bitpos - statep->intoffset + (bits_per_word - 1))
> +               / bits_per_word;
> +             this_slotno = statep->slotno
> +               + (statep->intoffset / bits_per_word);
> +
> +             if (SPARC_INT_ARG_MAX - this_slotno < intslots)
> +               intslots = SPARC_INT_ARG_MAX - this_slotno;
> +             if (intslots < 0)
> +               intslots = 0;
> +             statep->nregs += intslots;
> +             statep->intoffset = -1;
> +           }
> +
> +         statep->nregs += 1;
> +         if (TYPE_CODE (fp->type) == TYPE_CODE_COMPLEX)
> +           statep->nregs += 1;
> +       }
> +      else
> +       {
> +         if (statep->intoffset == -1)
> +           statep->intoffset = bitpos;
> +       }
> +    }
> +}
> +
> +static void
> +sp64_do_struct_regs_3 (struct value *val, int bitpos,
> +                      struct sp64_struct_regs_state *statep)
> +{
> +  int regno, startbit, endbit, this_slotno, intslots, intoffset;
> +  int bits_per_word = (SPARC_INTREG_SIZE * 8);
> +  char *zero_buf;
> +
> +  if (statep->intoffset == -1)
> +    return;
> +
> +  intoffset = statep->intoffset;
> +  statep->intoffset = -1;
> +
> +  startbit = intoffset & -bits_per_word;
> +  endbit = (bitpos + (bits_per_word - 1)) & -bits_per_word;
> +  intslots = (endbit - startbit) / bits_per_word;
> +  this_slotno = statep->slotno + (intoffset / bits_per_word);
> +
> +  if (SPARC_INT_ARG_MAX - this_slotno < intslots)
> +    intslots = SPARC_INT_ARG_MAX - this_slotno;
> +  if (intslots <= 0)
> +    return;
> +
> +  zero_buf = alloca(SPARC_INTREG_SIZE);
> +  memset (zero_buf, 0, sizeof (zero_buf));
> +
> +  intoffset /= 8;
> +  do
> +    {
> +      regno = O0_REGNUM + this_slotno;
> +
> +      if (intoffset % SPARC_INTREG_SIZE)
> +       {
> +         write_register_gen (regno, zero_buf);
> +         write_register_bytes (REGISTER_BYTE (regno)
> +                               + (intoffset % SPARC_INTREG_SIZE),
> +                               VALUE_CONTENTS (val) + intoffset,
> +                               SPARC_INTREG_SIZE
> +                               - (intoffset % SPARC_INTREG_SIZE));
> +       }
> +      else
> +       {
> +         write_register_gen (regno, VALUE_CONTENTS (val) + intoffset);
> +       }
> +
> +      this_slotno += 1;
> +      intoffset = (intoffset | (SPARC_INTREG_SIZE - 1)) + 1;
> +      statep->nregs += 1;
> +      intslots -= 1;
> +    }
> +  while (intslots > 0);
> +}
> +
> +static void
> +sp64_do_struct_regs_2 (struct value *val, struct type *tp,
> +                      struct sp64_struct_regs_state *statep)
> +{
> +  int field;
> +
> +  for (field = 0; field < tp->nfields; field++)
> +    {
> +      struct field *fp = &tp->fields[field];
> +      int bitpos = fp->loc.bitpos;
> +      int this_len = TYPE_LENGTH (check_typedef (fp->type));
> +
> +      if (this_len == 0)
> +       bitpos = 0;
> +
> +      if (TYPE_CODE (fp->type) == TYPE_CODE_STRUCT)
> +       sp64_do_struct_regs_2 (val, fp->type, statep);
> +      else if ((TYPE_CODE (fp->type) == TYPE_CODE_FLT
> +               || TYPE_CODE (fp->type) == TYPE_CODE_COMPLEX)
> +              && SPARC_HAS_FPU)
> +       {
> +         int bits_per_word = SPARC_INTREG_SIZE * 8;
> +         int this_slotno = statep->slotno + (bitpos / bits_per_word);
> +         int this_typelen = TYPE_LENGTH (check_typedef (fp->type));
> +         int regno;
> +
> +         sp64_do_struct_regs_3 (val, bitpos, statep);
> +         regno = FP0_REGNUM + this_slotno * 2
> +           + (this_typelen == 4 && (bitpos & 32) != 0);
> +
> +         write_register_bytes (REGISTER_BYTE (regno),
> +                               VALUE_CONTENTS (val) + (bitpos / 8),
> +                               this_typelen);
> +         statep->nregs += 1;
> +         if (TYPE_CODE (fp->type) == TYPE_CODE_COMPLEX)
> +           statep->nregs += 1;
> +       }
> +      else
> +       {
> +         if (statep->intoffset == -1)
> +           statep->intoffset = bitpos;
> +       }
> +    }
> +}
> +
> +static void
> +sp64_push_one_struct_regs (int slotno,
> +                          struct value *val, enum type_code type, int len)
> +{
> +  struct sp64_struct_regs_state state;
> +  int nregs;
> +
> +  state.slotno = slotno;
> +
> +  state.nregs = 0;
> +  state.intoffset = 0;
> +  sp64_struct_regs_analyze (VALUE_TYPE (val), &state);
> +
> +  if (state.intoffset != -1)
> +    {
> +      unsigned int startbit, endbit;
> +      int intslots, this_slotno;
> +      int bits_per_word;
> +
> +      bits_per_word = SPARC_INTREG_SIZE * 8;
> +
> +      startbit = state.intoffset & -bits_per_word;
> +      endbit = (len * 8 + (bits_per_word - 1)) & -bits_per_word;
> +      intslots = (endbit - startbit) / bits_per_word;
> +      this_slotno = slotno + state.intoffset / bits_per_word;
> +
> +      if (SPARC_INT_ARG_MAX - this_slotno < intslots)
> +       intslots = SPARC_INT_ARG_MAX - this_slotno;
> +      if (intslots < 0)
> +       intslots = 0;
> +
> +      state.nregs += intslots;
> +    }
> +  nregs = state.nregs;
> +
> +  if (nregs == 0)
> +    {
> +      /* Nothing can actually go in the registers, oh well...  */
> +      return;
> +    }
> +
> +  state.nregs = 0;
> +  state.intoffset = 0;
> +  sp64_do_struct_regs_2 (val, VALUE_TYPE (val), &state);
> +  sp64_do_struct_regs_3 (val, len * 8, &state);
> +  gdb_assert (state.nregs == nregs);
> +}
> +
> +static void
> +sp64_push_one_arg (CORE_ADDR *sp, CORE_ADDR args_base,
> +                  struct value *val, enum type_code type, int len)
> +{
> +  int cur_word = (*sp - args_base) / SPARC_INTREG_SIZE;
> +  int slotno, padding, regno, dummy;
> +  int orig_cur_word;
> +
> +  slotno = sp64_compute_arg_slotno (cur_word, &padding, &regno,
> +                                   val, type, len);
> +
> +  /* If integral, it may need promotion.  */
> +  if (INTEGER_P (type)
> +      && len < SPARC_INTREG_SIZE)
> +    {
> +      struct type *sparc_intreg_type =
> +       TYPE_LENGTH (builtin_type_long) == SPARC_INTREG_SIZE ?
> +       builtin_type_long : builtin_type_long_long;
> +
> +      val = value_cast (sparc_intreg_type, val);
> +      len = SPARC_INTREG_SIZE;
> +    }
> +
> +  if (slotno == -1)
> +    {
> +      /* Purely in memory on the stack  */
> +      write_memory (*sp, VALUE_CONTENTS (val), len);
> +      goto advance;
> +    }
> +
> +  if ((type == TYPE_CODE_FLT
> +       || type == TYPE_CODE_COMPLEX)
> +      && (regno >= FP0_REGNUM && regno < FP_MAX_REGNUM))
> +    {
> +      /* We copy the value onto the stack always even though
> +        in some cases the v9 ABI allows that to be optimized
> +        away.  */
> +      write_memory (*sp, VALUE_CONTENTS (val), len);
> +      write_register_bytes (REGISTER_BYTE (regno),
> +                           VALUE_CONTENTS (val),
> +                           len);
> +
> +      /* If this is one of the first 6 argument slots, we also copy
> +        to the integer register of the same slot to handle varargs
> +        properly.  */
> +      if ((regno - FP0_REGNUM) < SPARC_INT_ARG_MAX * 2)
> +       {
> +         int intreg = O0_REGNUM + (regno - FP0_REGNUM) / 2;
> +
> +         write_register_bytes (REGISTER_BYTE (intreg),
> +                               VALUE_CONTENTS (val),
> +                               len);
> +       }
> +    }
> +  else if (type == TYPE_CODE_STRUCT
> +          || type == TYPE_CODE_UNION)
> +    {
> +      /* Pass by reference of large structs is handled entirely in
> +        valops.c via REG_STRUCT_HAS_ADDR.  */
> +      gdb_assert (len <= 16);
> +
> +      /* On the stack, but partially in registers too.  */
> +      write_memory (*sp, VALUE_CONTENTS (val), len);
> +      if (type == TYPE_CODE_UNION)
> +       {
> +         /* Simplest case.  */
> +         write_register_bytes (REGISTER_BYTE (regno),
> +                               VALUE_CONTENTS (val),
> +                               len);
> +       }
> +      else
> +       {
> +         /* Complex case :( */
> +         sp64_push_one_struct_regs (slotno, val, type, len);
> +       }
> +    }
> +  else
> +    {
> +      struct value *copyval = val;
> +      int copylen = len;
> +
> +      write_memory (*sp, VALUE_CONTENTS (val), len);
> +      write_register_bytes (REGISTER_BYTE (regno),
> +                           VALUE_CONTENTS (val),
> +                           len);
> +    }
> +
> + advance:
> +  orig_cur_word = cur_word;
> +  sp64_arg_advance (&cur_word, val);
> +  *sp += ((cur_word - orig_cur_word) * SPARC_INTREG_SIZE);
> +}
> 
>  CORE_ADDR
>  sparc64_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
>                         int struct_return, CORE_ADDR struct_retaddr)
>  {
> -  int i, j, register_counter = 0;
> -  CORE_ADDR tempsp;
> +  int i, j;
> +  CORE_ADDR tempsp, struct_buf_sp;
>    struct type *sparc_intreg_type =
>      TYPE_LENGTH (builtin_type_long) == SPARC_INTREG_SIZE ?
>      builtin_type_long : builtin_type_long_long;
> +  int arg_words;
> 
>    sp = (sp & ~(((unsigned long) SPARC_INTREG_SIZE) - 1UL));
> 
>    /* Figure out how much space we'll need. */
> -  for (i = nargs - 1; i >= 0; i--)
> -    {
> -      int len = TYPE_LENGTH (check_typedef (VALUE_TYPE (args[i])));
> -      struct value *copyarg = args[i];
> -      int copylen = len;
> +  sp64_compute_arg_stack_space(&arg_words, nargs, args, struct_return);
> 
> -      if (copylen < SPARC_INTREG_SIZE)
> -       {
> -         copyarg = value_cast (sparc_intreg_type, copyarg);
> -         copylen = SPARC_INTREG_SIZE;
> -       }
> -      sp -= copylen;
> -    }
> +  /* Make room for at least 6 integer arguments for the sake of
> +     varargs.  Otherwise a varargs function, once called via
> +     a CALL_DUMMY, can write over other parts of the stack.  */
> +  if (arg_words < 6)
> +    arg_words = 6;
> 
> -  /* Round down. */
> -  sp = sp & ~7;
> +  sp -= arg_words * SPARC_INTREG_SIZE;
>    tempsp = sp;
> 
>    /* if STRUCT_RETURN, then first argument is the struct return location. */
>    if (struct_return)
> -    write_register (O0_REGNUM + register_counter++, struct_retaddr);
> +    {
> +      write_register (O0_REGNUM, struct_retaddr);
> +      write_memory (tempsp, (char *) &struct_retaddr, SPARC_INTREG_SIZE);
> 
> -  /* Now write the arguments onto the stack, while writing FP
> -     arguments into the FP registers, and other arguments into the
> -     first six 'O' registers.  */
> +      tempsp += SPARC_INTREG_SIZE;
> +    }
> 
> +  /* now actually push the arguments */
>    for (i = 0; i < nargs; i++)
>      {
> -      int len = TYPE_LENGTH (check_typedef (VALUE_TYPE (args[i])));
> -      struct value *copyarg = args[i];
> -      enum type_code typecode = TYPE_CODE (VALUE_TYPE (args[i]));
> -      int copylen = len;
> -
> -      if (typecode == TYPE_CODE_INT   ||
> -         typecode == TYPE_CODE_BOOL  ||
> -         typecode == TYPE_CODE_CHAR  ||
> -         typecode == TYPE_CODE_RANGE ||
> -         typecode == TYPE_CODE_ENUM)
> -       if (len < SPARC_INTREG_SIZE)
> -         {
> -           /* Small ints will all take up the size of one intreg on
> -              the stack.  */
> -           copyarg = value_cast (sparc_intreg_type, copyarg);
> -           copylen = SPARC_INTREG_SIZE;
> -         }
> -
> -      write_memory (tempsp, VALUE_CONTENTS (copyarg), copylen);
> -      tempsp += copylen;
> -
> -      /* Corner case: Structs consisting of a single float member are floats.
> -       * FIXME!  I don't know about structs containing multiple floats!
> -       * Structs containing mixed floats and ints are even more weird.
> -       */
> -
> +      struct value *val = args[i];
> +      enum type_code type = TYPE_CODE (VALUE_TYPE (val));
> +      int len = TYPE_LENGTH (check_typedef (VALUE_TYPE (val)));
> 
> -
> -      /* Separate float args from all other args.  */
> -      if (typecode == TYPE_CODE_FLT && SPARC_HAS_FPU)
> -       {
> -         if (register_counter < 16)
> -           {
> -             /* This arg gets copied into a FP register. */
> -             int fpreg;
> -
> -             switch (len) {
> -             case 4:   /* Single-precision (float) */
> -               fpreg = FP0_REGNUM + 2 * register_counter + 1;
> -               register_counter += 1;
> -               break;
> -             case 8:   /* Double-precision (double) */
> -               fpreg = FP0_REGNUM + 2 * register_counter;
> -               register_counter += 1;
> -               break;
> -             case 16:  /* Quad-precision (long double) */
> -               fpreg = FP0_REGNUM + 2 * register_counter;
> -               register_counter += 2;
> -               break;
> -             default:
> -               internal_error (__FILE__, __LINE__, "bad switch");
> -             }
> -             write_register_bytes (REGISTER_BYTE (fpreg),
> -                                   VALUE_CONTENTS (args[i]),
> -                                   len);
> -           }
> -       }
> -      else /* all other args go into the first six 'o' registers */
> -        {
> -          for (j = 0;
> -              j < len && register_counter < 6;
> -              j += SPARC_INTREG_SIZE)
> -           {
> -             int oreg = O0_REGNUM + register_counter;
> -
> -             write_register_gen (oreg, VALUE_CONTENTS (copyarg) + j);
> -             register_counter += 1;
> -           }
> -        }
> +      sp64_push_one_arg (&tempsp, sp,
> +                        val, type, len);
>      }
> +
>    return sp;
>  }
> 
> @@ -2441,7 +2898,9 @@ sp64_extract_return_value (struct type *
>    int typelen = TYPE_LENGTH (type);
>    int regsize = REGISTER_RAW_SIZE (O0_REGNUM);
> 
> -  if (TYPE_CODE (type) == TYPE_CODE_FLT && SPARC_HAS_FPU)
> +  if ((TYPE_CODE (type) == TYPE_CODE_FLT
> +       || TYPE_CODE (type) == TYPE_CODE_COMPLEX)
> +      && SPARC_HAS_FPU)
>      {
>        memcpy (valbuf, &regbuf[REGISTER_BYTE (FP0_REGNUM)], typelen);
>        return;


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