* gdb.texinfo (Packets): Fix typos "alligned".
[deliverable/binutils-gdb.git] / gdb / s390-tdep.c
index d79654d878f534b48779ce4453e288dc760c64b5..f19e4ddfdd8c9fcc91a22bbe4ba1adaa4f1fcb25 100644 (file)
@@ -1,5 +1,7 @@
 /* Target-dependent code for GDB, the GNU debugger.
 /* Target-dependent code for GDB, the GNU debugger.
-   Copyright 2001 Free Software Foundation, Inc.
+
+   Copyright 2001, 2002 Free Software Foundation, Inc.
+
    Contributed by D.J. Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
    for IBM Deutschland Entwicklung GmbH, IBM Corporation.
 
    Contributed by D.J. Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
    for IBM Deutschland Entwicklung GmbH, IBM Corporation.
 
 
 
 /* Number of bytes of storage in the actual machine representation
 
 
 /* Number of bytes of storage in the actual machine representation
-   for register N. 
-   Note that the unsigned cast here forces the result of the
-   subtraction to very high positive values if N < S390_FP0_REGNUM */
+   for register N.  */
 int
 s390_register_raw_size (int reg_nr)
 {
 int
 s390_register_raw_size (int reg_nr)
 {
-  return ((unsigned) reg_nr - S390_FP0_REGNUM) <
-    S390_NUM_FPRS ? S390_FPR_SIZE : 4;
+  if (S390_FP0_REGNUM <= reg_nr
+      && reg_nr < S390_FP0_REGNUM + S390_NUM_FPRS)
+    return S390_FPR_SIZE;
+  else
+    return 4;
 }
 
 int
 }
 
 int
@@ -131,8 +134,11 @@ s390_readinstruction (bfd_byte instr[], CORE_ADDR at,
   if ((*info->read_memory_func) (at, &instr[0], 2, info))
     return -1;
   instrlen = s390_instrlen[instr[0] >> 6];
   if ((*info->read_memory_func) (at, &instr[0], 2, info))
     return -1;
   instrlen = s390_instrlen[instr[0] >> 6];
-  if ((*info->read_memory_func) (at + 2, &instr[2], instrlen - 2, info))
-    return -1;
+  if (instrlen > 2)
+    {
+      if ((*info->read_memory_func) (at + 2, &instr[2], instrlen - 2, info))
+        return -1;
+    }
   return instrlen;
 }
 
   return instrlen;
 }
 
@@ -144,25 +150,26 @@ s390_memset_extra_info (struct frame_extra_info *fextra_info)
 
 
 
 
 
 
-char *
+const char *
 s390_register_name (int reg_nr)
 {
   static char *register_names[] = {
     "pswm", "pswa",
 s390_register_name (int reg_nr)
 {
   static char *register_names[] = {
     "pswm", "pswa",
-    "gpr0", "gpr1", "gpr2", "gpr3", "gpr4", "gpr5", "gpr6", "gpr7",
-    "gpr8", "gpr9", "gpr10", "gpr11", "gpr12", "gpr13", "gpr14", "gpr15",
+    "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+    "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
     "acr0", "acr1", "acr2", "acr3", "acr4", "acr5", "acr6", "acr7",
     "acr8", "acr9", "acr10", "acr11", "acr12", "acr13", "acr14", "acr15",
     "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7",
     "cr8", "cr9", "cr10", "cr11", "cr12", "cr13", "cr14", "cr15",
     "fpc",
     "acr0", "acr1", "acr2", "acr3", "acr4", "acr5", "acr6", "acr7",
     "acr8", "acr9", "acr10", "acr11", "acr12", "acr13", "acr14", "acr15",
     "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7",
     "cr8", "cr9", "cr10", "cr11", "cr12", "cr13", "cr14", "cr15",
     "fpc",
-    "fpr0", "fpr1", "fpr2", "fpr3", "fpr4", "fpr5", "fpr6", "fpr7",
-    "fpr8", "fpr9", "fpr10", "fpr11", "fpr12", "fpr13", "fpr14", "fpr15"
+    "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
+    "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15"
   };
 
   };
 
-  if (reg_nr >= S390_LAST_REGNUM)
+  if (reg_nr <= S390_LAST_REGNUM)
+    return register_names[reg_nr];
+  else
     return NULL;
     return NULL;
-  return register_names[reg_nr];
 }
 
 
 }
 
 
@@ -180,6 +187,14 @@ s390_stab_reg_to_regnum (int regno)
 }
 
 
 }
 
 
+/* Return true if REGIDX is the number of a register used to pass
+     arguments, false otherwise.  */
+static int
+is_arg_reg (int regidx)
+{
+  return 2 <= regidx && regidx <= 6;
+}
+
 
 /* s390_get_frame_info based on Hartmuts
    prologue definition in
 
 /* s390_get_frame_info based on Hartmuts
    prologue definition in
@@ -208,15 +223,45 @@ s390_get_frame_info (CORE_ADDR pc, struct frame_extra_info *fextra_info,
   int gprs_saved[S390_NUM_GPRS];
   int fprs_saved[S390_NUM_FPRS];
   int regidx, instrlen;
   int gprs_saved[S390_NUM_GPRS];
   int fprs_saved[S390_NUM_FPRS];
   int regidx, instrlen;
-  int save_link_regidx, subtract_sp_regidx;
-  int const_pool_state, save_link_state;
-  int frame_pointer_found, varargs_state;
+  int const_pool_state;
+  int varargs_state;
   int loop_cnt, gdb_gpr_store, gdb_fpr_store;
   int loop_cnt, gdb_gpr_store, gdb_fpr_store;
-  int frame_pointer_regidx = 0xf;
   int offset, expected_offset;
   int err = 0;
   disassemble_info info;
 
   int offset, expected_offset;
   int err = 0;
   disassemble_info info;
 
+  /* Have we seen an instruction initializing the frame pointer yet?
+     If we've seen an `lr %r11, %r15', then frame_pointer_found is
+     non-zero, and frame_pointer_regidx == 11.  Otherwise,
+     frame_pointer_found is zero and frame_pointer_regidx is 15,
+     indicating that we're using the stack pointer as our frame
+     pointer.  */
+  int frame_pointer_found = 0;
+  int frame_pointer_regidx = 0xf;
+
+  /* What we've seen so far regarding saving the back chain link:
+     0 -- nothing yet; sp still has the same value it had at the entry
+          point.  Since not all functions allocate frames, this is a
+          valid state for the prologue to finish in.
+     1 -- We've saved the original sp in some register other than the
+          frame pointer (hard-coded to be %r11, yuck).
+          save_link_regidx is the register we saved it in.
+     2 -- We've seen the initial `bras' instruction of the sequence for
+          reserving more than 32k of stack:
+                bras %rX, .+8
+                .long N
+                s %r15, 0(%rX)
+          where %rX is not the constant pool register.
+          subtract_sp_regidx is %rX, and fextra_info->stack_bought is N.
+     3 -- We've reserved space for a new stack frame.  This means we
+          either saw a simple `ahi %r15,-N' in state 1, or the final
+          `s %r15, ...' in state 2.
+     4 -- The frame and link are now fully initialized.  We've
+          reserved space for the new stack frame, and stored the old
+          stack pointer captured in the back chain pointer field.  */
+  int save_link_state = 0;
+  int save_link_regidx, subtract_sp_regidx;
+
   /* What we've seen so far regarding r12 --- the GOT (Global Offset
      Table) pointer.  We expect to see `l %r12, N(%r13)', which loads
      r12 with the offset from the constant pool to the GOT, and then
   /* What we've seen so far regarding r12 --- the GOT (Global Offset
      Table) pointer.  We expect to see `l %r12, N(%r13)', which loads
      r12 with the offset from the constant pool to the GOT, and then
@@ -228,11 +273,11 @@ s390_get_frame_info (CORE_ADDR pc, struct frame_extra_info *fextra_info,
      When got_state is 1, then got_load_addr is the address of the
      load instruction, and got_load_len is the length of that
      instruction.  */
      When got_state is 1, then got_load_addr is the address of the
      load instruction, and got_load_len is the length of that
      instruction.  */
-  int got_state;
+  int got_state= 0;
   CORE_ADDR got_load_addr = 0, got_load_len = 0;
 
   CORE_ADDR got_load_addr = 0, got_load_len = 0;
 
-  const_pool_state = save_link_state = got_state = varargs_state = 0;
-  frame_pointer_found = 0;
+  const_pool_state = varargs_state = 0;
+
   memset (gprs_saved, 0, sizeof (gprs_saved));
   memset (fprs_saved, 0, sizeof (fprs_saved));
   info.read_memory_func = dis_asm_read_memory;
   memset (gprs_saved, 0, sizeof (gprs_saved));
   memset (fprs_saved, 0, sizeof (fprs_saved));
   info.read_memory_func = dis_asm_read_memory;
@@ -242,7 +287,9 @@ s390_get_frame_info (CORE_ADDR pc, struct frame_extra_info *fextra_info,
     {
       if (fi && fi->frame)
        {
     {
       if (fi && fi->frame)
        {
-         orig_sp = fi->frame + fextra_info->stack_bought;
+          orig_sp = fi->frame;
+          if (! init_extra_info && fextra_info->initialised)
+            orig_sp += fextra_info->stack_bought;
          saved_regs = fi->saved_regs;
        }
       if (init_extra_info || !fextra_info->initialised)
          saved_regs = fi->saved_regs;
        }
       if (init_extra_info || !fextra_info->initialised)
@@ -374,6 +421,28 @@ s390_get_frame_info (CORE_ADDR pc, struct frame_extra_info *fextra_info,
          continue;
        }
 
          continue;
        }
 
+      /* Check for an fp-relative STG, ST, or STM.  This is probably
+          spilling an argument from a register out into a stack slot.
+          This could be a user instruction, but if we haven't included
+          any other suspicious instructions in the prologue, this
+          could only be an initializing store, which isn't too bad to
+          skip.  The consequences of not including arg-to-stack spills
+          are more serious, though --- you don't see the proper values
+          of the arguments.  */
+      if ((save_link_state == 3 || save_link_state == 4)
+          && ((instr[0] == 0x50      /* st %rA, D(%rX,%rB) */
+               && (instr[1] & 0xf) == 0 /* %rX is zero, no index reg */
+               && is_arg_reg ((instr[1] >> 4) & 0xf)
+               && ((instr[2] >> 4) & 0xf) == frame_pointer_regidx)
+              || (instr[0] == 0x90 /* stm %rA, %rB, D(%rC) */
+                  && is_arg_reg ((instr[1] >> 4) & 0xf)
+                  && is_arg_reg (instr[1] & 0xf)
+                  && ((instr[2] >> 4) & 0xf) == frame_pointer_regidx)))
+        {
+          valid_prologue = 1;
+          continue;
+        }
+
       /* check for STD */
       if (instr[0] == 0x60 && (instr[2] >> 4) == 0xf)
        {
       /* check for STD */
       if (instr[0] == 0x60 && (instr[2] >> 4) == 0xf)
        {
@@ -492,7 +561,8 @@ s390_get_frame_info (CORE_ADDR pc, struct frame_extra_info *fextra_info,
       /* Alternatively check for the complex construction for
          buying more than 32k of stack
          BRAS gprx,.+8
       /* Alternatively check for the complex construction for
          buying more than 32k of stack
          BRAS gprx,.+8
-         long vals    %r15,0(%gprx)  gprx currently r1 */
+         long val
+         s    %r15,0(%gprx)  gprx currently r1 */
       if ((save_link_state == 1) && (instr[0] == 0xa7)
          && ((instr[1] & 0xf) == 0x5) && (instr[2] == 0)
          && (instr[3] == 0x4) && ((instr[1] >> 4) != CONST_POOL_REGIDX))
       if ((save_link_state == 1) && (instr[0] == 0xa7)
          && ((instr[1] & 0xf) == 0x5) && (instr[2] == 0)
          && (instr[3] == 0x4) && ((instr[1] >> 4) != CONST_POOL_REGIDX))
@@ -884,20 +954,24 @@ s390_frame_saved_pc_nofix (struct frame_info *fi)
 {
   if (fi->extra_info && fi->extra_info->saved_pc_valid)
     return fi->extra_info->saved_pc;
 {
   if (fi->extra_info && fi->extra_info->saved_pc_valid)
     return fi->extra_info->saved_pc;
+
+  if (deprecated_generic_find_dummy_frame (fi->pc, fi->frame))
+    return deprecated_read_register_dummy (fi->pc, fi->frame, S390_PC_REGNUM);
+
   s390_frame_init_saved_regs (fi);
   if (fi->extra_info)
     {
       fi->extra_info->saved_pc_valid = 1;
   s390_frame_init_saved_regs (fi);
   if (fi->extra_info)
     {
       fi->extra_info->saved_pc_valid = 1;
-      if (fi->extra_info->good_prologue)
-       {
-         if (fi->saved_regs[S390_RETADDR_REGNUM])
-           {
-             return (fi->extra_info->saved_pc =
-                     ADDR_BITS_REMOVE (read_memory_integer
-                                       (fi->saved_regs[S390_RETADDR_REGNUM],
-                                        S390_GPR_SIZE)));
-           }
-       }
+      if (fi->extra_info->good_prologue
+          && fi->saved_regs[S390_RETADDR_REGNUM])
+        fi->extra_info->saved_pc
+          = ADDR_BITS_REMOVE (read_memory_integer
+                              (fi->saved_regs[S390_RETADDR_REGNUM],
+                               S390_GPR_SIZE));
+      else
+        fi->extra_info->saved_pc
+          = ADDR_BITS_REMOVE (read_register (S390_RETADDR_REGNUM));
+      return fi->extra_info->saved_pc;
     }
   return 0;
 }
     }
   return 0;
 }
@@ -935,8 +1009,9 @@ s390_frame_chain (struct frame_info *thisframe)
 {
   CORE_ADDR prev_fp = 0;
 
 {
   CORE_ADDR prev_fp = 0;
 
-  if (thisframe->prev && thisframe->prev->frame)
-    prev_fp = thisframe->prev->frame;
+  if (deprecated_generic_find_dummy_frame (thisframe->pc, thisframe->frame))
+    return deprecated_read_register_dummy (thisframe->pc, thisframe->frame,
+                                          S390_SP_REGNUM);
   else
     {
       int sigreturn = 0;
   else
     {
       int sigreturn = 0;
@@ -974,18 +1049,24 @@ s390_frame_chain (struct frame_info *thisframe)
        {
          if (thisframe->saved_regs)
            {
        {
          if (thisframe->saved_regs)
            {
-
              int regno;
 
              int regno;
 
-             regno =
-               ((prev_fextra_info.frame_pointer_saved_pc
-                 && thisframe->
-                 saved_regs[S390_FRAME_REGNUM]) ? S390_FRAME_REGNUM :
-                S390_SP_REGNUM);
+              if (prev_fextra_info.frame_pointer_saved_pc
+                  && thisframe->saved_regs[S390_FRAME_REGNUM])
+                regno = S390_FRAME_REGNUM;
+              else
+                regno = S390_SP_REGNUM;
+
              if (thisframe->saved_regs[regno])
              if (thisframe->saved_regs[regno])
-               prev_fp =
-                 read_memory_integer (thisframe->saved_regs[regno],
-                                      S390_GPR_SIZE);
+                {
+                  /* The SP's entry of `saved_regs' is special.  */
+                  if (regno == S390_SP_REGNUM)
+                    prev_fp = thisframe->saved_regs[regno];
+                  else
+                    prev_fp =
+                      read_memory_integer (thisframe->saved_regs[regno],
+                                           S390_GPR_SIZE);
+                }
            }
        }
     }
            }
        }
     }
@@ -1067,12 +1148,13 @@ s390_store_return_value (struct type *valtype, char *valbuf)
 
   if (TYPE_CODE (valtype) == TYPE_CODE_FLT)
     {
 
   if (TYPE_CODE (valtype) == TYPE_CODE_FLT)
     {
-      DOUBLEST tempfloat = extract_floating (valbuf, TYPE_LENGTH (valtype));
-
-      floatformat_from_doublest (&floatformat_ieee_double_big, &tempfloat,
-                                reg_buff);
-      write_register_bytes (REGISTER_BYTE (S390_FP0_REGNUM), reg_buff,
-                           S390_FPR_SIZE);
+      if (TYPE_LENGTH (valtype) == 4
+          || TYPE_LENGTH (valtype) == 8)
+        write_register_bytes (REGISTER_BYTE (S390_FP0_REGNUM), valbuf,
+                              TYPE_LENGTH (valtype));
+      else
+        error ("GDB is unable to return `long double' values "
+               "on this architecture.");
     }
   else
     {
     }
   else
     {
@@ -1107,7 +1189,7 @@ gdb_print_insn_s390 (bfd_vma memaddr, disassemble_info * info)
 
 /* Not the most efficent code in the world */
 int
 
 /* Not the most efficent code in the world */
 int
-s390_fp_regnum ()
+s390_fp_regnum (void)
 {
   int regno = S390_SP_REGNUM;
   struct frame_extra_info fextra_info;
 {
   int regno = S390_SP_REGNUM;
   struct frame_extra_info fextra_info;
@@ -1122,35 +1204,12 @@ s390_fp_regnum ()
 }
 
 CORE_ADDR
 }
 
 CORE_ADDR
-s390_read_fp ()
+s390_read_fp (void)
 {
   return read_register (s390_fp_regnum ());
 }
 
 
 {
   return read_register (s390_fp_regnum ());
 }
 
 
-void
-s390_write_fp (CORE_ADDR val)
-{
-  write_register (s390_fp_regnum (), val);
-}
-
-
-void
-s390_push_dummy_frame ()
-{
-  CORE_ADDR orig_sp = read_register (S390_SP_REGNUM), new_sp;
-  void *saved_regs = alloca (REGISTER_BYTES);
-
-  new_sp = (orig_sp - (REGISTER_BYTES + S390_GPR_SIZE));
-  read_register_bytes (0, (char *) saved_regs, REGISTER_BYTES);
-  /* Use saved copy instead of orig_sp as this will have the correct endianness */
-  write_memory (new_sp, (char *) saved_regs + REGISTER_BYTE (S390_SP_REGNUM),
-               S390_GPR_SIZE);
-  write_memory (new_sp + S390_GPR_SIZE, (char *) &saved_regs, REGISTER_BYTES);
-  write_register (S390_SP_REGNUM, new_sp);
-}
-
-
 static void
 s390_pop_frame_regular (struct frame_info *frame)
 {
 static void
 s390_pop_frame_regular (struct frame_info *frame)
 {
@@ -1159,20 +1218,23 @@ s390_pop_frame_regular (struct frame_info *frame)
   write_register (S390_PC_REGNUM, FRAME_SAVED_PC (frame));
 
   /* Restore any saved registers.  */
   write_register (S390_PC_REGNUM, FRAME_SAVED_PC (frame));
 
   /* Restore any saved registers.  */
-  for (regnum = 0; regnum < NUM_REGS; regnum++)
-    if (frame->saved_regs[regnum] != 0)
-      {
-        ULONGEST value;
-
-        value = read_memory_unsigned_integer (frame->saved_regs[regnum],
-                                              REGISTER_RAW_SIZE (regnum));
-        write_register (regnum, value);
-      }
+  if (frame->saved_regs)
+    {
+      for (regnum = 0; regnum < NUM_REGS; regnum++)
+        if (frame->saved_regs[regnum] != 0)
+          {
+            ULONGEST value;
+            
+            value = read_memory_unsigned_integer (frame->saved_regs[regnum],
+                                                  REGISTER_RAW_SIZE (regnum));
+            write_register (regnum, value);
+          }
 
 
-  /* Actually cut back the stack.  Remember that the SP's element of
-     saved_regs is the old SP itself, not the address at which it is
-     saved.  */
-  write_register (S390_SP_REGNUM, frame->saved_regs[S390_SP_REGNUM]);
+      /* Actually cut back the stack.  Remember that the SP's element of
+         saved_regs is the old SP itself, not the address at which it is
+         saved.  */
+      write_register (S390_SP_REGNUM, frame->saved_regs[S390_SP_REGNUM]);
+    }
 
   /* Throw away any cached frame information.  */
   flush_cached_frames ();
 
   /* Throw away any cached frame information.  */
   flush_cached_frames ();
@@ -1184,7 +1246,7 @@ s390_pop_frame_regular (struct frame_info *frame)
    Used in the contexts of the "return" command, and of 
    target function calls from the debugger.  */
 void
    Used in the contexts of the "return" command, and of 
    target function calls from the debugger.  */
 void
-s390_pop_frame ()
+s390_pop_frame (void)
 {
   /* This function checks for and handles generic dummy frames, and
      calls back to our function for ordinary frames.  */
 {
   /* This function checks for and handles generic dummy frames, and
      calls back to our function for ordinary frames.  */
@@ -1221,36 +1283,96 @@ is_pointer_like (struct type *type)
 }
 
 
 }
 
 
+/* Return non-zero if TYPE is a `float singleton' or `double
+   singleton', zero otherwise.
+
+   A `T singleton' is a struct type with one member, whose type is
+   either T or a `T singleton'.  So, the following are all float
+   singletons:
+
+   struct { float x };
+   struct { struct { float x; } x; };
+   struct { struct { struct { float x; } x; } x; };
+
+   ... and so on.
+
+   WHY THE HECK DO WE CARE ABOUT THIS???  Well, it turns out that GCC
+   passes all float singletons and double singletons as if they were
+   simply floats or doubles.  This is *not* what the ABI says it
+   should do.  */
+static int
+is_float_singleton (struct type *type)
+{
+  return (TYPE_CODE (type) == TYPE_CODE_STRUCT
+          && TYPE_NFIELDS (type) == 1
+          && (TYPE_CODE (TYPE_FIELD_TYPE (type, 0)) == TYPE_CODE_FLT
+              || is_float_singleton (TYPE_FIELD_TYPE (type, 0))));
+}
+
+
+/* Return non-zero if TYPE is a struct-like type, zero otherwise.
+   "Struct-like" types are those that should be passed as structs are:
+   structs and unions.
+
+   As an odd quirk, not mentioned in the ABI, GCC passes float and
+   double singletons as if they were a plain float, double, etc.  (The
+   corresponding union types are handled normally.)  So we exclude
+   those types here.  *shrug* */
+static int
+is_struct_like (struct type *type)
+{
+  enum type_code code = TYPE_CODE (type);
+
+  return (code == TYPE_CODE_UNION
+          || (code == TYPE_CODE_STRUCT && ! is_float_singleton (type)));
+}
+
+
+/* Return non-zero if TYPE is a float-like type, zero otherwise.
+   "Float-like" types are those that should be passed as
+   floating-point values are.
+
+   You'd think this would just be floats, doubles, long doubles, etc.
+   But as an odd quirk, not mentioned in the ABI, GCC passes float and
+   double singletons as if they were a plain float, double, etc.  (The
+   corresponding union types are handled normally.)  So we exclude
+   those types here.  *shrug* */
+static int
+is_float_like (struct type *type)
+{
+  return (TYPE_CODE (type) == TYPE_CODE_FLT
+          || is_float_singleton (type));
+}
+
+
 /* Return non-zero if TYPE is considered a `DOUBLE_OR_FLOAT', as
    defined by the parameter passing conventions described in the
 /* Return non-zero if TYPE is considered a `DOUBLE_OR_FLOAT', as
    defined by the parameter passing conventions described in the
-   "Linux for S/390 ELF Application Binary Interface Supplement".
+   "GNU/Linux for S/390 ELF Application Binary Interface Supplement".
    Otherwise, return zero.  */
 static int
 is_double_or_float (struct type *type)
 {
    Otherwise, return zero.  */
 static int
 is_double_or_float (struct type *type)
 {
-  return (TYPE_CODE (type) == TYPE_CODE_FLT
+  return (is_float_like (type)
           && (TYPE_LENGTH (type) == 4
               || TYPE_LENGTH (type) == 8));
 }
 
 
 /* Return non-zero if TYPE is considered a `SIMPLE_ARG', as defined by
           && (TYPE_LENGTH (type) == 4
               || TYPE_LENGTH (type) == 8));
 }
 
 
 /* Return non-zero if TYPE is considered a `SIMPLE_ARG', as defined by
-   the parameter passing conventions described in the "Linux for S/390
-   ELF Application Binary Interface Supplement".  Return zero otherwise.  */
+   the parameter passing conventions described in the "GNU/Linux for
+   S/390 ELF Application Binary Interface Supplement".  Return zero
+   otherwise.  */
 static int
 is_simple_arg (struct type *type)
 {
 static int
 is_simple_arg (struct type *type)
 {
-  enum type_code code = TYPE_CODE (type);
   unsigned length = TYPE_LENGTH (type);
 
   /* This is almost a direct translation of the ABI's language, except
      that we have to exclude 8-byte structs; those are DOUBLE_ARGs.  */
   return ((is_integer_like (type) && length <= 4)
           || is_pointer_like (type)
   unsigned length = TYPE_LENGTH (type);
 
   /* This is almost a direct translation of the ABI's language, except
      that we have to exclude 8-byte structs; those are DOUBLE_ARGs.  */
   return ((is_integer_like (type) && length <= 4)
           || is_pointer_like (type)
-          || ((code == TYPE_CODE_STRUCT
-               || code == TYPE_CODE_UNION)
-              && length != 8)
-          || (code == TYPE_CODE_FLT && length == 16));
+          || (is_struct_like (type) && length != 8)
+          || (is_float_like (type) && length == 16));
 }
 
 
 }
 
 
@@ -1260,12 +1382,10 @@ is_simple_arg (struct type *type)
 static int
 pass_by_copy_ref (struct type *type)
 {
 static int
 pass_by_copy_ref (struct type *type)
 {
-  enum type_code code = TYPE_CODE (type);
   unsigned length = TYPE_LENGTH (type);
 
   unsigned length = TYPE_LENGTH (type);
 
-  return (((code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION)
-           && length != 1 && length != 2 && length != 4)
-          || (code == TYPE_CODE_FLT && length == 16));
+  return ((is_struct_like (type) && length != 1 && length != 2 && length != 4)
+          || (is_float_like (type) && length == 16));
 }
 
 
 }
 
 
@@ -1289,17 +1409,16 @@ extend_simple_arg (struct value *arg)
 
 
 /* Return non-zero if TYPE is a `DOUBLE_ARG', as defined by the
 
 
 /* Return non-zero if TYPE is a `DOUBLE_ARG', as defined by the
-   parameter passing conventions described in the "Linux for S/390 ELF
-   Application Binary Interface Supplement".  Return zero otherwise.  */
+   parameter passing conventions described in the "GNU/Linux for S/390
+   ELF Application Binary Interface Supplement".  Return zero
+   otherwise.  */
 static int
 is_double_arg (struct type *type)
 {
 static int
 is_double_arg (struct type *type)
 {
-  enum type_code code = TYPE_CODE (type);
   unsigned length = TYPE_LENGTH (type);
 
   return ((is_integer_like (type)
   unsigned length = TYPE_LENGTH (type);
 
   return ((is_integer_like (type)
-           || code == TYPE_CODE_STRUCT
-           || code == TYPE_CODE_UNION)
+           || is_struct_like (type))
           && length == 8);
 }
 
           && length == 8);
 }
 
@@ -1363,8 +1482,8 @@ alignment_of (struct type *type)
 
 
 /* Put the actual parameter values pointed to by ARGS[0..NARGS-1] in
 
 
 /* Put the actual parameter values pointed to by ARGS[0..NARGS-1] in
-   place to be passed to a function, as specified by the "Linux for
-   S/390 ELF Application Binary Interface Supplement".
+   place to be passed to a function, as specified by the "GNU/Linux
+   for S/390 ELF Application Binary Interface Supplement".
 
    SP is the current stack pointer.  We must put arguments, links,
    padding, etc. whereever they belong, and return the new stack
 
    SP is the current stack pointer.  We must put arguments, links,
    padding, etc. whereever they belong, and return the new stack
@@ -1512,7 +1631,11 @@ s390_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
               }
             else
               {
               }
             else
               {
-                starg = round_up (starg, alignment_of (type));
+                /* You'd think we should say:
+                   starg = round_up (starg, alignment_of (type));
+                   Unfortunately, GCC seems to simply align the stack on
+                   a four-byte boundary, even when passing doubles.  */
+                starg = round_up (starg, 4);
                 write_memory (starg, VALUE_CONTENTS (arg), length);
                 starg += length;
               }
                 write_memory (starg, VALUE_CONTENTS (arg), length);
                 starg += length;
               }
@@ -1534,13 +1657,26 @@ s390_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
   return sp;
 }
 
   return sp;
 }
 
+
+static int
+s390_use_struct_convention (int gcc_p, struct type *value_type)
+{
+  enum type_code code = TYPE_CODE (value_type);
+
+  return (code == TYPE_CODE_STRUCT
+          || code == TYPE_CODE_UNION);
+}
+
+
 /* Return the GDB type object for the "standard" data type
    of data in register N.  */
 struct type *
 s390_register_virtual_type (int regno)
 {
 /* Return the GDB type object for the "standard" data type
    of data in register N.  */
 struct type *
 s390_register_virtual_type (int regno)
 {
-  return ((unsigned) regno - S390_FPC_REGNUM) <
-    S390_NUM_FPRS ? builtin_type_double : builtin_type_int;
+  if (S390_FP0_REGNUM <= regno && regno < S390_FP0_REGNUM + S390_NUM_FPRS)
+    return builtin_type_double;
+  else
+    return builtin_type_int;
 }
 
 
 }
 
 
@@ -1562,7 +1698,7 @@ s390_store_struct_return (CORE_ADDR addr, CORE_ADDR sp)
 
 
 
 
 
 
-static unsigned char *
+const static unsigned char *
 s390_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr)
 {
   static unsigned char breakpoint[] = { 0x0, 0x1 };
 s390_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr)
 {
   static unsigned char breakpoint[] = { 0x0, 0x1 };
@@ -1627,6 +1763,7 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   gdbarch = gdbarch_alloc (&info, NULL);
 
   set_gdbarch_believe_pcc_promotion (gdbarch, 0);
   gdbarch = gdbarch_alloc (&info, NULL);
 
   set_gdbarch_believe_pcc_promotion (gdbarch, 0);
+  set_gdbarch_char_signed (gdbarch, 0);
 
   set_gdbarch_frame_args_skip (gdbarch, 0);
   set_gdbarch_frame_args_address (gdbarch, s390_frame_args_address);
 
   set_gdbarch_frame_args_skip (gdbarch, 0);
   set_gdbarch_frame_args_address (gdbarch, s390_frame_args_address);
@@ -1636,14 +1773,13 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   /* We can't do this */
   set_gdbarch_frame_num_args (gdbarch, frame_num_args_unknown);
   set_gdbarch_store_struct_return (gdbarch, s390_store_struct_return);
   /* We can't do this */
   set_gdbarch_frame_num_args (gdbarch, frame_num_args_unknown);
   set_gdbarch_store_struct_return (gdbarch, s390_store_struct_return);
-  set_gdbarch_extract_return_value (gdbarch, s390_extract_return_value);
-  set_gdbarch_store_return_value (gdbarch, s390_store_return_value);
+  set_gdbarch_deprecated_extract_return_value (gdbarch, s390_extract_return_value);
+  set_gdbarch_deprecated_store_return_value (gdbarch, s390_store_return_value);
   /* Amount PC must be decremented by after a breakpoint.
      This is often the number of bytes in BREAKPOINT
      but not always.  */
   set_gdbarch_decr_pc_after_break (gdbarch, 2);
   set_gdbarch_pop_frame (gdbarch, s390_pop_frame);
   /* Amount PC must be decremented by after a breakpoint.
      This is often the number of bytes in BREAKPOINT
      but not always.  */
   set_gdbarch_decr_pc_after_break (gdbarch, 2);
   set_gdbarch_pop_frame (gdbarch, s390_pop_frame);
-  set_gdbarch_ieee_float (gdbarch, 1);
   /* Stack grows downward.  */
   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
   /* Offset from address of function to start of its code.
   /* Stack grows downward.  */
   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
   /* Offset from address of function to start of its code.
@@ -1656,7 +1792,6 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_init_extra_frame_info (gdbarch, s390_init_extra_frame_info);
   set_gdbarch_init_frame_pc_first (gdbarch, s390_init_frame_pc_first);
   set_gdbarch_read_fp (gdbarch, s390_read_fp);
   set_gdbarch_init_extra_frame_info (gdbarch, s390_init_extra_frame_info);
   set_gdbarch_init_frame_pc_first (gdbarch, s390_init_frame_pc_first);
   set_gdbarch_read_fp (gdbarch, s390_read_fp);
-  set_gdbarch_write_fp (gdbarch, s390_write_fp);
   /* This 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.  */
   /* This 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.  */
@@ -1676,13 +1811,15 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_num_regs (gdbarch, S390_NUM_REGS);
   set_gdbarch_cannot_fetch_register (gdbarch, s390_cannot_fetch_register);
   set_gdbarch_cannot_store_register (gdbarch, s390_cannot_fetch_register);
   set_gdbarch_num_regs (gdbarch, S390_NUM_REGS);
   set_gdbarch_cannot_fetch_register (gdbarch, s390_cannot_fetch_register);
   set_gdbarch_cannot_store_register (gdbarch, s390_cannot_fetch_register);
-  set_gdbarch_get_saved_register (gdbarch, generic_get_saved_register);
-  set_gdbarch_use_struct_convention (gdbarch, generic_use_struct_convention);
+  set_gdbarch_get_saved_register (gdbarch, generic_unwind_get_saved_register);
+  set_gdbarch_use_struct_convention (gdbarch, s390_use_struct_convention);
   set_gdbarch_frame_chain_valid (gdbarch, func_frame_chain_valid);
   set_gdbarch_register_name (gdbarch, s390_register_name);
   set_gdbarch_stab_reg_to_regnum (gdbarch, s390_stab_reg_to_regnum);
   set_gdbarch_dwarf_reg_to_regnum (gdbarch, s390_stab_reg_to_regnum);
   set_gdbarch_dwarf2_reg_to_regnum (gdbarch, s390_stab_reg_to_regnum);
   set_gdbarch_frame_chain_valid (gdbarch, func_frame_chain_valid);
   set_gdbarch_register_name (gdbarch, s390_register_name);
   set_gdbarch_stab_reg_to_regnum (gdbarch, s390_stab_reg_to_regnum);
   set_gdbarch_dwarf_reg_to_regnum (gdbarch, s390_stab_reg_to_regnum);
   set_gdbarch_dwarf2_reg_to_regnum (gdbarch, s390_stab_reg_to_regnum);
+  set_gdbarch_deprecated_extract_struct_value_address
+    (gdbarch, generic_cannot_extract_struct_value_address);
 
   /* Parameters for inferior function calls.  */
   set_gdbarch_call_dummy_p (gdbarch, 1);
 
   /* Parameters for inferior function calls.  */
   set_gdbarch_call_dummy_p (gdbarch, 1);
@@ -1694,10 +1831,10 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_pc_in_call_dummy (gdbarch, pc_in_call_dummy_at_entry_point);
   set_gdbarch_push_dummy_frame (gdbarch, generic_push_dummy_frame);
   set_gdbarch_push_arguments (gdbarch, s390_push_arguments);
   set_gdbarch_pc_in_call_dummy (gdbarch, pc_in_call_dummy_at_entry_point);
   set_gdbarch_push_dummy_frame (gdbarch, generic_push_dummy_frame);
   set_gdbarch_push_arguments (gdbarch, s390_push_arguments);
+  set_gdbarch_save_dummy_frame_tos (gdbarch, generic_save_dummy_frame_tos);
   set_gdbarch_call_dummy_breakpoint_offset_p (gdbarch, 1);
   set_gdbarch_call_dummy_breakpoint_offset (gdbarch, 0);
   set_gdbarch_call_dummy_stack_adjust_p (gdbarch, 0);
   set_gdbarch_call_dummy_breakpoint_offset_p (gdbarch, 1);
   set_gdbarch_call_dummy_breakpoint_offset (gdbarch, 0);
   set_gdbarch_call_dummy_stack_adjust_p (gdbarch, 0);
-  set_gdbarch_extract_struct_value_address (gdbarch, 0);
   set_gdbarch_fix_call_dummy (gdbarch, generic_fix_call_dummy);
   set_gdbarch_push_return_address (gdbarch, s390_push_return_address);
   set_gdbarch_sizeof_call_dummy_words (gdbarch,
   set_gdbarch_fix_call_dummy (gdbarch, generic_fix_call_dummy);
   set_gdbarch_push_return_address (gdbarch, s390_push_return_address);
   set_gdbarch_sizeof_call_dummy_words (gdbarch,
@@ -1708,7 +1845,7 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   switch (info.bfd_arch_info->mach)
     {
 
   switch (info.bfd_arch_info->mach)
     {
-    case bfd_mach_s390_esa:
+    case bfd_mach_s390_31:
       set_gdbarch_register_size (gdbarch, 4);
       set_gdbarch_register_raw_size (gdbarch, s390_register_raw_size);
       set_gdbarch_register_virtual_size (gdbarch, s390_register_raw_size);
       set_gdbarch_register_size (gdbarch, 4);
       set_gdbarch_register_raw_size (gdbarch, s390_register_raw_size);
       set_gdbarch_register_virtual_size (gdbarch, s390_register_raw_size);
@@ -1717,7 +1854,7 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       set_gdbarch_addr_bits_remove (gdbarch, s390_addr_bits_remove);
       set_gdbarch_register_bytes (gdbarch, S390_REGISTER_BYTES);
       break;
       set_gdbarch_addr_bits_remove (gdbarch, s390_addr_bits_remove);
       set_gdbarch_register_bytes (gdbarch, S390_REGISTER_BYTES);
       break;
-    case bfd_mach_s390_esame:
+    case bfd_mach_s390_64:
       set_gdbarch_register_size (gdbarch, 8);
       set_gdbarch_register_raw_size (gdbarch, s390x_register_raw_size);
       set_gdbarch_register_virtual_size (gdbarch, s390x_register_raw_size);
       set_gdbarch_register_size (gdbarch, 8);
       set_gdbarch_register_raw_size (gdbarch, s390x_register_raw_size);
       set_gdbarch_register_virtual_size (gdbarch, s390x_register_raw_size);
@@ -1737,7 +1874,7 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
 
 void
 
 
 void
-_initialize_s390_tdep ()
+_initialize_s390_tdep (void)
 {
 
   /* Hook us into the gdbarch mechanism.  */
 {
 
   /* Hook us into the gdbarch mechanism.  */
This page took 0.032255 seconds and 4 git commands to generate.