* gdbserver/low-hppabsd.c (read_inferior_memory): Add explicit
[deliverable/binutils-gdb.git] / gdb / sparc-tdep.c
index 50b56ad7f7756d2cdb073921b51a35e7c461f976..2cb27dbb8a59b0ed7a313c5c53229e075ec7c251 100644 (file)
@@ -1,6 +1,6 @@
 /* Target-dependent code for the SPARC for GDB, the GNU debugger.
-   Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997
-   Free Software Foundation, Inc.
+   Copyright 1986, 1987, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
+   1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 #include "value.h"
 #include "bfd.h"
 #include "gdb_string.h"
+#include "regcache.h"
 
 #ifdef USE_PROC_FS
 #include <sys/procfs.h>
+/* Prototypes for supply_gregset etc. */
+#include "gregset.h"
 #endif
 
 #include "gdbcore.h"
 
 #include "symfile.h"   /* for 'entry_point_address' */
 
-/* Prototypes for supply_gregset etc. */
-#include "gregset.h"
-
 /*
  * Some local macros that have multi-arch and non-multi-arch versions:
  */
@@ -340,7 +340,7 @@ sparc_init_extra_frame_info (int fromleaf, struct frame_info *fi)
          negative number if a flat frame) to the sp.  FIXME: Does not
          handle large frames which will need more than one instruction
          to adjust the sp.  */
-      insn = fetch_instruction (prologue_start, 4);
+      insn = fetch_instruction (prologue_start);
       if (X_OP (insn) == 2 && X_RD (insn) == 14 && X_OP3 (insn) == 0
          && X_I (insn) && X_SIMM13 (insn) < 0)
        {
@@ -426,7 +426,7 @@ CORE_ADDR
 sparc_frame_chain (struct frame_info *frame)
 {
   /* Value that will cause FRAME_CHAIN_VALID to not worry about the chain
-     value.  If it realy is zero, we detect it later in
+     value.  If it really is zero, we detect it later in
      sparc_init_prev_frame.  */
   return (CORE_ADDR) 1;
 }
@@ -527,7 +527,8 @@ setup_arbitrary_frame (int argc, CORE_ADDR *argv)
   frame = create_new_frame (argv[0], 0);
 
   if (!frame)
-    internal_error ("create_new_frame returned invalid frame");
+    internal_error (__FILE__, __LINE__,
+                   "create_new_frame returned invalid frame");
 
   frame->extra_info->bottom = argv[1];
   frame->pc = FRAME_SAVED_PC (frame);
@@ -1054,7 +1055,8 @@ sparc_frame_find_saved_regs (struct frame_info *fi, CORE_ADDR *saved_regs_addr)
   CORE_ADDR frame_addr = FRAME_FP (fi);
 
   if (!fi)
-    internal_error ("Bad frame info struct in FRAME_FIND_SAVED_REGS");
+    internal_error (__FILE__, __LINE__,
+                   "Bad frame info struct in FRAME_FIND_SAVED_REGS");
 
   memset (saved_regs_addr, 0, NUM_REGS * sizeof (CORE_ADDR));
 
@@ -2136,13 +2138,27 @@ sparc_fix_call_dummy (char *dummy, CORE_ADDR pc, CORE_ADDR fun,
                           | (((fun - (pc + CALL_DUMMY_CALL_OFFSET)) >> 2)
                              & 0x3fffffff)));
 
-  /* Comply with strange Sun cc calling convention for struct-returning
-     functions.  */
-  if (!using_gcc
-      && (TYPE_CODE (value_type) == TYPE_CODE_STRUCT
-         || TYPE_CODE (value_type) == TYPE_CODE_UNION))
-    store_unsigned_integer (dummy + CALL_DUMMY_CALL_OFFSET + 8, 4,
-                           TYPE_LENGTH (value_type) & 0x1fff);
+  /* If the called function returns an aggregate value, fill in the UNIMP
+     instruction containing the size of the returned aggregate return value,
+     which follows the call instruction.
+     For details see the SPARC Architecture Manual Version 8, Appendix D.3.
+
+     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.
+     Tweeking current_gdbarch is not an optimal solution, but the call to
+     sparc_fix_call_dummy is immediately followed by a call to run_stack_dummy,
+     which is the only function where dummy_breakpoint_offset is actually
+     used, if it is non-zero.  */
+  if (TYPE_CODE (value_type) == TYPE_CODE_STRUCT
+       || TYPE_CODE (value_type) == TYPE_CODE_UNION)
+    {
+      store_unsigned_integer (dummy + CALL_DUMMY_CALL_OFFSET + 8, 4,
+                             TYPE_LENGTH (value_type) & 0x1fff);
+      set_gdbarch_call_dummy_breakpoint_offset (current_gdbarch, 0x30);
+    }
+  else
+    set_gdbarch_call_dummy_breakpoint_offset (current_gdbarch, 0x2c);
 
   if (!(GDB_TARGET_IS_SPARC64))
     {
@@ -2365,6 +2381,8 @@ sparc64_push_arguments (int nargs, value_ptr *args, CORE_ADDR sp,
                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]),
@@ -2797,14 +2815,6 @@ sparc_frame_init_saved_regs (struct frame_info *fi_ignored)
 {      /* no-op */
 }
 
-/* The frame address: stored in the 'frame' field of the frame_info.  */
-
-static CORE_ADDR
-sparc_frame_address (struct frame_info *fi)
-{
-  return fi->frame;
-}
-
 /* gdbarch fix call dummy:
    All this function does is rearrange the arguments before calling
    sparc_fix_call_dummy (which does the real work).  */
@@ -2944,10 +2954,10 @@ sparc_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_float_bit (gdbarch, 4 * TARGET_CHAR_BIT);
   set_gdbarch_fp_regnum (gdbarch, SPARC_FP_REGNUM);
   set_gdbarch_fp0_regnum (gdbarch, SPARC_FP0_REGNUM);
-  set_gdbarch_frame_args_address (gdbarch, sparc_frame_address);
+  set_gdbarch_frame_args_address (gdbarch, default_frame_address);
   set_gdbarch_frame_chain (gdbarch, sparc_frame_chain);
   set_gdbarch_frame_init_saved_regs (gdbarch, sparc_frame_init_saved_regs);
-  set_gdbarch_frame_locals_address (gdbarch, sparc_frame_address);
+  set_gdbarch_frame_locals_address (gdbarch, default_frame_address);
   set_gdbarch_frame_num_args (gdbarch, frame_num_args_unknown);
   set_gdbarch_frame_saved_pc (gdbarch, sparc_frame_saved_pc);
   set_gdbarch_frameless_function_invocation (gdbarch, 
@@ -2961,11 +2971,6 @@ sparc_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_long_long_bit (gdbarch, 8 * TARGET_CHAR_BIT);
   set_gdbarch_max_register_raw_size (gdbarch, 8);
   set_gdbarch_max_register_virtual_size (gdbarch, 8);
-#ifdef DO_CALL_DUMMY_ON_STACK
-  set_gdbarch_pc_in_call_dummy (gdbarch, pc_in_call_dummy_on_stack);
-#else
-  set_gdbarch_pc_in_call_dummy (gdbarch, pc_in_call_dummy_at_entry_point);
-#endif
   set_gdbarch_pop_frame (gdbarch, sparc_pop_frame);
   set_gdbarch_push_return_address (gdbarch, sparc_push_return_address);
   set_gdbarch_push_dummy_frame (gdbarch, sparc_push_dummy_frame);
@@ -2999,12 +3004,14 @@ sparc_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       /* 32-bit machine types: */
 
 #ifdef SPARC32_CALL_DUMMY_ON_STACK
+      set_gdbarch_pc_in_call_dummy (gdbarch, pc_in_call_dummy_on_stack);
       set_gdbarch_call_dummy_address (gdbarch, sparc_call_dummy_address);
       set_gdbarch_call_dummy_breakpoint_offset (gdbarch, 0x30);
       set_gdbarch_call_dummy_length (gdbarch, 0x38);
       set_gdbarch_call_dummy_location (gdbarch, ON_STACK);
       set_gdbarch_call_dummy_words (gdbarch, call_dummy_32);
 #else
+      set_gdbarch_pc_in_call_dummy (gdbarch, pc_in_call_dummy_at_entry_point);
       set_gdbarch_call_dummy_address (gdbarch, entry_point_address);
       set_gdbarch_call_dummy_breakpoint_offset (gdbarch, 0);
       set_gdbarch_call_dummy_length (gdbarch, 0);
@@ -3053,6 +3060,7 @@ sparc_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
     default:   /* Any new machine type is likely to be 64-bit.  */
 
 #ifdef SPARC64_CALL_DUMMY_ON_STACK
+      set_gdbarch_pc_in_call_dummy (gdbarch, pc_in_call_dummy_on_stack);
       set_gdbarch_call_dummy_address (gdbarch, sparc_call_dummy_address);
       set_gdbarch_call_dummy_breakpoint_offset (gdbarch, 8 * 4);
       set_gdbarch_call_dummy_length (gdbarch, 192);
@@ -3060,6 +3068,7 @@ sparc_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       set_gdbarch_call_dummy_start_offset (gdbarch, 148);
       set_gdbarch_call_dummy_words (gdbarch, call_dummy_64);
 #else
+      set_gdbarch_pc_in_call_dummy (gdbarch, pc_in_call_dummy_at_entry_point);
       set_gdbarch_call_dummy_address (gdbarch, entry_point_address);
       set_gdbarch_call_dummy_breakpoint_offset (gdbarch, 0);
       set_gdbarch_call_dummy_length (gdbarch, 0);
This page took 0.025908 seconds and 4 git commands to generate.