#include "regcache.h"
#include "doublest.h"
+struct frame_extra_info
+ {
+ alpha_extra_func_info_t proc_desc;
+ int localoff;
+ int pc_reg;
+ };
+
/* FIXME: Some of this code should perhaps be merged with mips-tdep.c. */
/* Prototypes for local functions. */
+static void alpha_find_saved_regs (struct frame_info *);
+
static alpha_extra_func_info_t push_sigtramp_desc (CORE_ADDR low_addr);
static CORE_ADDR read_next_frame_reg (struct frame_info *, int);
}
*linked_proc_desc_table = NULL;
\f
+int
+alpha_osf_in_sigtramp (CORE_ADDR pc, char *func_name)
+{
+ return (func_name != NULL && STREQ ("__sigtramp", func_name));
+}
/* Under GNU/Linux, signal handler invocations can be identified by the
designated code sequence that is used to return from a signal
return (NULL);
return (register_names[regno]);
}
+
+int
+alpha_cannot_fetch_register (int regno)
+{
+ return (regno == FP_REGNUM || regno == ZERO_REGNUM);
+}
+
+int
+alpha_cannot_store_register (int regno)
+{
+ return (regno == FP_REGNUM || regno == ZERO_REGNUM);
+}
+
+int
+alpha_register_convertible (int regno)
+{
+ return (regno >= FP0_REGNUM && regno <= FP0_REGNUM + 31);
+}
+
+struct type *
+alpha_register_virtual_type (int regno)
+{
+ return ((regno >= FP0_REGNUM && regno < (FP0_REGNUM+31))
+ ? builtin_type_double : builtin_type_long);
+}
+
+int
+alpha_register_byte (int regno)
+{
+ return (regno * 8);
+}
+
+int
+alpha_register_raw_size (int regno)
+{
+ return 8;
+}
+
+int
+alpha_register_virtual_size (int regno)
+{
+ return 8;
+}
\f
/* Guaranteed to set frame->saved_regs to some values (it never leaves it
NULL). */
-void
+static void
alpha_find_saved_regs (struct frame_info *frame)
{
int ireg;
return;
}
- proc_desc = frame->proc_desc;
+ proc_desc = frame->extra_info->proc_desc;
if (proc_desc == NULL)
/* I'm not sure how/whether this can happen. Normally when we can't
find a proc_desc, we "synthesize" one using heuristic_proc_desc
frame->saved_regs[PC_REGNUM] = frame->saved_regs[returnreg];
}
+void
+alpha_frame_init_saved_regs (struct frame_info *fi)
+{
+ if (fi->saved_regs == NULL)
+ alpha_find_saved_regs (fi);
+ fi->saved_regs[SP_REGNUM] = fi->frame;
+}
+
+void
+alpha_init_frame_pc_first (int fromleaf, struct frame_info *prev)
+{
+ prev->pc = (fromleaf ? SAVED_PC_AFTER_CALL (prev->next) :
+ prev->next ? FRAME_SAVED_PC (prev->next) : read_pc ());
+}
+
static CORE_ADDR
read_next_frame_reg (struct frame_info *fi, int regno)
{
CORE_ADDR
alpha_frame_saved_pc (struct frame_info *frame)
{
- alpha_extra_func_info_t proc_desc = frame->proc_desc;
+ alpha_extra_func_info_t proc_desc = frame->extra_info->proc_desc;
/* We have to get the saved pc from the sigcontext
if it is a signal handler frame. */
- int pcreg = frame->signal_handler_caller ? PC_REGNUM : frame->pc_reg;
+ int pcreg = frame->signal_handler_caller ? PC_REGNUM
+ : frame->extra_info->pc_reg;
if (proc_desc && PROC_DESC_IS_DUMMY (proc_desc))
return read_memory_integer (frame->frame - 8, 8);
static struct alpha_extra_func_info temp_proc_desc;
-static struct frame_saved_regs temp_saved_regs;
+static CORE_ADDR temp_saved_regs[NUM_REGS];
/* Nonzero if instruction at PC is a return instruction. "ret
$zero,($ra),1" on alpha. */
if (start_pc == 0)
return NULL;
memset (&temp_proc_desc, '\0', sizeof (temp_proc_desc));
- memset (&temp_saved_regs, '\0', sizeof (struct frame_saved_regs));
+ memset (&temp_saved_regs, '\0', SIZEOF_FRAME_SAVED_REGS);
PROC_LOW_ADDR (&temp_proc_desc) = start_pc;
if (start_pc + 200 < limit_pc)
{
int reg = (word & 0x03e00000) >> 21;
reg_mask |= 1 << reg;
- temp_saved_regs.regs[reg] = sp + (short) word;
+ temp_saved_regs[reg] = sp + (short) word;
/* Starting with OSF/1-3.2C, the system libraries are shipped
without local symbols, but they still contain procedure
}
void
-init_extra_frame_info (struct frame_info *frame)
+alpha_print_extra_frame_info (struct frame_info *fi)
+{
+ if (fi
+ && fi->extra_info
+ && fi->extra_info->proc_desc
+ && fi->extra_info->proc_desc->pdr.framereg < NUM_REGS)
+ printf_filtered (" frame pointer is at %s+%s\n",
+ REGISTER_NAME (fi->extra_info->proc_desc->pdr.framereg),
+ paddr_d (fi->extra_info->proc_desc->pdr.frameoffset));
+}
+
+void
+alpha_init_extra_frame_info (int fromleaf, struct frame_info *frame)
{
/* Use proc_desc calculated in frame_chain */
alpha_extra_func_info_t proc_desc =
frame->next ? cached_proc_desc : find_proc_desc (frame->pc, frame->next);
+ frame->extra_info = (struct frame_extra_info *)
+ frame_obstack_alloc (sizeof (struct frame_extra_info));
+
frame->saved_regs = NULL;
- frame->localoff = 0;
- frame->pc_reg = RA_REGNUM;
- frame->proc_desc = proc_desc == &temp_proc_desc ? 0 : proc_desc;
+ frame->extra_info->localoff = 0;
+ frame->extra_info->pc_reg = RA_REGNUM;
+ frame->extra_info->proc_desc = proc_desc == &temp_proc_desc ? 0 : proc_desc;
if (proc_desc)
{
/* Get the locals offset and the saved pc register from the
procedure descriptor, they are valid even if we are in the
middle of the prologue. */
- frame->localoff = PROC_LOCALOFF (proc_desc);
- frame->pc_reg = PROC_PC_REG (proc_desc);
+ frame->extra_info->localoff = PROC_LOCALOFF (proc_desc);
+ frame->extra_info->pc_reg = PROC_PC_REG (proc_desc);
/* Fixup frame-pointer - only needed for top frame */
{
frame->saved_regs = (CORE_ADDR *)
frame_obstack_alloc (SIZEOF_FRAME_SAVED_REGS);
- memcpy (frame->saved_regs, temp_saved_regs.regs, SIZEOF_FRAME_SAVED_REGS);
+ memcpy (frame->saved_regs, temp_saved_regs,
+ SIZEOF_FRAME_SAVED_REGS);
frame->saved_regs[PC_REGNUM]
= frame->saved_regs[RA_REGNUM];
}
}
}
+CORE_ADDR
+alpha_frame_locals_address (struct frame_info *fi)
+{
+ return (fi->frame - fi->extra_info->localoff);
+}
+
+CORE_ADDR
+alpha_frame_args_address (struct frame_info *fi)
+{
+ return (fi->frame - (ALPHA_NUM_ARG_REGS * 8));
+}
+
/* ALPHA stack frames are almost impenetrable. When execution stops,
we basically have to look at symbol information for the function
that we stopped in, which tells us *which* register (if any) is
struct frame_info *frame = get_current_frame ();
CORE_ADDR new_sp = frame->frame;
- alpha_extra_func_info_t proc_desc = frame->proc_desc;
+ alpha_extra_func_info_t proc_desc = frame->extra_info->proc_desc;
/* we need proc_desc to know how to restore the registers;
if it is NULL, construct (a temporary) one */
Currently we must not skip more on the alpha, but we might need the
lenient stuff some day. */
-CORE_ADDR
-alpha_skip_prologue (CORE_ADDR pc, int lenient)
+static CORE_ADDR
+alpha_skip_prologue_internal (CORE_ADDR pc, int lenient)
{
unsigned long inst;
int offset;
return pc + offset;
}
+CORE_ADDR
+alpha_skip_prologue (CORE_ADDR addr)
+{
+ return (alpha_skip_prologue_internal (addr, 0));
+}
+
#if 0
/* Is address PC in the prologue (loosely defined) for function at
STARTADDR? */
static int
alpha_in_lenient_prologue (CORE_ADDR startaddr, CORE_ADDR pc)
{
- CORE_ADDR end_prologue = alpha_skip_prologue (startaddr, 1);
+ CORE_ADDR end_prologue = alpha_skip_prologue_internal (startaddr, 1);
return pc >= startaddr && pc < end_prologue;
}
#endif
return SYMBOL_VALUE_ADDRESS (sym) + 4;
}
+void
+alpha_fix_call_dummy (char *dummy, CORE_ADDR pc, CORE_ADDR fun, int nargs,
+ struct value **args, struct type *type, int gcc_p)
+{
+ CORE_ADDR bp_address = CALL_DUMMY_ADDRESS ();
+
+ if (bp_address == 0)
+ error ("no place to put call");
+ write_register (RA_REGNUM, bp_address);
+ write_register (T12_REGNUM, fun);
+}
+
+/* On the Alpha, the call dummy code is nevery copied to user space
+ (see alpha_fix_call_dummy() above). The contents of this do not
+ matter. */
+LONGEST alpha_call_dummy_words[] = { 0 };
+
+int
+alpha_use_struct_convention (int gcc_p, struct type *type)
+{
+ /* Structures are returned by ref in extra arg0. */
+ return 1;
+}
+
+void
+alpha_store_struct_return (CORE_ADDR addr, CORE_ADDR sp)
+{
+ /* Store the address of the place in which to copy the structure the
+ subroutine will return. Handled by alpha_push_arguments. */
+}
+
+CORE_ADDR
+alpha_extract_struct_value_address (char *regbuf)
+{
+ return (extract_address (regbuf + REGISTER_BYTE (V0_REGNUM),
+ REGISTER_RAW_SIZE (V0_REGNUM)));
+}
+
/* alpha_software_single_step() is called just before we want to resume
the inferior, if we want to single-step it but there is no hardware
or kernel single-step support (NetBSD on Alpha, for example). We find
&setlist);
/* We need to throw away the frame cache when we set this, since it
might change our ability to get backtraces. */
- c->function.sfunc = reinit_frame_cache_sfunc;
+ set_cmd_sfunc (c, reinit_frame_cache_sfunc);
add_show_from_set (c, &showlist);
}