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.
This commit is contained in:
Jim Blandy
2004-02-18 03:42:51 +00:00
parent f3205b34a1
commit d0f54f9d42
15 changed files with 935 additions and 483 deletions

View File

@@ -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

View File

@@ -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)

View File

@@ -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 */

View File

@@ -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

View File

@@ -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

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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
;;

View File

@@ -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,

View File

@@ -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

View File

@@ -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

View File

@@ -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;
/* Map registers to gregset/ptrace offsets.
These arrays are defined in s390-tdep.c. */
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
#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) &regs;
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 (&regs);
}
/* 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) &regs;
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 (&regs, 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

View File

@@ -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;
}
static int
s390x_register_raw_size (int reg_nr)
/* 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)
{
return (reg_nr == S390_FPC_REGNUM)
|| (reg_nr >= S390_FIRST_ACR && reg_nr <= S390_LAST_ACR) ? 4 : 8;
gdb_assert (regnum >= 0 && regnum < S390_NUM_TOTAL_REGS);
return *s390_register_info[regnum].type;
}
static int
s390_cannot_fetch_register (int regno)
/* DWARF Register Mapping. */
static int s390_dwarf_regmap[] =
{
return (regno >= S390_FIRST_CR && regno < (S390_FIRST_CR + 9)) ||
(regno >= (S390_FIRST_CR + 12) && regno <= S390_LAST_CR);
/* 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
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;
}
static int
s390_register_byte (int reg_nr)
/* Pseudo registers - PC and condition code. */
static void
s390_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
int regnum, void *buf)
{
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);
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)
{
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_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);
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_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, &regbuf[DEPRECATED_REGISTER_BYTE (S390_FP0_REGNUM)], len);
memcpy (valbuf, &regbuf[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,

105
gdb/s390-tdep.h Normal file
View File

@@ -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

View File

@@ -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" {