* c-valprint.c (c_value_print): Fix up some formatting. Use
[deliverable/binutils-gdb.git] / gdb / sparc-tdep.c
index 9facbadcad37bbedb821d9a373ce090c4117cee3..dcae0455885e9836ed09a6f7a74eaef886ec2355 100644 (file)
@@ -1,6 +1,6 @@
 /* Target-dependent code for SPARC.
 
-   Copyright 2003, 2004 Free Software Foundation, Inc.
+   Copyright 2003, 2004, 2005 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -80,10 +80,12 @@ struct regset;
 #define X_OP2(i) (((i) >> 22) & 0x7)
 #define X_IMM22(i) ((i) & 0x3fffff)
 #define X_OP3(i) (((i) >> 19) & 0x3f)
+#define X_RS1(i) (((i) >> 14) & 0x1f)
 #define X_I(i) (((i) >> 13) & 1)
 /* Sign extension macros.  */
 #define X_DISP22(i) ((X_IMM22 (i) ^ 0x200000) - 0x200000)
 #define X_DISP19(i) ((((i) & 0x7ffff) ^ 0x40000) - 0x40000)
+#define X_SIMM13(i) ((((i) & 0x1fff) ^ 0x1000) - 0x1000)
 
 /* Fetch the instruction at PC.  Instructions are always big-endian
    even if the processor operates in little-endian mode.  */
@@ -186,6 +188,8 @@ sparc_address_from_register (int regnum)
 static int
 sparc_integral_or_pointer_p (const struct type *type)
 {
+  int len = TYPE_LENGTH (type);
+
   switch (TYPE_CODE (type))
     {
     case TYPE_CODE_INT:
@@ -193,22 +197,14 @@ sparc_integral_or_pointer_p (const struct type *type)
     case TYPE_CODE_CHAR:
     case TYPE_CODE_ENUM:
     case TYPE_CODE_RANGE:
-      {
-       /* We have byte, half-word, word and extended-word/doubleword
-           integral types.  The doubleword is an extension to the
-           original 32-bit ABI by the SCD 2.4.x.  */
-       int len = TYPE_LENGTH (type);
-       return (len == 1 || len == 2 || len == 4 || len == 8);
-      }
-      return 1;
+      /* We have byte, half-word, word and extended-word/doubleword
+        integral types.  The doubleword is an extension to the
+        original 32-bit ABI by the SCD 2.4.x.  */
+      return (len == 1 || len == 2 || len == 4 || len == 8);
     case TYPE_CODE_PTR:
     case TYPE_CODE_REF:
-      {
-       /* Allow either 32-bit or 64-bit pointers.  */
-       int len = TYPE_LENGTH (type);
-       return (len == 4 || len == 8);
-      }
-      return 1;
+      /* Allow either 32-bit or 64-bit pointers.  */
+      return (len == 4 || len == 8);
     default:
       break;
     }
@@ -392,7 +388,7 @@ sparc32_store_arguments (struct regcache *regcache, int nargs,
              correct, and wasting a few bytes shouldn't be a problem.  */
          sp &= ~0x7;
 
-         write_memory (sp, VALUE_CONTENTS (args[i]), len);
+         write_memory (sp, value_contents (args[i]), len);
          args[i] = value_from_pointer (lookup_pointer_type (type), sp);
          num_elements++;
        }
@@ -427,7 +423,7 @@ sparc32_store_arguments (struct regcache *regcache, int nargs,
 
   for (i = 0; i < nargs; i++)
     {
-      char *valbuf = VALUE_CONTENTS (args[i]);
+      const bfd_byte *valbuf = value_contents (args[i]);
       struct type *type = value_type (args[i]);
       int len = TYPE_LENGTH (type);
 
@@ -609,7 +605,36 @@ sparc32_skip_prologue (CORE_ADDR start_pc)
        return sal.end;
     }
 
-  return sparc_analyze_prologue (start_pc, 0xffffffffUL, &cache);
+  start_pc = sparc_analyze_prologue (start_pc, 0xffffffffUL, &cache);
+
+  /* The psABI says that "Although the first 6 words of arguments
+     reside in registers, the standard stack frame reserves space for
+     them.".  It also suggests that a function may use that space to
+     "write incoming arguments 0 to 5" into that space, and that's
+     indeed what GCC seems to be doing.  In that case GCC will
+     generate debug information that points to the stack slots instead
+     of the registers, so we should consider the instructions that
+     write out these incoming arguments onto the stack.  Of course we
+     only need to do this if we have a stack frame.  */
+
+  while (!cache.frameless_p)
+    {
+      unsigned long insn = sparc_fetch_instruction (start_pc);
+
+      /* Recognize instructions that store incoming arguments in
+         %i0...%i5 into the corresponding stack slot.  */
+      if (X_OP (insn) == 3 && (X_OP3 (insn) & 0x3c) == 0x04 && X_I (insn)
+         && (X_RD (insn) >= 24 && X_RD (insn) <= 29) && X_RS1 (insn) == 30
+         && X_SIMM13 (insn) == 68 + (X_RD (insn) - 24) * 4)
+       {
+         start_pc += 4;
+         continue;
+       }
+
+      break;
+    }
+
+  return start_pc;
 }
 
 /* Normal frames.  */
@@ -648,6 +673,9 @@ sparc_frame_cache (struct frame_info *next_frame, void **this_cache)
        frame_unwind_register_unsigned (next_frame, SPARC_FP_REGNUM);
     }
 
+  if (cache->base & 1)
+    cache->base += BIAS;
+
   return cache;
 }
 
@@ -834,6 +862,8 @@ sparc_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame)
   CORE_ADDR sp;
 
   sp = frame_unwind_register_unsigned (next_frame, SPARC_SP_REGNUM);
+  if (sp & 1)
+    sp += BIAS;
   return frame_id_build (sp, frame_pc_unwind (next_frame));
 }
 \f
@@ -1242,6 +1272,16 @@ sparc_supply_rwindow (struct regcache *regcache, CORE_ADDR sp, int regnum)
          if (regnum == i || regnum == -1)
            {
              target_read_memory (sp + ((i - SPARC_L0_REGNUM) * 8), buf, 8);
+
+             /* Handle StackGhost.  */
+             if (i == SPARC_I7_REGNUM)
+               {
+                 ULONGEST wcookie = sparc_fetch_wcookie ();
+                 ULONGEST i7 = extract_unsigned_integer (buf + offset, 8);
+
+                 store_unsigned_integer (buf + offset, 8, i7 ^ wcookie);
+               }
+
              regcache_raw_supply (regcache, i, buf);
            }
        }
@@ -1300,6 +1340,16 @@ sparc_collect_rwindow (const struct regcache *regcache,
          if (regnum == -1 || regnum == SPARC_SP_REGNUM || regnum == i)
            {
              regcache_raw_collect (regcache, i, buf);
+
+             /* Handle StackGhost.  */
+             if (i == SPARC_I7_REGNUM)
+               {
+                 ULONGEST wcookie = sparc_fetch_wcookie ();
+                 ULONGEST i7 = extract_unsigned_integer (buf + offset, 8);
+
+                 store_unsigned_integer (buf, 8, i7 ^ wcookie);
+               }
+
              target_write_memory (sp + ((i - SPARC_L0_REGNUM) * 8), buf, 8);
            }
        }
This page took 0.025773 seconds and 4 git commands to generate.