/* Target-dependent code for GDB, the GNU debugger.
- Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007
+ Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
Free Software Foundation, Inc.
Contributed by D.J. Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
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
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
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., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "defs.h"
#include "arch-utils.h"
};
-/* 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)
+s390_register_name (struct gdbarch *gdbarch, int regnum)
{
+ static const char *register_names[S390_NUM_TOTAL_REGS] =
+ {
+ /* Program Status Word. */
+ "pswm", "pswa",
+ /* General Purpose Registers. */
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+ /* Access Registers. */
+ "acr0", "acr1", "acr2", "acr3", "acr4", "acr5", "acr6", "acr7",
+ "acr8", "acr9", "acr10", "acr11", "acr12", "acr13", "acr14", "acr15",
+ /* Floating Point Control Word. */
+ "fpc",
+ /* Floating Point Registers. */
+ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
+ "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
+ /* Pseudo registers. */
+ "pc", "cc",
+ };
+
gdb_assert (regnum >= 0 && regnum < S390_NUM_TOTAL_REGS);
- return s390_register_info[regnum].name;
+ return register_names[regnum];
}
/* Return the GDB type object for the "standard" data type of data in
- register REGNUM. */
+ 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;
+ if (regnum == S390_PSWM_REGNUM || regnum == S390_PSWA_REGNUM)
+ return builtin_type_long;
+ if (regnum >= S390_R0_REGNUM && regnum <= S390_R15_REGNUM)
+ return builtin_type_long;
+ if (regnum >= S390_A0_REGNUM && regnum <= S390_A15_REGNUM)
+ return builtin_type_int;
+ if (regnum == S390_FPC_REGNUM)
+ return builtin_type_int;
+ if (regnum >= S390_F0_REGNUM && regnum <= S390_F15_REGNUM)
+ return builtin_type_double;
+ if (regnum == S390_PC_REGNUM)
+ return builtin_type_void_func_ptr;
+ if (regnum == S390_CC_REGNUM)
+ return builtin_type_int;
+
+ internal_error (__FILE__, __LINE__, _("invalid regnum"));
}
/* DWARF Register Mapping. */
/* Convert DWARF register number REG to the appropriate register
number used by GDB. */
static int
-s390_dwarf_reg_to_regnum (int reg)
+s390_dwarf_reg_to_regnum (struct gdbarch *gdbarch, int reg)
{
int regnum = -1;
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
- if (strcmp (sect_name, ".reg") == 0 && sect_size == tdep->sizeof_gregset)
+ 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)
+ if (strcmp (sect_name, ".reg2") == 0 && sect_size >= tdep->sizeof_fpregset)
return tdep->fpregset;
return NULL;
static int s390_instrlen[] = { 2, 4, 4, 6 };
int instrlen;
- if (read_memory_nobpt (at, &instr[0], 2))
+ if (target_read_memory (at, &instr[0], 2))
return -1;
instrlen = s390_instrlen[instr[0] >> 6];
if (instrlen > 2)
{
- if (read_memory_nobpt (at + 2, &instr[2], instrlen - 2))
+ if (target_read_memory (at + 2, &instr[2], instrlen - 2))
return -1;
}
return instrlen;
/* Advance PC across any function entry prologue instructions to reach
some "real" code. */
static CORE_ADDR
-s390_skip_prologue (CORE_ADDR pc)
+s390_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
{
struct s390_prologue_data data;
CORE_ADDR skip_pc;
- skip_pc = s390_analyze_prologue (current_gdbarch, pc, (CORE_ADDR)-1, &data);
+ skip_pc = s390_analyze_prologue (gdbarch, pc, (CORE_ADDR)-1, &data);
return skip_pc ? skip_pc : pc;
}
int d2;
if (word_size == 4
- && !read_memory_nobpt (pc - 4, insn, 4)
+ && !target_read_memory (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 == 4
- && !read_memory_nobpt (pc - 6, insn, 6)
+ && !target_read_memory (pc - 6, insn, 6)
&& is_rsy (insn, op1_lmy, op2_lmy, &r1, &r3, &d2, &b2)
&& r3 == S390_SP_REGNUM - S390_R0_REGNUM)
return 1;
if (word_size == 8
- && !read_memory_nobpt (pc - 6, insn, 6)
+ && !target_read_memory (pc - 6, insn, 6)
&& is_rsy (insn, op1_lmg, op2_lmg, &r1, &r3, &d2, &b2)
&& r3 == S390_SP_REGNUM - S390_R0_REGNUM)
return 1;
CORE_ADDR pc = frame_pc_unwind (next_frame);
bfd_byte sigreturn[2];
- if (read_memory_nobpt (pc, sigreturn, 2))
+ if (target_read_memory (pc, sigreturn, 2))
return NULL;
if (sigreturn[0] != 0x0a /* svc */)
CHECK_TYPEDEF (singleton_type);
return (TYPE_CODE (singleton_type) == TYPE_CODE_FLT
+ || TYPE_CODE (singleton_type) == TYPE_CODE_DECFLOAT
|| is_float_singleton (singleton_type));
}
is_float_like (struct type *type)
{
return (TYPE_CODE (type) == TYPE_CODE_FLT
+ || TYPE_CODE (type) == TYPE_CODE_DECFLOAT
|| is_float_singleton (type));
}
if (is_integer_like (type)
|| is_pointer_like (type)
- || TYPE_CODE (type) == TYPE_CODE_FLT)
+ || TYPE_CODE (type) == TYPE_CODE_FLT
+ || TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
alignment = TYPE_LENGTH (type);
else if (TYPE_CODE (type) == TYPE_CODE_STRUCT
|| TYPE_CODE (type) == TYPE_CODE_UNION)
}
static enum return_value_convention
-s390_return_value (struct gdbarch *gdbarch, struct type *type,
- struct regcache *regcache, gdb_byte *out,
- const gdb_byte *in)
+s390_return_value (struct gdbarch *gdbarch, struct type *func_type,
+ struct type *type, struct regcache *regcache,
+ gdb_byte *out, const gdb_byte *in)
{
int word_size = gdbarch_ptr_bit (gdbarch) / 8;
int length = TYPE_LENGTH (type);
switch (rvc)
{
case RETURN_VALUE_REGISTER_CONVENTION:
- if (TYPE_CODE (type) == TYPE_CODE_FLT)
+ if (TYPE_CODE (type) == TYPE_CODE_FLT
+ || TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
{
/* When we store a single-precision value in an FP register,
it occupies the leftmost bits. */
switch (rvc)
{
case RETURN_VALUE_REGISTER_CONVENTION:
- if (TYPE_CODE (type) == TYPE_CODE_FLT)
+ if (TYPE_CODE (type) == TYPE_CODE_FLT
+ || TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
{
/* When we store a single-precision value in an FP register,
it occupies the leftmost bits. */
/* Breakpoints. */
static const gdb_byte *
-s390_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr)
+s390_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr, int *lenptr)
{
static const gdb_byte breakpoint[] = { 0x0, 0x1 };
set_gdbarch_believe_pcc_promotion (gdbarch, 0);
set_gdbarch_char_signed (gdbarch, 0);
+ /* S/390 GNU/Linux uses either 64-bit or 128-bit long doubles.
+ We can safely let them default to 128-bit, since the debug info
+ will give the size of type actually used in each case. */
+ set_gdbarch_long_double_bit (gdbarch, 128);
+ set_gdbarch_long_double_format (gdbarch, floatformats_ia64_quad);
+
/* Amount PC must be decremented by after a breakpoint. This is
often the number of bytes returned by gdbarch_breakpoint_from_pc but not
always. */