gdb/
[deliverable/binutils-gdb.git] / gdb / s390-tdep.c
index e7dc48d5eb07b8b167efe1740b6e6ebc48d720a4..ca7ecc789800248f3d1707140c4ad120eba7291a 100644 (file)
@@ -1,7 +1,7 @@
 /* Target-dependent code for GDB, the GNU debugger.
 
-   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
-   Free Software Foundation, Inc.
+   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
+   2011 Free Software Foundation, Inc.
 
    Contributed by D.J. Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
    for IBM Deutschland Entwicklung GmbH, IBM Corporation.
@@ -43,7 +43,7 @@
 #include "dis-asm.h"
 #include "solib-svr4.h"
 #include "prologue-value.h"
-
+#include "linux-tdep.h"
 #include "s390-tdep.h"
 
 #include "features/s390-linux32.c"
@@ -216,7 +216,7 @@ s390_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
   internal_error (__FILE__, __LINE__, _("invalid regnum"));
 }
 
-static void
+static enum register_status
 s390_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
                           int regnum, gdb_byte *buf)
 {
@@ -227,37 +227,53 @@ s390_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
 
   if (regnum == tdep->pc_regnum)
     {
-      regcache_raw_read_unsigned (regcache, S390_PSWA_REGNUM, &val);
-      if (register_size (gdbarch, S390_PSWA_REGNUM) == 4)
-       val &= 0x7fffffff;
-      store_unsigned_integer (buf, regsize, byte_order, val);
-      return;
+      enum register_status status;
+
+      status = regcache_raw_read_unsigned (regcache, S390_PSWA_REGNUM, &val);
+      if (status == REG_VALID)
+       {
+         if (register_size (gdbarch, S390_PSWA_REGNUM) == 4)
+           val &= 0x7fffffff;
+         store_unsigned_integer (buf, regsize, byte_order, val);
+       }
+      return status;
     }
 
   if (regnum == tdep->cc_regnum)
     {
-      regcache_raw_read_unsigned (regcache, S390_PSWM_REGNUM, &val);
-      if (register_size (gdbarch, S390_PSWA_REGNUM) == 4)
-       val = (val >> 12) & 3;
-      else
-       val = (val >> 44) & 3;
-      store_unsigned_integer (buf, regsize, byte_order, val);
-      return;
+      enum register_status status;
+
+      status = regcache_raw_read_unsigned (regcache, S390_PSWM_REGNUM, &val);
+      if (status == REG_VALID)
+       {
+         if (register_size (gdbarch, S390_PSWA_REGNUM) == 4)
+           val = (val >> 12) & 3;
+         else
+           val = (val >> 44) & 3;
+         store_unsigned_integer (buf, regsize, byte_order, val);
+       }
+      return status;
     }
 
   if (tdep->gpr_full_regnum != -1
       && regnum >= tdep->gpr_full_regnum
       && regnum < tdep->gpr_full_regnum + 16)
     {
+      enum register_status status;
       ULONGEST val_upper;
+
       regnum -= tdep->gpr_full_regnum;
 
-      regcache_raw_read_unsigned (regcache, S390_R0_REGNUM + regnum, &val);
-      regcache_raw_read_unsigned (regcache, S390_R0_UPPER_REGNUM + regnum,
-                                 &val_upper);
-      val |= val_upper << 32;
-      store_unsigned_integer (buf, regsize, byte_order, val);
-      return;
+      status = regcache_raw_read_unsigned (regcache, S390_R0_REGNUM + regnum, &val);
+      if (status == REG_VALID)
+       status = regcache_raw_read_unsigned (regcache, S390_R0_UPPER_REGNUM + regnum,
+                                            &val_upper);
+      if (status == REG_VALID)
+       {
+         val |= val_upper << 32;
+         store_unsigned_integer (buf, regsize, byte_order, val);
+       }
+      return status;
     }
 
   internal_error (__FILE__, __LINE__, _("invalid regnum"));
@@ -959,7 +975,8 @@ s390_load (struct s390_prologue_data *data,
    register was saved, record its offset in the reg_offset table in
    PROLOGUE_UNTYPED.  */
 static void
-s390_check_for_saved (void *data_untyped, pv_t addr, CORE_ADDR size, pv_t value)
+s390_check_for_saved (void *data_untyped, pv_t addr,
+                     CORE_ADDR size, pv_t value)
 {
   struct s390_prologue_data *data = data_untyped;
   int i, offset;
@@ -1118,7 +1135,8 @@ s390_analyze_prologue (struct gdbarch *gdbarch,
        s390_store (data, d2, x2, b2, data->fpr_size, data->fpr[r1]);
 
       /* STM r1, r3, d2(b2) --- store multiple.  */
-      /* STMY r1, r3, d2(b2) --- store multiple (long-displacement version).  */
+      /* STMY r1, r3, d2(b2) --- store multiple (long-displacement
+        version).  */
       /* STMG r1, r3, d2(b2) --- store multiple (64-bit version).  */
       else if (is_rs (insn32, op_stm, &r1, &r3, &d2, &b2)
               || is_rsy (insn32, op1_stmy, op2_stmy, &r1, &r3, &d2, &b2)
@@ -1289,7 +1307,7 @@ s390_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
      exactly one case: when pc points to that branch instruction.
 
      Thus we try to disassemble the one instructions immediately
-     preceeding pc and check whether it is an LM-type instruction
+     preceding pc and check whether it is an LM-type instruction
      modifying the stack pointer.
 
      Note that disassembling backwards is not reliable, so there
@@ -1532,7 +1550,7 @@ s390_prologue_frame_unwind_cache (struct frame_info *this_frame,
 
   /* If we've detected a function with stack frame, we'll still have to 
      treat it as frameless if we're currently within the function epilog 
-     code at a point where the frame pointer has already been restored.  
+     code at a point where the frame pointer has already been restored.
      This can only happen in an innermost frame.  */
   /* FIXME: cagney/2004-05-01: This sanity check shouldn't be needed,
      instead the code should simpliy rely on its analysis.  */
@@ -1740,6 +1758,7 @@ s390_frame_prev_register (struct frame_info *this_frame,
 
 static const struct frame_unwind s390_frame_unwind = {
   NORMAL_FRAME,
+  default_frame_unwind_stop_reason,
   s390_frame_this_id,
   s390_frame_prev_register,
   NULL,
@@ -1823,6 +1842,7 @@ s390_stub_frame_sniffer (const struct frame_unwind *self,
 
 static const struct frame_unwind s390_stub_frame_unwind = {
   NORMAL_FRAME,
+  default_frame_unwind_stop_reason,
   s390_stub_frame_this_id,
   s390_stub_frame_prev_register,
   NULL,
@@ -1865,7 +1885,7 @@ s390_sigtramp_frame_unwind_cache (struct frame_info *this_frame,
   /* New-style RT frame:
        retcode + alignment (8 bytes)
        siginfo (128 bytes)
-       ucontext (contains sigregs at offset 5 words)  */
+       ucontext (contains sigregs at offset 5 words).  */
   if (next_ra == next_cfa)
     {
       sigreg_ptr = next_cfa + 8 + 128 + align_up (5*word_size, 8);
@@ -1876,7 +1896,7 @@ s390_sigtramp_frame_unwind_cache (struct frame_info *this_frame,
 
   /* Old-style RT frame and all non-RT frames:
        old signal mask (8 bytes)
-       pointer to sigregs  */
+       pointer to sigregs.  */
   else
     {
       sigreg_ptr = read_memory_unsigned_integer (next_cfa + 8,
@@ -2014,6 +2034,7 @@ s390_sigtramp_frame_sniffer (const struct frame_unwind *self,
 
 static const struct frame_unwind s390_sigtramp_frame_unwind = {
   SIGTRAMP_FRAME,
+  default_frame_unwind_stop_reason,
   s390_sigtramp_frame_this_id,
   s390_sigtramp_frame_prev_register,
   NULL,
@@ -2343,14 +2364,13 @@ s390_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   int word_size = gdbarch_ptr_bit (gdbarch) / 8;
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
-  ULONGEST orig_sp;
   int i;
 
   /* If the i'th argument is passed as a reference to a copy, then
      copy_addr[i] is the address of the copy we made.  */
   CORE_ADDR *copy_addr = alloca (nargs * sizeof (CORE_ADDR));
 
-  /* Build the reference-to-copy area.  */
+  /* Reserve space for the reference-to-copy area.  */
   for (i = 0; i < nargs; i++)
     {
       struct value *arg = args[i];
@@ -2361,7 +2381,6 @@ s390_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
         {
           sp -= length;
           sp = align_down (sp, alignment_of (type));
-          write_memory (sp, value_contents (arg), length);
           copy_addr[i] = sp;
         }
     }
@@ -2376,13 +2395,26 @@ s390_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
      boundary.  */
   sp = align_down (sp, 8);
 
+  /* Allocate the standard frame areas: the register save area, the
+     word reserved for the compiler (which seems kind of meaningless),
+     and the back chain pointer.  */
+  sp -= 16*word_size + 32;
+
+  /* Now we have the final SP value.  Make sure we didn't underflow;
+     on 31-bit, this would result in addresses with the high bit set,
+     which causes confusion elsewhere.  Note that if we error out
+     here, stack and registers remain untouched.  */
+  if (gdbarch_addr_bits_remove (gdbarch, sp) != sp)
+    error (_("Stack overflow"));
+
+
   /* Finally, place the actual parameters, working from SP towards
      higher addresses.  The code above is supposed to reserve enough
      space for this.  */
   {
     int fr = 0;
     int gr = 2;
-    CORE_ADDR starg = sp;
+    CORE_ADDR starg = sp + 16*word_size + 32;
 
     /* A struct is returned using general register 2.  */
     if (struct_return)
@@ -2400,6 +2432,10 @@ s390_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
 
        if (s390_function_arg_pass_by_reference (type))
          {
+           /* Actually copy the argument contents to the stack slot
+              that was reserved above.  */
+           write_memory (copy_addr[i], value_contents (arg), length);
+
            if (gr <= 6)
              {
                regcache_cooked_write_unsigned (regcache, S390_R0_REGNUM + gr,
@@ -2439,7 +2475,8 @@ s390_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
              {
                /* Integer arguments are always extended to word size.  */
                regcache_cooked_write_signed (regcache, S390_R0_REGNUM + gr,
-                                             extend_simple_arg (gdbarch, arg));
+                                             extend_simple_arg (gdbarch,
+                                                                arg));
                gr++;
              }
            else
@@ -2475,11 +2512,6 @@ s390_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
       }
   }
 
-  /* Allocate the standard frame areas: the register save area, the
-     word reserved for the compiler (which seems kind of meaningless),
-     and the back chain pointer.  */
-  sp -= 16*word_size + 32;
-
   /* Store return address.  */
   regcache_cooked_write_unsigned (regcache, S390_RETADDR_REGNUM, bp_addr);
   
@@ -2624,7 +2656,8 @@ s390_return_value (struct gdbarch *gdbarch, struct type *func_type,
 /* Breakpoints.  */
 
 static const gdb_byte *
-s390_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr, int *lenptr)
+s390_breakpoint_from_pc (struct gdbarch *gdbarch,
+                        CORE_ADDR *pcptr, int *lenptr)
 {
   static const gdb_byte breakpoint[] = { 0x0, 0x1 };
 
@@ -2660,7 +2693,8 @@ s390_address_class_type_flags_to_name (struct gdbarch *gdbarch, int type_flags)
 }
 
 static int
-s390_address_class_name_to_type_flags (struct gdbarch *gdbarch, const char *name,
+s390_address_class_name_to_type_flags (struct gdbarch *gdbarch,
+                                      const char *name,
                                       int *type_flags_ptr)
 {
   if (strcmp (name, "mode32") == 0)
@@ -2899,6 +2933,10 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
                                        displaced_step_at_entry_point);
   set_gdbarch_max_insn_length (gdbarch, S390_MAX_INSTR_SIZE);
 
+  /* Note that GNU/Linux is the only OS supported on this
+     platform.  */
+  linux_init_abi (info, gdbarch);
+
   switch (tdep->abi)
     {
     case ABI_LINUX_S390:
This page took 0.02647 seconds and 4 git commands to generate.