s390: gdbarch_tdep add field tdesc
[deliverable/binutils-gdb.git] / gdb / s390-linux-tdep.c
index 6d682608d41e408e2bac59f997691f3b281eb330..557eac3275fa0faabfa515380b15aee9af43172b 100644 (file)
@@ -1,6 +1,6 @@
 /* Target-dependent code for GDB, the GNU debugger.
 
-   Copyright (C) 2001-2017 Free Software Foundation, Inc.
+   Copyright (C) 2001-2018 Free Software Foundation, Inc.
 
    Contributed by D.J. Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
    for IBM Deutschland Entwicklung GmbH, IBM Corporation.
@@ -30,7 +30,6 @@
 #include "gdbcore.h"
 #include "gdbcmd.h"
 #include "objfiles.h"
-#include "floatformat.h"
 #include "regcache.h"
 #include "trad-frame.h"
 #include "frame-base.h"
 #include "features/s390-te-linux64.c"
 #include "features/s390-vx-linux64.c"
 #include "features/s390-tevx-linux64.c"
+#include "features/s390-gs-linux64.c"
 #include "features/s390x-linux64.c"
 #include "features/s390x-linux64v1.c"
 #include "features/s390x-linux64v2.c"
 #include "features/s390x-te-linux64.c"
 #include "features/s390x-vx-linux64.c"
 #include "features/s390x-tevx-linux64.c"
+#include "features/s390x-gs-linux64.c"
 
 #define XML_SYSCALL_FILENAME_S390 "syscalls/s390-linux.xml"
 #define XML_SYSCALL_FILENAME_S390X "syscalls/s390x-linux.xml"
@@ -84,6 +85,7 @@ static char *s390_disassembler_options;
 
 enum s390_abi_kind
 {
+  ABI_NONE,
   ABI_LINUX_S390,
   ABI_LINUX_ZSERIES
 };
@@ -98,6 +100,9 @@ enum s390_vector_abi_kind
 
 struct gdbarch_tdep
 {
+  /* Target description.  */
+  const struct target_desc *tdesc;
+
   /* ABI version.  */
   enum s390_abi_kind abi;
 
@@ -110,9 +115,12 @@ struct gdbarch_tdep
   int cc_regnum;
   int v0_full_regnum;
 
-  int have_linux_v1;
-  int have_linux_v2;
-  int have_tdb;
+  bool have_upper;
+  bool have_linux_v1;
+  bool have_linux_v2;
+  bool have_tdb;
+  bool have_vx;
+  bool have_gs;
 };
 
 
@@ -155,7 +163,7 @@ s390_cannot_store_register (struct gdbarch *gdbarch, int regnum)
 static void
 s390_write_pc (struct regcache *regcache, CORE_ADDR pc)
 {
-  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch *gdbarch = regcache->arch ();
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
   regcache_cooked_write_unsigned (regcache, tdep->pc_regnum, pc);
@@ -397,7 +405,7 @@ s390_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
     {
       enum register_status status;
 
-      status = regcache_raw_read_unsigned (regcache, S390_PSWA_REGNUM, &val);
+      status = regcache->raw_read (S390_PSWA_REGNUM, &val);
       if (status == REG_VALID)
        {
          if (register_size (gdbarch, S390_PSWA_REGNUM) == 4)
@@ -411,7 +419,7 @@ s390_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
     {
       enum register_status status;
 
-      status = regcache_raw_read_unsigned (regcache, S390_PSWM_REGNUM, &val);
+      status = regcache->raw_read (S390_PSWM_REGNUM, &val);
       if (status == REG_VALID)
        {
          if (register_size (gdbarch, S390_PSWA_REGNUM) == 4)
@@ -430,10 +438,10 @@ s390_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
 
       regnum -= tdep->gpr_full_regnum;
 
-      status = regcache_raw_read_unsigned (regcache, S390_R0_REGNUM + regnum, &val);
+      status = regcache->raw_read (S390_R0_REGNUM + regnum, &val);
       if (status == REG_VALID)
-       status = regcache_raw_read_unsigned (regcache, S390_R0_UPPER_REGNUM + regnum,
-                                            &val_upper);
+       status = regcache->raw_read (S390_R0_UPPER_REGNUM + regnum,
+                                    &val_upper);
       if (status == REG_VALID)
        {
          val |= val_upper << 32;
@@ -448,10 +456,9 @@ s390_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
 
       regnum -= tdep->v0_full_regnum;
 
-      status = regcache_raw_read (regcache, S390_F0_REGNUM + regnum, buf);
+      status = regcache->raw_read (S390_F0_REGNUM + regnum, buf);
       if (status == REG_VALID)
-       status = regcache_raw_read (regcache,
-                                   S390_V0_LOWER_REGNUM + regnum, buf + 8);
+       status = regcache->raw_read (S390_V0_LOWER_REGNUM + regnum, buf + 8);
       return status;
     }
 
@@ -728,7 +735,7 @@ s390_is_partial_instruction (struct gdbarch *gdbarch, CORE_ADDR loc, int *len)
 static std::vector<CORE_ADDR>
 s390_software_single_step (struct regcache *regcache)
 {
-  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch *gdbarch = regcache->arch ();
   CORE_ADDR loc = regcache_read_pc (regcache);
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   int len;
@@ -834,6 +841,24 @@ static const struct regcache_map_entry s390_regmap_vxrs_high[] =
     { 0 }
   };
 
+static const struct regcache_map_entry s390_regmap_gs[] =
+  {
+    { 1, REGCACHE_MAP_SKIP, 8 },
+    { 1, S390_GSD_REGNUM, 8 },
+    { 1, S390_GSSM_REGNUM, 8 },
+    { 1, S390_GSEPLA_REGNUM, 8 },
+    { 0 }
+  };
+
+static const struct regcache_map_entry s390_regmap_gsbc[] =
+  {
+    { 1, REGCACHE_MAP_SKIP, 8 },
+    { 1, S390_BC_GSD_REGNUM, 8 },
+    { 1, S390_BC_GSSM_REGNUM, 8 },
+    { 1, S390_BC_GSEPLA_REGNUM, 8 },
+    { 0 }
+  };
+
 
 /* Supply the TDB regset.  Like regcache_supply_regset, but invalidate
    the TDB registers unless the TDB format field is valid.  */
@@ -905,6 +930,18 @@ const struct regset s390_vxrs_high_regset = {
   regcache_collect_regset
 };
 
+const struct regset s390_gs_regset = {
+  s390_regmap_gs,
+  regcache_supply_regset,
+  regcache_collect_regset
+};
+
+const struct regset s390_gsbc_regset = {
+  s390_regmap_gsbc,
+  regcache_supply_regset,
+  regcache_collect_regset
+};
+
 /* Iterate over supported core file register note sections. */
 
 static void
@@ -951,6 +988,23 @@ s390_iterate_over_regset_sections (struct gdbarch *gdbarch,
       cb (".reg-s390-vxrs-high", 16 * 16, &s390_vxrs_high_regset,
          "s390 vector registers 16-31", cb_data);
     }
+
+  /* Iterate over the guarded-storage regsets if in "read" mode, or if
+     their registers are available.  */
+  if (tdep->have_gs)
+    {
+      if (regcache == NULL
+         || REG_VALID == regcache_register_status (regcache,
+                                                   S390_GSD_REGNUM))
+       cb (".reg-s390-gs-cb", 4 * 8, &s390_gs_regset,
+           "s390 guarded-storage registers", cb_data);
+
+      if (regcache == NULL
+         || REG_VALID == regcache_register_status (regcache,
+                                                   S390_BC_GSD_REGNUM))
+       cb (".reg-s390-gs-bc", 4 * 8, &s390_gsbc_regset,
+           "s390 guarded-storage broadcast control", cb_data);
+    }
 }
 
 static const struct target_desc *
@@ -959,7 +1013,7 @@ s390_core_read_description (struct gdbarch *gdbarch,
 {
   asection *section = bfd_get_section_by_name (abfd, ".reg");
   CORE_ADDR hwcap = 0;
-  int high_gprs, v1, v2, te, vx;
+  bool high_gprs, v1, v2, te, vx, gs;
 
   target_auxv_search (target, AT_HWCAP, &hwcap);
   if (!section)
@@ -971,12 +1025,14 @@ s390_core_read_description (struct gdbarch *gdbarch,
   v2 = (bfd_get_section_by_name (abfd, ".reg-s390-system-call") != NULL);
   vx = (hwcap & HWCAP_S390_VX);
   te = (hwcap & HWCAP_S390_TE);
+  gs = (hwcap & HWCAP_S390_GS);
 
   switch (bfd_section_size (abfd, section))
     {
     case s390_sizeof_gregset:
       if (high_gprs)
-       return (te && vx ? tdesc_s390_tevx_linux64 :
+       return (gs ? tdesc_s390_gs_linux64 :
+               te && vx ? tdesc_s390_tevx_linux64 :
                vx ? tdesc_s390_vx_linux64 :
                te ? tdesc_s390_te_linux64 :
                v2 ? tdesc_s390_linux64v2 :
@@ -986,7 +1042,8 @@ s390_core_read_description (struct gdbarch *gdbarch,
                v1 ? tdesc_s390_linux32v1 : tdesc_s390_linux32);
 
     case s390x_sizeof_gregset:
-      return (te && vx ? tdesc_s390x_tevx_linux64 :
+      return (gs ? tdesc_s390x_gs_linux64 :
+             te && vx ? tdesc_s390x_tevx_linux64 :
              vx ? tdesc_s390x_vx_linux64 :
              te ? tdesc_s390x_te_linux64 :
              v2 ? tdesc_s390x_linux64v2 :
@@ -1323,8 +1380,8 @@ s390_store (struct s390_prologue_data *data,
 
 
   /* Check whether we are storing a register into the stack.  */
-  if (!pv_area_store_would_trash (data->stack, addr))
-    pv_area_store (data->stack, addr, size, value);
+  if (!data->stack->store_would_trash (addr))
+    data->stack->store (addr, size, value);
 
 
   /* Note: If this is some store we cannot identify, you might think we
@@ -1361,11 +1418,11 @@ s390_load (struct s390_prologue_data *data,
     }
 
   /* Check whether we are accessing one of our save slots.  */
-  return pv_area_fetch (data->stack, addr, size);
+  return data->stack->fetch (addr, size);
 }
 
 /* Function for finding saved registers in a 'struct pv_area'; we pass
-   this to pv_area_scan.
+   this to pv_area::scan.
 
    If VALUE is a saved register, ADDR says it was saved at a constant
    offset from the frame base, and SIZE indicates that the whole
@@ -1434,12 +1491,13 @@ s390_analyze_prologue (struct gdbarch *gdbarch,
   /* The address of the next instruction after that.  */
   CORE_ADDR next_pc;
 
+  pv_area stack (S390_SP_REGNUM, gdbarch_addr_bit (gdbarch));
+  scoped_restore restore_stack = make_scoped_restore (&data->stack, &stack);
+
   /* Set up everything's initial value.  */
   {
     int i;
 
-    data->stack = make_pv_area (S390_SP_REGNUM, gdbarch_addr_bit (gdbarch));
-
     /* For the purpose of prologue tracking, we consider the GPR size to
        be equal to the ABI word size, even if it is actually larger
        (i.e. when running a 32-bit binary under a 64-bit kernel).  */
@@ -1678,10 +1736,7 @@ s390_analyze_prologue (struct gdbarch *gdbarch,
     }
 
   /* Record where all the registers were saved.  */
-  pv_area_scan (data->stack, s390_check_for_saved, data);
-
-  free_pv_area (data->stack);
-  data->stack = NULL;
+  data->stack->scan (s390_check_for_saved, data);
 
   return result;
 }
@@ -1811,6 +1866,8 @@ is_non_branch_ril (gdb_byte *insn)
   return 0;
 }
 
+typedef buf_displaced_step_closure s390_displaced_step_closure;
+
 /* Implementation of gdbarch_displaced_step_copy_insn.  */
 
 static struct displaced_step_closure *
@@ -1819,8 +1876,9 @@ s390_displaced_step_copy_insn (struct gdbarch *gdbarch,
                               struct regcache *regs)
 {
   size_t len = gdbarch_max_insn_length (gdbarch);
-  gdb_byte *buf = (gdb_byte *) xmalloc (len);
-  struct cleanup *old_chain = make_cleanup (xfree, buf);
+  std::unique_ptr<s390_displaced_step_closure> closure
+    (new s390_displaced_step_closure (len));
+  gdb_byte *buf = closure->buf.data ();
 
   read_memory (from, buf, len);
 
@@ -1848,7 +1906,7 @@ s390_displaced_step_copy_insn (struct gdbarch *gdbarch,
                                  "RIL instruction: offset %s out of range\n",
                                  plongest (offset));
            }
-         do_cleanups (old_chain);
+
          return NULL;
        }
 
@@ -1864,20 +1922,21 @@ s390_displaced_step_copy_insn (struct gdbarch *gdbarch,
       displaced_step_dump_bytes (gdb_stdlog, buf, len);
     }
 
-  discard_cleanups (old_chain);
-  return (struct displaced_step_closure *) buf;
+  return closure.release ();
 }
 
 /* Fix up the state of registers and memory after having single-stepped
    a displaced instruction.  */
 static void
 s390_displaced_step_fixup (struct gdbarch *gdbarch,
-                          struct displaced_step_closure *closure,
+                          struct displaced_step_closure *closure_,
                           CORE_ADDR from, CORE_ADDR to,
                           struct regcache *regs)
 {
   /* Our closure is a copy of the instruction.  */
-  gdb_byte *insn = (gdb_byte *) closure;
+  s390_displaced_step_closure *closure
+    = (s390_displaced_step_closure *) closure_;
+  gdb_byte *insn = closure->buf.data ();
   static int s390_instrlen[] = { 2, 4, 4, 6 };
   int insnlen = s390_instrlen[insn[0] >> 6];
 
@@ -2643,7 +2702,7 @@ static struct linux_record_tdep s390x_linux_record_tdep;
 static int
 s390_all_but_pc_registers_record (struct regcache *regcache)
 {
-  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch *gdbarch = regcache->arch ();
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   int i;
 
@@ -2845,7 +2904,7 @@ s390_canonicalize_syscall (int syscall, enum s390_abi_kind abi)
 static int
 s390_linux_syscall_record (struct regcache *regcache, LONGEST syscall_native)
 {
-  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch *gdbarch = regcache->arch ();
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   int ret;
   enum gdb_syscall syscall_gdb;
@@ -4992,6 +5051,8 @@ ex:
         case 0xb9e9: /* SGRK - subtract */
         case 0xb9ea: /* ALGRK - add logical */
         case 0xb9eb: /* SLGRK - subtract logical */
+       case 0xb9ed: /* MSGRKC - multiply single 64x64 -> 64 */
+       case 0xb9fd: /* MSRKC - multiply single 32x32 -> 32 */
           /* 64-bit gpr destination + flags */
           if (s390_record_gpr_g (gdbarch, regcache, inib[6]))
             return -1;
@@ -5019,7 +5080,7 @@ ex:
         case 0xb914: /* LGFR - load */
         case 0xb916: /* LLGFR - load logical */
         case 0xb917: /* LLGTR - load logical thirty one bits */
-        case 0xb91c: /* MSGFR - load */
+       case 0xb91c: /* MSGFR - multiply single 64<32 */
         case 0xb946: /* BCTGR - branch on count */
         case 0xb984: /* LLGCR - load logical character */
         case 0xb985: /* LLGHR - load logical halfword */
@@ -5038,6 +5099,7 @@ ex:
         case 0xb91d: /* DSGFR - divide single */
         case 0xb986: /* MLGR - multiply logical */
         case 0xb987: /* DLGR - divide logical */
+       case 0xb9ec: /* MGRK - multiply 64x64 -> 128 */
           /* 64-bit gpr pair destination  */
           if (s390_record_gpr_g (gdbarch, regcache, inib[6]))
             return -1;
@@ -5106,8 +5168,8 @@ ex:
         /* 0xb922-0xb924 undefined */
         /* 0xb925 privileged */
         /* 0xb928 privileged */
-        /* 0xb929 undefined */
 
+       case 0xb929: /* KMA - cipher message with authentication */
         case 0xb92a: /* KMF - cipher message with cipher feedback [partial] */
         case 0xb92b: /* KMO - cipher message with output feedback [partial] */
         case 0xb92f: /* KMC - cipher message with chaining [partial] */
@@ -5170,6 +5232,15 @@ ex:
               if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + (inib[7] | 1)))
                 return -1;
             }
+         if (tmp != 0 && insn[0] == 0xb929)
+           {
+             if (record_full_arch_list_add_reg (regcache,
+                                                S390_R0_REGNUM + inib[4]))
+               return -1;
+             if (record_full_arch_list_add_reg (regcache,
+                                                S390_R0_REGNUM + (inib[4] | 1)))
+               return -1;
+           }
           if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
             return -1;
           break;
@@ -5571,10 +5642,11 @@ ex:
 
         /* 0xb9e3 undefined */
         /* 0xb9e5 undefined */
-        /* 0xb9ec-0xb9f1 undefined */
+       /* 0xb9ee-0xb9f1 undefined */
         /* 0xb9f3 undefined */
         /* 0xb9f5 undefined */
-        /* 0xb9fc-0xb9ff undefined */
+       /* 0xb9fc undefined */
+       /* 0xb9fe -0xb9ff undefined */
 
         default:
           goto UNKNOWN_OP;
@@ -5962,6 +6034,7 @@ ex:
       break;
 
     case 0xe3:
+    case 0xe6:
     case 0xe7:
     case 0xeb:
     case 0xed:
@@ -6006,6 +6079,7 @@ ex:
         case 0xe31c: /* MSGF - multiply single */
         case 0xe32a: /* LZRG - load and zero rightmost byte */
         case 0xe33a: /* LLZRGF - load logical and zero rightmost byte */
+       case 0xe33c: /* MGH - multiply halfword 64x16mem -> 64 */
         case 0xe346: /* BCTG - branch on count */
         case 0xe377: /* LGB - load byte */
         case 0xe390: /* LLGC - load logical character */
@@ -6036,6 +6110,7 @@ ex:
 
         case 0xe30d: /* DSG - divide single */
         case 0xe31d: /* DSGF - divide single */
+       case 0xe384: /* MG - multiply 64x64mem -> 128 */
         case 0xe386: /* MLG - multiply logical */
         case 0xe387: /* DLG - divide logical */
         case 0xe38f: /* LPQ - load pair from quadword */
@@ -6057,6 +6132,9 @@ ex:
         /* 0xe310-0xe311 undefined */
 
         case 0xe312: /* LT - load and test */
+       case 0xe338: /* AGH - add halfword to 64 bit value */
+       case 0xe339: /* SGH - subtract halfword from 64 bit value */
+       case 0xe353: /* MSC - multiply single 32x32mem -> 32 */
         case 0xe354: /* NY - and */
         case 0xe356: /* OY - or */
         case 0xe357: /* XY - xor */
@@ -6066,13 +6144,14 @@ ex:
         case 0xe35f: /* SLY - subtract logical */
         case 0xe37a: /* AHY - add halfword */
         case 0xe37b: /* SHY - subtract halfword */
+       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 0xeb81: /* ICMY - insert characters under mask */
         case 0xebdc: /* SRAK - shift left single */
         case 0xebdd: /* SLAK - shift left single */
-          /* 32-bit gpr destination + flags */
+         /* 32/64-bit gpr destination + flags */
           if (record_full_arch_list_add_reg (regcache, S390_R0_REGNUM + inib[2]))
             return -1;
           if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
@@ -6160,7 +6239,7 @@ ex:
         case 0xe336: /* PFD - prefetch data */
           break;
 
-        /* 0xe337-0xe339 undefined */
+       /* 0xe337 undefined */
         /* 0xe33c-0xe33d undefined */
 
         case 0xe33e: /* STRV - store reversed */
@@ -6183,8 +6262,12 @@ ex:
           break;
 
         /* 0xe340-0xe345 undefined */
-        /* 0xe347-0xe34f undefined */
-        /* 0xe352-0xe353 undefined */
+
+       case 0xe347: /* BIC - branch indirect on condition */
+         break;
+
+       /* 0xe348-0xe34f undefined */
+       /* 0xe352 undefined */
 
         case 0xe35c: /* MFY - multiply */
         case 0xe396: /* ML - multiply logical */
@@ -6216,11 +6299,12 @@ ex:
           break;
 
         /* 0xe37d-0xe37f undefined */
-        /* 0xe383-0xe384 undefined */
 
         case 0xe385: /* LGAT - load and trap */
         case 0xe39c: /* LLGTAT - load logical thirty one bits and trap */
         case 0xe39d: /* LLGFAT - load logical and trap */
+       case 0xe650: /* VCVB - vector convert to binary 32 bit*/
+       case 0xe652: /* VCVBG - vector convert to binary 64 bit*/
         case 0xe721: /* VLGV - vector load gr from vr element */
           /* 64-bit gpr destination + fpc for possible DXC write */
           if (s390_record_gpr_g (gdbarch, regcache, inib[2]))
@@ -6271,6 +6355,10 @@ ex:
         /* 0xe3ce undefined */
         /* 0xe3d0-0xe3ff undefined */
 
+       case 0xe634: /* VPKZ - vector pack zoned */
+       case 0xe635: /* VLRL - vector load rightmost with immed. length */
+       case 0xe637: /* VLRLR - vector load rightmost with length */
+       case 0xe649: /* VLIP - vector load immediate decimal */
         case 0xe700: /* VLEB - vector load element */
         case 0xe701: /* VLEH - vector load element */
         case 0xe702: /* VLEG - vector load element */
@@ -6311,7 +6399,10 @@ ex:
         case 0xe769: /* VNC - vector and with complement */
         case 0xe76a: /* VO - vector or */
         case 0xe76b: /* VNO - vector nor */
+       case 0xe76c: /* VNX - vector not exclusive or */
         case 0xe76d: /* VX - vector xor */
+       case 0xe76e: /* VNN - vector nand */
+       case 0xe76f: /* VOC - vector or with complement */
         case 0xe770: /* VESLV - vector element shift left */
         case 0xe772: /* VERIM - vector element rotate and insert under mask */
         case 0xe773: /* VERLLV - vector element rotate left logical */
@@ -6325,11 +6416,14 @@ ex:
         case 0xe77e: /* VSRA - vector shift right arithmetic */
         case 0xe77f: /* VSRAB - vector shift right arithmetic by byte */
         case 0xe784: /* VPDI - vector permute doubleword immediate */
+       case 0xe785: /* VBPERM - vector bit permute */
         case 0xe78c: /* VPERM - vector permute */
         case 0xe78d: /* VSEL - vector select */
         case 0xe78e: /* VFMS - vector fp multiply and subtract */
         case 0xe78f: /* VFMA - vector fp multiply and add */
         case 0xe794: /* VPK - vector pack */
+       case 0xe79e: /* VFNMS - vector fp negative multiply and subtract */
+       case 0xe79f: /* VFNMA - vector fp negative multiply and add */
         case 0xe7a1: /* VMLH - vector multiply logical high */
         case 0xe7a2: /* VML - vector multiply low */
         case 0xe7a3: /* VMH - vector multiply high */
@@ -6345,6 +6439,7 @@ ex:
         case 0xe7ae: /* VMAE - vector multiply and add even */
         case 0xe7af: /* VMAO - vector multiply and add odd */
         case 0xe7b4: /* VGFM - vector Galois field multiply sum */
+       case 0xe7b8: /* VMSL - vector multiply sum logical */
         case 0xe7b9: /* VACCC - vector add with carry compute carry */
         case 0xe7bb: /* VAC - vector add with carry */
         case 0xe7bc: /* VGFMA - vector Galois field multiply sum and accumulate */
@@ -6354,8 +6449,8 @@ ex:
         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 0xe7c4: /* VLDE - vector fp load lengthened */
-        case 0xe7c5: /* VLED - vector fp load rounded */
+       case 0xe7c4: /* VLDE/VFLL - vector fp load lengthened */
+       case 0xe7c5: /* VLED/VFLR - vector fp load rounded */
         case 0xe7c7: /* VFI - vector load fp integer */
         case 0xe7cc: /* VFPSO - vector fp perform sign operation */
         case 0xe7ce: /* VFSQ - vector fp square root */
@@ -6369,6 +6464,8 @@ ex:
         case 0xe7e3: /* VFA - vector fp add */
         case 0xe7e5: /* VFD - vector fp divide */
         case 0xe7e7: /* VFM - vector fp multiply */
+       case 0xe7ee: /* VFMIN - vector fp minimum */
+       case 0xe7ef: /* VFMAX - vector fp maximum */
         case 0xe7f0: /* VAVGL - vector average logical */
         case 0xe7f1: /* VACC - vector add and compute carry */
         case 0xe7f2: /* VAVG - vector average */
@@ -6386,6 +6483,14 @@ ex:
             return -1;
           break;
 
+       case 0xe63d: /* VSTRL - vector store rightmost with immed. length */
+         oaddr = s390_record_calc_disp (gdbarch, regcache, 0, insn[1], 0);
+         if (record_full_arch_list_add_mem (oaddr, inib[3] + 1))
+           return -1;
+         if (record_full_arch_list_add_reg (regcache, S390_FPC_REGNUM))
+           return -1;
+         break;
+
         case 0xe708: /* VSTEB - vector store element */
           oaddr = s390_record_calc_disp (gdbarch, regcache, inib[3], insn[1], 0);
           if (record_full_arch_list_add_mem (oaddr, 1))
@@ -6480,13 +6585,22 @@ ex:
             return -1;
           break;
 
+       case 0xe63c: /* VUPKZ - vector unpack zoned */
+         oaddr = s390_record_calc_disp (gdbarch, regcache, 0, insn[1], 0);
+         if (record_full_arch_list_add_mem (oaddr, (ibyte[1] + 1) & 31))
+           return -1;
+         if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+           return -1;
+         break;
+
+       case 0xe63f: /* VSTRLR - vector store rightmost with length */
         case 0xe73f: /* VSTL - vector store with length */
           oaddr = s390_record_calc_disp (gdbarch, regcache, 0, insn[1], 0);
           regcache_raw_read_unsigned (regcache, S390_R0_REGNUM + inib[3], &tmp);
           tmp &= 0xffffffffu;
-          if (tmp > 16)
-            tmp = 16;
-          if (record_full_arch_list_add_mem (oaddr, tmp))
+         if (tmp > 15)
+           tmp = 15;
+         if (record_full_arch_list_add_mem (oaddr, tmp + 1))
             return -1;
           if (record_full_arch_list_add_reg (regcache, S390_FPC_REGNUM))
             return -1;
@@ -6494,6 +6608,17 @@ ex:
 
         /* 0xe747-0xe749 undefined */
 
+       case 0xe658: /* VCVD - vector convert to decimal 32 bit */
+       case 0xe659: /* VSRP - vector shift and round decimal */
+       case 0xe65a: /* VCVDG - vector convert to decimal 64 bit*/
+       case 0xe65b: /* VPSOP - vector perform sign operation decimal */
+       case 0xe671: /* VAP - vector add decimal */
+       case 0xe673: /* VSP - vector subtract decimal */
+       case 0xe678: /* VMP - vector multiply decimal */
+       case 0xe679: /* VMSP - vector multiply decimal */
+       case 0xe67a: /* VDP - vector divide decimal */
+       case 0xe67b: /* VRP - vector remainder decimal */
+       case 0xe67e: /* VSDP - vector shift and divide decimal */
         case 0xe74a: /* VFTCI - vector fp test data class immediate */
         case 0xe75c: /* VISTR - vector isolate string */
         case 0xe780: /* VFEE - vector find element equal */
@@ -6504,7 +6629,7 @@ ex:
         case 0xe797: /* VPKS - vector pack saturate */
         case 0xe7e8: /* VFCE - vector fp compare equal */
         case 0xe7ea: /* VFCHE - vector fp compare high or equal */
-        case 0xe7eb: /* VFCE - vector fp compare high */
+       case 0xe7eb: /* VFCH - vector fp compare high */
         case 0xe7f8: /* VCEQ - vector compare equal */
         case 0xe7f9: /* VCHL - vector compare high logical */
         case 0xe7fb: /* VCH - vector compare high */
@@ -6517,6 +6642,14 @@ ex:
             return -1;
           break;
 
+       case 0xe65f: /* VTP - vector test decimal */
+         /* flags + FPC */
+         if (record_full_arch_list_add_reg (regcache, S390_PSWM_REGNUM))
+           return -1;
+         if (record_full_arch_list_add_reg (regcache, S390_FPC_REGNUM))
+           return -1;
+         break;
+
         /* 0xe74b-0xe74c undefined */
         /* 0xe74e-0xe74f undefined */
         /* 0xe751 undefined */
@@ -6524,26 +6657,26 @@ ex:
         /* 0xe757-0xe75b undefined */
         /* 0xe75d-0xe75e undefined */
         /* 0xe763 undefined */
-        /* 0xe76c undefined */
-        /* 0xe76e-0xe76f undefined */
         /* 0xe771 undefined */
         /* 0xe776 undefined */
         /* 0xe779 undefined */
         /* 0xe77b undefined */
         /* 0xe783 undefined */
-        /* 0xe785-0xe789 undefined */
+       /* 0xe786-0xe789 undefined */
         /* 0xe78b undefined */
         /* 0xe790-0xe793 undefined */
         /* 0xe796 undefined */
-        /* 0xe798-0xe7a0 undefined */
-        /* 0xe7a8 undefined */
+       /* 0xe798-0xe79d undefined */
+       /* 0xe7a0 undefined */
+       /* 0xe7a8 undefined */
         /* 0xe7b0-0xe7b3 undefined */
-        /* 0xe7b5-0xe7b8 undefined */
+       /* 0xe7b5-0xe7b7 undefined */
         /* 0xe7ba undefined */
         /* 0xe7be undefined */
         /* 0xe7c6 undefined */
         /* 0xe7c8-0xe7c9 undefined */
 
+       case 0xe677: /* VCP - vector compare decimal */
         case 0xe7ca: /* WFK - vector fp compare and signal scalar */
         case 0xe7cb: /* WFC - vector fp compare scalar */
         case 0xe7d8: /* VTM - vector test under mask */
@@ -6568,7 +6701,7 @@ ex:
         /* 0xe7e4 undefined */
         /* 0xe7e6 undefined */
         /* 0xe7e9 undefined */
-        /* 0xe7ec-0xe7ef undefined */
+       /* 0xe7ec-0xe7ed undefined */
         /* 0xe7f4 undefined */
         /* 0xe7f6 undefined */
         /* 0xe7fa undefined */
@@ -7048,8 +7181,6 @@ ex:
         }
       break;
 
-    /* 0xe6 undefined */
-
     case 0xec:
       /* RIE/RIS/RRS-format instruction */
       switch (ibyte[0] << 8 | ibyte[5])
@@ -7679,6 +7810,34 @@ s390_init_linux_record_tdep (struct linux_record_tdep *record_tdep,
   record_tdep->ioctl_FIOQSIZE = 0x545e;
 }
 
+/* Allocate and initialize new gdbarch_tdep.  Caller is responsible to free
+   memory after use.  */
+
+static struct gdbarch_tdep *
+s390_gdbarch_tdep_alloc ()
+{
+  struct gdbarch_tdep *tdep = XCNEW (struct gdbarch_tdep);
+
+  tdep->tdesc = NULL;
+
+  tdep->abi = ABI_NONE;
+  tdep->vector_abi = S390_VECTOR_ABI_NONE;
+
+  tdep->gpr_full_regnum = -1;
+  tdep->v0_full_regnum = -1;
+  tdep->pc_regnum = -1;
+  tdep->cc_regnum = -1;
+
+  tdep->have_upper = false;
+  tdep->have_linux_v1 = false;
+  tdep->have_linux_v2 = false;
+  tdep->have_tdb = false;
+  tdep->have_vx = false;
+  tdep->have_gs = false;
+
+  return tdep;
+}
+
 /* Set up gdbarch struct.  */
 
 static struct gdbarch *
@@ -7686,15 +7845,6 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 {
   const struct target_desc *tdesc = info.target_desc;
   struct tdesc_arch_data *tdesc_data = NULL;
-  struct gdbarch *gdbarch;
-  struct gdbarch_tdep *tdep;
-  enum s390_abi_kind tdep_abi;
-  enum s390_vector_abi_kind vector_abi;
-  int have_upper = 0;
-  int have_linux_v1 = 0;
-  int have_linux_v2 = 0;
-  int have_tdb = 0;
-  int have_vx = 0;
   int first_pseudo_reg, last_pseudo_reg;
   static const char *const stap_register_prefixes[] = { "%", NULL };
   static const char *const stap_register_indirection_prefixes[] = { "(",
@@ -7702,29 +7852,35 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   static const char *const stap_register_indirection_suffixes[] = { ")",
                                                                    NULL };
 
+  struct gdbarch_tdep *tdep = s390_gdbarch_tdep_alloc ();
+  struct gdbarch *gdbarch = gdbarch_alloc (&info, tdep);
+
   /* Default ABI and register size.  */
   switch (info.bfd_arch_info->mach)
     {
     case bfd_mach_s390_31:
-      tdep_abi = ABI_LINUX_S390;
+      tdep->abi = ABI_LINUX_S390;
       break;
 
     case bfd_mach_s390_64:
-      tdep_abi = ABI_LINUX_ZSERIES;
+      tdep->abi = ABI_LINUX_ZSERIES;
       break;
 
     default:
+      xfree (tdep);
+      gdbarch_free (gdbarch);
       return NULL;
     }
 
   /* Use default target description if none provided by the target.  */
   if (!tdesc_has_registers (tdesc))
     {
-      if (tdep_abi == ABI_LINUX_S390)
+      if (tdep->abi == ABI_LINUX_S390)
        tdesc = tdesc_s390_linux32;
       else
        tdesc = tdesc_s390x_linux64;
     }
+  tdep->tdesc = tdesc;
 
   /* Check any target description for validity.  */
   if (tdesc_has_registers (tdesc))
@@ -7762,12 +7918,22 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
        "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23", "v24",
        "v25", "v26", "v27", "v28", "v29", "v30", "v31",
       };
+      static const char *const gs_cb[] = {
+       "gsd", "gssm", "gsepla",
+      };
+      static const char *const gs_bc[] = {
+       "bc_gsd", "bc_gssm", "bc_gsepla",
+      };
       const struct tdesc_feature *feature;
       int i, valid_p = 1;
 
       feature = tdesc_find_feature (tdesc, "org.gnu.gdb.s390.core");
       if (feature == NULL)
-       return NULL;
+       {
+         xfree (tdep);
+         gdbarch_free (gdbarch);
+         return NULL;
+       }
 
       tdesc_data = tdesc_data_alloc ();
 
@@ -7784,7 +7950,7 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
        }
       else
        {
-         have_upper = 1;
+         tdep->have_upper = true;
 
          for (i = 0; i < 16; i++)
            valid_p &= tdesc_numbered_register (feature, tdesc_data,
@@ -7800,6 +7966,8 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       if (feature == NULL)
        {
          tdesc_data_cleanup (tdesc_data);
+         xfree (tdep);
+         gdbarch_free (gdbarch);
          return NULL;
        }
 
@@ -7813,6 +7981,8 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       if (feature == NULL)
        {
          tdesc_data_cleanup (tdesc_data);
+         xfree (tdep);
+         gdbarch_free (gdbarch);
          return NULL;
        }
 
@@ -7829,13 +7999,13 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
          if (tdesc_numbered_register (feature, tdesc_data,
                                       S390_LAST_BREAK_REGNUM, "last_break"))
-           have_linux_v1 = 1;
+           tdep->have_linux_v1 = true;
 
          if (tdesc_numbered_register (feature, tdesc_data,
                                       S390_SYSTEM_CALL_REGNUM, "system_call"))
-           have_linux_v2 = 1;
+           tdep->have_linux_v2 = true;
 
-         if (have_linux_v2 > have_linux_v1)
+         if (tdep->have_linux_v2 && !tdep->have_linux_v1)
            valid_p = 0;
        }
 
@@ -7847,7 +8017,7 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
            valid_p &= tdesc_numbered_register (feature, tdesc_data,
                                                S390_TDB_DWORD0_REGNUM + i,
                                                tdb_regs[i]);
-         have_tdb = 1;
+         tdep->have_tdb = true;
        }
 
       /* Vector registers.  */
@@ -7862,26 +8032,50 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
            valid_p &= tdesc_numbered_register (feature, tdesc_data,
                                                S390_V16_REGNUM + i,
                                                vxrs_high[i]);
-         have_vx = 1;
+         tdep->have_vx = true;
+       }
+
+      /* Guarded-storage registers.  */
+      feature = tdesc_find_feature (tdesc, "org.gnu.gdb.s390.gs");
+      if (feature)
+       {
+         for (i = 0; i < 3; i++)
+           valid_p &= tdesc_numbered_register (feature, tdesc_data,
+                                               S390_GSD_REGNUM + i,
+                                               gs_cb[i]);
+         tdep->have_gs = true;
+       }
+
+      /* Guarded-storage broadcast control.  */
+      feature = tdesc_find_feature (tdesc, "org.gnu.gdb.s390.gsbc");
+      if (feature)
+       {
+         valid_p &= tdep->have_gs;
+
+         for (i = 0; i < 3; i++)
+           valid_p &= tdesc_numbered_register (feature, tdesc_data,
+                                               S390_BC_GSD_REGNUM + i,
+                                               gs_bc[i]);
        }
 
       if (!valid_p)
        {
          tdesc_data_cleanup (tdesc_data);
+         xfree (tdep);
+         gdbarch_free (gdbarch);
          return NULL;
        }
     }
 
   /* Determine vector ABI.  */
-  vector_abi = S390_VECTOR_ABI_NONE;
 #ifdef HAVE_ELF
-  if (have_vx
+  if (tdep->have_vx
       && info.abfd != NULL
       && info.abfd->format == bfd_object
       && bfd_get_flavour (info.abfd) == bfd_target_elf_flavour
       && bfd_elf_get_obj_attr_int (info.abfd, OBJ_ATTR_GNU,
                                   Tag_GNU_S390_ABI_Vector) == 2)
-    vector_abi = S390_VECTOR_ABI_128;
+    tdep->vector_abi = S390_VECTOR_ABI_128;
 #endif
 
   /* Find a candidate among extant architectures.  */
@@ -7889,29 +8083,21 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
        arches != NULL;
        arches = gdbarch_list_lookup_by_info (arches->next, &info))
     {
-      tdep = gdbarch_tdep (arches->gdbarch);
-      if (!tdep)
-       continue;
-      if (tdep->abi != tdep_abi)
+      struct gdbarch_tdep *tmp = gdbarch_tdep (arches->gdbarch);
+      if (!tmp)
        continue;
-      if (tdep->vector_abi != vector_abi)
-       continue;
-      if ((tdep->gpr_full_regnum != -1) != have_upper)
+      /* A program can 'choose' not to use the vector registers when they
+        are present.  Leading to the same tdesc but different tdep and
+        thereby a different gdbarch.  */
+      if (tmp->vector_abi != tdep->vector_abi)
        continue;
       if (tdesc_data != NULL)
        tdesc_data_cleanup (tdesc_data);
+      xfree (tdep);
+      gdbarch_free (gdbarch);
       return arches->gdbarch;
     }
 
-  /* Otherwise create a new gdbarch for the specified machine type.  */
-  tdep = XCNEW (struct gdbarch_tdep);
-  tdep->abi = tdep_abi;
-  tdep->vector_abi = vector_abi;
-  tdep->have_linux_v1 = have_linux_v1;
-  tdep->have_linux_v2 = have_linux_v2;
-  tdep->have_tdb = have_tdb;
-  gdbarch = gdbarch_alloc (&info, tdep);
-
   set_gdbarch_believe_pcc_promotion (gdbarch, 0);
   set_gdbarch_char_signed (gdbarch, 0);
 
@@ -7957,20 +8143,18 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_ax_pseudo_register_push_stack
       (gdbarch, s390_ax_pseudo_register_push_stack);
   set_gdbarch_gen_return_address (gdbarch, s390_gen_return_address);
-  tdesc_use_registers (gdbarch, tdesc, tdesc_data);
+  tdesc_use_registers (gdbarch, tdep->tdesc, tdesc_data);
   set_gdbarch_register_name (gdbarch, s390_register_name);
 
   /* Assign pseudo register numbers.  */
   first_pseudo_reg = gdbarch_num_regs (gdbarch);
   last_pseudo_reg = first_pseudo_reg;
-  tdep->gpr_full_regnum = -1;
-  if (have_upper)
+  if (tdep->have_upper)
     {
       tdep->gpr_full_regnum = last_pseudo_reg;
       last_pseudo_reg += 16;
     }
-  tdep->v0_full_regnum = -1;
-  if (have_vx)
+  if (tdep->have_vx)
     {
       tdep->v0_full_regnum = last_pseudo_reg;
       last_pseudo_reg += 16;
@@ -8005,8 +8189,6 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_displaced_step_copy_insn (gdbarch,
                                        s390_displaced_step_copy_insn);
   set_gdbarch_displaced_step_fixup (gdbarch, s390_displaced_step_fixup);
-  set_gdbarch_displaced_step_free_closure (gdbarch,
-                                          simple_displaced_step_free_closure);
   set_gdbarch_displaced_step_location (gdbarch, linux_displaced_step_location);
   set_gdbarch_max_insn_length (gdbarch, S390_MAX_INSTR_SIZE);
 
@@ -8071,9 +8253,6 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   return gdbarch;
 }
 
-
-extern initialize_file_ftype _initialize_s390_tdep; /* -Wmissing-prototypes */
-
 void
 _initialize_s390_tdep (void)
 {
@@ -8090,10 +8269,12 @@ _initialize_s390_tdep (void)
   initialize_tdesc_s390_te_linux64 ();
   initialize_tdesc_s390_vx_linux64 ();
   initialize_tdesc_s390_tevx_linux64 ();
+  initialize_tdesc_s390_gs_linux64 ();
   initialize_tdesc_s390x_linux64 ();
   initialize_tdesc_s390x_linux64v1 ();
   initialize_tdesc_s390x_linux64v2 ();
   initialize_tdesc_s390x_te_linux64 ();
   initialize_tdesc_s390x_vx_linux64 ();
   initialize_tdesc_s390x_tevx_linux64 ();
+  initialize_tdesc_s390x_gs_linux64 ();
 }
This page took 0.037716 seconds and 4 git commands to generate.