[PATCH/RFA] Generic OS ABI handling for PowerPC

Jason R Thorpe thorpej@wasabisystems.com
Tue May 28 12:41:00 GMT 2002


This makes the PowerPC/RS6000 target use the generic OS ABI framework,
and also moves some SVR4 ABI stuff out of ppc-linux-tdep.c into
rs6000-tdep.c.

OK to commit?

	* Makefile.in (ppc_tdep_h): Define.
	(ppc-linux-nat.o, ppc-linux-tdep.o, rs6000-tdep.o): Use $(ppc_tdep_h).
	* ppc-tdep.h: Use generic OS ABI framework.
	* ppc-linux-tdep.c (_initialize_ppc_linux_tdep,
	ppc_linux_init_abi): New functions.
	(ppc_sysv_abi_broken_use_struct_convention,
	ppc_sysv_abi_use_struct_convention,
	ppc_sysv_abi_push_arguments): Move to...
	* rs6000-tdep.c: ...here.
	(process_note_abi_tag_sections, get_elfosabi): Remove.
	(rs6000_gdbarch_init): Use generic OS ABI framework.
	(rs6000_dump_tdep): New function.
	(_initialize_rs6000_tdep): Use gdbarch_register.

-- 
        -- Jason R. Thorpe <thorpej@wasabisystems.com>
-------------- next part --------------
Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.200
diff -u -r1.200 Makefile.in
--- Makefile.in	24 May 2002 00:12:16 -0000	1.200
+++ Makefile.in	28 May 2002 19:15:46 -0000
@@ -646,6 +646,7 @@
 monitor_h =	monitor.h
 objfiles_h =	objfiles.h
 parser_defs_h =	parser-defs.h $(doublest_h)
+ppc_tdep_h =	ppc-tdep.h osabi.h
 regcache_h =	regcache.h
 remote_h =	remote.h
 remote_utils_h =  remote-utils.h $(target_h)
@@ -1899,10 +1900,10 @@
 	$(objfiles_h) $(gdb_stabs_h) $(serial_h) ocd.h $(regcache_h)
 
 ppc-linux-nat.o: ppc-linux-nat.c $(defs_h) $(gdbcore_h) $(frame_h) \
-	$(inferior_h) $(target_h) $(regcache_h) ppc-tdep.h
+	$(inferior_h) $(target_h) $(regcache_h) $(ppc_tdep_h)
 
 ppc-linux-tdep.o: ppc-linux-tdep.c $(defs_h) $(gdbcore_h) $(inferior_h) \
-	$(target_h) ppc-tdep.h $(regcache_h) $(value_h)
+	$(target_h) $(ppc_tdep_h) $(regcache_h) $(value_h)
 
 ppcbug-rom.o: ppcbug-rom.c $(monitor_h) $(bfd_h) $(gdb_wait_h) $(defs_h) \
 	$(gdbcmd_h) $(inferior_h) $(target_h) $(serial_h) $(terminal_h) \
@@ -2038,7 +2039,7 @@
 	$(gdb_stabs_h) $(regcache_h) $(arch_utils_h)
 
 rs6000-tdep.o: rs6000-tdep.c $(defs_h) $(gdbcore_h) $(inferior_h) \
-	$(target_h) ppc-tdep.h $(regcache_h) $(value_h) $(parser_defs_h)
+	$(target_h) $(ppc_tdep_h) $(regcache_h) $(value_h) $(parser_defs_h)
 
 s390-tdep.o: s390-tdep.c $(defs_h) $(arch_utils_h) $(frame_h) $(inferior_h) \
 	$(symtab_h) $(target_h) $(gdbcore_h) $(gdbcmd_h) $(symfile_h) \
Index: ppc-linux-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/ppc-linux-tdep.c,v
retrieving revision 1.17
diff -u -r1.17 ppc-linux-tdep.c
--- ppc-linux-tdep.c	29 Apr 2002 15:10:06 -0000	1.17
+++ ppc-linux-tdep.c	28 May 2002 19:15:48 -0000
@@ -411,293 +411,6 @@
     return rs6000_frame_chain (thisframe);
 }
 
-/* FIXME: Move the following to rs6000-tdep.c (or some other file where
-   it may be used generically by ports which use either the SysV ABI or
-   the EABI */
-
-/* Until November 2001, gcc was not complying to the SYSV ABI for
-   returning structures less than or equal to 8 bytes in size.  It was
-   returning everything in memory.  When this was corrected, it wasn't
-   fixed for native platforms.  */
-int
-ppc_sysv_abi_broken_use_struct_convention (int gcc_p, struct type *value_type)
-{
-  if (TYPE_LENGTH (value_type) == 16
-      && TYPE_VECTOR (value_type))
-    return 0;
-
-  return generic_use_struct_convention (gcc_p, value_type);
-}
-
-/* Structures 8 bytes or less long are returned in the r3 & r4
-   registers, according to the SYSV ABI. */
-int
-ppc_sysv_abi_use_struct_convention (int gcc_p, struct type *value_type)
-{
-  if (TYPE_LENGTH (value_type) == 16
-      && TYPE_VECTOR (value_type))
-    return 0;
-
-  return (TYPE_LENGTH (value_type) > 8);
-}
-
-/* round2 rounds x up to the nearest multiple of s assuming that s is a
-   power of 2 */
-
-#undef round2
-#define round2(x,s) ((((long) (x) - 1) & ~(long)((s)-1)) + (s))
-
-/* Pass the arguments in either registers, or in the stack. Using the
-   ppc sysv ABI, the first eight words of the argument list (that might
-   be less than eight parameters if some parameters occupy more than one
-   word) are passed in r3..r10 registers.  float and double parameters are
-   passed in fpr's, in addition to that. Rest of the parameters if any
-   are passed in user stack. 
-
-   If the function is returning a structure, then the return address is passed
-   in r3, then the first 7 words of the parametes can be passed in registers,
-   starting from r4. */
-
-CORE_ADDR
-ppc_sysv_abi_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
-			     int struct_return, CORE_ADDR struct_addr)
-{
-  int argno;
-  /* Next available general register for non-float, non-vector arguments. */
-  int greg;
-  /* Next available floating point register for float arguments. */
-  int freg;
-  /* Next available vector register for vector arguments. */
-  int vreg;
-  int argstkspace;
-  int structstkspace;
-  int argoffset;
-  int structoffset;
-  struct value *arg;
-  struct type *type;
-  int len;
-  char old_sp_buf[4];
-  CORE_ADDR saved_sp;
-
-  greg = struct_return ? 4 : 3;
-  freg = 1;
-  vreg = 2;
-  argstkspace = 0;
-  structstkspace = 0;
-
-  /* Figure out how much new stack space is required for arguments
-     which don't fit in registers.  Unlike the PowerOpen ABI, the
-     SysV ABI doesn't reserve any extra space for parameters which
-     are put in registers. */
-  for (argno = 0; argno < nargs; argno++)
-    {
-      arg = args[argno];
-      type = check_typedef (VALUE_TYPE (arg));
-      len = TYPE_LENGTH (type);
-
-      if (TYPE_CODE (type) == TYPE_CODE_FLT)
-	{
-	  if (freg <= 8)
-	    freg++;
-	  else
-	    {
-	      /* SysV ABI converts floats to doubles when placed in
-	         memory and requires 8 byte alignment */
-	      if (argstkspace & 0x4)
-		argstkspace += 4;
-	      argstkspace += 8;
-	    }
-	}
-      else if (TYPE_CODE (type) == TYPE_CODE_INT && len == 8)	/* long long */
-	{
-	  if (greg > 9)
-	    {
-	      greg = 11;
-	      if (argstkspace & 0x4)
-		argstkspace += 4;
-	      argstkspace += 8;
-	    }
-	  else
-	    {
-	      if ((greg & 1) == 0)
-		greg++;
-	      greg += 2;
-	    }
-	}
-      else if (!TYPE_VECTOR (type))
-        {
-	  if (len > 4
-	      || TYPE_CODE (type) == TYPE_CODE_STRUCT
-	      || TYPE_CODE (type) == TYPE_CODE_UNION)
-	    {
-	      /* Rounding to the nearest multiple of 8 may not be necessary,
-		 but it is safe.  Particularly since we don't know the
-		 field types of the structure */
-	      structstkspace += round2 (len, 8);
-	    }
-	  if (greg <= 10)
-	    greg++;
-	  else
-	    argstkspace += 4;
-    	}
-      else
-        {
-          if (len == 16
-	      && TYPE_CODE (type) == TYPE_CODE_ARRAY
-	      && TYPE_VECTOR (type))
-	    {
-	      if (vreg <= 13)
-		vreg++;
-	      else
-		{
-		  /* Vector arguments must be aligned to 16 bytes on
-                     the stack. */
-		  argstkspace += round2 (argstkspace, 16);
-		  argstkspace += 16;
-		}
-	    }
-	}
-    }
-
-  /* Get current SP location */
-  saved_sp = read_sp ();
-
-  sp -= argstkspace + structstkspace;
-
-  /* Allocate space for backchain and callee's saved lr */
-  sp -= 8;
-
-  /* Make sure that we maintain 16 byte alignment */
-  sp &= ~0x0f;
-
-  /* Update %sp before proceeding any further */
-  write_register (SP_REGNUM, sp);
-
-  /* write the backchain */
-  store_address (old_sp_buf, 4, saved_sp);
-  write_memory (sp, old_sp_buf, 4);
-
-  argoffset = 8;
-  structoffset = argoffset + argstkspace;
-  freg = 1;
-  greg = 3;
-  vreg = 2;
-  /* Fill in r3 with the return structure, if any */
-  if (struct_return)
-    {
-      char val_buf[4];
-      store_address (val_buf, 4, struct_addr);
-      memcpy (&registers[REGISTER_BYTE (greg)], val_buf, 4);
-      greg++;
-    }
-  /* Now fill in the registers and stack... */
-  for (argno = 0; argno < nargs; argno++)
-    {
-      arg = args[argno];
-      type = check_typedef (VALUE_TYPE (arg));
-      len = TYPE_LENGTH (type);
-
-      if (TYPE_CODE (type) == TYPE_CODE_FLT)
-	{
-	  if (freg <= 8)
-	    {
-	      if (len > 8)
-		printf_unfiltered (
-				   "Fatal Error: a floating point parameter #%d with a size > 8 is found!\n", argno);
-	      memcpy (&registers[REGISTER_BYTE (FP0_REGNUM + freg)],
-		      VALUE_CONTENTS (arg), len);
-	      freg++;
-	    }
-	  else
-	    {
-	      /* SysV ABI converts floats to doubles when placed in
-	         memory and requires 8 byte alignment */
-	      /* FIXME: Convert floats to doubles */
-	      if (argoffset & 0x4)
-		argoffset += 4;
-	      write_memory (sp + argoffset, (char *) VALUE_CONTENTS (arg), len);
-	      argoffset += 8;
-	    }
-	}
-      else if (TYPE_CODE (type) == TYPE_CODE_INT && len == 8)	/* long long */
-	{
-	  if (greg > 9)
-	    {
-	      greg = 11;
-	      if (argoffset & 0x4)
-		argoffset += 4;
-	      write_memory (sp + argoffset, (char *) VALUE_CONTENTS (arg), len);
-	      argoffset += 8;
-	    }
-	  else
-	    {
-	      if ((greg & 1) == 0)
-		greg++;
-
-	      memcpy (&registers[REGISTER_BYTE (greg)],
-		      VALUE_CONTENTS (arg), 4);
-	      memcpy (&registers[REGISTER_BYTE (greg + 1)],
-		      VALUE_CONTENTS (arg) + 4, 4);
-	      greg += 2;
-	    }
-	}
-      else if (!TYPE_VECTOR (type))
-	{
-	  char val_buf[4];
-	  if (len > 4
-	      || TYPE_CODE (type) == TYPE_CODE_STRUCT
-	      || TYPE_CODE (type) == TYPE_CODE_UNION)
-	    {
-	      write_memory (sp + structoffset, VALUE_CONTENTS (arg), len);
-	      store_address (val_buf, 4, sp + structoffset);
-	      structoffset += round2 (len, 8);
-	    }
-	  else
-	    {
-	      memset (val_buf, 0, 4);
-	      memcpy (val_buf, VALUE_CONTENTS (arg), len);
-	    }
-	  if (greg <= 10)
-	    {
-	      memcpy (&registers[REGISTER_BYTE (greg)], val_buf, 4);
-	      greg++;
-	    }
-	  else
-	    {
-	      write_memory (sp + argoffset, val_buf, 4);
-	      argoffset += 4;
-	    }
-	}
-      else
-	{
-	  if (len == 16
-	      && TYPE_CODE (type) == TYPE_CODE_ARRAY
-	      && TYPE_VECTOR (type))
-	    {
-	      struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
-	      char *v_val_buf = alloca (16);
-	      memset (v_val_buf, 0, 16);
-	      memcpy (v_val_buf, VALUE_CONTENTS (arg), len);
-	      if (vreg <= 13)
-		{
-		  memcpy (&registers[REGISTER_BYTE (tdep->ppc_vr0_regnum
-						    + vreg)],
-			  v_val_buf, 16);
-		  vreg++;
-		}
-	      else
-		{
-		  write_memory (sp + argoffset, v_val_buf, 16);
-		  argoffset += 16;
-		}
-	    }
-        }
-    }
-
-  target_store_registers (-1);
-  return sp;
-}
-
 /* ppc_linux_memory_remove_breakpoints attempts to remove a breakpoint
    in much the same fashion as memory_remove_breakpoint in mem-break.c,
    but is careful not to write back the previous contents if the code
@@ -885,4 +598,45 @@
     }
 
   return lmp;
+}
+
+static void
+ppc_linux_init_abi (struct gdbarch_info info,
+                    struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  /* Until November 2001, gcc was not complying to the SYSV ABI for
+     returning structures less than or equal to 8 bytes in size. It was
+     returning everything in memory. When this was corrected, it wasn't
+     fixed for native platforms.  */
+  set_gdbarch_use_struct_convention (gdbarch,
+                                   ppc_sysv_abi_broken_use_struct_convention);
+
+  if (tdep->wordsize == 4)
+    {
+      /* Note: kevinb/2002-04-12: See note in rs6000_gdbarch_init regarding
+	 *_push_arguments().  The same remarks hold for the methods below.  */
+      set_gdbarch_frameless_function_invocation (gdbarch,
+        ppc_linux_frameless_function_invocation);
+      set_gdbarch_frame_chain (gdbarch, ppc_linux_frame_chain);
+      set_gdbarch_frame_saved_pc (gdbarch, ppc_linux_frame_saved_pc);
+
+      set_gdbarch_frame_init_saved_regs (gdbarch,
+                                         ppc_linux_frame_init_saved_regs);
+      set_gdbarch_init_extra_frame_info (gdbarch,
+                                         ppc_linux_init_extra_frame_info);
+
+      set_gdbarch_memory_remove_breakpoint (gdbarch,
+                                            ppc_linux_memory_remove_breakpoint);
+      set_solib_svr4_fetch_link_map_offsets
+        (gdbarch, ppc_linux_svr4_fetch_link_map_offsets);
+    }
+}
+
+void
+_initialize_ppc_linux_tdep (void)
+{
+  gdbarch_register_osabi (bfd_arch_powerpc, GDB_OSABI_LINUX,
+			  ppc_linux_init_abi);
 }
Index: ppc-tdep.h
===================================================================
RCS file: /cvs/src/src/gdb/ppc-tdep.h,v
retrieving revision 1.10
diff -u -r1.10 ppc-tdep.h
--- ppc-tdep.h	29 Apr 2002 15:10:06 -0000	1.10
+++ ppc-tdep.h	28 May 2002 19:15:48 -0000
@@ -22,6 +22,8 @@
 #ifndef PPC_TDEP_H
 #define PPC_TDEP_H
 
+#include "osabi.h"
+
 struct frame_info;
 struct value;
 
@@ -52,7 +54,7 @@
 struct gdbarch_tdep
   {
     int wordsize;              /* size in bytes of fixed-point word */
-    int osabi;                 /* OS / ABI from ELF header */
+    enum gdb_osabi osabi;      /* OS / ABI from ELF header */
     int *regoff;               /* byte offsets in register arrays */
     const struct reg *regs;    /* from current variant */
     int ppc_gp0_regnum;		/* GPR register 0 */
Index: rs6000-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/rs6000-tdep.c,v
retrieving revision 1.65
diff -u -r1.65 rs6000-tdep.c
--- rs6000-tdep.c	20 May 2002 17:45:43 -0000	1.65
+++ rs6000-tdep.c	28 May 2002 19:15:52 -0000
@@ -1128,6 +1128,263 @@
   return sp;
 }
 
+/* round2 rounds x up to the nearest multiple of s assuming that s is a
+   power of 2 */
+
+#undef round2
+#define round2(x,s) ((((long) (x) - 1) & ~(long)((s)-1)) + (s))
+
+/* Pass the arguments in either registers, or in the stack. Using the
+   ppc sysv ABI, the first eight words of the argument list (that might
+   be less than eight parameters if some parameters occupy more than one
+   word) are passed in r3..r10 registers.  float and double parameters are
+   passed in fpr's, in addition to that. Rest of the parameters if any
+   are passed in user stack. 
+
+   If the function is returning a structure, then the return address is passed
+   in r3, then the first 7 words of the parametes can be passed in registers,
+   starting from r4. */
+
+CORE_ADDR
+ppc_sysv_abi_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
+			     int struct_return, CORE_ADDR struct_addr)
+{
+  int argno;
+  /* Next available general register for non-float, non-vector arguments. */
+  int greg;
+  /* Next available floating point register for float arguments. */
+  int freg;
+  /* Next available vector register for vector arguments. */
+  int vreg;
+  int argstkspace;
+  int structstkspace;
+  int argoffset;
+  int structoffset;
+  struct value *arg;
+  struct type *type;
+  int len;
+  char old_sp_buf[4];
+  CORE_ADDR saved_sp;
+
+  greg = struct_return ? 4 : 3;
+  freg = 1;
+  vreg = 2;
+  argstkspace = 0;
+  structstkspace = 0;
+
+  /* Figure out how much new stack space is required for arguments
+     which don't fit in registers.  Unlike the PowerOpen ABI, the
+     SysV ABI doesn't reserve any extra space for parameters which
+     are put in registers. */
+  for (argno = 0; argno < nargs; argno++)
+    {
+      arg = args[argno];
+      type = check_typedef (VALUE_TYPE (arg));
+      len = TYPE_LENGTH (type);
+
+      if (TYPE_CODE (type) == TYPE_CODE_FLT)
+	{
+	  if (freg <= 8)
+	    freg++;
+	  else
+	    {
+	      /* SysV ABI converts floats to doubles when placed in
+	         memory and requires 8 byte alignment */
+	      if (argstkspace & 0x4)
+		argstkspace += 4;
+	      argstkspace += 8;
+	    }
+	}
+      else if (TYPE_CODE (type) == TYPE_CODE_INT && len == 8)	/* long long */
+	{
+	  if (greg > 9)
+	    {
+	      greg = 11;
+	      if (argstkspace & 0x4)
+		argstkspace += 4;
+	      argstkspace += 8;
+	    }
+	  else
+	    {
+	      if ((greg & 1) == 0)
+		greg++;
+	      greg += 2;
+	    }
+	}
+      else if (!TYPE_VECTOR (type))
+        {
+	  if (len > 4
+	      || TYPE_CODE (type) == TYPE_CODE_STRUCT
+	      || TYPE_CODE (type) == TYPE_CODE_UNION)
+	    {
+	      /* Rounding to the nearest multiple of 8 may not be necessary,
+		 but it is safe.  Particularly since we don't know the
+		 field types of the structure */
+	      structstkspace += round2 (len, 8);
+	    }
+	  if (greg <= 10)
+	    greg++;
+	  else
+	    argstkspace += 4;
+    	}
+      else
+        {
+          if (len == 16
+	      && TYPE_CODE (type) == TYPE_CODE_ARRAY
+	      && TYPE_VECTOR (type))
+	    {
+	      if (vreg <= 13)
+		vreg++;
+	      else
+		{
+		  /* Vector arguments must be aligned to 16 bytes on
+                     the stack. */
+		  argstkspace += round2 (argstkspace, 16);
+		  argstkspace += 16;
+		}
+	    }
+	}
+    }
+
+  /* Get current SP location */
+  saved_sp = read_sp ();
+
+  sp -= argstkspace + structstkspace;
+
+  /* Allocate space for backchain and callee's saved lr */
+  sp -= 8;
+
+  /* Make sure that we maintain 16 byte alignment */
+  sp &= ~0x0f;
+
+  /* Update %sp before proceeding any further */
+  write_register (SP_REGNUM, sp);
+
+  /* write the backchain */
+  store_address (old_sp_buf, 4, saved_sp);
+  write_memory (sp, old_sp_buf, 4);
+
+  argoffset = 8;
+  structoffset = argoffset + argstkspace;
+  freg = 1;
+  greg = 3;
+  vreg = 2;
+  /* Fill in r3 with the return structure, if any */
+  if (struct_return)
+    {
+      char val_buf[4];
+      store_address (val_buf, 4, struct_addr);
+      memcpy (&registers[REGISTER_BYTE (greg)], val_buf, 4);
+      greg++;
+    }
+  /* Now fill in the registers and stack... */
+  for (argno = 0; argno < nargs; argno++)
+    {
+      arg = args[argno];
+      type = check_typedef (VALUE_TYPE (arg));
+      len = TYPE_LENGTH (type);
+
+      if (TYPE_CODE (type) == TYPE_CODE_FLT)
+	{
+	  if (freg <= 8)
+	    {
+	      if (len > 8)
+		printf_unfiltered (
+				   "Fatal Error: a floating point parameter #%d with a size > 8 is found!\n", argno);
+	      memcpy (&registers[REGISTER_BYTE (FP0_REGNUM + freg)],
+		      VALUE_CONTENTS (arg), len);
+	      freg++;
+	    }
+	  else
+	    {
+	      /* SysV ABI converts floats to doubles when placed in
+	         memory and requires 8 byte alignment */
+	      /* FIXME: Convert floats to doubles */
+	      if (argoffset & 0x4)
+		argoffset += 4;
+	      write_memory (sp + argoffset, (char *) VALUE_CONTENTS (arg), len);
+	      argoffset += 8;
+	    }
+	}
+      else if (TYPE_CODE (type) == TYPE_CODE_INT && len == 8)	/* long long */
+	{
+	  if (greg > 9)
+	    {
+	      greg = 11;
+	      if (argoffset & 0x4)
+		argoffset += 4;
+	      write_memory (sp + argoffset, (char *) VALUE_CONTENTS (arg), len);
+	      argoffset += 8;
+	    }
+	  else
+	    {
+	      if ((greg & 1) == 0)
+		greg++;
+
+	      memcpy (&registers[REGISTER_BYTE (greg)],
+		      VALUE_CONTENTS (arg), 4);
+	      memcpy (&registers[REGISTER_BYTE (greg + 1)],
+		      VALUE_CONTENTS (arg) + 4, 4);
+	      greg += 2;
+	    }
+	}
+      else if (!TYPE_VECTOR (type))
+	{
+	  char val_buf[4];
+	  if (len > 4
+	      || TYPE_CODE (type) == TYPE_CODE_STRUCT
+	      || TYPE_CODE (type) == TYPE_CODE_UNION)
+	    {
+	      write_memory (sp + structoffset, VALUE_CONTENTS (arg), len);
+	      store_address (val_buf, 4, sp + structoffset);
+	      structoffset += round2 (len, 8);
+	    }
+	  else
+	    {
+	      memset (val_buf, 0, 4);
+	      memcpy (val_buf, VALUE_CONTENTS (arg), len);
+	    }
+	  if (greg <= 10)
+	    {
+	      memcpy (&registers[REGISTER_BYTE (greg)], val_buf, 4);
+	      greg++;
+	    }
+	  else
+	    {
+	      write_memory (sp + argoffset, val_buf, 4);
+	      argoffset += 4;
+	    }
+	}
+      else
+	{
+	  if (len == 16
+	      && TYPE_CODE (type) == TYPE_CODE_ARRAY
+	      && TYPE_VECTOR (type))
+	    {
+	      struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+	      char *v_val_buf = alloca (16);
+	      memset (v_val_buf, 0, 16);
+	      memcpy (v_val_buf, VALUE_CONTENTS (arg), len);
+	      if (vreg <= 13)
+		{
+		  memcpy (&registers[REGISTER_BYTE (tdep->ppc_vr0_regnum
+						    + vreg)],
+			  v_val_buf, 16);
+		  vreg++;
+		}
+	      else
+		{
+		  write_memory (sp + argoffset, v_val_buf, 16);
+		  argoffset += 16;
+		}
+	    }
+        }
+    }
+
+  target_store_registers (-1);
+  return sp;
+}
+
 /* Function: ppc_push_return_address (pc, sp)
    Set up the return address for the inferior function call. */
 
@@ -1195,6 +1452,32 @@
 
 static CORE_ADDR rs6000_struct_return_address;
 
+/* Until November 2001, gcc was not complying to the SYSV ABI for 
+   returning structures less than or equal to 8 bytes in size.  It was
+   returning everything in memory.  When this was corrected, it wasn't
+   fixed for native platforms.  */
+int     
+ppc_sysv_abi_broken_use_struct_convention (int gcc_p, struct type *value_type)
+{  
+  if (TYPE_LENGTH (value_type) == 16 
+      && TYPE_VECTOR (value_type))
+    return 0;                            
+
+  return generic_use_struct_convention (gcc_p, value_type);
+}
+
+/* Structures 8 bytes or less long are returned in the r3 & r4
+   registers, according to the SYSV ABI. */
+int
+ppc_sysv_abi_use_struct_convention (int gcc_p, struct type *value_type)
+{
+  if (TYPE_LENGTH (value_type) == 16
+      && TYPE_VECTOR (value_type))
+    return 0;
+
+  return (TYPE_LENGTH (value_type) > 8);
+}   
+
 /* Return whether handle_inferior_event() should proceed through code
    starting at PC in function NAME when stepping.
 
@@ -2402,88 +2685,7 @@
 
   return NULL;
 }
-
-
-
 
-static void
-process_note_abi_tag_sections (bfd *abfd, asection *sect, void *obj)
-{
-  int *os_ident_ptr = obj;
-  const char *name;
-  unsigned int sectsize;
-
-  name = bfd_get_section_name (abfd, sect);
-  sectsize = bfd_section_size (abfd, sect);
-  if (strcmp (name, ".note.ABI-tag") == 0 && sectsize > 0)
-    {
-      unsigned int name_length, data_length, note_type;
-      char *note = alloca (sectsize);
-
-      bfd_get_section_contents (abfd, sect, note,
-                                (file_ptr) 0, (bfd_size_type) sectsize);
-
-      name_length = bfd_h_get_32 (abfd, note);
-      data_length = bfd_h_get_32 (abfd, note + 4);
-      note_type   = bfd_h_get_32 (abfd, note + 8);
-
-      if (name_length == 4 && data_length == 16 && note_type == 1
-          && strcmp (note + 12, "GNU") == 0)
-	{
-	  int os_number = bfd_h_get_32 (abfd, note + 16);
-
-	  /* The case numbers are from abi-tags in glibc */
-	  switch (os_number)
-	    {
-	    case 0 :
-	      *os_ident_ptr = ELFOSABI_LINUX;
-	      break;
-	    case 1 :
-	      *os_ident_ptr = ELFOSABI_HURD;
-	      break;
-	    case 2 :
-	      *os_ident_ptr = ELFOSABI_SOLARIS;
-	      break;
-	    default :
-	      internal_error (__FILE__, __LINE__,
-			      "process_note_abi_sections: unknown OS number %d",
-			      os_number);
-	      break;
-	    }
-	}
-    }
-}
-
-/* Return one of the ELFOSABI_ constants for BFDs representing ELF
-   executables.  If it's not an ELF executable or if the OS/ABI couldn't
-   be determined, simply return -1. */
-
-static int
-get_elfosabi (bfd *abfd)
-{
-  int elfosabi = -1;
-
-  if (abfd != NULL && bfd_get_flavour (abfd) == bfd_target_elf_flavour)
-    {
-      elfosabi = elf_elfheader (abfd)->e_ident[EI_OSABI];
-
-      /* When elfosabi is 0 (ELFOSABI_NONE), this is supposed to indicate
-         that we're on a SYSV system.  However, GNU/Linux uses a note section
-	 to record OS/ABI info, but leaves e_ident[EI_OSABI] zero.  So we
-	 have to check the note sections too. */
-      if (elfosabi == 0)
-	{
-	  bfd_map_over_sections (abfd,
-	                         process_note_abi_tag_sections,
-				 &elfosabi);
-	}
-    }
-
-  return elfosabi;
-}
-
-
-
 /* Initialize the current architecture based on INFO.  If possible, re-use an
    architecture from ARCHES, which is a list of architectures already created
    during this debugging session.
@@ -2502,7 +2704,8 @@
   enum bfd_architecture arch;
   unsigned long mach;
   bfd abfd;
-  int osabi, sysv_abi;
+  int sysv_abi;
+  enum gdb_osabi osabi = GDB_OSABI_UNKNOWN;
   gdbarch_print_insn_ftype *print_insn;
 
   from_xcoff_exec = info.abfd && info.abfd->format == bfd_object &&
@@ -2513,7 +2716,8 @@
 
   sysv_abi = info.abfd && bfd_get_flavour (info.abfd) == bfd_target_elf_flavour;
 
-  osabi = get_elfosabi (info.abfd);
+  if (info.abfd)
+    osabi = gdbarch_lookup_osabi (info.abfd);
 
   /* Check word size.  If INFO is from a binary file, infer it from
      that, else choose a likely default. */
@@ -2726,57 +2930,23 @@
   /* Not sure on this. FIXMEmgo */
   set_gdbarch_frame_args_skip (gdbarch, 8);
 
-  /* Until November 2001, gcc was not complying to the SYSV ABI for
-     returning structures less than or equal to 8 bytes in size. It was
-     returning everything in memory. When this was corrected, it wasn't
-     fixed for native platforms. */
   if (sysv_abi)
-    {
-      if (osabi == ELFOSABI_LINUX
-          || osabi == ELFOSABI_NETBSD
-          || osabi == ELFOSABI_FREEBSD)
-	set_gdbarch_use_struct_convention (gdbarch,
-					   ppc_sysv_abi_broken_use_struct_convention);
-      else
-	set_gdbarch_use_struct_convention (gdbarch,
-					   ppc_sysv_abi_use_struct_convention);
-    }
+    set_gdbarch_use_struct_convention (gdbarch,
+    				       ppc_sysv_abi_use_struct_convention);
   else
-    {
-      set_gdbarch_use_struct_convention (gdbarch,
-					 generic_use_struct_convention);
-    }
+    set_gdbarch_use_struct_convention (gdbarch,
+				       generic_use_struct_convention);
 
   set_gdbarch_frame_chain_valid (gdbarch, file_frame_chain_valid);
-  /* Note: kevinb/2002-04-12: See note above regarding *_push_arguments().
-     The same remarks hold for the methods below.  */
-  if (osabi == ELFOSABI_LINUX && wordsize == 4)
-    {
-      set_gdbarch_frameless_function_invocation (gdbarch,
-	ppc_linux_frameless_function_invocation);
-      set_gdbarch_frame_chain (gdbarch, ppc_linux_frame_chain);
-      set_gdbarch_frame_saved_pc (gdbarch, ppc_linux_frame_saved_pc);
-
-      set_gdbarch_frame_init_saved_regs (gdbarch,
-	                                 ppc_linux_frame_init_saved_regs);
-      set_gdbarch_init_extra_frame_info (gdbarch,
-	                                 ppc_linux_init_extra_frame_info);
-
-      set_gdbarch_memory_remove_breakpoint (gdbarch,
-	                                    ppc_linux_memory_remove_breakpoint);
-      set_solib_svr4_fetch_link_map_offsets 
-	(gdbarch, ppc_linux_svr4_fetch_link_map_offsets);
-    }
-  else
-    {
-      set_gdbarch_frameless_function_invocation (gdbarch,
-	rs6000_frameless_function_invocation);
-      set_gdbarch_frame_chain (gdbarch, rs6000_frame_chain);
-      set_gdbarch_frame_saved_pc (gdbarch, rs6000_frame_saved_pc);
 
-      set_gdbarch_frame_init_saved_regs (gdbarch, rs6000_frame_init_saved_regs);
-      set_gdbarch_init_extra_frame_info (gdbarch, rs6000_init_extra_frame_info);
-    }
+  set_gdbarch_frameless_function_invocation (gdbarch,
+                                         rs6000_frameless_function_invocation);
+  set_gdbarch_frame_chain (gdbarch, rs6000_frame_chain);
+  set_gdbarch_frame_saved_pc (gdbarch, rs6000_frame_saved_pc);
+
+  set_gdbarch_frame_init_saved_regs (gdbarch, rs6000_frame_init_saved_regs);
+  set_gdbarch_init_extra_frame_info (gdbarch, rs6000_init_extra_frame_info);
+
   if (!sysv_abi)
     {
       /* Handle RS/6000 function pointers (which are really function
@@ -2792,9 +2962,24 @@
      now that the C compiler delays popping them.  */
   set_gdbarch_frame_num_args (gdbarch, frame_num_args_unknown);
 
+  /* Hook in ABI-specific overrides, if they have been registered.  */
+  gdbarch_init_osabi (info, gdbarch, osabi);
+
   return gdbarch;
 }
 
+static void
+rs6000_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+
+  if (tdep == NULL)
+    return;
+
+  fprintf_unfiltered (file, "rs6000_dump_tdep: OS ABI = %s\n",
+		      gdbarch_osabi_name (tdep->osabi));
+}
+
 static struct cmd_list_element *info_powerpc_cmdlist = NULL;
 
 static void
@@ -2808,8 +2993,8 @@
 void
 _initialize_rs6000_tdep (void)
 {
-  register_gdbarch_init (bfd_arch_rs6000, rs6000_gdbarch_init);
-  register_gdbarch_init (bfd_arch_powerpc, rs6000_gdbarch_init);
+  gdbarch_register (bfd_arch_rs6000, rs6000_gdbarch_init, rs6000_dump_tdep);
+  gdbarch_register (bfd_arch_powerpc, rs6000_gdbarch_init, rs6000_dump_tdep);
 
   /* Add root prefix command for "info powerpc" commands */
   add_prefix_cmd ("powerpc", class_info, rs6000_info_powerpc_command,
@@ -2819,5 +3004,4 @@
   add_cmd ("altivec", class_info, rs6000_altivec_registers_info,
 	   "Display the contents of the AltiVec registers.",
 	   &info_powerpc_cmdlist);
-
 }
Index: config/powerpc/nbsd.mh
===================================================================
RCS file: /cvs/src/src/gdb/config/powerpc/nbsd.mh,v
retrieving revision 1.10
diff -u -r1.10 nbsd.mh
--- config/powerpc/nbsd.mh	28 May 2002 18:43:08 -0000	1.10
+++ config/powerpc/nbsd.mh	28 May 2002 19:15:53 -0000
@@ -1,3 +1,3 @@
 # Host: PowerPC, running NetBSD
-NATDEPFILES= fork-child.o infptrace.o inftarg.o ppcnbsd-nat.o solib-legacy.o
+NATDEPFILES= fork-child.o infptrace.o inftarg.o ppcnbsd-nat.o
 NAT_FILE= nm-nbsd.h
Index: config/powerpc/nbsd.mt
===================================================================
RCS file: /cvs/src/src/gdb/config/powerpc/nbsd.mt,v
retrieving revision 1.10
diff -u -r1.10 nbsd.mt
--- config/powerpc/nbsd.mt	28 May 2002 18:43:08 -0000	1.10
+++ config/powerpc/nbsd.mt	28 May 2002 19:15:53 -0000
@@ -1,5 +1,5 @@
 # Target: PowerPC, running NetBSD
-TDEPFILES= rs6000-tdep.o ppcnbsd-tdep.o nbsd-tdep.o ppc-linux-tdep.o corelow.o \
+TDEPFILES= rs6000-tdep.o ppcnbsd-tdep.o nbsd-tdep.o corelow.o \
 	solib.o solib-svr4.o
 TM_FILE= tm-nbsd.h
 


More information about the Gdb-patches mailing list