From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 22698 invoked by alias); 4 Dec 2003 20:06:31 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 22547 invoked from network); 4 Dec 2003 20:06:20 -0000 Received: from unknown (HELO faui10.informatik.uni-erlangen.de) (131.188.31.10) by sources.redhat.com with SMTP; 4 Dec 2003 20:06:20 -0000 Received: from faui1d.informatik.uni-erlangen.de (faui1d [131.188.31.34]) by faui10.informatik.uni-erlangen.de (8.9.3p3/8.1.9-FAU) with ESMTP id VAA22198; Thu, 4 Dec 2003 21:06:18 +0100 (CET) From: Ulrich Weigand Received: (from weigand@localhost) by faui1d.informatik.uni-erlangen.de (8.9.3p3/8.1.6-FAU) id VAA07701; Thu, 4 Dec 2003 21:06:17 +0100 (CET) Message-Id: <200312042006.VAA07701@faui1d.informatik.uni-erlangen.de> Subject: [PATCH] S/390 port modernization 1/4 To: gdb-patches@sources.redhat.com Date: Thu, 04 Dec 2003 20:06:00 -0000 Cc: uweigand@de.ibm.com MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit X-SW-Source: 2003-12/txt/msg00126.txt.bz2 Hello, this is patch 1/4 to update the s390 backend. The main focus of this patch is to get register handling switched to the new methods. The changes in particular: - Remove the gdbarch calls to: set_gdbarch_deprecated_max_register_raw_size, set_gdbarch_deprecated_max_register_virtual_size, set_gdbarch_deprecated_register_byte, 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. and replace them by a new register_type and an updated register_name gdbarch function. - Completely remove all mention of control registers, as these are not accessible from user space anyway. This allows us to get rid of the cannot_fetch_register / cannot_store_register calls. This change also affects gdbserver. - Implement the pseudo-register mechanism to break out the two user- visible components of the Program Status Word, namely the PC and the condition code, into separate pseudo registers. - Implement the register-group mechanism to restrict the default display of 'info reg' to the important registers: the general purpose registers, PC and condition code. - Implement convert_register_p, register_to_value, and value_to_register in order to correctly access 'float' values in the *high-order* part of floating point registers. - Implement regset_from_core_section to replace the core-regset.o method. - Implement in_function_epilogue_p to fix watch point test case regressions. - Update the gdb.base/float.exp test case to work on s390*-*-*. - Implement fetch_inferior_registers and store_inferior_registers in s390-nat.c, replacing the core-aout.o mechanism. This also allows for more efficient ptrace access by retrieving registers in a single ptrace call. In addition, the patch implements some cleanups to the build process that became possible by the above changes: - Merge s390-*-* and s390x-*-* into a single target in configure.tgt and remove the s390x.mt fragment. - Completely remove the tm-s390.h header file; all values defined there are either no longer used or moved to s390-tdep.c. Tested on s390-ibm-linux and s390x-ibm-linux with no new regressions. Fixes 5 unexpected failures on s390 and 52 unexpected failures on s390x. Bye, Ulrich ChangeLog: * 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. * 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-nat.c: Do not include or . Include "inferior.h", , and . Remove private definition of offsetof. (s390_register_u_addr): Remove. (s390_gregset_regmap, s390_gregset_regmap_len): New variables. (s390_fpregset_regmap, s390_fpregset_regmap_len): Likewise. (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 . Include "reggroups.h" and "regset.h". (struct gdbarch_tdep): Define. (S390_PSWM_REGNUM, S390_PSWA_REGNUM, S390_R0_REGNUM-S390_R15_REGNUM, S390_A0_REGNUM-S390_A15_REGNUM, S390_F0_REGNUM-S390_F15_REGNUM, S390_FPC_REGNUM, S390_NUM_REGS): Define. (S390_PC_REGNUM, S390_CC_REGNUM, S390_NUM_PSEUDO_REGS, S390_NUM_TOTAL_REGS): Define. (S390_SP_REGNUM, S390_RETADDR_REGNUM, S390_FRAME_REGNUM): Define. Global replace of S390_GP0_REGNUM by S390_R0_REGNUM. Global replace of S390_FP0_REGNUM by S390_F0_REGNUM. (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, s390_dwarf_regmap_len): New variables. (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_sizeof_gregset, s390x_sizeof_gregset): Define. (s390_regmap_gregset, s390x_regmap_gregset): New variables. (s390_sizeof_fpregset): Define. (s390_regmap_fpregset): New variable. (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. gdbserver/ChangeLog: * linux-s390-low.c (s390_num_regs): Update. (s390_regmap): Remove control registers. Use __s390x__ predefine instead of GPR_SIZE to distiguish s390 and s390x targets. testsuite/ChangeLog: * gdb.base/float.exp: Support s390*-*-* targets. diff -c -p -r -N gdb-head/gdb/Makefile.in gdb-head-new/gdb/Makefile.in *** gdb-head/gdb/Makefile.in Tue Dec 2 17:47:36 2003 --- gdb-head-new/gdb/Makefile.in Tue Dec 2 16:36:15 2003 *************** rs6000-tdep.o: rs6000-tdep.c $(defs_h) $ *** 2249,2259 **** $(parser_defs_h) $(osabi_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) $(symfile_h) \ $(objfiles_h) $(tm_h) $(__bfd_bfd_h) $(floatformat_h) $(regcache_h) \ ! $(value_h) $(gdb_assert_h) $(dis_asm_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) --- 2249,2259 ---- $(parser_defs_h) $(osabi_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) $(inferior_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) 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 -c -p -r -N gdb-head/gdb/config/s390/nm-linux.h gdb-head-new/gdb/config/s390/nm-linux.h *** gdb-head/gdb/config/s390/nm-linux.h Tue Dec 2 17:47:36 2003 --- gdb-head-new/gdb/config/s390/nm-linux.h Tue Dec 2 16:36:15 2003 *************** *** 27,55 **** #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); ! /* Return sizeof user struct to callers in less machine dependent routines */ ! ! #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 */ --- 27,42 ---- #include "config/nm-linux.h" ! /* ptrace access. */ + #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); /* WATCHPOINT SPECIFIC STUFF */ *************** extern int s390_remove_watchpoint (int p *** 81,88 **** ((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 */ --- 68,71 ---- diff -c -p -r -N gdb-head/gdb/config/s390/s390.mh gdb-head-new/gdb/config/s390/s390.mh *** gdb-head/gdb/config/s390/s390.mh Tue Dec 2 17:47:36 2003 --- gdb-head-new/gdb/config/s390/s390.mh Tue Dec 2 16:36:15 2003 *************** *** 1,6 **** # 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 LOADLIBES = -ldl -rdynamic --- 1,5 ---- # Host: S390, running Linux NAT_FILE= nm-linux.h NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o s390-nat.o \ ! linux-proc.o gcore.o thread-db.o lin-lwp.o proc-service.o linux-nat.o LOADLIBES = -ldl -rdynamic diff -c -p -r -N gdb-head/gdb/config/s390/s390x.mt gdb-head-new/gdb/config/s390/s390x.mt *** gdb-head/gdb/config/s390/s390x.mt Tue Dec 2 17:47:36 2003 --- gdb-head-new/gdb/config/s390/s390x.mt Thu Jan 1 01:00:00 1970 *************** *** 1,8 **** - # 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 --- 0 ---- diff -c -p -r -N gdb-head/gdb/config/s390/tm-linux.h gdb-head-new/gdb/config/s390/tm-linux.h *** gdb-head/gdb/config/s390/tm-linux.h Tue Dec 2 17:47:36 2003 --- gdb-head-new/gdb/config/s390/tm-linux.h Tue Dec 2 16:36:15 2003 *************** *** 25,42 **** #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 */ --- 25,30 ---- diff -c -p -r -N gdb-head/gdb/config/s390/tm-s390.h gdb-head-new/gdb/config/s390/tm-s390.h *** gdb-head/gdb/config/s390/tm-s390.h Tue Dec 2 17:47:36 2003 --- gdb-head-new/gdb/config/s390/tm-s390.h Thu Jan 1 01:00:00 1970 *************** *** 1,78 **** - /* 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 */ --- 0 ---- diff -c -p -r -N gdb-head/gdb/configure.tgt gdb-head-new/gdb/configure.tgt *** gdb-head/gdb/configure.tgt Tue Dec 2 17:47:36 2003 --- gdb-head-new/gdb/configure.tgt Tue Dec 2 16:36:15 2003 *************** rs6000-*-lynxos*) gdb_target=rs6000lynx *** 167,176 **** rs6000-*-aix4*) gdb_target=aix4 ;; rs6000-*-*) gdb_target=rs6000 ;; ! s390-*-*) gdb_target=s390 ! build_gdbserver=yes ! ;; ! s390x-*-*) gdb_target=s390x build_gdbserver=yes ;; --- 167,173 ---- rs6000-*-aix4*) gdb_target=aix4 ;; rs6000-*-*) gdb_target=rs6000 ;; ! s390*-*-*) gdb_target=s390 build_gdbserver=yes ;; diff -c -p -r -N gdb-head/gdb/gdbserver/linux-s390-low.c gdb-head-new/gdb/gdbserver/linux-s390-low.c *** gdb-head/gdb/gdbserver/linux-s390-low.c Tue Dec 2 17:47:36 2003 --- gdb-head-new/gdb/gdbserver/linux-s390-low.c Tue Dec 2 16:36:15 2003 *************** *** 27,33 **** #include ! #define s390_num_regs 67 static int s390_regmap[] = { PT_PSWMASK, PT_PSWADDR, --- 27,33 ---- #include ! #define s390_num_regs 51 static int s390_regmap[] = { PT_PSWMASK, PT_PSWADDR, *************** static int s390_regmap[] = { *** 42,56 **** 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, ! /* defines GPR_SIZE. */ ! #if GPR_SIZE == 4 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, --- 42,50 ---- PT_ACR8, PT_ACR9, PT_ACR10, PT_ACR11, PT_ACR12, PT_ACR13, PT_ACR14, PT_ACR15, PT_FPC, ! #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 -c -p -r -N gdb-head/gdb/regformats/reg-s390.dat gdb-head-new/gdb/regformats/reg-s390.dat *** gdb-head/gdb/regformats/reg-s390.dat Tue Dec 2 17:47:36 2003 --- gdb-head-new/gdb/regformats/reg-s390.dat Tue Dec 2 16:36:15 2003 *************** expedite:r14,r15,pswa *** 34,55 **** 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 --- 34,39 ---- diff -c -p -r -N gdb-head/gdb/regformats/reg-s390x.dat gdb-head-new/gdb/regformats/reg-s390x.dat *** gdb-head/gdb/regformats/reg-s390x.dat Tue Dec 2 17:47:36 2003 --- gdb-head-new/gdb/regformats/reg-s390x.dat Tue Dec 2 16:36:15 2003 *************** expedite:r14,r15,pswa *** 34,55 **** 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 --- 34,39 ---- diff -c -p -r -N gdb-head/gdb/s390-nat.c gdb-head-new/gdb/s390-nat.c *** gdb-head/gdb/s390-nat.c Tue Dec 2 17:47:36 2003 --- gdb-head-new/gdb/s390-nat.c Tue Dec 2 16:36:15 2003 *************** *** 22,73 **** #include "defs.h" #include "tm.h" #include "regcache.h" #include #include - #include #include #include #include - #include #include - #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 #else ! PT_FPR0_HI #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; } /* 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. --- 22,280 ---- #include "defs.h" #include "tm.h" #include "regcache.h" + #include "inferior.h" + #include + #include #include #include #include #include #include #include ! /* Map registers to gregset/ptrace offsets. */ ! ! /* NOTE: The register ordering here must correspond to the ! gdb-internal register numbers defined in s390-tdep.c. */ ! static int s390_gregset_regmap[] = ! { ! #ifndef __s390x__ ! /* 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, #else ! 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, #endif ! }; ! ! static const int s390_gregset_regmap_len = ! (sizeof (s390_gregset_regmap) / sizeof (s390_gregset_regmap[0])); ! ! static int s390_fpregset_regmap[] = ! { ! /* 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, ! }; ! ! static const int s390_fpregset_regmap_len = ! (sizeof (s390_fpregset_regmap) / sizeof (s390_fpregset_regmap[0])); ! ! ! /* 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_gregset_regmap_len; i++) ! if (s390_gregset_regmap[i] != -1) ! supply_register (i, (char *)regp + s390_gregset_regmap[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_gregset_regmap_len; i++) ! if (s390_gregset_regmap[i] != -1) ! if (regno == -1 || regno == i) ! regcache_collect (i, (char *)regp + s390_gregset_regmap[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_fpregset_regmap_len; i++) ! if (s390_fpregset_regmap[i] != -1) ! supply_register (i, ((char *)regp) + s390_fpregset_regmap[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_fpregset_regmap_len; i++) ! if (s390_fpregset_regmap[i] != -1) ! if (regno == -1 || regno == i) ! regcache_collect (i, ((char *)regp) + s390_fpregset_regmap[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_gregset_regmap_len ! && s390_gregset_regmap[regnum] != -1)) ! fetch_regs (tid); ! ! if (regnum == -1 ! || (regnum < s390_fpregset_regmap_len ! && s390_fpregset_regmap[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_gregset_regmap_len ! && s390_gregset_regmap[regnum] != -1)) ! store_regs (tid, regnum); ! ! if (regnum == -1 ! || (regnum < s390_fpregset_regmap_len ! && s390_fpregset_regmap[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. *************** kernel_u_size (void) *** 232,358 **** 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 --- 439,441 ---- diff -c -p -r -N gdb-head/gdb/s390-tdep.c gdb-head-new/gdb/s390-tdep.c *** gdb-head/gdb/s390-tdep.c Tue Dec 2 17:47:50 2003 --- gdb-head-new/gdb/s390-tdep.c Tue Dec 2 17:44:36 2003 *************** *** 22,29 **** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ ! #define S390_TDEP /* for special macros in tm-s390.h */ ! #include #include "arch-utils.h" #include "frame.h" #include "inferior.h" --- 22,28 ---- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ ! #include "defs.h" #include "arch-utils.h" #include "frame.h" #include "inferior.h" *************** *** 37,89 **** #include "../bfd/bfd.h" #include "floatformat.h" #include "regcache.h" #include "value.h" #include "gdb_assert.h" #include "dis-asm.h" ! /* Number of bytes of storage in the actual machine representation ! for register N. */ ! static int ! s390_register_raw_size (int reg_nr) { ! if (S390_FP0_REGNUM <= reg_nr ! && reg_nr < S390_FP0_REGNUM + S390_NUM_FPRS) ! return S390_FPR_SIZE; ! else ! return 4; } static int ! s390x_register_raw_size (int reg_nr) { ! return (reg_nr == S390_FPC_REGNUM) ! || (reg_nr >= S390_FIRST_ACR && reg_nr <= S390_LAST_ACR) ? 4 : 8; } static int ! s390_cannot_fetch_register (int regno) { ! return (regno >= S390_FIRST_CR && regno < (S390_FIRST_CR + 9)) || ! (regno >= (S390_FIRST_CR + 12) && regno <= S390_LAST_CR); } 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); } #define S390_MAX_INSTR_SIZE (6) #define S390_SYSCALL_OPCODE (0x0a) #define S390_SYSCALL_SIZE (2) --- 36,556 ---- #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" ! /* The tdep structure. */ ! ! struct gdbarch_tdep { ! /* Core file register sets. */ ! struct regset *gregset; ! int sizeof_gregset; ! int *regmap_gregset; ! ! struct regset *fpregset; ! int sizeof_fpregset; ! int *regmap_fpregset; ! }; ! ! ! /* 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 ! ! 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 + }; + + static const int s390_dwarf_regmap_len = + (sizeof (s390_dwarf_regmap) / sizeof (s390_dwarf_regmap[0])); + + /* Convert DWARF register number REG to the appropriate register + number used by GDB. */ static int ! s390_dwarf_reg_to_regnum (int reg) ! { ! int regnum = -1; ! ! if (reg >= 0 || reg < s390_dwarf_regmap_len) ! 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: ! abort (); ! } ! } ! ! static void ! s390_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache, ! int regnum, const void *buf) { ! 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: ! abort (); ! } } + 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: + abort (); + } + } + + 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: + abort (); + } + } + + /* 'float' values are stored in the upper half of floating-point + registers, even though we are otherwise a big-endian platform. */ + static int ! s390_convert_register_p (int regno, struct type *type) { ! 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); + + frame_register_read (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_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. */ + + #define s390_sizeof_gregset 0x90 + static 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, + }; + + #define s390x_sizeof_gregset 0xd8 + static 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, + }; + + #define s390_sizeof_fpregset 0x88 + static 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]); + } + } + + /* 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) + { + if (tdep->gregset == NULL) + { + tdep->gregset = XMALLOC (struct regset); + tdep->gregset->descr = tdep->regmap_gregset; + tdep->gregset->supply_regset = s390_supply_regset; + } + return tdep->gregset; + } + + if (strcmp (sect_name, ".reg2") == 0 && sect_size == tdep->sizeof_fpregset) + { + if (tdep->fpregset == NULL) + { + tdep->fpregset = XMALLOC (struct regset); + tdep->fpregset->descr = tdep->regmap_fpregset; + tdep->fpregset->supply_regset = s390_supply_regset; + } + 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) *************** s390_register_byte (int reg_nr) *** 93,100 **** #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_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 --- 560,567 ---- #define S390X_SIGREGS_FP0_OFFSET (216) #define S390_UC_MCONTEXT_OFFSET (256) #define S390X_UC_MCONTEXT_OFFSET (344) ! #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 *************** s390_memset_extra_info (struct frame_ext *** 150,193 **** } - - 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 --- 617,622 ---- *************** enum *** 599,604 **** --- 1028,1035 ---- 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, }; *************** compute_x_addr (struct prologue_value *a *** 787,792 **** --- 1218,1225 ---- 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, *************** s390_on_stack (struct prologue_value *ad *** 820,826 **** /* 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]; /* 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 --- 1253,1259 ---- /* 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_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 *************** s390_get_signal_frame_info (struct frame *** 903,914 **** /* 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)); int reg; for (reg = 0; reg < S390_NUM_GPRS; reg++) { ! saved_regs[S390_GP0_REGNUM + reg] = save_reg_addr; save_reg_addr += S390_GPR_SIZE; } --- 1336,1347 ---- /* 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_R0_REGNUM)); int reg; for (reg = 0; reg < S390_NUM_GPRS; reg++) { ! saved_regs[S390_R0_REGNUM + reg] = save_reg_addr; save_reg_addr += S390_GPR_SIZE; } *************** s390_get_signal_frame_info (struct frame *** 917,923 **** S390_SIGREGS_FP0_OFFSET)); for (reg = 0; reg < S390_NUM_FPRS; reg++) { ! saved_regs[S390_FP0_REGNUM + reg] = save_reg_addr; save_reg_addr += S390_FPR_SIZE; } } --- 1350,1356 ---- S390_SIGREGS_FP0_OFFSET)); for (reg = 0; reg < S390_NUM_FPRS; reg++) { ! saved_regs[S390_F0_REGNUM + reg] = save_reg_addr; save_reg_addr += S390_FPR_SIZE; } } *************** s390_get_frame_info (CORE_ADDR start_pc, *** 967,976 **** int i; for (i = 0; i < S390_NUM_GPRS; i++) ! pv_set_to_register (&gpr[i], S390_GP0_REGNUM + i, 0); for (i = 0; i < S390_NUM_FPRS; i++) ! pv_set_to_register (&fpr[i], S390_FP0_REGNUM + i, 0); for (i = 0; i < S390_NUM_SPILL_SLOTS; i++) pv_set_to_unknown (&spill[i]); --- 1400,1409 ---- int i; for (i = 0; i < S390_NUM_GPRS; i++) ! 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_F0_REGNUM + i, 0); for (i = 0; i < S390_NUM_SPILL_SLOTS; i++) pv_set_to_unknown (&spill[i]); *************** s390_get_frame_info (CORE_ADDR start_pc, *** 1004,1011 **** 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_back_chain = back_chain; /* A special case, first --- only recognized as the very first --- 1437,1444 ---- next_pc = pc + insn_len; ! 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 *************** s390_get_frame_info (CORE_ADDR start_pc, *** 1287,1294 **** 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]; if ((! pv_is_identical (&pre_insn_sp, sp) && ! pv_is_register (sp, S390_SP_REGNUM, 0)) --- 1720,1727 ---- restore instructions. (The back chain is never restored, just popped.) */ { ! 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)) *************** s390_get_frame_info (CORE_ADDR start_pc, *** 1318,1324 **** 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]; if (fp->kind == pv_register && fp->reg == S390_SP_REGNUM) --- 1751,1757 ---- 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_R0_REGNUM]; if (fp->kind == pv_register && fp->reg == S390_SP_REGNUM) *************** s390_get_frame_info (CORE_ADDR start_pc, *** 1349,1355 **** else frame_base_regno = S390_SP_REGNUM; ! frame_base = &gpr[frame_base_regno - S390_GP0_REGNUM]; /* We know the frame base address; if the value of whatever register it came from is a constant offset from the --- 1782,1788 ---- else frame_base_regno = S390_SP_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 *************** s390_get_frame_info (CORE_ADDR start_pc, *** 1363,1369 **** /* 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]; if (sp->kind == pv_register && sp->reg == S390_SP_REGNUM) --- 1796,1802 ---- /* 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_R0_REGNUM]; if (sp->kind == pv_register && sp->reg == S390_SP_REGNUM) *************** s390_get_frame_info (CORE_ADDR start_pc, *** 1476,1481 **** --- 1909,1958 ---- 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) *************** s390_is_sigreturn (CORE_ADDR pc, struct *** 1662,1669 **** *sigcaller_pc = ADDR_BITS_REMOVE ((CORE_ADDR) read_memory_integer (temp_sregs + ! DEPRECATED_REGISTER_BYTE (S390_PC_REGNUM), ! S390_PSW_ADDR_SIZE)); } } retval = 1; --- 2139,2146 ---- *sigcaller_pc = ADDR_BITS_REMOVE ((CORE_ADDR) read_memory_integer (temp_sregs + ! DEPRECATED_REGISTER_BYTE (S390_PSWA_REGNUM), ! S390_GPR_SIZE)); } } retval = 1; *************** s390_frame_chain (struct frame_info *thi *** 1832,1838 **** { /* read sigregs,regs.gprs[11 or 15] */ prev_fp = read_memory_integer (sregs + ! DEPRECATED_REGISTER_BYTE (S390_GP0_REGNUM + (prev_fextra_info. frame_pointer_saved_pc ? 11 : 15)), --- 2309,2315 ---- { /* read sigregs,regs.gprs[11 or 15] */ prev_fp = read_memory_integer (sregs + ! DEPRECATED_REGISTER_BYTE (S390_R0_REGNUM + (prev_fextra_info. frame_pointer_saved_pc ? 11 : 15)), *************** s390_extract_return_value (struct type * *** 1894,1900 **** int len = TYPE_LENGTH (valtype); if (TYPE_CODE (valtype) == TYPE_CODE_FLT) ! memcpy (valbuf, ®buf[DEPRECATED_REGISTER_BYTE (S390_FP0_REGNUM)], len); else { int offset = 0; --- 2371,2377 ---- int len = TYPE_LENGTH (valtype); if (TYPE_CODE (valtype) == TYPE_CODE_FLT) ! memcpy (valbuf, ®buf[DEPRECATED_REGISTER_BYTE (S390_F0_REGNUM)], len); else { int offset = 0; *************** s390_extract_return_value (struct type * *** 1902,1908 **** 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, TYPE_LENGTH (valtype)); } } --- 2379,2385 ---- if (TYPE_LENGTH (valtype) < S390_GPR_SIZE) offset = S390_GPR_SIZE - TYPE_LENGTH (valtype); memcpy (valbuf, ! regbuf + DEPRECATED_REGISTER_BYTE (S390_R0_REGNUM + 2) + offset, TYPE_LENGTH (valtype)); } } *************** static void *** 1947,1959 **** s390_store_return_value (struct type *valtype, char *valbuf) { int arglen; ! char *reg_buff = alloca (max (S390_FPR_SIZE, DEPRECATED_REGISTER_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), valbuf, TYPE_LENGTH (valtype)); else error ("GDB is unable to return `long double' values " --- 2424,2436 ---- s390_store_return_value (struct type *valtype, char *valbuf) { int arglen; ! 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_F0_REGNUM), valbuf, TYPE_LENGTH (valtype)); else error ("GDB is unable to return `long double' values " *************** s390_store_return_value (struct type *va *** 1964,1970 **** 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), value, arglen); } } --- 2441,2447 ---- 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_R0_REGNUM + 2), value, arglen); } } *************** is_simple_arg (struct type *type) *** 2171,2177 **** /* 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) || is_pointer_like (type) || (is_struct_like (type) && !is_double_arg (type))); } --- 2648,2654 ---- /* 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 <= S390_GPR_SIZE) || is_pointer_like (type) || (is_struct_like (type) && !is_double_arg (type))); } *************** pass_by_copy_ref (struct type *type) *** 2192,2198 **** unsigned length = TYPE_LENGTH (type); return (is_struct_like (type) ! && !(is_power_of_two (length) && length <= DEPRECATED_REGISTER_SIZE)); } --- 2669,2675 ---- unsigned length = TYPE_LENGTH (type); return (is_struct_like (type) ! && !(is_power_of_two (length) && length <= S390_GPR_SIZE)); } *************** s390_push_arguments (int nargs, struct v *** 2312,2320 **** sp = align_down (sp, alignment_of (type)); ! /* SIMPLE_ARG values get extended to DEPRECATED_REGISTER_SIZE bytes. Assume every argument is. */ ! if (length < DEPRECATED_REGISTER_SIZE) length = DEPRECATED_REGISTER_SIZE; sp -= length; } } --- 2789,2797 ---- sp = align_down (sp, alignment_of (type)); ! /* SIMPLE_ARG values get extended to S390_GPR_SIZE bytes. Assume every argument is. */ ! if (length < S390_GPR_SIZE) length = S390_GPR_SIZE; sp -= length; } } *************** s390_push_arguments (int nargs, struct v *** 2349,2355 **** { /* 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), VALUE_CONTENTS (arg), TYPE_LENGTH (type)); fr += 2; --- 2826,2832 ---- { /* When we store a single-precision value in an FP register, it occupies the leftmost bits. */ ! deprecated_write_register_bytes (DEPRECATED_REGISTER_BYTE (S390_F0_REGNUM + fr), VALUE_CONTENTS (arg), TYPE_LENGTH (type)); fr += 2; *************** s390_push_arguments (int nargs, struct v *** 2360,2378 **** /* 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]); else ! write_register (S390_GP0_REGNUM + gr, extend_simple_arg (arg)); gr++; } else if (is_double_arg (type) && gr <= 5) { ! deprecated_write_register_gen (S390_GP0_REGNUM + gr, VALUE_CONTENTS (arg)); ! deprecated_write_register_gen (S390_GP0_REGNUM + gr + 1, ! VALUE_CONTENTS (arg) + DEPRECATED_REGISTER_SIZE); gr += 2; } else --- 2837,2855 ---- /* Do we need to pass a pointer to our copy of this argument? */ if (pass_by_copy_ref (type)) ! write_register (S390_R0_REGNUM + gr, copy_addr[i]); else ! write_register (S390_R0_REGNUM + gr, extend_simple_arg (arg)); gr++; } else if (is_double_arg (type) && gr <= 5) { ! deprecated_write_register_gen (S390_R0_REGNUM + gr, VALUE_CONTENTS (arg)); ! deprecated_write_register_gen (S390_R0_REGNUM + gr + 1, ! VALUE_CONTENTS (arg) + S390_GPR_SIZE); gr += 2; } else *************** s390_push_arguments (int nargs, struct v *** 2389,2396 **** if (is_simple_arg (type)) { /* Simple args are always extended to ! DEPRECATED_REGISTER_SIZE bytes. */ ! starg = align_up (starg, DEPRECATED_REGISTER_SIZE); /* Do we need to pass a pointer to our copy of this argument? */ --- 2866,2873 ---- if (is_simple_arg (type)) { /* Simple args are always extended to ! S390_GPR_SIZE bytes. */ ! starg = align_up (starg, S390_GPR_SIZE); /* Do we need to pass a pointer to our copy of this argument? */ *************** s390_push_arguments (int nargs, struct v *** 2399,2408 **** copy_addr[i]); else /* Simple args are always extended to ! DEPRECATED_REGISTER_SIZE bytes. */ ! write_memory_signed_integer (starg, DEPRECATED_REGISTER_SIZE, extend_simple_arg (arg)); ! starg += DEPRECATED_REGISTER_SIZE; } else { --- 2876,2885 ---- copy_addr[i]); else /* Simple args are always extended to ! S390_GPR_SIZE bytes. */ ! write_memory_signed_integer (starg, S390_GPR_SIZE, extend_simple_arg (arg)); ! starg += S390_GPR_SIZE; } else { *************** s390_use_struct_convention (int gcc_p, s *** 2451,2483 **** || 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); } --- 2928,2937 ---- || code == TYPE_CODE_UNION); } static void s390_store_struct_return (CORE_ADDR addr, CORE_ADDR sp) { ! write_register (S390_R0_REGNUM + 2, addr); } *************** s390_gdbarch_init (struct gdbarch_info i *** 2575,2581 **** return NULL; /* No; then it's not for us. */ /* Yes: create a new gdbarch for the specified machine type. */ ! gdbarch = gdbarch_alloc (&info, NULL); /* 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()). */ --- 3029,3036 ---- return NULL; /* No; then it's not for us. */ /* Yes: create a new gdbarch for the specified machine type. */ ! 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()). */ *************** s390_gdbarch_init (struct gdbarch_info i *** 2600,2612 **** /* Offset from address of function to start of its code. Zero on most machines. */ set_gdbarch_function_start_offset (gdbarch, 0); - 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); /* 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. */ --- 3055,3066 ---- /* Offset from address of function to start of its code. Zero on most machines. */ set_gdbarch_function_start_offset (gdbarch, 0); 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. */ *************** s390_gdbarch_init (struct gdbarch_info i *** 2618,2636 **** 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_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_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_extract_struct_value_address (gdbarch, s390_cannot_extract_struct_value_address); /* Parameters for inferior function calls. */ --- 3072,3095 ---- 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_pc_regnum (gdbarch, S390_PC_REGNUM); set_gdbarch_sp_regnum (gdbarch, S390_SP_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_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_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_extract_struct_value_address (gdbarch, s390_cannot_extract_struct_value_address); /* Parameters for inferior function calls. */ *************** s390_gdbarch_init (struct gdbarch_info i *** 2646,2669 **** 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); set_gdbarch_addr_bits_remove (gdbarch, s390_addr_bits_remove); ! set_gdbarch_deprecated_register_bytes (gdbarch, S390_REGISTER_BYTES); 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); 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_address_class_type_flags (gdbarch, s390_address_class_type_flags); set_gdbarch_address_class_type_flags_to_name (gdbarch, --- 3105,3130 ---- switch (info.bfd_arch_info->mach) { case bfd_mach_s390_31: ! tdep->sizeof_gregset = s390_sizeof_gregset; ! tdep->regmap_gregset = s390_regmap_gregset; ! tdep->sizeof_fpregset = s390_sizeof_fpregset; ! tdep->regmap_fpregset = s390_regmap_fpregset; set_gdbarch_addr_bits_remove (gdbarch, s390_addr_bits_remove); ! 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: ! tdep->sizeof_gregset = s390x_sizeof_gregset; ! tdep->regmap_gregset = s390x_regmap_gregset; ! tdep->sizeof_fpregset = s390_sizeof_fpregset; ! tdep->regmap_fpregset = s390_regmap_fpregset; set_gdbarch_long_bit (gdbarch, 64); set_gdbarch_long_long_bit (gdbarch, 64); set_gdbarch_ptr_bit (gdbarch, 64); ! 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 -c -p -r -N gdb-head/gdb/testsuite/gdb.base/float.exp gdb-head-new/gdb/testsuite/gdb.base/float.exp *** gdb-head/gdb/testsuite/gdb.base/float.exp Tue Dec 2 17:47:36 2003 --- gdb-head-new/gdb/testsuite/gdb.base/float.exp Tue Dec 2 16:36:15 2003 *************** if { [istarget "alpha*-*-*"] } then { *** 63,68 **** --- 63,70 ---- 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" { -- Dr. Ulrich Weigand weigand@informatik.uni-erlangen.de