gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gdb / s390-tdep.c
index 1f2a536cd100b0ebcf35a9db82827ec26672b8ef..66369c690934b25be4d6755f343e235d1b3d6f2e 100644 (file)
@@ -1,6 +1,6 @@
 /* Target-dependent code for s390.
 
-   Copyright (C) 2001-2018 Free Software Foundation, Inc.
+   Copyright (C) 2001-2020 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -21,7 +21,7 @@
 
 #include "arch-utils.h"
 #include "ax-gdb.h"
-#include "dwarf2-frame.h"
+#include "dwarf2/frame.h"
 #include "elf/s390.h"
 #include "elf-bfd.h"
 #include "frame-base.h"
@@ -40,6 +40,9 @@
 #include "trad-frame.h"
 #include "value.h"
 
+#include "features/s390-linux32.c"
+#include "features/s390x-linux64.c"
+
 /* Holds the current set of options to be passed to the disassembler.  */
 static char *s390_disassembler_options;
 
@@ -49,6 +52,37 @@ constexpr gdb_byte s390_break_insn[] = { 0x0, 0x1 };
 
 typedef BP_MANIPULATION (s390_break_insn) s390_breakpoint;
 
+/* Types.  */
+
+/* Implement the gdbarch type alignment method.  */
+
+static ULONGEST
+s390_type_align (gdbarch *gdbarch, struct type *t)
+{
+  t = check_typedef (t);
+
+  if (TYPE_LENGTH (t) > 8)
+    {
+      switch (t->code ())
+       {
+       case TYPE_CODE_INT:
+       case TYPE_CODE_RANGE:
+       case TYPE_CODE_FLT:
+       case TYPE_CODE_ENUM:
+       case TYPE_CODE_CHAR:
+       case TYPE_CODE_BOOL:
+       case TYPE_CODE_DECFLOAT:
+         return 8;
+
+       case TYPE_CODE_ARRAY:
+         if (TYPE_VECTOR (t))
+           return 8;
+         break;
+       }
+    }
+  return 0;
+}
+
 /* Decoding S/390 instructions.  */
 
 /* Read a single instruction from address AT.  */
@@ -387,18 +421,18 @@ is_non_branch_ril (gdb_byte *insn)
   return 0;
 }
 
-typedef buf_displaced_step_closure s390_displaced_step_closure;
+typedef buf_displaced_step_copy_insn_closure s390_displaced_step_copy_insn_closure;
 
 /* Implementation of gdbarch_displaced_step_copy_insn.  */
 
-static struct displaced_step_closure *
+static displaced_step_copy_insn_closure_up
 s390_displaced_step_copy_insn (struct gdbarch *gdbarch,
                               CORE_ADDR from, CORE_ADDR to,
                               struct regcache *regs)
 {
   size_t len = gdbarch_max_insn_length (gdbarch);
-  std::unique_ptr<s390_displaced_step_closure> closure
-    (new s390_displaced_step_closure (len));
+  std::unique_ptr<s390_displaced_step_copy_insn_closure> closure
+    (new s390_displaced_step_copy_insn_closure (len));
   gdb_byte *buf = closure->buf.data ();
 
   read_memory (from, buf, len);
@@ -443,7 +477,8 @@ s390_displaced_step_copy_insn (struct gdbarch *gdbarch,
       displaced_step_dump_bytes (gdb_stdlog, buf, len);
     }
 
-  return closure.release ();
+  /* This is a work around for a problem with g++ 4.8.  */
+  return displaced_step_copy_insn_closure_up (closure.release ());
 }
 
 /* Fix up the state of registers and memory after having single-stepped
@@ -451,13 +486,13 @@ s390_displaced_step_copy_insn (struct gdbarch *gdbarch,
 
 static void
 s390_displaced_step_fixup (struct gdbarch *gdbarch,
-                          struct displaced_step_closure *closure_,
+                          struct displaced_step_copy_insn_closure *closure_,
                           CORE_ADDR from, CORE_ADDR to,
                           struct regcache *regs)
 {
   /* Our closure is a copy of the instruction.  */
-  s390_displaced_step_closure *closure
-    = (s390_displaced_step_closure *) closure_;
+  s390_displaced_step_copy_insn_closure *closure
+    = (s390_displaced_step_copy_insn_closure *) closure_;
   gdb_byte *insn = closure->buf.data ();
   static int s390_instrlen[] = { 2, 4, 4, 6 };
   int insnlen = s390_instrlen[insn[0] >> 6];
@@ -489,6 +524,9 @@ s390_displaced_step_fixup (struct gdbarch *gdbarch,
       /* Recompute saved return address in R1.  */
       regcache_cooked_write_unsigned (regs, S390_R0_REGNUM + r1,
                                      amode | (from + insnlen));
+      /* Update PC iff the instruction doesn't actually branch.  */
+      if (insn[0] == op_basr && r2 == 0)
+       regcache_write_pc (regs, from + insnlen);
     }
 
   /* Handle absolute branch instructions.  */
@@ -549,7 +587,7 @@ s390_displaced_step_fixup (struct gdbarch *gdbarch,
 
 static int
 s390_displaced_step_hw_singlestep (struct gdbarch *gdbarch,
-                                  struct displaced_step_closure *closure)
+                                  struct displaced_step_copy_insn_closure *closure)
 {
   return 1;
 }
@@ -658,11 +696,9 @@ s390_load (struct s390_prologue_data *data,
   if (pv_is_constant (addr))
     {
       struct target_section *secp;
-      secp = target_section_by_addr (&current_target, addr.k);
+      secp = target_section_by_addr (current_top_target (), addr.k);
       if (secp != NULL
-         && (bfd_get_section_flags (secp->the_bfd_section->owner,
-                                    secp->the_bfd_section)
-             & SEC_READONLY))
+         && (bfd_section_flags (secp->the_bfd_section) & SEC_READONLY))
        return pv_constant (read_memory_integer (addr.k, size,
                                                 data->byte_order));
     }
@@ -1071,10 +1107,10 @@ s390_guess_tracepoint_registers (struct gdbarch *gdbarch,
     }
 
   store_unsigned_integer (reg, sz, gdbarch_byte_order (gdbarch), pswa);
-  regcache_raw_supply (regcache, S390_PSWA_REGNUM, reg);
+  regcache->raw_supply (S390_PSWA_REGNUM, reg);
 
   store_unsigned_integer (reg, sz, gdbarch_byte_order (gdbarch), pswm);
-  regcache_raw_supply (regcache, S390_PSWM_REGNUM, reg);
+  regcache->raw_supply (S390_PSWM_REGNUM, reg);
 }
 
 /* Return the name of register REGNO.  Return the empty string for
@@ -1269,8 +1305,9 @@ s390_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
   if (regnum_is_gpr_full (tdep, regnum))
     return builtin_type (gdbarch)->builtin_uint64;
 
+  /* For the "concatenated" vector registers use the same type as v16.  */
   if (regnum_is_vxr_full (tdep, regnum))
-    return tdesc_find_type (gdbarch, "vec128");
+    return tdesc_register_type (gdbarch, S390_V16_REGNUM);
 
   internal_error (__FILE__, __LINE__, _("invalid regnum"));
 }
@@ -1278,7 +1315,7 @@ s390_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
 /* Implement pseudo_register_read gdbarch method.  */
 
 static enum register_status
-s390_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
+s390_pseudo_register_read (struct gdbarch *gdbarch, readable_regcache *regcache,
                           int regnum, gdb_byte *buf)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
@@ -1399,8 +1436,8 @@ s390_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
   if (regnum_is_vxr_full (tdep, regnum))
     {
       regnum -= tdep->v0_full_regnum;
-      regcache_raw_write (regcache, S390_F0_REGNUM + regnum, buf);
-      regcache_raw_write (regcache, S390_V0_LOWER_REGNUM + regnum, buf + 8);
+      regcache->raw_write (S390_F0_REGNUM + regnum, buf);
+      regcache->raw_write (S390_V0_LOWER_REGNUM + regnum, buf + 8);
       return;
     }
 
@@ -1601,11 +1638,26 @@ s390_address_class_name_to_type_flags (struct gdbarch *gdbarch,
 static struct type *
 s390_effective_inner_type (struct type *type, unsigned int min_size)
 {
-  while (TYPE_CODE (type) == TYPE_CODE_STRUCT
-        && TYPE_NFIELDS (type) == 1)
+  while (type->code () == TYPE_CODE_STRUCT)
     {
-      struct type *inner = check_typedef (TYPE_FIELD_TYPE (type, 0));
+      struct type *inner = NULL;
+
+      /* Find a non-static field, if any.  Unless there's exactly one,
+        abort the unwrapping.  */
+      for (int i = 0; i < type->num_fields (); i++)
+       {
+         struct field f = type->field (i);
+
+         if (field_is_static (&f))
+           continue;
+         if (inner != NULL)
+           return type;
+         inner = FIELD_TYPE (f);
+       }
 
+      if (inner == NULL)
+       break;
+      inner = check_typedef (inner);
       if (TYPE_LENGTH (inner) < min_size)
        break;
       type = inner;
@@ -1629,8 +1681,8 @@ s390_function_arg_float (struct type *type)
      or double.  */
   type = s390_effective_inner_type (type, 0);
 
-  return (TYPE_CODE (type) == TYPE_CODE_FLT
-         || TYPE_CODE (type) == TYPE_CODE_DECFLOAT);
+  return (type->code () == TYPE_CODE_FLT
+         || type->code () == TYPE_CODE_DECFLOAT);
 }
 
 /* Return non-zero if TYPE should be passed like a vector.  */
@@ -1644,7 +1696,7 @@ s390_function_arg_vector (struct type *type)
   /* Structs containing just a vector are passed like a vector.  */
   type = s390_effective_inner_type (type, TYPE_LENGTH (type));
 
-  return TYPE_CODE (type) == TYPE_CODE_ARRAY && TYPE_VECTOR (type);
+  return type->code () == TYPE_CODE_ARRAY && TYPE_VECTOR (type);
 }
 
 /* Determine whether N is a power of two.  */
@@ -1662,7 +1714,7 @@ is_power_of_two (unsigned int n)
 static int
 s390_function_arg_integer (struct type *type)
 {
-  enum type_code code = TYPE_CODE (type);
+  enum type_code code = type->code ();
 
   if (TYPE_LENGTH (type) > 8)
     return 0;
@@ -1720,10 +1772,8 @@ s390_handle_arg (struct s390_arg_state *as, struct value *arg,
          /* When we store a single-precision value in an FP register,
             it occupies the leftmost bits.  */
          if (write_mode)
-           regcache_cooked_write_part (as->regcache,
-                                       S390_F0_REGNUM + as->fr,
-                                       0, length,
-                                       value_contents (arg));
+           as->regcache->cooked_write_part (S390_F0_REGNUM + as->fr, 0, length,
+                                            value_contents (arg));
          as->fr += 2;
        }
       else
@@ -1746,9 +1796,8 @@ s390_handle_arg (struct s390_arg_state *as, struct value *arg,
          int regnum = S390_V24_REGNUM + use_vr[as->vr] - 24;
 
          if (write_mode)
-           regcache_cooked_write_part (as->regcache, regnum,
-                                       0, length,
-                                       value_contents (arg));
+           as->regcache->cooked_write_part (regnum, 0, length,
+                                            value_contents (arg));
          as->vr++;
        }
       else
@@ -1797,12 +1846,10 @@ s390_handle_arg (struct s390_arg_state *as, struct value *arg,
        {
          if (write_mode)
            {
-             regcache_cooked_write (as->regcache,
-                                    S390_R0_REGNUM + as->gr,
-                                    value_contents (arg));
-             regcache_cooked_write (as->regcache,
-                                    S390_R0_REGNUM + as->gr + 1,
-                                    value_contents (arg) + word_size);
+             as->regcache->cooked_write (S390_R0_REGNUM + as->gr,
+                                         value_contents (arg));
+             as->regcache->cooked_write (S390_R0_REGNUM + as->gr + 1,
+                                         value_contents (arg) + word_size);
            }
          as->gr += 2;
        }
@@ -1863,7 +1910,8 @@ static CORE_ADDR
 s390_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                      struct regcache *regcache, CORE_ADDR bp_addr,
                      int nargs, struct value **args, CORE_ADDR sp,
-                     int struct_return, CORE_ADDR struct_addr)
+                     function_call_return_method return_method,
+                     CORE_ADDR struct_addr)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   int word_size = gdbarch_ptr_bit (gdbarch) / 8;
@@ -1873,11 +1921,11 @@ s390_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
   CORE_ADDR param_area_start, new_sp;
   struct type *ftype = check_typedef (value_type (function));
 
-  if (TYPE_CODE (ftype) == TYPE_CODE_PTR)
+  if (ftype->code () == TYPE_CODE_PTR)
     ftype = check_typedef (TYPE_TARGET_TYPE (ftype));
 
   arg_prep.copy = sp;
-  arg_prep.gr = struct_return ? 3 : 2;
+  arg_prep.gr = (return_method == return_method_struct) ? 3 : 2;
   arg_prep.fr = 0;
   arg_prep.vr = 0;
   arg_prep.argp = 0;
@@ -1890,7 +1938,7 @@ s390_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
      and arg_state.argp with the size of the parameter area.  */
   for (i = 0; i < nargs; i++)
     s390_handle_arg (&arg_state, args[i], tdep, word_size, byte_order,
-                    TYPE_VARARGS (ftype) && i >= TYPE_NFIELDS (ftype));
+                    TYPE_VARARGS (ftype) && i >= ftype->num_fields ());
 
   param_area_start = align_down (arg_state.copy - arg_state.argp, 8);
 
@@ -1906,7 +1954,7 @@ s390_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
     error (_("Stack overflow"));
 
   /* Pass the structure return address in general register 2.  */
-  if (struct_return)
+  if (return_method == return_method_struct)
     regcache_cooked_write_unsigned (regcache, S390_R2_REGNUM, struct_addr);
 
   /* Initialize arg_state for "write mode".  */
@@ -1917,7 +1965,7 @@ s390_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
   /* Write all parameters.  */
   for (i = 0; i < nargs; i++)
     s390_handle_arg (&arg_state, args[i], tdep, word_size, byte_order,
-                    TYPE_VARARGS (ftype) && i >= TYPE_NFIELDS (ftype));
+                    TYPE_VARARGS (ftype) && i >= ftype->num_fields ());
 
   /* Store return PSWA.  In 31-bit mode, keep addressing mode bit.  */
   if (word_size == 4)
@@ -1973,34 +2021,30 @@ s390_register_return_value (struct gdbarch *gdbarch, struct type *type,
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   int word_size = gdbarch_ptr_bit (gdbarch) / 8;
   int length = TYPE_LENGTH (type);
-  int code = TYPE_CODE (type);
+  int code = type->code ();
 
   if (code == TYPE_CODE_FLT || code == TYPE_CODE_DECFLOAT)
     {
       /* Float-like value: left-aligned in f0.  */
       if (in != NULL)
-       regcache_cooked_write_part (regcache, S390_F0_REGNUM,
-                                   0, length, in);
+       regcache->cooked_write_part (S390_F0_REGNUM, 0, length, in);
       else
-       regcache_cooked_read_part (regcache, S390_F0_REGNUM,
-                                  0, length, out);
+       regcache->cooked_read_part (S390_F0_REGNUM, 0, length, out);
     }
   else if (code == TYPE_CODE_ARRAY)
     {
       /* Vector: left-aligned in v24.  */
       if (in != NULL)
-       regcache_cooked_write_part (regcache, S390_V24_REGNUM,
-                                   0, length, in);
+       regcache->cooked_write_part (S390_V24_REGNUM, 0, length, in);
       else
-       regcache_cooked_read_part (regcache, S390_V24_REGNUM,
-                                  0, length, out);
+       regcache->cooked_read_part (S390_V24_REGNUM, 0, length, out);
     }
   else if (length <= word_size)
     {
       /* Integer: zero- or sign-extended in r2.  */
       if (out != NULL)
-       regcache_cooked_read_part (regcache, S390_R2_REGNUM,
-                                  word_size - length, length, out);
+       regcache->cooked_read_part (S390_R2_REGNUM, word_size - length, length,
+                                   out);
       else if (TYPE_UNSIGNED (type))
        regcache_cooked_write_unsigned
          (regcache, S390_R2_REGNUM,
@@ -2015,15 +2059,13 @@ s390_register_return_value (struct gdbarch *gdbarch, struct type *type,
       /* Double word: in r2 and r3.  */
       if (in != NULL)
        {
-         regcache_cooked_write (regcache, S390_R2_REGNUM, in);
-         regcache_cooked_write (regcache, S390_R3_REGNUM,
-                                in + word_size);
+         regcache->cooked_write (S390_R2_REGNUM, in);
+         regcache->cooked_write (S390_R3_REGNUM, in + word_size);
        }
       else
        {
-         regcache_cooked_read (regcache, S390_R2_REGNUM, out);
-         regcache_cooked_read (regcache, S390_R3_REGNUM,
-                               out + word_size);
+         regcache->cooked_read (S390_R2_REGNUM, out);
+         regcache->cooked_read (S390_R3_REGNUM, out + word_size);
        }
     }
   else
@@ -2041,7 +2083,7 @@ s390_return_value (struct gdbarch *gdbarch, struct value *function,
 
   type = check_typedef (type);
 
-  switch (TYPE_CODE (type))
+  switch (type->code ())
     {
     case TYPE_CODE_STRUCT:
     case TYPE_CODE_UNION:
@@ -2075,7 +2117,7 @@ s390_return_value (struct gdbarch *gdbarch, struct value *function,
 
 /* Frame unwinding.  */
 
-/* Implmement the stack_frame_destroyed_p gdbarch method.  */
+/* Implement the stack_frame_destroyed_p gdbarch method.  */
 
 static int
 s390_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc)
@@ -2365,11 +2407,11 @@ s390_prologue_frame_unwind_cache (struct frame_info *this_frame,
             Recognize this case by looking ahead a bit ...  */
 
          struct s390_prologue_data data2;
-         pv_t *sp = &data2.gpr[S390_SP_REGNUM - S390_R0_REGNUM];
+         pv_t *sp2 = &data2.gpr[S390_SP_REGNUM - S390_R0_REGNUM];
 
          if (!(s390_analyze_prologue (gdbarch, func, (CORE_ADDR)-1, &data2)
-               && pv_is_register (*sp, S390_SP_REGNUM)
-               && sp->k != 0))
+               && pv_is_register (*sp2, S390_SP_REGNUM)
+               && sp2->k != 0))
            return 0;
        }
     }
@@ -2550,19 +2592,18 @@ s390_frame_unwind_cache (struct frame_info *this_frame,
   info->frame_base = -1;
   info->local_base = -1;
 
-  TRY
+  try
     {
       /* Try to use prologue analysis to fill the unwind cache.
         If this fails, fall back to reading the stack backchain.  */
       if (!s390_prologue_frame_unwind_cache (this_frame, info))
        s390_backchain_frame_unwind_cache (this_frame, info);
     }
-  CATCH (ex, RETURN_MASK_ERROR)
+  catch (const gdb_exception_error &ex)
     {
       if (ex.error != NOT_AVAILABLE_ERROR)
-       throw_exception (ex);
+       throw;
     }
-  END_CATCH
 
   return info;
 }
@@ -2811,9 +2852,9 @@ s390_record_calc_disp_vsce (struct gdbarch *gdbarch, struct regcache *regcache,
   if (tdep->v0_full_regnum == -1 || el * es >= 16)
     return -1;
   if (vx < 16)
-    regcache_cooked_read (regcache, tdep->v0_full_regnum + vx, buf);
+    regcache->cooked_read (tdep->v0_full_regnum + vx, buf);
   else
-    regcache_raw_read (regcache, S390_V16_REGNUM + vx - 16, buf);
+    regcache->raw_read (S390_V16_REGNUM + vx - 16, buf);
   x = extract_unsigned_integer (buf + el * es, es, byte_order);
   *res = s390_record_calc_disp_common (gdbarch, regcache, x, bd, dh);
   return 0;
@@ -4109,6 +4150,7 @@ ex:
        case 0xb998: /* ALCR - add logical with carry */
        case 0xb999: /* SLBR - subtract logical with borrow */
        case 0xb9f4: /* NRK - and */
+       case 0xb9f5: /* NCRK - and with complement */
        case 0xb9f6: /* ORK - or */
        case 0xb9f7: /* XRK - xor */
        case 0xb9f8: /* ARK - add */
@@ -4141,20 +4183,32 @@ ex:
        case 0xb919: /* SGFR - subtract */
        case 0xb91a: /* ALGFR - add logical */
        case 0xb91b: /* SLGFR - subtract logical */
+       case 0xb964: /* NNGRK - and 64 bit */
+       case 0xb965: /* OCGRK - or with complement 64 bit */
+       case 0xb966: /* NOGRK - or 64 bit */
+       case 0xb967: /* NXGRK - not exclusive or 64 bit */
+       case 0xb974: /* NNRK - and 32 bit */
+       case 0xb975: /* OCRK - or with complement 32 bit */
+       case 0xb976: /* NORK - or 32 bit */
+       case 0xb977: /* NXRK - not exclusive or 32 bit */
        case 0xb980: /* NGR - and */
        case 0xb981: /* OGR - or */
        case 0xb982: /* XGR - xor */
        case 0xb988: /* ALCGR - add logical with carry */
        case 0xb989: /* SLBGR - subtract logical with borrow */
+       case 0xb9c0: /* SELFHR - select high */
        case 0xb9e1: /* POPCNT - population count */
        case 0xb9e4: /* NGRK - and */
+       case 0xb9e5: /* NCGRK - and with complement */
        case 0xb9e6: /* OGRK - or */
        case 0xb9e7: /* XGRK - xor */
        case 0xb9e8: /* AGRK - add */
        case 0xb9e9: /* SGRK - subtract */
        case 0xb9ea: /* ALGRK - add logical */
+       case 0xb9e3: /* SELGR - select 64 bit */
        case 0xb9eb: /* SLGRK - subtract logical */
        case 0xb9ed: /* MSGRKC - multiply single 64x64 -> 64 */
+       case 0xb9f0: /* SELR - select 32 bit */
        case 0xb9fd: /* MSRKC - multiply single 32x32 -> 32 */
          /* 64-bit gpr destination + flags */
          if (s390_record_gpr_g (gdbarch, regcache, inib[6]))
@@ -4315,7 +4369,8 @@ ex:
                      return -1;
                    break;
                  }
-               /* For other instructions, fallthru.  */
+               /* For other instructions... */
+               /* Fall through.  */
              default:
                fprintf_unfiltered (gdb_stdlog, "Warning: Unknown KM* function %02x at %s.\n",
                                    (int)tmp, paddress (gdbarch, addr));
@@ -4529,7 +4584,13 @@ ex:
            return -1;
          break;
 
-       /* 0xb932-0xb93b undefined */
+       /* 0xb932-0xb937 undefined */
+
+       /* 0xb938 unsupported: SORTL - sort lists */
+       /* 0xb939 unsupported: DFLTCC - deflate conversion call */
+       /* 0xb93a unsupported: KDSA - compute dig. signature auth. */
+
+       /* 0xb93b undefined */
 
        case 0xb93c: /* PPNO - perform pseudorandom number operation [partial] */
          regcache_raw_read_unsigned (regcache, S390_R1_REGNUM, &tmp);
@@ -4617,7 +4678,8 @@ ex:
                      return -1;
                    break;
                  }
-               /* For KLMD, fallthru.  */
+               /* For KLMD...  */
+               /* Fall through.  */
              default:
                fprintf_unfiltered (gdb_stdlog, "Warning: Unknown KMAC function %02x at %s.\n",
                                    (int)tmp, paddress (gdbarch, addr));
@@ -5250,7 +5312,7 @@ ex:
        case 0xe383: /* MSGC - multiply single 64x64mem -> 64 */
        case 0xe398: /* ALC - add logical with carry */
        case 0xe399: /* SLB - subtract logical with borrow */
-       case 0xe727: /* LCBB - load count to block bounduary */
+       case 0xe727: /* LCBB - load count to block boundary */
        case 0xeb81: /* ICMY - insert characters under mask */
        case 0xebdc: /* SRAK - shift left single */
        case 0xebdd: /* SLAK - shift left single */
@@ -5458,6 +5520,13 @@ ex:
        /* 0xe3ce undefined */
        /* 0xe3d0-0xe3ff undefined */
 
+       case 0xe601: /* VLEBRH - vector load byte reversed element */
+       case 0xe602: /* VLEBRG - vector load byte reversed element */
+       case 0xe603: /* VLEBRF - vector load byte reversed element */
+       case 0xe604: /* VLLEBRZ - vector load byte rev. el. and zero */
+       case 0xe605: /* VLBRREP - vector load byte rev. el. and replicate */
+       case 0xe606: /* VLBR - vector load byte reversed elements */
+       case 0xe607: /* VLER - vector load elements reversed */
        case 0xe634: /* VPKZ - vector pack zoned */
        case 0xe635: /* VLRL - vector load rightmost with immed. length */
        case 0xe637: /* VLRLR - vector load rightmost with length */
@@ -5469,7 +5538,7 @@ ex:
        case 0xe704: /* VLLEZ - vector load logical element and zero */
        case 0xe705: /* VLREP - vector load and replicate */
        case 0xe706: /* VL - vector load */
-       case 0xe707: /* VLBB - vector load to block bounduary */
+       case 0xe707: /* VLBB - vector load to block boundary */
        case 0xe712: /* VGEG - vector gather element */
        case 0xe713: /* VGEF - vector gather element */
        case 0xe722: /* VLVG - vector load vr element from gr */
@@ -5520,6 +5589,9 @@ ex:
        case 0xe77f: /* VSRAB - vector shift right arithmetic by byte */
        case 0xe784: /* VPDI - vector permute doubleword immediate */
        case 0xe785: /* VBPERM - vector bit permute */
+       case 0xe786: /* VSLD - vector shift left double by bit */
+       case 0xe787: /* VSRD - vector shift right double by bit */
+       case 0xe78b: /* VSTRS - vector string search */
        case 0xe78c: /* VPERM - vector permute */
        case 0xe78d: /* VSEL - vector select */
        case 0xe78e: /* VFMS - vector fp multiply and subtract */
@@ -5548,10 +5620,10 @@ ex:
        case 0xe7bc: /* VGFMA - vector Galois field multiply sum and accumulate */
        case 0xe7bd: /* VSBCBI - vector subtract with borrow compute borrow indication */
        case 0xe7bf: /* VSBI - vector subtract with borrow indication */
-       case 0xe7c0: /* VCLGD - vector convert to logical 64-bit */
-       case 0xe7c1: /* VCDLG - vector convert from logical 64-bit */
-       case 0xe7c2: /* VCGD - vector convert to fixed 64-bit */
-       case 0xe7c3: /* VCDG - vector convert from fixed 64-bit */
+       case 0xe7c0: /* VCLFP - vector fp convert to logical */
+       case 0xe7c1: /* VCFPL - vector fp convert from logical */
+       case 0xe7c2: /* VCSFP - vector fp convert to fixed */
+       case 0xe7c3: /* VCFPS - vector fp convert from fixed */
        case 0xe7c4: /* VLDE/VFLL - vector fp load lengthened */
        case 0xe7c5: /* VLED/VFLR - vector fp load rounded */
        case 0xe7c7: /* VFI - vector load fp integer */
@@ -5602,6 +5674,7 @@ ex:
            return -1;
          break;
 
+       case 0xe609: /* VSTEBRH - vector store byte reversed element */
        case 0xe709: /* VSTEH - vector store element */
          oaddr = s390_record_calc_disp (gdbarch, regcache, inib[3], insn[1], 0);
          if (record_full_arch_list_add_mem (oaddr, 2))
@@ -5610,6 +5683,7 @@ ex:
            return -1;
          break;
 
+       case 0xe60a: /* VSTEBRG - vector store byte reversed element */
        case 0xe70a: /* VSTEG - vector store element */
          oaddr = s390_record_calc_disp (gdbarch, regcache, inib[3], insn[1], 0);
          if (record_full_arch_list_add_mem (oaddr, 8))
@@ -5618,6 +5692,7 @@ ex:
            return -1;
          break;
 
+       case 0xe60b: /* VSTEBRF - vector store byte reversed element */
        case 0xe70b: /* VSTEF - vector store element */
          oaddr = s390_record_calc_disp (gdbarch, regcache, inib[3], insn[1], 0);
          if (record_full_arch_list_add_mem (oaddr, 4))
@@ -5628,6 +5703,8 @@ ex:
 
        /* 0xe70c-0xe70d undefined */
 
+       case 0xe60e: /* VSTBR - vector store byte reversed elements */
+       case 0xe60f: /* VSTER - vector store elements reversed */
        case 0xe70e: /* VST - vector store */
          oaddr = s390_record_calc_disp (gdbarch, regcache, inib[3], insn[1], 0);
          if (record_full_arch_list_add_mem (oaddr, 16))
@@ -6162,7 +6239,7 @@ ex:
            return -1;
          break;
 
-       /* 0xed42-0xed47 undefind */
+       /* 0xed42-0xed47 undefined */
 
        case 0xed48: /* SLXT - shift significand left */
        case 0xed49: /* SRXT - shift significand right */
@@ -6177,10 +6254,10 @@ ex:
            return -1;
          break;
 
-       /* 0xed4a-0xed4f undefind */
-       /* 0xed52-0xed53 undefind */
-       /* 0xed56-0xed57 undefind */
-       /* 0xed5a-0xed63 undefind */
+       /* 0xed4a-0xed4f undefined */
+       /* 0xed52-0xed53 undefined */
+       /* 0xed56-0xed57 undefined */
+       /* 0xed5a-0xed63 undefined */
        /* 0xed68-0xeda7 undefined */
 
        case 0xeda8: /* CZDT - convert to zoned */
@@ -6207,7 +6284,16 @@ ex:
       /* SSE/SIL-format instruction */
       switch (insn[0])
        {
-       /* 0xe500-0xe543 undefined, privileged, or unsupported */
+       /* 0xe500-0xe509 undefined, privileged, or unsupported */
+
+       case 0xe50a: /* MVCRL - move right to left */
+         regcache_raw_read_unsigned (regcache, S390_R0_REGNUM, &tmp);
+         oaddr = s390_record_calc_disp (gdbarch, regcache, 0, insn[1], 0);
+         if (record_full_arch_list_add_mem (oaddr, (tmp & 0xff) + 1))
+           return -1;
+         break;
+
+       /* 0xe50b-0xe543 undefined, privileged, or unsupported */
 
        case 0xe544: /* MVHHI - move */
          oaddr = s390_record_calc_disp (gdbarch, regcache, 0, insn[1], 0);
@@ -6694,10 +6780,10 @@ UNKNOWN_OP:
 /* Implement gdbarch_gcc_target_options.  GCC does not know "-m32" or
    "-mcmodel=large".  */
 
-static char *
+static std::string
 s390_gcc_target_options (struct gdbarch *gdbarch)
 {
-  return xstrdup (gdbarch_ptr_bit (gdbarch) == 64 ? "-m64" : "-m31");
+  return gdbarch_ptr_bit (gdbarch) == 64 ? "-m64" : "-m31";
 }
 
 /* Implement gdbarch_gnu_triplet_regexp.  Target triplets are "s390-*"
@@ -6789,6 +6875,9 @@ s390_tdesc_valid (struct gdbarch_tdep *tdep,
   const struct target_desc *tdesc = tdep->tdesc;
   const struct tdesc_feature *feature;
 
+  if (!tdesc_has_registers (tdesc))
+    return false;
+
   /* Core registers, i.e. general purpose and PSW.  */
   feature = tdesc_find_feature (tdesc, "org.gnu.gdb.s390.core");
   if (feature == NULL)
@@ -6929,7 +7018,6 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   static const char *const stap_register_indirection_suffixes[] = { ")",
                                                                    NULL };
 
-  /* Otherwise create a new gdbarch for the specified machine type.  */
   struct gdbarch_tdep *tdep = s390_gdbarch_tdep_alloc ();
   struct gdbarch *gdbarch = gdbarch_alloc (&info, tdep);
   struct tdesc_arch_data *tdesc_data = tdesc_data_alloc ();
@@ -6944,6 +7032,8 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_long_double_bit (gdbarch, 128);
   set_gdbarch_long_double_format (gdbarch, floatformats_ia64_quad);
 
+  set_gdbarch_type_align (gdbarch, s390_type_align);
+
   /* Breakpoints.  */
   /* Amount PC must be decremented by after a breakpoint.  This is
      often the number of bytes returned by gdbarch_breakpoint_from_pc but not
@@ -7044,8 +7134,19 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   /* Initialize the OSABI.  */
   gdbarch_init_osabi (info, gdbarch);
 
+  /* Always create a default tdesc.  Otherwise commands like 'set osabi'
+     cause GDB to crash with an internal error when the user tries to set
+     an unsupported OSABI.  */
+  if (!tdesc_has_registers (tdesc))
+  {
+    if (info.bfd_arch_info->mach == bfd_mach_s390_31)
+      tdesc = tdesc_s390_linux32;
+    else
+      tdesc = tdesc_s390x_linux64;
+  }
+  tdep->tdesc = tdesc;
+
   /* Check any target description for validity.  */
-  gdb_assert (tdesc_has_registers (tdep->tdesc));
   if (!s390_tdesc_valid (tdep, tdesc_data))
     {
       tdesc_data_cleanup (tdesc_data);
@@ -7115,9 +7216,13 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   return gdbarch;
 }
 
+void _initialize_s390_tdep ();
 void
-_initialize_s390_tdep (void)
+_initialize_s390_tdep ()
 {
   /* Hook us into the gdbarch mechanism.  */
   register_gdbarch_init (bfd_arch_s390, s390_gdbarch_init);
+
+  initialize_tdesc_s390_linux32 ();
+  initialize_tdesc_s390x_linux64 ();
 }
This page took 0.042566 seconds and 4 git commands to generate.