diff options
Diffstat (limited to 'gdb')
-rw-r--r-- | gdb/ChangeLog | 89 | ||||
-rw-r--r-- | gdb/Makefile.in | 13 | ||||
-rw-r--r-- | gdb/config/s390/nm-linux.h | 29 | ||||
-rw-r--r-- | gdb/config/s390/s390.mh | 3 | ||||
-rw-r--r-- | gdb/config/s390/s390x.mt | 8 | ||||
-rw-r--r-- | gdb/config/s390/tm-linux.h | 14 | ||||
-rw-r--r-- | gdb/config/s390/tm-s390.h | 78 | ||||
-rw-r--r-- | gdb/configure.tgt | 5 | ||||
-rw-r--r-- | gdb/gdbserver/linux-s390-low.c | 10 | ||||
-rw-r--r-- | gdb/regformats/reg-s390.dat | 16 | ||||
-rw-r--r-- | gdb/regformats/reg-s390x.dat | 16 | ||||
-rw-r--r-- | gdb/s390-nat.c | 345 | ||||
-rw-r--r-- | gdb/s390-tdep.c | 683 | ||||
-rw-r--r-- | gdb/s390-tdep.h | 105 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/float.exp | 2 |
15 files changed, 934 insertions, 482 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 0171e988cec..c95392b031c 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,92 @@ +2004-02-17 Ulrich Weigand <Ulrich.Weigand@de.ibm.com> + + Committed by Jim Blandy <jimb@redhat.com>. + * config/s390/nm-linux.h: Update comments. Do not include "solib.h". + (KERNEL_U_ADDR, REGISTER_U_ADDR, U_REGS_OFFSET): Remove. + (FETCH_INFERIOR_REGISTERS): Define. + * config/s390/s390.mh (NATDEPFILES): Remove core-aout.o and + core-regset.o. + * config/s390/s390x.mt: Remove. + * config/s390/tm-s390.h: Remove. + * config/s390/tm-linux.h: Do not include "s390/tm-s390.h". + (TARGET_ELF64): Remove. + (SKIP_TRAMPOLINE_CODE): Do not undefine. + * configure.tgt [s390-*-*, s390x-*-*]: Merge into single + s390*-*-* case; always set gdb_target to s390. + * regformats/reg-s390.dat: Remove control registers. + * regformats/reg-s390x.dat: Likewise. + * s390-tdep.h: New file. + * s390-nat.c: Do not include <asm/processor.h> or <value.h>. + Include "inferior.h" and "s390-tdep.h". + Remove private definition of offsetof. + (s390_register_u_addr): Remove. + (regmap_gregset, regmap_fpregset): Define. + (supply_gregset, fill_gregset): Reimplement. + (supply_fpregset, fill_fpregset): Likewise. + (s390_inferior_tid): New function. + (fetch_regs, store_regs, fetch_fpregs, store_fpregs): Likewise. + (fetch_inferior_registers, store_inferior_registers): Likewise. + * s390-tdep.c: Do not define S390_TDEP. Include "defs.h" instead + of <defs.h>. Include "reggroups.h", "regset.h", and "s390-tdep.h". + Global replace of S390_GP0_REGNUM by S390_R0_REGNUM. + Global replace of S390_FP0_REGNUM by S390_F0_REGNUM. + (struct gdbarch_tdep): Define. + (struct s390_register_info): Define. + (s390_register_info): New variable. + (s390_register_name): Reimplement. + (s390_register_type): New function. + (s390_register_raw_size, s390x_register_raw_size): Remove. + (s390_cannot_fetch_register): Remove. + (s390_register_byte): Remove. + (s390_register_virtual_type, s390x_register_virtual_type): Remove. + (s390_dwarf_regmap): New variable. + (s390_dwarf_reg_to_regnum): New function. + (s390_stab_reg_to_regnum): Remove. + (s390_pseudo_register_read, s390_pseudo_register_write): New functions. + (s390x_pseudo_register_read, s390x_pseudo_register_write): Likewise. + (s390_convert_register_p): Likewise. + (s390_register_to_value, s390_value_to_register): Likewise. + (s390_register_reggroup_p): Likewise. + (s390_regmap_gregset, s390x_regmap_gregset, s390_regmap_fpregset, + s390_gregset, s390x_gregset, s390_fpregset): New variables. + (s390_supply_regset, s390_regset_from_core_section): New functions. + (GDB_TARGET_IS_ESAME): Move here from tm-s390.h. + (S390_FPR_SIZE): Likewise. + (S390_GPR_SIZE): Likewise. Redefine in terms of GDB_TARGET_IS_ESAME. + Global replace of DEPRECATED_REGISTER_SIZE by S390_GPR_SIZE. + (S390_NUM_GPRS): Move here from tm-s390.h. + (S390_NUM_FPRS): Likewise. + (s390_in_function_epilogue_p): New function. + (s390_is_sigreturn): Replace S390_PSW_ADDR_SIZE by S390_GPR_SIZE. + Replace S390_PC_REGNUM by S390_PSWA_REGNUM. + (s390_gdbarch_init): Allocate and set up gdbarch_tdep structure. + Replace s390_stab_reg_to_regnum by s390_dwarf_reg_to_regnum. + Replace S390_FP_REGNUM by S390_SP_REGNUM. + Remove calls to: + set_gdbarch_deprecated_max_register_raw_size, + set_gdbarch_deprecated_max_register_virtual_size, + set_gdbarch_deprecated_register_byte, + set_gdbarch_cannot_fetch_register, + set_gdbarch_cannot_store_register, + set_gdbarch_deprecated_register_size, + set_gdbarch_deprecated_register_raw_size, + set_gdbarch_deprecated_register_virtual_size, + set_gdbarch_deprecated_register_virtual_type, + set_gdbarch_deprecated_register_bytes. + Add calls to: + set_gdbarch_num_pseudo_regs, + set_gdbarch_register_type, + set_gdbarch_convert_register_p, + set_gdbarch_register_to_value, + set_gdbarch_value_to_register, + set_gdbarch_register_reggroup_p, + set_gdbarch_regset_from_core_section, + set_gdbarch_pseudo_register_read, + set_gdbarch_pseudo_register_write, + set_gdbarch_in_function_epilogue_p. + * Makefile.in (s390-nat.o, s390-tdep.o): Update dependencies. + (s390_tdep_h): New variable. + 2004-02-17 Jim Blandy <jimb@redhat.com> * findvar.c (value_from_register): If the type has no length, just diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 82471f196fd..ff141061434 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -727,6 +727,7 @@ regset_h = regset.h remote_fileio_h = remote-fileio.h remote_h = remote.h remote_utils_h = remote-utils.h $(target_h) +s390_tdep_h = s390-tdep.h scm_lang_h = scm-lang.h $(scm_tags_h) scm_tags_h = scm-tags.h sentinel_frame_h = sentinel-frame.h @@ -2175,11 +2176,13 @@ rs6000-tdep.o: rs6000-tdep.c $(defs_h) $(frame_h) $(inferior_h) $(symtab_h) \ $(libbfd_h) $(coff_internal_h) $(libcoff_h) $(coff_xcoff_h) \ $(libxcoff_h) $(elf_bfd_h) $(solib_svr4_h) $(ppc_tdep_h) \ $(gdb_assert_h) $(dis_asm_h) -s390-nat.o: s390-nat.c $(defs_h) $(tm_h) $(regcache_h) -s390-tdep.o: s390-tdep.c $(arch_utils_h) $(frame_h) $(inferior_h) \ - $(symtab_h) $(target_h) $(gdbcore_h) $(gdbcmd_h) $(objfiles_h) \ - $(tm_h) $(__bfd_bfd_h) $(floatformat_h) $(regcache_h) $(value_h) \ - $(gdb_assert_h) $(dis_asm_h) +s390-nat.o: s390-nat.c $(defs_h) $(tm_h) $(regcache_h) $(inferior_h) \ + $(s390_tdep_h) +s390-tdep.o: s390-tdep.c $(defs_h) $(arch_utils_h) $(frame_h) $(inferior_h) \ + $(symtab_h) $(target_h) $(gdbcore_h) $(gdbcmd_h) $(symfile_h) \ + $(objfiles_h) $(tm_h) $(__bfd_bfd_h) $(floatformat_h) $(regcache_h) \ + $(reggroups_h) $(regset_h) $(value_h) $(gdb_assert_h) $(dis_asm_h) \ + $(s390_tdep_h) scm-exp.o: scm-exp.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(expression_h) \ $(parser_defs_h) $(language_h) $(value_h) $(c_lang_h) $(scm_lang_h) \ $(scm_tags_h) diff --git a/gdb/config/s390/nm-linux.h b/gdb/config/s390/nm-linux.h index df601de6ed3..6931efb4c00 100644 --- a/gdb/config/s390/nm-linux.h +++ b/gdb/config/s390/nm-linux.h @@ -1,6 +1,6 @@ /* Native support for GNU/Linux on S390. - Copyright 2001, 2002 Free Software Foundation, Inc. + Copyright 2001, 2002, 2003 Free Software Foundation, Inc. Ported by D.J. Barrow for IBM Deutschland Entwicklung GmbH, IBM Corporation. derived from i390-nmlinux.h @@ -27,30 +27,17 @@ #include "config/nm-linux.h" -/* This is the amount to subtract from u.u_ar0 - to get the offset in the core file of the register values. */ -#define KERNEL_U_ADDR 0x0 -#define REGISTER_U_ADDR(addr, blockend, regno) \ - (addr) = s390_register_u_addr((blockend),(regno)); -extern int s390_register_u_addr (int, int); +/* ptrace access. */ -/* Return sizeof user struct to callers in less machine dependent routines */ +#define PTRACE_ARG3_TYPE long +#define PTRACE_XFER_TYPE long + +#define FETCH_INFERIOR_REGISTERS #define KERNEL_U_SIZE kernel_u_size() extern int kernel_u_size (void); -#define U_REGS_OFFSET 0 - - -/* We define this if link.h is available, because with ELF we use SVR4 style - shared libraries. */ - -#ifdef HAVE_LINK_H -#define SVR4_SHARED_LIBS -#include "solib.h" /* Support for shared libraries. */ -#endif - /* WATCHPOINT SPECIFIC STUFF */ @@ -81,8 +68,4 @@ extern int s390_remove_watchpoint (int pid, CORE_ADDR addr, int len); ((type) == bp_read_watchpoint) || \ ((type) == bp_access_watchpoint)) - -/* Needed for s390x */ -#define PTRACE_ARG3_TYPE long -#define PTRACE_XFER_TYPE long #endif /* nm_linux.h */ diff --git a/gdb/config/s390/s390.mh b/gdb/config/s390/s390.mh index b45fa116d4b..3db7bd91f99 100644 --- a/gdb/config/s390/s390.mh +++ b/gdb/config/s390/s390.mh @@ -1,6 +1,5 @@ # Host: S390, running Linux NAT_FILE= nm-linux.h NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o s390-nat.o \ - core-aout.o core-regset.o linux-proc.o gcore.o thread-db.o lin-lwp.o \ - proc-service.o linux-nat.o + linux-proc.o gcore.o thread-db.o lin-lwp.o proc-service.o linux-nat.o LOADLIBES = -ldl -rdynamic diff --git a/gdb/config/s390/s390x.mt b/gdb/config/s390/s390x.mt deleted file mode 100644 index d0c8262f72d..00000000000 --- a/gdb/config/s390/s390x.mt +++ /dev/null @@ -1,8 +0,0 @@ -# Target: S390 running Linux -TM_FILE= tm-linux.h -TDEPFILES=s390-tdep.o solib.o -# Post 5.0 tdep-files -TDEPFILES+=solib-svr4.o solib-legacy.o - -# needed for gdbserver. -MT_CFLAGS= -DCONFIG_ARCH_S390X diff --git a/gdb/config/s390/tm-linux.h b/gdb/config/s390/tm-linux.h index 7b406e0dc0a..d13d06dc139 100644 --- a/gdb/config/s390/tm-linux.h +++ b/gdb/config/s390/tm-linux.h @@ -1,6 +1,6 @@ /* Target definitions for GDB for a s390 running GNU/Linux. - Copyright 2001, 2002 Free Software Foundation, Inc. + Copyright 2001, 2002, 2003 Free Software Foundation, Inc. Contributed by D.J. Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com) for IBM Deutschland Entwicklung GmbH, IBM Corporation. @@ -25,18 +25,6 @@ #ifndef TM_LINUX_H #define TM_LINUX_H -#undef TARGET_ELF64 -#define TARGET_ELF64 (gdbarch_tdep (current_gdbarch)->intreg_size==8) - #include "config/tm-linux.h" -/* Zap several macros defined in the above header so that multi-arch - can safely re-define them. The ``correct fix'' involves - eliminating either the above include or even this file. */ -#undef SKIP_TRAMPOLINE_CODE - -#include "s390/tm-s390.h" - - - #endif /* TM_LINUX_H */ diff --git a/gdb/config/s390/tm-s390.h b/gdb/config/s390/tm-s390.h deleted file mode 100644 index d36c2798f4f..00000000000 --- a/gdb/config/s390/tm-s390.h +++ /dev/null @@ -1,78 +0,0 @@ -/* Macro definitions for GDB on an S390. - Copyright 2001 Free Software Foundation, Inc. - Contributed by D.J. Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com) - for IBM Deutschland Entwicklung GmbH, IBM Corporation. - - This file is part of GDB. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. */ - -#if !defined(TM_S390_H) -#define TM_S390_H 1 - -#define S390_NUM_GPRS (16) -#define S390_GPR_SIZE DEPRECATED_REGISTER_SIZE -#define S390_PSW_MASK_SIZE DEPRECATED_REGISTER_SIZE -#define S390_PSW_ADDR_SIZE DEPRECATED_REGISTER_SIZE -#define S390_NUM_FPRS (16) -#define S390_FPR_SIZE (8) -#define S390_FPC_SIZE (4) -#define S390_FPC_PAD_SIZE (4) /* gcc insists on aligning the fpregs */ -#define S390_NUM_CRS (16) -#define S390_CR_SIZE DEPRECATED_REGISTER_SIZE -#define S390_NUM_ACRS (16) -#define S390_ACR_SIZE (4) - -#define S390_NUM_REGS (2+S390_NUM_GPRS+S390_NUM_ACRS+S390_NUM_CRS+1+S390_NUM_FPRS) -#define S390_FIRST_ACR (2+S390_NUM_GPRS) -#define S390_LAST_ACR (S390_FIRST_ACR+S390_NUM_ACRS-1) -#define S390_FIRST_CR (S390_FIRST_ACR+S390_NUM_ACRS) -#define S390_LAST_CR (S390_FIRST_CR+S390_NUM_CRS-1) - -#define S390_PSWM_REGNUM 0 -#define S390_PC_REGNUM 1 -#define S390_GP0_REGNUM 2 /* GPR register 0 */ -#define S390_GP_LAST_REGNUM (S390_GP0_REGNUM+S390_NUM_GPRS-1) -/* Usually return address */ -#define S390_RETADDR_REGNUM (S390_GP0_REGNUM+14) -/* Contains address of top of stack */ -#define S390_SP_REGNUM (S390_GP0_REGNUM+15) -/* needed in findvar.c still */ -#define S390_FP_REGNUM S390_SP_REGNUM -#define S390_FRAME_REGNUM (S390_GP0_REGNUM+11) -#define S390_FPC_REGNUM (S390_GP0_REGNUM+S390_NUM_GPRS+S390_NUM_ACRS+S390_NUM_CRS) -/* FPR (Floating point) register 0 */ -#define S390_FP0_REGNUM (S390_FPC_REGNUM+1) -/* Last floating point register */ -#define S390_FPLAST_REGNUM (S390_FP0_REGNUM+S390_NUM_FPRS-1) -#define S390_LAST_REGNUM S390_FPLAST_REGNUM - - -#define S390_ACR0_OFFSET ((S390_PSW_MASK_SIZE+S390_PSW_ADDR_SIZE)+(S390_GPR_SIZE*S390_NUM_GPRS)) -#define S390_CR0_OFFSET (S390_ACR0_OFFSET+(S390_ACR_SIZE*S390_NUM_ACRS)) -#define S390_FPC_OFFSET (S390_CR0_OFFSET+(S390_CR_SIZE*S390_NUM_CRS)) -#define S390_FP0_OFFSET (S390_FPC_OFFSET+(S390_FPC_SIZE+S390_FPC_PAD_SIZE)) -#define S390_GPR6_STACK_OFFSET (GDB_TARGET_IS_ESAME ? 48:24) - -#define S390_REGISTER_BYTES ((4+4)+(4*S390_NUM_GPRS)+(4*S390_NUM_ACRS)+ \ -(4*S390_NUM_CRS)+(S390_FPC_SIZE+S390_FPC_PAD_SIZE)+(S390_FPR_SIZE*S390_NUM_FPRS)) - -#define S390X_REGISTER_BYTES ((8+8)+(8*S390_NUM_GPRS)+(4*S390_NUM_ACRS)+ \ -(8*S390_NUM_CRS)+(S390_FPC_SIZE+S390_FPC_PAD_SIZE)+(S390_FPR_SIZE*S390_NUM_FPRS)) - -#define GDB_TARGET_IS_ESAME (TARGET_ARCHITECTURE->mach == bfd_mach_s390_64) - -#endif /* ifndef TM_S390_H */ diff --git a/gdb/configure.tgt b/gdb/configure.tgt index 0d159d48216..fe1702e43bc 100644 --- a/gdb/configure.tgt +++ b/gdb/configure.tgt @@ -168,10 +168,7 @@ rs6000-*-lynxos*) gdb_target=rs6000lynx ;; rs6000-*-aix4*) gdb_target=aix4 ;; rs6000-*-*) gdb_target=rs6000 ;; -s390-*-*) gdb_target=s390 - build_gdbserver=yes - ;; -s390x-*-*) gdb_target=s390x +s390*-*-*) gdb_target=s390 build_gdbserver=yes ;; diff --git a/gdb/gdbserver/linux-s390-low.c b/gdb/gdbserver/linux-s390-low.c index 9213f68ef00..d1a94fb791b 100644 --- a/gdb/gdbserver/linux-s390-low.c +++ b/gdb/gdbserver/linux-s390-low.c @@ -27,7 +27,7 @@ #include <asm/ptrace.h> -#define s390_num_regs 67 +#define s390_num_regs 51 static int s390_regmap[] = { PT_PSWMASK, PT_PSWADDR, @@ -42,15 +42,9 @@ static int s390_regmap[] = { PT_ACR8, PT_ACR9, PT_ACR10, PT_ACR11, PT_ACR12, PT_ACR13, PT_ACR14, PT_ACR15, - -1, -1, -1, -1, - -1, -1, -1, -1, - -1, PT_CR_9, PT_CR_10, PT_CR_11, - -1, -1, -1, -1, - PT_FPC, -/* <asm/ptrace.h> defines GPR_SIZE. */ -#if GPR_SIZE == 4 +#ifndef __s390x__ PT_FPR0_HI, PT_FPR1_HI, PT_FPR2_HI, PT_FPR3_HI, PT_FPR4_HI, PT_FPR5_HI, PT_FPR6_HI, PT_FPR7_HI, PT_FPR8_HI, PT_FPR9_HI, PT_FPR10_HI, PT_FPR11_HI, diff --git a/gdb/regformats/reg-s390.dat b/gdb/regformats/reg-s390.dat index c533a489459..79e07b969d4 100644 --- a/gdb/regformats/reg-s390.dat +++ b/gdb/regformats/reg-s390.dat @@ -34,22 +34,6 @@ expedite:r14,r15,pswa 32:acr13 32:acr14 32:acr15 -32:cr0 -32:cr1 -32:cr2 -32:cr3 -32:cr4 -32:cr5 -32:cr6 -32:cr7 -32:cr8 -32:cr9 -32:cr10 -32:cr11 -32:cr12 -32:cr13 -32:cr14 -32:cr15 32:fpc 64:f0 64:f1 diff --git a/gdb/regformats/reg-s390x.dat b/gdb/regformats/reg-s390x.dat index 25bef05645a..2e24f53d0d5 100644 --- a/gdb/regformats/reg-s390x.dat +++ b/gdb/regformats/reg-s390x.dat @@ -34,22 +34,6 @@ expedite:r14,r15,pswa 32:acr13 32:acr14 32:acr15 -64:cr0 -64:cr1 -64:cr2 -64:cr3 -64:cr4 -64:cr5 -64:cr6 -64:cr7 -64:cr8 -64:cr9 -64:cr10 -64:cr11 -64:cr12 -64:cr13 -64:cr14 -64:cr15 32:fpc 64:f0 64:f1 diff --git a/gdb/s390-nat.c b/gdb/s390-nat.c index 732cf94451a..ed6c4088b10 100644 --- a/gdb/s390-nat.c +++ b/gdb/s390-nat.c @@ -1,7 +1,9 @@ /* S390 native-dependent code for GDB, the GNU debugger. - Copyright 2001 Free Software Foundation, Inc + Copyright 2001, 2003 Free Software Foundation, Inc + Contributed by D.J. Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com) for IBM Deutschland Entwicklung GmbH, IBM Corporation. + This file is part of GDB. This program is free software; you can redistribute it and/or modify @@ -22,52 +24,201 @@ #include "defs.h" #include "tm.h" #include "regcache.h" +#include "inferior.h" + +#include "s390-tdep.h" + #include <asm/ptrace.h> #include <sys/ptrace.h> -#include <asm/processor.h> #include <asm/types.h> #include <sys/procfs.h> #include <sys/user.h> -#include <value.h> #include <sys/ucontext.h> -#ifndef offsetof -#define offsetof(type,member) ((size_t) &((type *)0)->member) -#endif -int -s390_register_u_addr (int blockend, int regnum) -{ - int retval; - - if (regnum >= S390_GP0_REGNUM && regnum <= S390_GP_LAST_REGNUM) - retval = PT_GPR0 + ((regnum - S390_GP0_REGNUM) * S390_GPR_SIZE); - else if (regnum >= S390_PSWM_REGNUM && regnum <= S390_PC_REGNUM) - retval = PT_PSWMASK + ((regnum - S390_PSWM_REGNUM) * S390_PSW_MASK_SIZE); - else if (regnum == S390_FPC_REGNUM) - retval = PT_FPC; - else if (regnum >= S390_FP0_REGNUM && regnum <= S390_FPLAST_REGNUM) - retval = -#if CONFIG_ARCH_S390X - PT_FPR0 +/* Map registers to gregset/ptrace offsets. + These arrays are defined in s390-tdep.c. */ + +#ifdef __s390x__ +#define regmap_gregset s390x_regmap_gregset #else - PT_FPR0_HI +#define regmap_gregset s390_regmap_gregset #endif - + ((regnum - S390_FP0_REGNUM) * S390_FPR_SIZE); - else if (regnum >= S390_FIRST_ACR && regnum <= S390_LAST_ACR) - retval = PT_ACR0 + ((regnum - S390_FIRST_ACR) * S390_ACR_SIZE); - else if (regnum >= (S390_FIRST_CR + 9) && regnum <= (S390_FIRST_CR + 11)) - retval = PT_CR_9 + ((regnum - (S390_FIRST_CR + 9)) * S390_CR_SIZE); - else - { - internal_error (__FILE__, __LINE__, - "s390_register_u_addr invalid regnum regnum=%d", - regnum); - retval = 0; - } - return retval + blockend; + +#define regmap_fpregset s390_regmap_fpregset + + +/* Fill GDB's register array with the general-purpose register values + in *REGP. */ +void +supply_gregset (gregset_t *regp) +{ + int i; + for (i = 0; i < S390_NUM_REGS; i++) + if (regmap_gregset[i] != -1) + regcache_raw_supply (current_regcache, i, + (char *)regp + regmap_gregset[i]); +} + +/* Fill register REGNO (if it is a general-purpose register) in + *REGP with the value in GDB's register array. If REGNO is -1, + do this for all registers. */ +void +fill_gregset (gregset_t *regp, int regno) +{ + int i; + for (i = 0; i < S390_NUM_REGS; i++) + if (regmap_gregset[i] != -1) + if (regno == -1 || regno == i) + regcache_raw_collect (current_regcache, i, + (char *)regp + regmap_gregset[i]); +} + +/* Fill GDB's register array with the floating-point register values + in *REGP. */ +void +supply_fpregset (fpregset_t *regp) +{ + int i; + for (i = 0; i < S390_NUM_REGS; i++) + if (regmap_fpregset[i] != -1) + regcache_raw_supply (current_regcache, i, + ((char *)regp) + regmap_fpregset[i]); +} + +/* Fill register REGNO (if it is a general-purpose register) in + *REGP with the value in GDB's register array. If REGNO is -1, + do this for all registers. */ +void +fill_fpregset (fpregset_t *regp, int regno) +{ + int i; + for (i = 0; i < S390_NUM_REGS; i++) + if (regmap_fpregset[i] != -1) + if (regno == -1 || regno == i) + regcache_raw_collect (current_regcache, i, + ((char *)regp) + regmap_fpregset[i]); +} + +/* Find the TID for the current inferior thread to use with ptrace. */ +static int +s390_inferior_tid (void) +{ + /* GNU/Linux LWP ID's are process ID's. */ + int tid = TIDGET (inferior_ptid); + if (tid == 0) + tid = PIDGET (inferior_ptid); /* Not a threaded program. */ + + return tid; +} + +/* Fetch all general-purpose registers from process/thread TID and + store their values in GDB's register cache. */ +static void +fetch_regs (int tid) +{ + gregset_t regs; + ptrace_area parea; + + parea.len = sizeof (regs); + parea.process_addr = (addr_t) ®s; + parea.kernel_addr = offsetof (struct user_regs_struct, psw); + if (ptrace (PTRACE_PEEKUSR_AREA, tid, (long) &parea) < 0) + perror_with_name ("Couldn't get registers"); + + supply_gregset (®s); +} + +/* Store all valid general-purpose registers in GDB's register cache + into the process/thread specified by TID. */ +static void +store_regs (int tid, int regnum) +{ + gregset_t regs; + ptrace_area parea; + + parea.len = sizeof (regs); + parea.process_addr = (addr_t) ®s; + parea.kernel_addr = offsetof (struct user_regs_struct, psw); + if (ptrace (PTRACE_PEEKUSR_AREA, tid, (long) &parea) < 0) + perror_with_name ("Couldn't get registers"); + + fill_gregset (®s, regnum); + + if (ptrace (PTRACE_POKEUSR_AREA, tid, (long) &parea) < 0) + perror_with_name ("Couldn't write registers"); +} + +/* Fetch all floating-point registers from process/thread TID and store + their values in GDB's register cache. */ +static void +fetch_fpregs (int tid) +{ + fpregset_t fpregs; + ptrace_area parea; + + parea.len = sizeof (fpregs); + parea.process_addr = (addr_t) &fpregs; + parea.kernel_addr = offsetof (struct user_regs_struct, fp_regs); + if (ptrace (PTRACE_PEEKUSR_AREA, tid, (long) &parea) < 0) + perror_with_name ("Couldn't get floating point status"); + + supply_fpregset (&fpregs); +} + +/* Store all valid floating-point registers in GDB's register cache + into the process/thread specified by TID. */ +static void +store_fpregs (int tid, int regnum) +{ + fpregset_t fpregs; + ptrace_area parea; + + parea.len = sizeof (fpregs); + parea.process_addr = (addr_t) &fpregs; + parea.kernel_addr = offsetof (struct user_regs_struct, fp_regs); + if (ptrace (PTRACE_PEEKUSR_AREA, tid, (long) &parea) < 0) + perror_with_name ("Couldn't get floating point status"); + + fill_fpregset (&fpregs, regnum); + + if (ptrace (PTRACE_POKEUSR_AREA, tid, (long) &parea) < 0) + perror_with_name ("Couldn't write floating point status"); +} + +/* Fetch register REGNUM from the child process. If REGNUM is -1, do + this for all registers. */ +void +fetch_inferior_registers (int regnum) +{ + int tid = s390_inferior_tid (); + + if (regnum == -1 + || (regnum < S390_NUM_REGS && regmap_gregset[regnum] != -1)) + fetch_regs (tid); + + if (regnum == -1 + || (regnum < S390_NUM_REGS && regmap_fpregset[regnum] != -1)) + fetch_fpregs (tid); +} + +/* Store register REGNUM back into the child process. If REGNUM is + -1, do this for all registers. */ +void +store_inferior_registers (int regnum) +{ + int tid = s390_inferior_tid (); + + if (regnum == -1 + || (regnum < S390_NUM_REGS && regmap_gregset[regnum] != -1)) + store_regs (tid, regnum); + + if (regnum == -1 + || (regnum < S390_NUM_REGS && regmap_fpregset[regnum] != -1)) + store_fpregs (tid, regnum); } + /* watch_areas are required if you put 2 or more watchpoints on the same address or overlapping areas gdb will call us to delete the watchpoint more than once when we try to delete them. @@ -232,127 +383,3 @@ kernel_u_size (void) return sizeof (struct user); } - -#if (defined (S390_FP0_REGNUM) && defined (HAVE_FPREGSET_T) && defined(HAVE_SYS_PROCFS_H) && defined (HAVE_GREGSET_T)) -void -supply_gregset (gregset_t * gregsetp) -{ - int regi; - greg_t *gregp = (greg_t *) gregsetp; - - supply_register (S390_PSWM_REGNUM, (char *) &gregp[S390_PSWM_REGNUM]); - supply_register (S390_PC_REGNUM, (char *) &gregp[S390_PC_REGNUM]); - for (regi = 0; regi < S390_NUM_GPRS; regi++) - supply_register (S390_GP0_REGNUM + regi, - (char *) &gregp[S390_GP0_REGNUM + regi]); - -#if defined (CONFIG_ARCH_S390X) - /* On the s390x, each element of gregset_t is 8 bytes long, but - each access register is still only 32 bits long. So they're - packed two per element. It's apparently traditional that - gregset_t must be an array, so when the registers it provides - have different sizes, something has to get strange - somewhere. */ - { - unsigned int *acrs = (unsigned int *) &gregp[S390_FIRST_ACR]; - - for (regi = 0; regi < S390_NUM_ACRS; regi++) - supply_register (S390_FIRST_ACR + regi, (char *) &acrs[regi]); - } -#else - for (regi = 0; regi < S390_NUM_ACRS; regi++) - supply_register (S390_FIRST_ACR + regi, - (char *) &gregp[S390_FIRST_ACR + regi]); -#endif - - /* unfortunately this isn't in gregsetp */ - for (regi = 0; regi < S390_NUM_CRS; regi++) - supply_register (S390_FIRST_CR + regi, NULL); -} - - -void -supply_fpregset (fpregset_t * fpregsetp) -{ - int regi; - - supply_register (S390_FPC_REGNUM, (char *) &fpregsetp->fpc); - for (regi = 0; regi < S390_NUM_FPRS; regi++) - supply_register (S390_FP0_REGNUM + regi, (char *) &fpregsetp->fprs[regi]); - -} - -void -fill_gregset (gregset_t * gregsetp, int regno) -{ - int regi; - greg_t *gregp = (greg_t *) gregsetp; - - if (regno < 0) - { - regcache_collect (S390_PSWM_REGNUM, &gregp[S390_PSWM_REGNUM]); - regcache_collect (S390_PC_REGNUM, &gregp[S390_PC_REGNUM]); - for (regi = 0; regi < S390_NUM_GPRS; regi++) - regcache_collect (S390_GP0_REGNUM + regi, - &gregp[S390_GP0_REGNUM + regi]); -#if defined (CONFIG_ARCH_S390X) - /* See the comments about the access registers in - supply_gregset, above. */ - { - unsigned int *acrs = (unsigned int *) &gregp[S390_FIRST_ACR]; - - for (regi = 0; regi < S390_NUM_ACRS; regi++) - regcache_collect (S390_FIRST_ACR + regi, &acrs[regi]); - } -#else - for (regi = 0; regi < S390_NUM_ACRS; regi++) - regcache_collect (S390_FIRST_ACR + regi, - &gregp[S390_FIRST_ACR + regi]); -#endif - } - else if (regno >= S390_PSWM_REGNUM && regno < S390_FIRST_ACR) - regcache_collect (regno, &gregp[regno]); - else if (regno >= S390_FIRST_ACR && regno <= S390_LAST_ACR) - { -#if defined (CONFIG_ARCH_S390X) - /* See the comments about the access registers in - supply_gregset, above. */ - unsigned int *acrs = (unsigned int *) &gregp[S390_FIRST_ACR]; - - regcache_collect (regno, &acrs[regno - S390_FIRST_ACR]); -#else - regcache_collect (regno, &gregp[regno]); -#endif - } -} - -/* Given a pointer to a floating point register set in /proc format - (fpregset_t *), update the register specified by REGNO from gdb's idea - of the current floating point register set. If REGNO is -1, update - them all. */ - -void -fill_fpregset (fpregset_t * fpregsetp, int regno) -{ - int regi; - - if (regno < 0) - { - regcache_collect (S390_FPC_REGNUM, &fpregsetp->fpc); - for (regi = 0; regi < S390_NUM_FPRS; regi++) - regcache_collect (S390_FP0_REGNUM + regi, &fpregsetp->fprs[regi]); - } - else if (regno == S390_FPC_REGNUM) - regcache_collect (S390_FPC_REGNUM, &fpregsetp->fpc); - else if (regno >= S390_FP0_REGNUM && regno <= S390_FPLAST_REGNUM) - regcache_collect (regno, &fpregsetp->fprs[regno - S390_FP0_REGNUM]); -} - - -#else -#error "There are a few possibilities here" -#error "1) You aren't compiling for linux & don't need a core dumps to work." -#error "2) The header files sys/elf.h sys/user.h sys/ptrace.h & sys/procfs.h" -#error "libc files are inconsistent with linux/include/asm-s390/" -#error "3) you didn't do a completely clean build & delete config.cache." -#endif diff --git a/gdb/s390-tdep.c b/gdb/s390-tdep.c index 2d3f3ad8161..7b44a68ec33 100644 --- a/gdb/s390-tdep.c +++ b/gdb/s390-tdep.c @@ -22,8 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#define S390_TDEP /* for special macros in tm-s390.h */ -#include <defs.h> +#include "defs.h" #include "arch-utils.h" #include "frame.h" #include "inferior.h" @@ -36,53 +35,443 @@ #include "../bfd/bfd.h" #include "floatformat.h" #include "regcache.h" +#include "reggroups.h" +#include "regset.h" #include "value.h" #include "gdb_assert.h" #include "dis-asm.h" +#include "s390-tdep.h" -/* Number of bytes of storage in the actual machine representation - for register N. */ -static int -s390_register_raw_size (int reg_nr) +/* The tdep structure. */ + +struct gdbarch_tdep { - if (S390_FP0_REGNUM <= reg_nr - && reg_nr < S390_FP0_REGNUM + S390_NUM_FPRS) - return S390_FPR_SIZE; - else - return 4; + /* Core file register sets. */ + const struct regset *gregset; + int sizeof_gregset; + + const struct regset *fpregset; + int sizeof_fpregset; +}; + + +/* Register information. */ + +struct s390_register_info +{ + char *name; + struct type **type; +}; + +static struct s390_register_info s390_register_info[S390_NUM_TOTAL_REGS] = +{ + /* Program Status Word. */ + { "pswm", &builtin_type_long }, + { "pswa", &builtin_type_long }, + + /* General Purpose Registers. */ + { "r0", &builtin_type_long }, + { "r1", &builtin_type_long }, + { "r2", &builtin_type_long }, + { "r3", &builtin_type_long }, + { "r4", &builtin_type_long }, + { "r5", &builtin_type_long }, + { "r6", &builtin_type_long }, + { "r7", &builtin_type_long }, + { "r8", &builtin_type_long }, + { "r9", &builtin_type_long }, + { "r10", &builtin_type_long }, + { "r11", &builtin_type_long }, + { "r12", &builtin_type_long }, + { "r13", &builtin_type_long }, + { "r14", &builtin_type_long }, + { "r15", &builtin_type_long }, + + /* Access Registers. */ + { "acr0", &builtin_type_int }, + { "acr1", &builtin_type_int }, + { "acr2", &builtin_type_int }, + { "acr3", &builtin_type_int }, + { "acr4", &builtin_type_int }, + { "acr5", &builtin_type_int }, + { "acr6", &builtin_type_int }, + { "acr7", &builtin_type_int }, + { "acr8", &builtin_type_int }, + { "acr9", &builtin_type_int }, + { "acr10", &builtin_type_int }, + { "acr11", &builtin_type_int }, + { "acr12", &builtin_type_int }, + { "acr13", &builtin_type_int }, + { "acr14", &builtin_type_int }, + { "acr15", &builtin_type_int }, + + /* Floating Point Control Word. */ + { "fpc", &builtin_type_int }, + + /* Floating Point Registers. */ + { "f0", &builtin_type_double }, + { "f1", &builtin_type_double }, + { "f2", &builtin_type_double }, + { "f3", &builtin_type_double }, + { "f4", &builtin_type_double }, + { "f5", &builtin_type_double }, + { "f6", &builtin_type_double }, + { "f7", &builtin_type_double }, + { "f8", &builtin_type_double }, + { "f9", &builtin_type_double }, + { "f10", &builtin_type_double }, + { "f11", &builtin_type_double }, + { "f12", &builtin_type_double }, + { "f13", &builtin_type_double }, + { "f14", &builtin_type_double }, + { "f15", &builtin_type_double }, + + /* Pseudo registers. */ + { "pc", &builtin_type_void_func_ptr }, + { "cc", &builtin_type_int }, +}; + +/* Return the name of register REGNUM. */ +static const char * +s390_register_name (int regnum) +{ + gdb_assert (regnum >= 0 && regnum < S390_NUM_TOTAL_REGS); + return s390_register_info[regnum].name; +} + +/* Return the GDB type object for the "standard" data type of data in + register REGNUM. */ +static struct type * +s390_register_type (struct gdbarch *gdbarch, int regnum) +{ + gdb_assert (regnum >= 0 && regnum < S390_NUM_TOTAL_REGS); + return *s390_register_info[regnum].type; } +/* DWARF Register Mapping. */ + +static int s390_dwarf_regmap[] = +{ + /* General Purpose Registers. */ + S390_R0_REGNUM, S390_R1_REGNUM, S390_R2_REGNUM, S390_R3_REGNUM, + S390_R4_REGNUM, S390_R5_REGNUM, S390_R6_REGNUM, S390_R7_REGNUM, + S390_R8_REGNUM, S390_R9_REGNUM, S390_R10_REGNUM, S390_R11_REGNUM, + S390_R12_REGNUM, S390_R13_REGNUM, S390_R14_REGNUM, S390_R15_REGNUM, + + /* Floating Point Registers. */ + S390_F0_REGNUM, S390_F2_REGNUM, S390_F4_REGNUM, S390_F6_REGNUM, + S390_F1_REGNUM, S390_F3_REGNUM, S390_F5_REGNUM, S390_F7_REGNUM, + S390_F8_REGNUM, S390_F10_REGNUM, S390_F12_REGNUM, S390_F14_REGNUM, + S390_F9_REGNUM, S390_F11_REGNUM, S390_F13_REGNUM, S390_F15_REGNUM, + + /* Control Registers (not mapped). */ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + + /* Access Registers. */ + S390_A0_REGNUM, S390_A1_REGNUM, S390_A2_REGNUM, S390_A3_REGNUM, + S390_A4_REGNUM, S390_A5_REGNUM, S390_A6_REGNUM, S390_A7_REGNUM, + S390_A8_REGNUM, S390_A9_REGNUM, S390_A10_REGNUM, S390_A11_REGNUM, + S390_A12_REGNUM, S390_A13_REGNUM, S390_A14_REGNUM, S390_A15_REGNUM, + + /* Program Status Word. */ + S390_PSWM_REGNUM, + S390_PSWA_REGNUM +}; + +/* Convert DWARF register number REG to the appropriate register + number used by GDB. */ static int -s390x_register_raw_size (int reg_nr) +s390_dwarf_reg_to_regnum (int reg) +{ + int regnum = -1; + + if (reg >= 0 || reg < ARRAY_SIZE (s390_dwarf_regmap)) + regnum = s390_dwarf_regmap[reg]; + + if (regnum == -1) + warning ("Unmapped DWARF Register #%d encountered\n", reg); + + return regnum; +} + +/* Pseudo registers - PC and condition code. */ + +static void +s390_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache, + int regnum, void *buf) +{ + ULONGEST val; + + switch (regnum) + { + case S390_PC_REGNUM: + regcache_raw_read_unsigned (regcache, S390_PSWA_REGNUM, &val); + store_unsigned_integer (buf, 4, val & 0x7fffffff); + break; + + case S390_CC_REGNUM: + regcache_raw_read_unsigned (regcache, S390_PSWM_REGNUM, &val); + store_unsigned_integer (buf, 4, (val >> 12) & 3); + break; + + default: + internal_error (__FILE__, __LINE__, "invalid regnum"); + } +} + +static void +s390_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache, + int regnum, const void *buf) { - return (reg_nr == S390_FPC_REGNUM) - || (reg_nr >= S390_FIRST_ACR && reg_nr <= S390_LAST_ACR) ? 4 : 8; + ULONGEST val, psw; + + switch (regnum) + { + case S390_PC_REGNUM: + val = extract_unsigned_integer (buf, 4); + regcache_raw_read_unsigned (regcache, S390_PSWA_REGNUM, &psw); + psw = (psw & 0x80000000) | (val & 0x7fffffff); + regcache_raw_write_unsigned (regcache, S390_PSWA_REGNUM, psw); + break; + + case S390_CC_REGNUM: + val = extract_unsigned_integer (buf, 4); + regcache_raw_read_unsigned (regcache, S390_PSWM_REGNUM, &psw); + psw = (psw & ~((ULONGEST)3 << 12)) | ((val & 3) << 12); + regcache_raw_write_unsigned (regcache, S390_PSWM_REGNUM, psw); + break; + + default: + internal_error (__FILE__, __LINE__, "invalid regnum"); + } } +static void +s390x_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache, + int regnum, void *buf) +{ + ULONGEST val; + + switch (regnum) + { + case S390_PC_REGNUM: + regcache_raw_read (regcache, S390_PSWA_REGNUM, buf); + break; + + case S390_CC_REGNUM: + regcache_raw_read_unsigned (regcache, S390_PSWM_REGNUM, &val); + store_unsigned_integer (buf, 4, (val >> 44) & 3); + break; + + default: + internal_error (__FILE__, __LINE__, "invalid regnum"); + } +} + +static void +s390x_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache, + int regnum, const void *buf) +{ + ULONGEST val, psw; + + switch (regnum) + { + case S390_PC_REGNUM: + regcache_raw_write (regcache, S390_PSWA_REGNUM, buf); + break; + + case S390_CC_REGNUM: + val = extract_unsigned_integer (buf, 4); + regcache_raw_read_unsigned (regcache, S390_PSWM_REGNUM, &psw); + psw = (psw & ~((ULONGEST)3 << 44)) | ((val & 3) << 44); + regcache_raw_write_unsigned (regcache, S390_PSWM_REGNUM, psw); + break; + + default: + internal_error (__FILE__, __LINE__, "invalid regnum"); + } +} + +/* 'float' values are stored in the upper half of floating-point + registers, even though we are otherwise a big-endian platform. */ + static int -s390_cannot_fetch_register (int regno) +s390_convert_register_p (int regno, struct type *type) { - return (regno >= S390_FIRST_CR && regno < (S390_FIRST_CR + 9)) || - (regno >= (S390_FIRST_CR + 12) && regno <= S390_LAST_CR); + return (regno >= S390_F0_REGNUM && regno <= S390_F15_REGNUM) + && TYPE_LENGTH (type) < 8; } +static void +s390_register_to_value (struct frame_info *frame, int regnum, + struct type *valtype, void *out) +{ + char in[8]; + int len = TYPE_LENGTH (valtype); + gdb_assert (len < 8); + + get_frame_register (frame, regnum, in); + memcpy (out, in, len); +} + +static void +s390_value_to_register (struct frame_info *frame, int regnum, + struct type *valtype, const void *in) +{ + char out[8]; + int len = TYPE_LENGTH (valtype); + gdb_assert (len < 8); + + memset (out, 0, 8); + memcpy (out, in, len); + put_frame_register (frame, regnum, out); +} + +/* Register groups. */ + static int -s390_register_byte (int reg_nr) -{ - if (reg_nr <= S390_GP_LAST_REGNUM) - return reg_nr * S390_GPR_SIZE; - if (reg_nr <= S390_LAST_ACR) - return S390_ACR0_OFFSET + (((reg_nr) - S390_FIRST_ACR) * S390_ACR_SIZE); - if (reg_nr <= S390_LAST_CR) - return S390_CR0_OFFSET + (((reg_nr) - S390_FIRST_CR) * S390_CR_SIZE); - if (reg_nr == S390_FPC_REGNUM) - return S390_FPC_OFFSET; - else - return S390_FP0_OFFSET + (((reg_nr) - S390_FP0_REGNUM) * S390_FPR_SIZE); +s390_register_reggroup_p (struct gdbarch *gdbarch, int regnum, + struct reggroup *group) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + /* Registers displayed via 'info regs'. */ + if (group == general_reggroup) + return (regnum >= S390_R0_REGNUM && regnum <= S390_R15_REGNUM) + || regnum == S390_PC_REGNUM + || regnum == S390_CC_REGNUM; + + /* Registers displayed via 'info float'. */ + if (group == float_reggroup) + return (regnum >= S390_F0_REGNUM && regnum <= S390_F15_REGNUM) + || regnum == S390_FPC_REGNUM; + + /* Registers that need to be saved/restored in order to + push or pop frames. */ + if (group == save_reggroup || group == restore_reggroup) + return regnum != S390_PSWM_REGNUM && regnum != S390_PSWA_REGNUM; + + return default_register_reggroup_p (gdbarch, regnum, group); +} + + +/* Core file register sets. */ + +int s390_regmap_gregset[S390_NUM_REGS] = +{ + /* Program Status Word. */ + 0x00, 0x04, + /* General Purpose Registers. */ + 0x08, 0x0c, 0x10, 0x14, + 0x18, 0x1c, 0x20, 0x24, + 0x28, 0x2c, 0x30, 0x34, + 0x38, 0x3c, 0x40, 0x44, + /* Access Registers. */ + 0x48, 0x4c, 0x50, 0x54, + 0x58, 0x5c, 0x60, 0x64, + 0x68, 0x6c, 0x70, 0x74, + 0x78, 0x7c, 0x80, 0x84, + /* Floating Point Control Word. */ + -1, + /* Floating Point Registers. */ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, +}; + +int s390x_regmap_gregset[S390_NUM_REGS] = +{ + 0x00, 0x08, + /* General Purpose Registers. */ + 0x10, 0x18, 0x20, 0x28, + 0x30, 0x38, 0x40, 0x48, + 0x50, 0x58, 0x60, 0x68, + 0x70, 0x78, 0x80, 0x88, + /* Access Registers. */ + 0x90, 0x94, 0x98, 0x9c, + 0xa0, 0xa4, 0xa8, 0xac, + 0xb0, 0xb4, 0xb8, 0xbc, + 0xc0, 0xc4, 0xc8, 0xcc, + /* Floating Point Control Word. */ + -1, + /* Floating Point Registers. */ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, +}; + +int s390_regmap_fpregset[S390_NUM_REGS] = +{ + /* Program Status Word. */ + -1, -1, + /* General Purpose Registers. */ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + /* Access Registers. */ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + /* Floating Point Control Word. */ + 0x00, + /* Floating Point Registers. */ + 0x08, 0x10, 0x18, 0x20, + 0x28, 0x30, 0x38, 0x40, + 0x48, 0x50, 0x58, 0x60, + 0x68, 0x70, 0x78, 0x80, +}; + +/* Supply register REGNUM from the register set REGSET to register cache + REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */ +static void +s390_supply_regset (const struct regset *regset, struct regcache *regcache, + int regnum, const void *regs, size_t len) +{ + const int *offset = regset->descr; + int i; + + for (i = 0; i < S390_NUM_REGS; i++) + { + if ((regnum == i || regnum == -1) && offset[i] != -1) + regcache_raw_supply (regcache, i, (const char *)regs + offset[i]); + } +} + +static const struct regset s390_gregset = { + s390_regmap_gregset, + s390_supply_regset +}; + +static const struct regset s390x_gregset = { + s390x_regmap_gregset, + s390_supply_regset +}; + +static const struct regset s390_fpregset = { + s390_regmap_fpregset, + s390_supply_regset +}; + +/* Return the appropriate register set for the core section identified + by SECT_NAME and SECT_SIZE. */ +const struct regset * +s390_regset_from_core_section (struct gdbarch *gdbarch, + const char *sect_name, size_t sect_size) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + if (strcmp (sect_name, ".reg") == 0 && sect_size == tdep->sizeof_gregset) + return tdep->gregset; + + if (strcmp (sect_name, ".reg2") == 0 && sect_size == tdep->sizeof_fpregset) + return tdep->fpregset; + + return NULL; } + +#define GDB_TARGET_IS_ESAME (TARGET_ARCHITECTURE->mach == bfd_mach_s390_64) +#define S390_GPR_SIZE (GDB_TARGET_IS_ESAME ? 8 : 4) +#define S390_FPR_SIZE (8) #define S390_MAX_INSTR_SIZE (6) #define S390_SYSCALL_OPCODE (0x0a) #define S390_SYSCALL_SIZE (2) @@ -92,8 +481,8 @@ s390_register_byte (int reg_nr) #define S390X_SIGREGS_FP0_OFFSET (216) #define S390_UC_MCONTEXT_OFFSET (256) #define S390X_UC_MCONTEXT_OFFSET (344) -#define S390_STACK_FRAME_OVERHEAD 16*DEPRECATED_REGISTER_SIZE+32 -#define S390_STACK_PARAMETER_ALIGNMENT DEPRECATED_REGISTER_SIZE +#define S390_STACK_FRAME_OVERHEAD 16*S390_GPR_SIZE+32 +#define S390_STACK_PARAMETER_ALIGNMENT S390_GPR_SIZE #define S390_NUM_FP_PARAMETER_REGISTERS (GDB_TARGET_IS_ESAME ? 4:2) #define S390_SIGNAL_FRAMESIZE (GDB_TARGET_IS_ESAME ? 160:96) #define s390_NR_sigreturn 119 @@ -149,44 +538,6 @@ s390_memset_extra_info (struct frame_extra_info *fextra_info) } - -static const char * -s390_register_name (int reg_nr) -{ - static char *register_names[] = { - "pswm", "pswa", - "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", - "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", - "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15" - }; - - if (reg_nr <= S390_LAST_REGNUM) - return register_names[reg_nr]; - else - return NULL; -} - - - - -static int -s390_stab_reg_to_regnum (int regno) -{ - return regno >= 64 ? S390_PSWM_REGNUM - 64 : - regno >= 48 ? S390_FIRST_ACR - 48 : - regno >= 32 ? S390_FIRST_CR - 32 : - regno <= 15 ? (regno + 2) : - S390_FP0_REGNUM + ((regno - 16) & 8) + (((regno - 16) & 3) << 1) + - (((regno - 16) & 4) >> 2); -} - - /* Prologue analysis. */ /* When we analyze a prologue, we're really doing 'abstract @@ -598,6 +949,8 @@ enum op1_stg = 0xe3, op2_stg = 0x24, op_stm = 0x90, op1_stmg = 0xeb, op2_stmg = 0x24, + op_lm = 0x98, + op1_lmg = 0xeb, op2_lmg = 0x04, op_svc = 0x0a, }; @@ -786,6 +1139,8 @@ compute_x_addr (struct prologue_value *addr, track general-purpose registers r2 -- r15, and floating-point registers f0, f2, f4, and f6. */ #define S390_NUM_SPILL_SLOTS (14 + 4) +#define S390_NUM_GPRS 16 +#define S390_NUM_FPRS 16 /* If the SIZE bytes at ADDR are a stack slot we're actually tracking, @@ -819,7 +1174,7 @@ s390_on_stack (struct prologue_value *addr, /* Construct the addresses of the spill arrays and the back chain. */ pv_set_to_register (&gpr_spill_addr, S390_SP_REGNUM, 2 * S390_GPR_SIZE); pv_set_to_register (&fpr_spill_addr, S390_SP_REGNUM, 16 * S390_GPR_SIZE); - back_chain_addr = gpr[S390_SP_REGNUM - S390_GP0_REGNUM]; + back_chain_addr = gpr[S390_SP_REGNUM - S390_R0_REGNUM]; /* We have to check for GPR and FPR references using two separate calls to pv_is_array_ref, since the GPR and FPR spill slots are @@ -902,12 +1257,12 @@ s390_get_signal_frame_info (struct frame_info *fi) /* We're definitely backtracing from a signal handler. */ CORE_ADDR *saved_regs = deprecated_get_frame_saved_regs (fi); CORE_ADDR save_reg_addr = (get_frame_extra_info (next_frame)->sigcontext - + DEPRECATED_REGISTER_BYTE (S390_GP0_REGNUM)); + + DEPRECATED_REGISTER_BYTE (S390_R0_REGNUM)); int reg; for (reg = 0; reg < S390_NUM_GPRS; reg++) { - saved_regs[S390_GP0_REGNUM + reg] = save_reg_addr; + saved_regs[S390_R0_REGNUM + reg] = save_reg_addr; save_reg_addr += S390_GPR_SIZE; } @@ -916,7 +1271,7 @@ s390_get_signal_frame_info (struct frame_info *fi) S390_SIGREGS_FP0_OFFSET)); for (reg = 0; reg < S390_NUM_FPRS; reg++) { - saved_regs[S390_FP0_REGNUM + reg] = save_reg_addr; + saved_regs[S390_F0_REGNUM + reg] = save_reg_addr; save_reg_addr += S390_FPR_SIZE; } } @@ -966,10 +1321,10 @@ s390_get_frame_info (CORE_ADDR start_pc, int i; for (i = 0; i < S390_NUM_GPRS; i++) - pv_set_to_register (&gpr[i], S390_GP0_REGNUM + i, 0); + pv_set_to_register (&gpr[i], S390_R0_REGNUM + i, 0); for (i = 0; i < S390_NUM_FPRS; i++) - pv_set_to_register (&fpr[i], S390_FP0_REGNUM + i, 0); + pv_set_to_register (&fpr[i], S390_F0_REGNUM + i, 0); for (i = 0; i < S390_NUM_SPILL_SLOTS; i++) pv_set_to_unknown (&spill[i]); @@ -1003,8 +1358,8 @@ s390_get_frame_info (CORE_ADDR start_pc, next_pc = pc + insn_len; - pre_insn_sp = gpr[S390_SP_REGNUM - S390_GP0_REGNUM]; - pre_insn_fp = gpr[S390_FRAME_REGNUM - S390_GP0_REGNUM]; + pre_insn_sp = gpr[S390_SP_REGNUM - S390_R0_REGNUM]; + pre_insn_fp = gpr[S390_FRAME_REGNUM - S390_R0_REGNUM]; pre_insn_back_chain = back_chain; /* A special case, first --- only recognized as the very first @@ -1286,8 +1641,8 @@ s390_get_frame_info (CORE_ADDR start_pc, restore instructions. (The back chain is never restored, just popped.) */ { - struct prologue_value *sp = &gpr[S390_SP_REGNUM - S390_GP0_REGNUM]; - struct prologue_value *fp = &gpr[S390_FRAME_REGNUM - S390_GP0_REGNUM]; + struct prologue_value *sp = &gpr[S390_SP_REGNUM - S390_R0_REGNUM]; + struct prologue_value *fp = &gpr[S390_FRAME_REGNUM - S390_R0_REGNUM]; if ((! pv_is_identical (&pre_insn_sp, sp) && ! pv_is_register (sp, S390_SP_REGNUM, 0)) @@ -1317,7 +1672,7 @@ s390_get_frame_info (CORE_ADDR start_pc, that strongly suggests that we're going to use that as our frame pointer register, not the SP. */ { - struct prologue_value *fp = &gpr[S390_FRAME_REGNUM - S390_GP0_REGNUM]; + struct prologue_value *fp = &gpr[S390_FRAME_REGNUM - S390_R0_REGNUM]; if (fp->kind == pv_register && fp->reg == S390_SP_REGNUM) @@ -1348,7 +1703,7 @@ s390_get_frame_info (CORE_ADDR start_pc, else frame_base_regno = S390_SP_REGNUM; - frame_base = &gpr[frame_base_regno - S390_GP0_REGNUM]; + frame_base = &gpr[frame_base_regno - S390_R0_REGNUM]; /* We know the frame base address; if the value of whatever register it came from is a constant offset from the @@ -1362,7 +1717,7 @@ s390_get_frame_info (CORE_ADDR start_pc, /* If the analysis said that the current SP value is the original value less some constant, then that constant is the frame size. */ { - struct prologue_value *sp = &gpr[S390_SP_REGNUM - S390_GP0_REGNUM]; + struct prologue_value *sp = &gpr[S390_SP_REGNUM - S390_R0_REGNUM]; if (sp->kind == pv_register && sp->reg == S390_SP_REGNUM) @@ -1475,6 +1830,50 @@ s390_get_frame_info (CORE_ADDR start_pc, return result; } +/* Return true if we are in the functin's epilogue, i.e. after the + instruction that destroyed the function's stack frame. */ +static int +s390_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc) +{ + int word_size = gdbarch_ptr_bit (gdbarch) / 8; + + /* In frameless functions, there's not frame to destroy and thus + we don't care about the epilogue. + + In functions with frame, the epilogue sequence is a pair of + a LM-type instruction that restores (amongst others) the + return register %r14 and the stack pointer %r15, followed + by a branch 'br %r14' --or equivalent-- that effects the + actual return. + + In that situation, this function needs to return 'true' in + exactly one case: when pc points to that branch instruction. + + Thus we try to disassemble the one instructions immediately + preceeding pc and check whether it is an LM-type instruction + modifying the stack pointer. + + Note that disassembling backwards is not reliable, so there + is a slight chance of false positives here ... */ + + bfd_byte insn[6]; + unsigned int r1, r3, b2; + int d2; + + if (word_size == 4 + && !read_memory_nobpt (pc - 4, insn, 4) + && is_rs (insn, op_lm, &r1, &r3, &d2, &b2) + && r3 == S390_SP_REGNUM - S390_R0_REGNUM) + return 1; + + if (word_size == 8 + && !read_memory_nobpt (pc - 6, insn, 6) + && is_rse (insn, op1_lmg, op2_lmg, &r1, &r3, &d2, &b2) + && r3 == S390_SP_REGNUM - S390_R0_REGNUM) + return 1; + + return 0; +} static int s390_check_function_end (CORE_ADDR pc) @@ -1645,8 +2044,8 @@ s390_is_sigreturn (CORE_ADDR pc, struct frame_info *sighandler_fi, *sigcaller_pc = ADDR_BITS_REMOVE ((CORE_ADDR) read_memory_integer (temp_sregs + - DEPRECATED_REGISTER_BYTE (S390_PC_REGNUM), - S390_PSW_ADDR_SIZE)); + DEPRECATED_REGISTER_BYTE (S390_PSWA_REGNUM), + S390_GPR_SIZE)); } } retval = 1; @@ -1815,7 +2214,7 @@ s390_frame_chain (struct frame_info *thisframe) { /* read sigregs,regs.gprs[11 or 15] */ prev_fp = read_memory_integer (sregs + - DEPRECATED_REGISTER_BYTE (S390_GP0_REGNUM + + DEPRECATED_REGISTER_BYTE (S390_R0_REGNUM + (prev_fextra_info. frame_pointer_saved_pc ? 11 : 15)), @@ -1877,7 +2276,7 @@ s390_extract_return_value (struct type *valtype, char *regbuf, char *valbuf) int len = TYPE_LENGTH (valtype); if (TYPE_CODE (valtype) == TYPE_CODE_FLT) - memcpy (valbuf, ®buf[DEPRECATED_REGISTER_BYTE (S390_FP0_REGNUM)], len); + memcpy (valbuf, ®buf[DEPRECATED_REGISTER_BYTE (S390_F0_REGNUM)], len); else { int offset = 0; @@ -1885,7 +2284,7 @@ s390_extract_return_value (struct type *valtype, char *regbuf, char *valbuf) if (TYPE_LENGTH (valtype) < S390_GPR_SIZE) offset = S390_GPR_SIZE - TYPE_LENGTH (valtype); memcpy (valbuf, - regbuf + DEPRECATED_REGISTER_BYTE (S390_GP0_REGNUM + 2) + offset, + regbuf + DEPRECATED_REGISTER_BYTE (S390_R0_REGNUM + 2) + offset, TYPE_LENGTH (valtype)); } } @@ -1930,13 +2329,13 @@ static void s390_store_return_value (struct type *valtype, char *valbuf) { int arglen; - char *reg_buff = alloca (max (S390_FPR_SIZE, DEPRECATED_REGISTER_SIZE)), *value; + char *reg_buff = alloca (max (S390_FPR_SIZE, S390_GPR_SIZE)), *value; if (TYPE_CODE (valtype) == TYPE_CODE_FLT) { if (TYPE_LENGTH (valtype) == 4 || TYPE_LENGTH (valtype) == 8) - deprecated_write_register_bytes (DEPRECATED_REGISTER_BYTE (S390_FP0_REGNUM), + deprecated_write_register_bytes (DEPRECATED_REGISTER_BYTE (S390_F0_REGNUM), valbuf, TYPE_LENGTH (valtype)); else error ("GDB is unable to return `long double' values " @@ -1947,7 +2346,7 @@ s390_store_return_value (struct type *valtype, char *valbuf) value = s390_promote_integer_argument (valtype, valbuf, reg_buff, &arglen); /* Everything else is returned in GPR2 and up. */ - deprecated_write_register_bytes (DEPRECATED_REGISTER_BYTE (S390_GP0_REGNUM + 2), + deprecated_write_register_bytes (DEPRECATED_REGISTER_BYTE (S390_R0_REGNUM + 2), value, arglen); } } @@ -2154,7 +2553,7 @@ is_simple_arg (struct type *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 <= DEPRECATED_REGISTER_SIZE) + return ((is_integer_like (type) && length <= S390_GPR_SIZE) || is_pointer_like (type) || (is_struct_like (type) && !is_double_arg (type))); } @@ -2175,7 +2574,7 @@ pass_by_copy_ref (struct type *type) unsigned length = TYPE_LENGTH (type); return (is_struct_like (type) - && !(is_power_of_two (length) && length <= DEPRECATED_REGISTER_SIZE)); + && !(is_power_of_two (length) && length <= S390_GPR_SIZE)); } @@ -2295,9 +2694,9 @@ s390_push_arguments (int nargs, struct value **args, CORE_ADDR sp, sp = align_down (sp, alignment_of (type)); - /* SIMPLE_ARG values get extended to DEPRECATED_REGISTER_SIZE bytes. + /* SIMPLE_ARG values get extended to S390_GPR_SIZE bytes. Assume every argument is. */ - if (length < DEPRECATED_REGISTER_SIZE) length = DEPRECATED_REGISTER_SIZE; + if (length < S390_GPR_SIZE) length = S390_GPR_SIZE; sp -= length; } } @@ -2332,7 +2731,7 @@ s390_push_arguments (int nargs, struct value **args, CORE_ADDR sp, { /* When we store a single-precision value in an FP register, it occupies the leftmost bits. */ - deprecated_write_register_bytes (DEPRECATED_REGISTER_BYTE (S390_FP0_REGNUM + fr), + deprecated_write_register_bytes (DEPRECATED_REGISTER_BYTE (S390_F0_REGNUM + fr), VALUE_CONTENTS (arg), TYPE_LENGTH (type)); fr += 2; @@ -2343,19 +2742,19 @@ s390_push_arguments (int nargs, struct value **args, CORE_ADDR sp, /* Do we need to pass a pointer to our copy of this argument? */ if (pass_by_copy_ref (type)) - write_register (S390_GP0_REGNUM + gr, copy_addr[i]); + write_register (S390_R0_REGNUM + gr, copy_addr[i]); else - write_register (S390_GP0_REGNUM + gr, extend_simple_arg (arg)); + write_register (S390_R0_REGNUM + gr, extend_simple_arg (arg)); gr++; } else if (is_double_arg (type) && gr <= 5) { - deprecated_write_register_gen (S390_GP0_REGNUM + gr, + deprecated_write_register_gen (S390_R0_REGNUM + gr, VALUE_CONTENTS (arg)); - deprecated_write_register_gen (S390_GP0_REGNUM + gr + 1, - VALUE_CONTENTS (arg) + DEPRECATED_REGISTER_SIZE); + deprecated_write_register_gen (S390_R0_REGNUM + gr + 1, + VALUE_CONTENTS (arg) + S390_GPR_SIZE); gr += 2; } else @@ -2372,8 +2771,8 @@ s390_push_arguments (int nargs, struct value **args, CORE_ADDR sp, if (is_simple_arg (type)) { /* Simple args are always extended to - DEPRECATED_REGISTER_SIZE bytes. */ - starg = align_up (starg, DEPRECATED_REGISTER_SIZE); + S390_GPR_SIZE bytes. */ + starg = align_up (starg, S390_GPR_SIZE); /* Do we need to pass a pointer to our copy of this argument? */ @@ -2382,10 +2781,10 @@ s390_push_arguments (int nargs, struct value **args, CORE_ADDR sp, copy_addr[i]); else /* Simple args are always extended to - DEPRECATED_REGISTER_SIZE bytes. */ - write_memory_signed_integer (starg, DEPRECATED_REGISTER_SIZE, + S390_GPR_SIZE bytes. */ + write_memory_signed_integer (starg, S390_GPR_SIZE, extend_simple_arg (arg)); - starg += DEPRECATED_REGISTER_SIZE; + starg += S390_GPR_SIZE; } else { @@ -2434,33 +2833,10 @@ s390_use_struct_convention (int gcc_p, struct type *value_type) || code == TYPE_CODE_UNION); } - -/* Return the GDB type object for the "standard" data type - of data in register N. */ -static struct type * -s390_register_virtual_type (int regno) -{ - if (S390_FP0_REGNUM <= regno && regno < S390_FP0_REGNUM + S390_NUM_FPRS) - return builtin_type_double; - else - return builtin_type_int; -} - - -static struct type * -s390x_register_virtual_type (int regno) -{ - return (regno == S390_FPC_REGNUM) || - (regno >= S390_FIRST_ACR && regno <= S390_LAST_ACR) ? builtin_type_int : - (regno >= S390_FP0_REGNUM) ? builtin_type_double : builtin_type_long; -} - - - static void s390_store_struct_return (CORE_ADDR addr, CORE_ADDR sp) { - write_register (S390_GP0_REGNUM + 2, addr); + write_register (S390_R0_REGNUM + 2, addr); } @@ -2558,7 +2934,8 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) return NULL; /* No; then it's not for us. */ /* Yes: create a new gdbarch for the specified machine type. */ - gdbarch = gdbarch_alloc (&info, NULL); + tdep = XCALLOC (1, struct gdbarch_tdep); + gdbarch = gdbarch_alloc (&info, tdep); /* NOTE: cagney/2002-12-06: This can be deleted when this arch is ready to unwind the PC first (see frame.c:get_prev_frame()). */ @@ -2579,13 +2956,12 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_deprecated_pop_frame (gdbarch, s390_pop_frame); /* Stack grows downward. */ set_gdbarch_inner_than (gdbarch, core_addr_lessthan); - set_gdbarch_deprecated_max_register_raw_size (gdbarch, 8); - set_gdbarch_deprecated_max_register_virtual_size (gdbarch, 8); set_gdbarch_breakpoint_from_pc (gdbarch, s390_breakpoint_from_pc); set_gdbarch_skip_prologue (gdbarch, s390_skip_prologue); set_gdbarch_deprecated_init_extra_frame_info (gdbarch, s390_init_extra_frame_info); set_gdbarch_deprecated_init_frame_pc_first (gdbarch, s390_init_frame_pc_first); set_gdbarch_deprecated_target_read_fp (gdbarch, s390_read_fp); + set_gdbarch_in_function_epilogue_p (gdbarch, s390_in_function_epilogue_p); /* 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. */ @@ -2596,19 +2972,24 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) produces the frame's chain-pointer. */ set_gdbarch_deprecated_frame_chain (gdbarch, s390_frame_chain); set_gdbarch_deprecated_saved_pc_after_call (gdbarch, s390_saved_pc_after_call); - set_gdbarch_deprecated_register_byte (gdbarch, s390_register_byte); set_gdbarch_pc_regnum (gdbarch, S390_PC_REGNUM); set_gdbarch_sp_regnum (gdbarch, S390_SP_REGNUM); - set_gdbarch_deprecated_fp_regnum (gdbarch, S390_FP_REGNUM); - set_gdbarch_fp0_regnum (gdbarch, S390_FP0_REGNUM); + set_gdbarch_deprecated_fp_regnum (gdbarch, S390_SP_REGNUM); + set_gdbarch_fp0_regnum (gdbarch, S390_F0_REGNUM); 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_pseudo_regs (gdbarch, S390_NUM_PSEUDO_REGS); set_gdbarch_use_struct_convention (gdbarch, s390_use_struct_convention); 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_register_type (gdbarch, s390_register_type); + set_gdbarch_stab_reg_to_regnum (gdbarch, s390_dwarf_reg_to_regnum); + set_gdbarch_dwarf_reg_to_regnum (gdbarch, s390_dwarf_reg_to_regnum); + set_gdbarch_dwarf2_reg_to_regnum (gdbarch, s390_dwarf_reg_to_regnum); + set_gdbarch_convert_register_p (gdbarch, s390_convert_register_p); + set_gdbarch_register_to_value (gdbarch, s390_register_to_value); + set_gdbarch_value_to_register (gdbarch, s390_value_to_register); + set_gdbarch_register_reggroup_p (gdbarch, s390_register_reggroup_p); + set_gdbarch_regset_from_core_section (gdbarch, + s390_regset_from_core_section); set_gdbarch_deprecated_extract_struct_value_address (gdbarch, s390_cannot_extract_struct_value_address); /* Parameters for inferior function calls. */ @@ -2624,24 +3005,26 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) switch (info.bfd_arch_info->mach) { case bfd_mach_s390_31: - set_gdbarch_deprecated_register_size (gdbarch, 4); - set_gdbarch_deprecated_register_raw_size (gdbarch, s390_register_raw_size); - set_gdbarch_deprecated_register_virtual_size (gdbarch, s390_register_raw_size); - set_gdbarch_deprecated_register_virtual_type (gdbarch, s390_register_virtual_type); + tdep->gregset = &s390_gregset; + tdep->sizeof_gregset = s390_sizeof_gregset; + tdep->fpregset = &s390_fpregset; + tdep->sizeof_fpregset = s390_sizeof_fpregset; set_gdbarch_addr_bits_remove (gdbarch, s390_addr_bits_remove); - set_gdbarch_deprecated_register_bytes (gdbarch, S390_REGISTER_BYTES); + set_gdbarch_pseudo_register_read (gdbarch, s390_pseudo_register_read); + set_gdbarch_pseudo_register_write (gdbarch, s390_pseudo_register_write); break; case bfd_mach_s390_64: - set_gdbarch_deprecated_register_size (gdbarch, 8); - set_gdbarch_deprecated_register_raw_size (gdbarch, s390x_register_raw_size); - set_gdbarch_deprecated_register_virtual_size (gdbarch, s390x_register_raw_size); - set_gdbarch_deprecated_register_virtual_type (gdbarch, s390x_register_virtual_type); + tdep->gregset = &s390x_gregset; + tdep->sizeof_gregset = s390x_sizeof_gregset; + tdep->fpregset = &s390_fpregset; + tdep->sizeof_fpregset = s390_sizeof_fpregset; set_gdbarch_long_bit (gdbarch, 64); set_gdbarch_long_long_bit (gdbarch, 64); set_gdbarch_ptr_bit (gdbarch, 64); - set_gdbarch_deprecated_register_bytes (gdbarch, S390X_REGISTER_BYTES); + set_gdbarch_pseudo_register_read (gdbarch, s390x_pseudo_register_read); + set_gdbarch_pseudo_register_write (gdbarch, s390x_pseudo_register_write); set_gdbarch_address_class_type_flags (gdbarch, s390_address_class_type_flags); set_gdbarch_address_class_type_flags_to_name (gdbarch, diff --git a/gdb/s390-tdep.h b/gdb/s390-tdep.h new file mode 100644 index 00000000000..241c1feb2f2 --- /dev/null +++ b/gdb/s390-tdep.h @@ -0,0 +1,105 @@ +/* Target-dependent code for GDB, the GNU debugger. + Copyright 2003 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#ifndef S390_TDEP_H +#define S390_TDEP_H + +/* Register information. */ + +/* Program Status Word. */ +#define S390_PSWM_REGNUM 0 +#define S390_PSWA_REGNUM 1 +/* General Purpose Registers. */ +#define S390_R0_REGNUM 2 +#define S390_R1_REGNUM 3 +#define S390_R2_REGNUM 4 +#define S390_R3_REGNUM 5 +#define S390_R4_REGNUM 6 +#define S390_R5_REGNUM 7 +#define S390_R6_REGNUM 8 +#define S390_R7_REGNUM 9 +#define S390_R8_REGNUM 10 +#define S390_R9_REGNUM 11 +#define S390_R10_REGNUM 12 +#define S390_R11_REGNUM 13 +#define S390_R12_REGNUM 14 +#define S390_R13_REGNUM 15 +#define S390_R14_REGNUM 16 +#define S390_R15_REGNUM 17 +/* Access Registers. */ +#define S390_A0_REGNUM 18 +#define S390_A1_REGNUM 19 +#define S390_A2_REGNUM 20 +#define S390_A3_REGNUM 21 +#define S390_A4_REGNUM 22 +#define S390_A5_REGNUM 23 +#define S390_A6_REGNUM 24 +#define S390_A7_REGNUM 25 +#define S390_A8_REGNUM 26 +#define S390_A9_REGNUM 27 +#define S390_A10_REGNUM 28 +#define S390_A11_REGNUM 29 +#define S390_A12_REGNUM 30 +#define S390_A13_REGNUM 31 +#define S390_A14_REGNUM 32 +#define S390_A15_REGNUM 33 +/* Floating Point Control Word. */ +#define S390_FPC_REGNUM 34 +/* Floating Point Registers. */ +#define S390_F0_REGNUM 35 +#define S390_F1_REGNUM 36 +#define S390_F2_REGNUM 37 +#define S390_F3_REGNUM 38 +#define S390_F4_REGNUM 39 +#define S390_F5_REGNUM 40 +#define S390_F6_REGNUM 41 +#define S390_F7_REGNUM 42 +#define S390_F8_REGNUM 43 +#define S390_F9_REGNUM 44 +#define S390_F10_REGNUM 45 +#define S390_F11_REGNUM 46 +#define S390_F12_REGNUM 47 +#define S390_F13_REGNUM 48 +#define S390_F14_REGNUM 49 +#define S390_F15_REGNUM 50 +/* Total. */ +#define S390_NUM_REGS 51 + +/* Pseudo registers -- PC and condition code. */ +#define S390_PC_REGNUM S390_NUM_REGS +#define S390_CC_REGNUM (S390_NUM_REGS+1) +#define S390_NUM_PSEUDO_REGS 2 +#define S390_NUM_TOTAL_REGS (S390_NUM_REGS+2) + +/* Special register usage. */ +#define S390_SP_REGNUM S390_R15_REGNUM +#define S390_RETADDR_REGNUM S390_R14_REGNUM +#define S390_FRAME_REGNUM S390_R11_REGNUM + +/* Core file register sets, defined in s390-tdep.c. */ +#define s390_sizeof_gregset 0x90 +extern int s390_regmap_gregset[S390_NUM_REGS]; +#define s390x_sizeof_gregset 0xd8 +extern int s390x_regmap_gregset[S390_NUM_REGS]; +#define s390_sizeof_fpregset 0x88 +extern int s390_regmap_fpregset[S390_NUM_REGS]; + +#endif + diff --git a/gdb/testsuite/gdb.base/float.exp b/gdb/testsuite/gdb.base/float.exp index 6c80fbb07c3..01b0a998132 100644 --- a/gdb/testsuite/gdb.base/float.exp +++ b/gdb/testsuite/gdb.base/float.exp @@ -63,6 +63,8 @@ if { [istarget "alpha*-*-*"] } then { gdb_test "info float" "f0.*f1.*f127.*" "info float" } elseif [istarget "m68k-*-*"] then { gdb_test "info float" "fp0.*fp1.*fp7.*" "info float" +} elseif [istarget "s390*-*-*"] then { + gdb_test "info float" "fpc.*f0.*f1.*f15.*" "info float" } elseif [istarget "sh*-*"] then { # SH may or may not have an FPU gdb_test_multiple "info float" "info float" { |