* hppa-tdep.h (hppa_regnum): Add HPPA_DP_REGNUM, HPPA_RET0_REGNUM,

HPPA_RET1_REGNUM and HPPA64_FP4_REGNUM.
* hppa-tdep.c (hppa64_integral_or_pointer_p)
(hppa64_floating_p) New functions.
(hppa64_push_dummy_call): Re-implement.
(hppa32_register_type): Rename argument reg_nr to regnum.
(hppa64_register_type): Likewise.  Use HPPA64_FP4_REGNUM instead
of HPPA_FP4_REGNUM.
(hppa32_cannot_store_register): Renamed from
hppa_cannot_store_register.
(hppa64_cannot_store_register): New function.
(hppa_gdbarch_init): Set cannot_store_register and
cannot_fetch_register to hppa32_cannot_store_register or
hppa64_cannot_store_register when appropriate.
This commit is contained in:
Mark Kettenis 2004-12-19 21:09:40 +00:00
parent a94ab04713
commit 38ca4e0c24
3 changed files with 206 additions and 109 deletions

View file

@ -1,3 +1,20 @@
2004-12-19 Mark Kettenis <kettenis@gnu.org>
* hppa-tdep.h (hppa_regnum): Add HPPA_DP_REGNUM, HPPA_RET0_REGNUM,
HPPA_RET1_REGNUM and HPPA64_FP4_REGNUM.
* hppa-tdep.c (hppa64_integral_or_pointer_p)
(hppa64_floating_p) New functions.
(hppa64_push_dummy_call): Re-implement.
(hppa32_register_type): Rename argument reg_nr to regnum.
(hppa64_register_type): Likewise. Use HPPA64_FP4_REGNUM instead
of HPPA_FP4_REGNUM.
(hppa32_cannot_store_register): Renamed from
hppa_cannot_store_register.
(hppa64_cannot_store_register): New function.
(hppa_gdbarch_init): Set cannot_store_register and
cannot_fetch_register to hppa32_cannot_store_register or
hppa64_cannot_store_register when appropriate.
2004-12-18 Mark Kettenis <kettenis@gnu.org>
* hppah-nat.c: Remove file.

View file

@ -928,138 +928,203 @@ hppa32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
return param_end;
}
/* This function pushes a stack frame with arguments as part of the
inferior function calling mechanism.
/* The 64-bit PA-RISC calling conventions are documented in "64-Bit
Runtime Architecture for PA-RISC 2.0", which is distributed as part
as of the HP-UX Software Transition Kit (STK). This implementation
is based on version 3.3, dated October 6, 1997. */
This is the version for the PA64, in which later arguments appear
at higher addresses. (The stack always grows towards higher
addresses.)
/* Check whether TYPE is an "Integral or Pointer Scalar Type". */
We simply allocate the appropriate amount of stack space and put
arguments into their proper slots.
static int
hppa64_integral_or_pointer_p (const struct type *type)
{
switch (TYPE_CODE (type))
{
case TYPE_CODE_INT:
case TYPE_CODE_BOOL:
case TYPE_CODE_CHAR:
case TYPE_CODE_ENUM:
case TYPE_CODE_RANGE:
{
int len = TYPE_LENGTH (type);
return (len == 1 || len == 2 || len == 4 || len == 8);
}
case TYPE_CODE_PTR:
case TYPE_CODE_REF:
return (TYPE_LENGTH (type) == 8);
default:
break;
}
return 0;
}
/* Check whether TYPE is a "Floating Scalar Type". */
static int
hppa64_floating_p (const struct type *type)
{
switch (TYPE_CODE (type))
{
case TYPE_CODE_FLT:
{
int len = TYPE_LENGTH (type);
return (len == 4 || len == 8 || len == 16);
}
default:
break;
}
return 0;
}
This ABI also requires that the caller provide an argument pointer
to the callee, so we do that too. */
static CORE_ADDR
hppa64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
struct regcache *regcache, CORE_ADDR bp_addr,
int nargs, struct value **args, CORE_ADDR sp,
int struct_return, CORE_ADDR struct_addr)
{
/* NOTE: cagney/2004-02-27: This is a guess - its implemented by
reverse engineering testsuite failures. */
/* Stack base address at which any pass-by-reference parameters are
stored. */
CORE_ADDR struct_end = 0;
/* Stack base address at which the first parameter is stored. */
CORE_ADDR param_end = 0;
/* The inner most end of the stack after all the parameters have
been pushed. */
CORE_ADDR new_sp = 0;
/* Global pointer (r27) of the function we are trying to call. */
CORE_ADDR gp;
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
int i, offset = 0;
CORE_ADDR gp;
/* Two passes. First pass computes the location of everything,
second pass writes the bytes out. */
int write_pass;
for (write_pass = 0; write_pass < 2; write_pass++)
/* "The outgoing parameter area [...] must be aligned at a 16-byte
boundary." */
sp = align_up (sp, 16);
for (i = 0; i < nargs; i++)
{
CORE_ADDR struct_ptr = 0;
CORE_ADDR param_ptr = 0;
int i;
for (i = 0; i < nargs; i++)
struct value *arg = args[i];
struct type *type = value_type (arg);
int len = TYPE_LENGTH (type);
char *valbuf;
int regnum;
/* "Each parameter begins on a 64-bit (8-byte) boundary." */
offset = align_up (offset, 8);
if (hppa64_integral_or_pointer_p (type))
{
struct value *arg = args[i];
struct type *type = check_typedef (value_type (arg));
if ((TYPE_CODE (type) == TYPE_CODE_INT
|| TYPE_CODE (type) == TYPE_CODE_ENUM)
&& TYPE_LENGTH (type) <= 8)
/* "Integral scalar parameters smaller than 64 bits are
padded on the left (i.e., the value is in the
least-significant bits of the 64-bit storage unit, and
the high-order bits are undefined)." Therefore we can
safely sign-extend them. */
if (len < 8)
{
/* Integer value store, right aligned. "unpack_long"
takes care of any sign-extension problems. */
param_ptr += 8;
if (write_pass)
{
ULONGEST val = unpack_long (type, VALUE_CONTENTS (arg));
int reg = 27 - param_ptr / 8;
write_memory_unsigned_integer (param_end - param_ptr,
val, 8);
if (reg >= 19)
regcache_cooked_write_unsigned (regcache, reg, val);
}
arg = value_cast (builtin_type_int64, arg);
len = 8;
}
}
else if (hppa64_floating_p (type))
{
if (len > 8)
{
/* "Quad-precision (128-bit) floating-point scalar
parameters are aligned on a 16-byte boundary." */
offset = align_up (offset, 16);
/* "Double-extended- and quad-precision floating-point
parameters within the first 64 bytes of the parameter
list are always passed in general registers." */
}
else
{
/* Small struct value, store left aligned? */
int reg;
if (TYPE_LENGTH (type) > 8)
if (len == 4)
{
param_ptr = align_up (param_ptr, 16);
reg = 26 - param_ptr / 8;
param_ptr += align_up (TYPE_LENGTH (type), 16);
/* "Single-precision (32-bit) floating-point scalar
parameters are padded on the left with 32 bits of
garbage (i.e., the floating-point value is in the
least-significant 32 bits of a 64-bit storage
unit)." */
offset += 4;
}
else
/* "Single- and double-precision floating-point
parameters in this area are passed according to the
available formal parameter information in a function
prototype. [...] If no prototype is in scope,
floating-point parameters must be passed both in the
corresponding general registers and in the
corresponding floating-point registers." */
regnum = HPPA64_FP4_REGNUM + offset / 8;
if (regnum < HPPA64_FP4_REGNUM + 8)
{
param_ptr = align_up (param_ptr, 8);
reg = 26 - param_ptr / 8;
param_ptr += align_up (TYPE_LENGTH (type), 8);
}
if (write_pass)
{
int byte;
write_memory (param_end - param_ptr, VALUE_CONTENTS (arg),
TYPE_LENGTH (type));
for (byte = 0; byte < TYPE_LENGTH (type); byte += 8)
{
if (reg >= 19)
{
int len = min (8, TYPE_LENGTH (type) - byte);
regcache_cooked_write_part (regcache, reg, 0, len,
VALUE_CONTENTS (arg) + byte);
}
reg--;
}
/* "Single-precision floating-point parameters, when
passed in floating-point registers, are passed in
the right halves of the floating point registers;
the left halves are unused." */
regcache_cooked_write_part (regcache, regnum, offset % 8,
len, VALUE_CONTENTS (arg));
}
}
}
/* Update the various stack pointers. */
if (!write_pass)
else
{
struct_end = sp + struct_ptr;
/* PARAM_PTR already accounts for all the arguments passed
by the user. However, the ABI mandates minimum stack
space allocations for outgoing arguments. The ABI also
mandates minimum stack alignments which we must
preserve. */
param_end = struct_end + max (align_up (param_ptr, 16), 64);
if (len > 8)
{
/* "Aggregates larger than 8 bytes are aligned on a
16-byte boundary, possibly leaving an unused argument
slot, which is filled with garbage. If necessary,
they are padded on the right (with garbage), to a
multiple of 8 bytes." */
offset = align_up (offset, 16);
}
}
/* Always store the argument in memory. */
write_memory (sp + offset, VALUE_CONTENTS (arg), len);
valbuf = VALUE_CONTENTS (arg);
regnum = HPPA_ARG0_REGNUM - offset / 8;
while (regnum > HPPA_ARG0_REGNUM - 8 && len > 0)
{
regcache_cooked_write_part (regcache, regnum,
offset % 8, min (len, 8), valbuf);
offset += min (len, 8);
valbuf += min (len, 8);
len -= min (len, 8);
regnum--;
}
offset += len;
}
/* If a structure has to be returned, set up register 28 to hold its
address */
/* Set up GR29 (%ret1) to hold the argument pointer (ap). */
regcache_cooked_write_unsigned (regcache, HPPA_RET1_REGNUM, sp + 64);
/* Allocate the outgoing parameter area. Make sure the outgoing
parameter area is multiple of 16 bytes in length. */
sp += max (align_up (offset, 16), 64);
/* Allocate 32-bytes of scratch space. The documentation doesn't
mention this, but it seems to be needed. */
sp += 32;
/* Allocate the frame marker area. */
sp += 16;
/* If a structure has to be returned, set up GR 28 (%ret0) to hold
its address. */
if (struct_return)
write_register (28, struct_addr);
regcache_cooked_write_unsigned (regcache, HPPA_RET0_REGNUM, struct_addr);
/* Set up GR27 (%dp) to hold the global pointer (gp). */
gp = tdep->find_global_pointer (function);
if (gp != 0)
write_register (27, gp);
regcache_cooked_write_unsigned (regcache, HPPA_DP_REGNUM, gp);
/* Set the return address. */
/* Set up GR2 (%rp) to hold the return pointer (rp). */
if (!gdbarch_push_dummy_code_p (gdbarch))
regcache_cooked_write_unsigned (regcache, HPPA_RP_REGNUM, bp_addr);
/* Update the Stack Pointer. */
regcache_cooked_write_unsigned (regcache, HPPA_SP_REGNUM, param_end + 64);
/* Set up GR30 to hold the stack pointer (sp). */
regcache_cooked_write_unsigned (regcache, HPPA_SP_REGNUM, sp);
/* The stack will have 32 bytes of additional space for a frame marker. */
return param_end + 64;
return sp;
}
static CORE_ADDR
hppa32_convert_from_func_ptr_addr (struct gdbarch *gdbarch,
@ -2426,41 +2491,46 @@ hppa_pc_requires_run_before_use (CORE_ADDR pc)
return (!target_has_stack && (pc & 0xFF000000));
}
/* Return the GDB type object for the "standard" data type of data
in register N. */
/* Return the GDB type object for the "standard" data type of data in
register REGNUM. */
static struct type *
hppa32_register_type (struct gdbarch *gdbarch, int reg_nr)
hppa32_register_type (struct gdbarch *gdbarch, int regnum)
{
if (reg_nr < HPPA_FP4_REGNUM)
if (regnum < HPPA_FP4_REGNUM)
return builtin_type_uint32;
else
return builtin_type_ieee_single_big;
}
/* Return the GDB type object for the "standard" data type of data
in register N. hppa64 version. */
static struct type *
hppa64_register_type (struct gdbarch *gdbarch, int reg_nr)
hppa64_register_type (struct gdbarch *gdbarch, int regnum)
{
if (reg_nr < HPPA_FP4_REGNUM)
if (regnum < HPPA64_FP4_REGNUM)
return builtin_type_uint64;
else
return builtin_type_ieee_double_big;
}
/* Return True if REGNUM is not a register available to the user
through ptrace(). */
/* Return non-zero if REGNUM is not a register available to the user
through ptrace/ttrace. */
static int
hppa_cannot_store_register (int regnum)
hppa32_cannot_store_register (int regnum)
{
return (regnum == 0
|| regnum == HPPA_PCSQ_HEAD_REGNUM
|| (regnum >= HPPA_PCSQ_TAIL_REGNUM && regnum < HPPA_IPSW_REGNUM)
|| (regnum > HPPA_IPSW_REGNUM && regnum < HPPA_FP4_REGNUM));
}
static int
hppa64_cannot_store_register (int regnum)
{
return (regnum == 0
|| regnum == HPPA_PCSQ_HEAD_REGNUM
|| (regnum >= HPPA_PCSQ_TAIL_REGNUM && regnum < HPPA_IPSW_REGNUM)
|| (regnum > HPPA_IPSW_REGNUM && regnum < HPPA64_FP4_REGNUM));
}
static CORE_ADDR
@ -2636,11 +2706,19 @@ hppa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
set_gdbarch_num_regs (gdbarch, hppa32_num_regs);
set_gdbarch_register_name (gdbarch, hppa32_register_name);
set_gdbarch_register_type (gdbarch, hppa32_register_type);
set_gdbarch_cannot_store_register (gdbarch,
hppa32_cannot_store_register);
set_gdbarch_cannot_fetch_register (gdbarch,
hppa32_cannot_store_register);
break;
case 8:
set_gdbarch_num_regs (gdbarch, hppa64_num_regs);
set_gdbarch_register_name (gdbarch, hppa64_register_name);
set_gdbarch_register_type (gdbarch, hppa64_register_type);
set_gdbarch_cannot_store_register (gdbarch,
hppa64_cannot_store_register);
set_gdbarch_cannot_fetch_register (gdbarch,
hppa64_cannot_store_register);
break;
default:
internal_error (__FILE__, __LINE__, "Unsupported address size: %d",
@ -2664,8 +2742,6 @@ hppa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
set_gdbarch_inner_than (gdbarch, core_addr_greaterthan);
set_gdbarch_sp_regnum (gdbarch, HPPA_SP_REGNUM);
set_gdbarch_fp0_regnum (gdbarch, HPPA_FP0_REGNUM);
set_gdbarch_cannot_store_register (gdbarch, hppa_cannot_store_register);
set_gdbarch_cannot_fetch_register (gdbarch, hppa_cannot_store_register);
set_gdbarch_addr_bits_remove (gdbarch, hppa_smash_text_address);
set_gdbarch_smash_text_address (gdbarch, hppa_smash_text_address);
set_gdbarch_believe_pcc_promotion (gdbarch, 1);

View file

@ -40,6 +40,9 @@ enum hppa_regnum
HPPA_FLAGS_REGNUM = 0, /* Various status flags */
HPPA_RP_REGNUM = 2, /* return pointer */
HPPA_FP_REGNUM = 3, /* The ABI's frame pointer, when used */
HPPA_DP_REGNUM = 27,
HPPA_RET0_REGNUM = 28,
HPPA_RET1_REGNUM = 29,
HPPA_SP_REGNUM = 30, /* Stack pointer. */
HPPA_R31_REGNUM = 31,
HPPA_SAR_REGNUM = 32, /* Shift Amount Register */
@ -63,6 +66,7 @@ enum hppa_regnum
HPPA_CR27_REGNUM = 60, /* Base register for thread-local storage, cr27 */
HPPA_FP0_REGNUM = 64, /* First floating-point. */
HPPA_FP4_REGNUM = 72,
HPPA64_FP4_REGNUM = 68,
HPPA_ARG0_REGNUM = 26, /* The first argument of a callee. */
HPPA_ARG1_REGNUM = 25, /* The second argument of a callee. */