/* Target-dependent code for s390.
- Copyright (C) 2001-2018 Free Software Foundation, Inc.
+ Copyright (C) 2001-2019 Free Software Foundation, Inc.
This file is part of GDB.
#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;
/* 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. */
if (pv_is_constant (addr))
{
struct target_section *secp;
- secp = target_section_by_addr (¤t_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)
}
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
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"));
}
/* 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);
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;
}
/* 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
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
{
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;
}
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;
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;
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". */
{
/* 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,
/* 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
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;
}
}
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;
}
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;
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));
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));
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)
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 ();
/* 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);
{
/* Hook us into the gdbarch mechanism. */
register_gdbarch_init (bfd_arch_s390, s390_gdbarch_init);
+
+ initialize_tdesc_s390_linux32 ();
+ initialize_tdesc_s390x_linux64 ();
}