* m68k-tdep.h (enum struct_return): Define.
authorAndreas Schwab <schwab@linux-m68k.org>
Wed, 9 Jul 2003 21:36:08 +0000 (21:36 +0000)
committerAndreas Schwab <schwab@linux-m68k.org>
Wed, 9 Jul 2003 21:36:08 +0000 (21:36 +0000)
(struct gdbarch_tdep): Add struct_return.
* m68k-tdep.c (m68k_push_dummy_call): Non-scalars bigger than 4
bytes are padded to the right, not to the left.  Pass struct value
address in register %a1, not on stack.
(m68k_use_struct_convention): New function.
(m68k_gdbarch_init): Set use_struct_convention.  Initialize
struct_return in tdep to pcc_struct_return.
* m68klinux-tdep.c (m68k_linux_init_abi): Set struct_return to
reg_struct_return.

gdb/ChangeLog
gdb/m68k-tdep.c
gdb/m68k-tdep.h
gdb/m68klinux-tdep.c

index e4f5445..3ad82ca 100644 (file)
@@ -1,3 +1,16 @@
+2003-07-09  Andreas Schwab  <schwab@suse.de>
+
+       * m68k-tdep.h (enum struct_return): Define.
+       (struct gdbarch_tdep): Add struct_return.
+       * m68k-tdep.c (m68k_push_dummy_call): Non-scalars bigger than 4
+       bytes are padded to the right, not to the left.  Pass struct value
+       address in register %a1, not on stack.
+       (m68k_use_struct_convention): New function.
+       (m68k_gdbarch_init): Set use_struct_convention.  Initialize
+       struct_return in tdep to pcc_struct_return.
+       * m68klinux-tdep.c (m68k_linux_init_abi): Set struct_return to
+       reg_struct_return.
+
 2003-07-09  Joel Brobecker  <brobecker@gnat.com>      
 
        * somread.c (som_symfile_offsets): Fix compilation error.   
index 2a675e0..97ac076 100644 (file)
@@ -235,6 +235,16 @@ m68k_extract_struct_value_address (struct regcache *regcache)
   return extract_unsigned_integer (buf, 4);
 }
 
+static int
+m68k_use_struct_convention (int gcc_p, struct type *type)
+{
+  enum struct_return struct_return;
+
+  struct_return = gdbarch_tdep (current_gdbarch)->struct_return;
+  return generic_use_struct_convention (struct_return == reg_struct_return,
+                                       type);
+}
+
 /* A function that tells us whether the function invocation represented
    by fi does not have a frame on the stack associated with it.  If it
    does not, FRAMELESS is set to 1, else 0.  */
@@ -317,20 +327,29 @@ m68k_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
   /* Push arguments in reverse order.  */
   for (i = nargs - 1; i >= 0; i--)
     {
-      int len = TYPE_LENGTH (VALUE_ENCLOSING_TYPE (args[i]));
+      struct type *value_type = VALUE_ENCLOSING_TYPE (args[i]);
+      int len = TYPE_LENGTH (value_type);
       int container_len = (len + 3) & ~3;
-      int offset = container_len - len;
-
+      int offset;
+
+      /* Non-scalars bigger than 4 bytes are left aligned, others are
+        right aligned.  */
+      if ((TYPE_CODE (value_type) == TYPE_CODE_STRUCT
+          || TYPE_CODE (value_type) == TYPE_CODE_UNION
+          || TYPE_CODE (value_type) == TYPE_CODE_ARRAY)
+         && len > 4)
+       offset = 0;
+      else
+       offset = container_len - len;
       sp -= container_len;
       write_memory (sp + offset, VALUE_CONTENTS_ALL (args[i]), len);
     }
 
-  /* Push value address.  */
+  /* Store struct value address.  */
   if (struct_return)
     {
-      sp -= 4;
       store_unsigned_integer (buf, 4, struct_addr);
-      write_memory (sp, buf, 4);
+      regcache_cooked_write (regcache, M68K_A1_REGNUM, buf);
     }
 
   /* Store return address.  */
@@ -1100,6 +1119,7 @@ m68k_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_store_return_value (gdbarch, m68k_store_return_value);
   set_gdbarch_extract_struct_value_address (gdbarch,
                                            m68k_extract_struct_value_address);
+  set_gdbarch_use_struct_convention (gdbarch, m68k_use_struct_convention);
 
   set_gdbarch_frameless_function_invocation (gdbarch,
                                             m68k_frameless_function_invocation);
@@ -1126,6 +1146,7 @@ m68k_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   tdep->jb_pc = -1;
 #endif
   tdep->get_sigtramp_info = NULL;
+  tdep->struct_return = pcc_struct_return;
 
   /* Frame unwinder.  */
   set_gdbarch_unwind_dummy_id (gdbarch, m68k_unwind_dummy_id);
index a81cc8c..702e4fc 100644 (file)
@@ -61,6 +61,14 @@ struct m68k_sigtramp_info
   int *sc_reg_offset;
 };
 
+/* Convention for returning structures.  */
+
+enum struct_return
+{
+  pcc_struct_return,           /* Return "short" structures in memory.  */
+  reg_struct_return            /* Return "short" structures in registers.  */
+};
+
 /* Target-dependent structure in gdbarch.  */
 struct gdbarch_tdep
 {
@@ -72,6 +80,9 @@ struct gdbarch_tdep
 
   /* Get info about sigtramp.  */
   struct m68k_sigtramp_info (*get_sigtramp_info) (struct frame_info *);
+
+  /* Convention for returning structures.  */
+  enum struct_return struct_return;
 };
 
 #endif /* M68K_TDEP_H */
index 422f9af..b39eebe 100644 (file)
@@ -290,6 +290,7 @@ m68k_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   tdep->jb_pc = M68K_LINUX_JB_PC;
   tdep->jb_elt_size = M68K_LINUX_JB_ELEMENT_SIZE;
   tdep->get_sigtramp_info = m68k_linux_get_sigtramp_info;
+  tdep->struct_return = reg_struct_return;
 
   set_gdbarch_extract_return_value (gdbarch, m68k_linux_extract_return_value);
   set_gdbarch_store_return_value (gdbarch, m68k_linux_store_return_value);