Index: arm-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/arm-tdep.c,v
retrieving revision 1.82
diff -p -p -r1.82 arm-tdep.c
*** arm-tdep.c	11 Dec 2002 02:26:34 -0000	1.82
--- arm-tdep.c	14 Dec 2002 10:30:14 -0000
*************** static void set_disassembly_flavor_sfunc
*** 131,137 ****
  					 struct cmd_list_element *);
  static void set_disassembly_flavor (void);
  
! static void convert_from_extended (void *ptr, void *dbl);
  
  /* Define other aspects of the stack frame.  We keep the offsets of
     all saved registers, 'cause we need 'em a lot!  We also keep the
--- 131,140 ----
  					 struct cmd_list_element *);
  static void set_disassembly_flavor (void);
  
! static void convert_from_extended (const struct floatformat *, const void *,
! 				   void *);
! static void convert_to_extended (const struct floatformat *, void *,
! 				 const void *);
  
  /* Define other aspects of the stack frame.  We keep the offsets of
     all saved registers, 'cause we need 'em a lot!  We also keep the
*************** arm_register_sim_regno (int regnum)
*** 1664,1670 ****
     little-endian systems.  */
  
  static void
! convert_from_extended (void *ptr, void *dbl)
  {
    DOUBLEST d;
    if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
--- 1667,1674 ----
     little-endian systems.  */
  
  static void
! convert_from_extended (const struct floatformat *fmt, const void *ptr,
! 		       void *dbl)
  {
    DOUBLEST d;
    if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
*************** convert_from_extended (void *ptr, void *
*** 1672,1685 ****
    else
      floatformat_to_doublest (&floatformat_arm_ext_littlebyte_bigword,
  			     ptr, &d);
!   floatformat_from_doublest (TARGET_DOUBLE_FORMAT, &d, dbl);
  }
  
  static void
! convert_to_extended (void *dbl, void *ptr)
  {
    DOUBLEST d;
!   floatformat_to_doublest (TARGET_DOUBLE_FORMAT, ptr, &d);
    if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
      floatformat_from_doublest (&floatformat_arm_ext_big, &d, dbl);
    else
--- 1676,1689 ----
    else
      floatformat_to_doublest (&floatformat_arm_ext_littlebyte_bigword,
  			     ptr, &d);
!   floatformat_from_doublest (fmt, &d, dbl);
  }
  
  static void
! convert_to_extended (const struct floatformat *fmt, void *dbl, const void *ptr)
  {
    DOUBLEST d;
!   floatformat_to_doublest (fmt, ptr, &d);
    if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
      floatformat_from_doublest (&floatformat_arm_ext_big, &d, dbl);
    else
*************** arm_breakpoint_from_pc (CORE_ADDR *pcptr
*** 2217,2225 ****
  
  static void
  arm_extract_return_value (struct type *type,
! 			  char regbuf[REGISTER_BYTES],
! 			  char *valbuf)
  {
    if (TYPE_CODE_FLT == TYPE_CODE (type))
      {
        struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
--- 2221,2231 ----
  
  static void
  arm_extract_return_value (struct type *type,
! 			  struct regcache *regs,
! 			  void *dst)
  {
+   bfd_byte *valbuf = dst;
+ 
    if (TYPE_CODE_FLT == TYPE_CODE (type))
      {
        struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
*************** arm_extract_return_value (struct type *t
*** 2227,2240 ****
        switch (tdep->fp_model)
  	{
  	case ARM_FLOAT_FPA:
! 	  convert_from_extended (&regbuf[REGISTER_BYTE (ARM_F0_REGNUM)],
! 				 valbuf);
  	  break;
  
  	case ARM_FLOAT_SOFT:
  	case ARM_FLOAT_SOFT_VFP:
! 	  memcpy (valbuf, &regbuf[REGISTER_BYTE (ARM_A1_REGNUM)],
! 		  TYPE_LENGTH (type));
  	  break;
  
  	default:
--- 2233,2256 ----
        switch (tdep->fp_model)
  	{
  	case ARM_FLOAT_FPA:
! 	  {
! 	    /* The value is in register F0 in internal format.  We need to
! 	       extract the raw value and then convert it to the desired
! 	       internal type.  */
! 	    bfd_byte tmpbuf[FP_REGISTER_RAW_SIZE];
! 
! 	    regcache_cooked_read (regs, ARM_F0_REGNUM, tmpbuf);
! 	    convert_from_extended (floatformat_from_type (type), tmpbuf,
! 				   valbuf);
! 	  }
  	  break;
  
  	case ARM_FLOAT_SOFT:
  	case ARM_FLOAT_SOFT_VFP:
! 	  regcache_cooked_read (regs, ARM_A1_REGNUM, valbuf);
! 	  if (TYPE_LENGTH (type) > 4)
! 	    regcache_cooked_read (regs, ARM_A1_REGNUM + 1,
! 				  valbuf + INT_REGISTER_RAW_SIZE);
  	  break;
  
  	default:
*************** arm_extract_return_value (struct type *t
*** 2244,2252 ****
  	  break;
  	}
      }
    else
!     memcpy (valbuf, &regbuf[REGISTER_BYTE (ARM_A1_REGNUM)],
! 	    TYPE_LENGTH (type));
  }
  
  /* Extract from an array REGBUF containing the (raw) register state
--- 2260,2309 ----
  	  break;
  	}
      }
+   else if (TYPE_CODE (type) == TYPE_CODE_INT
+ 	   || TYPE_CODE (type) == TYPE_CODE_CHAR
+ 	   || TYPE_CODE (type) == TYPE_CODE_BOOL
+ 	   || TYPE_CODE (type) == TYPE_CODE_PTR
+ 	   || TYPE_CODE (type) == TYPE_CODE_REF
+ 	   || TYPE_CODE (type) == TYPE_CODE_ENUM)
+     {
+       /* If the the type is a plain integer, then the access is
+ 	 straight-forward.  Otherwise we have to play around a bit more.  */
+       int len = TYPE_LENGTH (type);
+       int regno = ARM_A1_REGNUM;
+       ULONGEST tmp;
+ 
+       while (len > 0)
+ 	{
+ 	  /* By using store_unsigned_integer we avoid having to do
+ 	     anything special for small big-endian values.  */
+ 	  regcache_cooked_read_unsigned (regs, regno++, &tmp);
+ 	  store_unsigned_integer (valbuf, 
+ 				  (len > INT_REGISTER_RAW_SIZE
+ 				   ? INT_REGISTER_RAW_SIZE : len),
+ 				  tmp);
+ 	  len -= INT_REGISTER_RAW_SIZE;
+ 	  valbuf += INT_REGISTER_RAW_SIZE;
+ 	}
+     }
    else
!     {
!       /* For a structure or union the behaviour is as if the value had
!          been stored to word-aligned memory and then loaded into 
!          registers with 32-bit load instruction(s).  */
!       int len = TYPE_LENGTH (type);
!       int regno = ARM_A1_REGNUM;
!       bfd_byte tmpbuf[INT_REGISTER_RAW_SIZE];
! 
!       while (len > 0)
! 	{
! 	  regcache_cooked_read (regs, regno++, tmpbuf);
! 	  memcpy (valbuf, tmpbuf,
! 		  len > INT_REGISTER_RAW_SIZE ? INT_REGISTER_RAW_SIZE : len);
! 	  len -= INT_REGISTER_RAW_SIZE;
! 	  valbuf += INT_REGISTER_RAW_SIZE;
! 	}
!     }
  }
  
  /* Extract from an array REGBUF containing the (raw) register state
*************** arm_use_struct_convention (int gcc_p, st
*** 2359,2366 ****
     TYPE, given in virtual format.  */
  
  static void
! arm_store_return_value (struct type *type, char *valbuf)
  {
    if (TYPE_CODE (type) == TYPE_CODE_FLT)
      {
        struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
--- 2416,2426 ----
     TYPE, given in virtual format.  */
  
  static void
! arm_store_return_value (struct type *type, struct regcache *regs,
! 			const void *src)
  {
+   const bfd_byte *valbuf = src;
+ 
    if (TYPE_CODE (type) == TYPE_CODE_FLT)
      {
        struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
*************** arm_store_return_value (struct type *typ
*** 2370,2384 ****
  	{
  	case ARM_FLOAT_FPA:
  
! 	  convert_to_extended (valbuf, buf);
! 	  deprecated_write_register_bytes (REGISTER_BYTE (ARM_F0_REGNUM), buf,
! 					   FP_REGISTER_RAW_SIZE);
  	  break;
  
  	case ARM_FLOAT_SOFT:
  	case ARM_FLOAT_SOFT_VFP:
! 	  deprecated_write_register_bytes (ARM_A1_REGNUM, valbuf,
! 					   TYPE_LENGTH (type));
  	  break;
  
  	default:
--- 2430,2445 ----
  	{
  	case ARM_FLOAT_FPA:
  
! 	  convert_to_extended (floatformat_from_type (type), buf, valbuf);
! 	  regcache_cooked_write (regs, ARM_F0_REGNUM, buf);
  	  break;
  
  	case ARM_FLOAT_SOFT:
  	case ARM_FLOAT_SOFT_VFP:
! 	  regcache_cooked_write (regs, ARM_A1_REGNUM, valbuf);
! 	  if (TYPE_LENGTH (type) > 4)
! 	    regcache_cooked_write (regs, ARM_A1_REGNUM + 1, 
! 				   valbuf + INT_REGISTER_RAW_SIZE);
  	  break;
  
  	default:
*************** arm_store_return_value (struct type *typ
*** 2388,2396 ****
  	  break;
  	}
      }
    else
!     deprecated_write_register_bytes (ARM_A1_REGNUM, valbuf,
! 				     TYPE_LENGTH (type));
  }
  
  /* Store the address of the place in which to copy the structure the
--- 2449,2505 ----
  	  break;
  	}
      }
+   else if (TYPE_CODE (type) == TYPE_CODE_INT
+ 	   || TYPE_CODE (type) == TYPE_CODE_CHAR
+ 	   || TYPE_CODE (type) == TYPE_CODE_BOOL
+ 	   || TYPE_CODE (type) == TYPE_CODE_PTR
+ 	   || TYPE_CODE (type) == TYPE_CODE_REF
+ 	   || TYPE_CODE (type) == TYPE_CODE_ENUM)
+     {
+       if (TYPE_LENGTH (type) <= 4)
+ 	{
+ 	  /* Values of one word or less are zero/sign-extended and
+ 	     returned in r0.  */
+ 	  bfd_byte tmpbuf[INT_REGISTER_RAW_SIZE];
+ 	  LONGEST val = unpack_long (type, valbuf);
+ 
+ 	  store_signed_integer (tmpbuf, INT_REGISTER_RAW_SIZE, val);
+ 	  regcache_cooked_write (regs, ARM_A1_REGNUM, tmpbuf);
+ 	}
+       else
+ 	{
+ 	  /* Integral values greater than one word are stored in consecutive
+ 	     registers starting with r0.  This will always be a multiple of
+ 	     the regiser size.  */
+ 	  int len = TYPE_LENGTH (type);
+ 	  int regno = ARM_A1_REGNUM;
+ 
+ 	  while (len > 0)
+ 	    {
+ 	      regcache_cooked_write (regs, regno++, valbuf);
+ 	      len -= INT_REGISTER_RAW_SIZE;
+ 	      valbuf += INT_REGISTER_RAW_SIZE;
+ 	    }
+ 	}
+     }
    else
!     {
!       /* For a structure or union the behaviour is as if the value had
!          been stored to word-aligned memory and then loaded into 
!          registers with 32-bit load instruction(s).  */
!       int len = TYPE_LENGTH (type);
!       int regno = ARM_A1_REGNUM;
!       bfd_byte tmpbuf[INT_REGISTER_RAW_SIZE];
! 
!       while (len > 0)
! 	{
! 	  memcpy (tmpbuf, valbuf,
! 		  len > INT_REGISTER_RAW_SIZE ? INT_REGISTER_RAW_SIZE : len);
! 	  regcache_cooked_write (regs, regno++, tmpbuf);
! 	  len -= INT_REGISTER_RAW_SIZE;
! 	  valbuf += INT_REGISTER_RAW_SIZE;
! 	}
!     }
  }
  
  /* Store the address of the place in which to copy the structure the
*************** arm_gdbarch_init (struct gdbarch_info in
*** 2869,2876 ****
    set_gdbarch_register_name (gdbarch, arm_register_name);
  
    /* Returning results.  */
!   set_gdbarch_deprecated_extract_return_value (gdbarch, arm_extract_return_value);
!   set_gdbarch_deprecated_store_return_value (gdbarch, arm_store_return_value);
    set_gdbarch_store_struct_return (gdbarch, arm_store_struct_return);
    set_gdbarch_use_struct_convention (gdbarch, arm_use_struct_convention);
    set_gdbarch_extract_struct_value_address (gdbarch,
--- 2978,2985 ----
    set_gdbarch_register_name (gdbarch, arm_register_name);
  
    /* Returning results.  */
!   set_gdbarch_extract_return_value (gdbarch, arm_extract_return_value);
!   set_gdbarch_store_return_value (gdbarch, arm_store_return_value);
    set_gdbarch_store_struct_return (gdbarch, arm_store_struct_return);
    set_gdbarch_use_struct_convention (gdbarch, arm_use_struct_convention);
    set_gdbarch_extract_struct_value_address (gdbarch,
