#include "defs.h"
#include "frame.h"
#include "inferior.h"
#include "symtab.h"
#include "value.h"
#include "gdbcmd.h"
#include "gdbcore.h"
#include "dis-asm.h"
#include "symfile.h"
#include "objfiles.h"
#include "gdb_string.h"
#include "linespec.h"
#include "regcache.h"
#include "doublest.h"
#include "arch-utils.h"
#include "osabi.h"
#include "elf-bfd.h"
#include "alpha-tdep.h"
static gdbarch_init_ftype alpha_gdbarch_init;
static gdbarch_register_name_ftype alpha_register_name;
static gdbarch_register_raw_size_ftype alpha_register_raw_size;
static gdbarch_register_virtual_size_ftype alpha_register_virtual_size;
static gdbarch_register_virtual_type_ftype alpha_register_virtual_type;
static gdbarch_register_byte_ftype alpha_register_byte;
static gdbarch_cannot_fetch_register_ftype alpha_cannot_fetch_register;
static gdbarch_cannot_store_register_ftype alpha_cannot_store_register;
static gdbarch_register_convertible_ftype alpha_register_convertible;
static gdbarch_register_convert_to_virtual_ftype
alpha_register_convert_to_virtual;
static gdbarch_register_convert_to_raw_ftype alpha_register_convert_to_raw;
static gdbarch_store_struct_return_ftype alpha_store_struct_return;
static gdbarch_deprecated_extract_return_value_ftype alpha_extract_return_value;
static gdbarch_deprecated_extract_struct_value_address_ftype
alpha_extract_struct_value_address;
static gdbarch_use_struct_convention_ftype alpha_use_struct_convention;
static gdbarch_breakpoint_from_pc_ftype alpha_breakpoint_from_pc;
static gdbarch_frame_args_address_ftype alpha_frame_args_address;
static gdbarch_frame_locals_address_ftype alpha_frame_locals_address;
static gdbarch_skip_prologue_ftype alpha_skip_prologue;
static gdbarch_saved_pc_after_call_ftype alpha_saved_pc_after_call;
static gdbarch_frame_chain_ftype alpha_frame_chain;
static gdbarch_frame_saved_pc_ftype alpha_frame_saved_pc;
static gdbarch_frame_init_saved_regs_ftype alpha_frame_init_saved_regs;
static gdbarch_push_arguments_ftype alpha_push_arguments;
static gdbarch_push_dummy_frame_ftype alpha_push_dummy_frame;
static gdbarch_pop_frame_ftype alpha_pop_frame;
static gdbarch_fix_call_dummy_ftype alpha_fix_call_dummy;
static gdbarch_init_extra_frame_info_ftype alpha_init_extra_frame_info;
static gdbarch_get_longjmp_target_ftype alpha_get_longjmp_target;
struct frame_extra_info
{
alpha_extra_func_info_t proc_desc;
int localoff;
int pc_reg;
};
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);
static CORE_ADDR heuristic_proc_start (CORE_ADDR);
static alpha_extra_func_info_t heuristic_proc_desc (CORE_ADDR,
CORE_ADDR,
struct frame_info *);
static alpha_extra_func_info_t find_proc_desc (CORE_ADDR,
struct frame_info *);
#if 0
static int alpha_in_lenient_prologue (CORE_ADDR, CORE_ADDR);
#endif
static void reinit_frame_cache_sfunc (char *, int, struct cmd_list_element *);
static CORE_ADDR after_prologue (CORE_ADDR pc,
alpha_extra_func_info_t proc_desc);
static int alpha_in_prologue (CORE_ADDR pc,
alpha_extra_func_info_t proc_desc);
static int alpha_about_to_return (CORE_ADDR pc);
void _initialize_alpha_tdep (void);
static unsigned int heuristic_fence_post = 0;
#define PROC_LOW_ADDR(proc) ((proc)->pdr.adr)
#define PROC_HIGH_ADDR(proc) ((proc)->pdr.iline)
#define PROC_DUMMY_FRAME(proc) ((proc)->pdr.cbLineOffset)
#define PROC_FRAME_OFFSET(proc) ((proc)->pdr.frameoffset)
#define PROC_FRAME_REG(proc) ((proc)->pdr.framereg)
#define PROC_REG_MASK(proc) ((proc)->pdr.regmask)
#define PROC_FREG_MASK(proc) ((proc)->pdr.fregmask)
#define PROC_REG_OFFSET(proc) ((proc)->pdr.regoffset)
#define PROC_FREG_OFFSET(proc) ((proc)->pdr.fregoffset)
#define PROC_PC_REG(proc) ((proc)->pdr.pcreg)
#define PROC_LOCALOFF(proc) ((proc)->pdr.localoff)
#define PROC_SYMBOL(proc) (*(struct symbol**)&(proc)->pdr.isym)
#define _PROC_MAGIC_ 0x0F0F0F0F
#define PROC_DESC_IS_DUMMY(proc) ((proc)->pdr.isym == _PROC_MAGIC_)
#define SET_PROC_DESC_IS_DUMMY(proc) ((proc)->pdr.isym = _PROC_MAGIC_)
struct linked_proc_info
{
struct alpha_extra_func_info info;
struct linked_proc_info *next;
}
*linked_proc_desc_table = NULL;
static CORE_ADDR
alpha_frame_past_sigtramp_frame (struct frame_info *frame, CORE_ADDR pc)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
if (tdep->skip_sigtramp_frame != NULL)
return (tdep->skip_sigtramp_frame (frame, pc));
return (0);
}
static LONGEST
alpha_dynamic_sigtramp_offset (CORE_ADDR pc)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
if (tdep->dynamic_sigtramp_offset != NULL)
return (tdep->dynamic_sigtramp_offset (pc));
return (-1);
}
#define ALPHA_PROC_SIGTRAMP_MAGIC 0x0e0f0f0f
static int
alpha_proc_desc_is_dyn_sigtramp (struct alpha_extra_func_info *proc)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
if (tdep->dynamic_sigtramp_offset != NULL)
return (proc->pdr.isym == ALPHA_PROC_SIGTRAMP_MAGIC);
return (0);
}
static void
alpha_set_proc_desc_is_dyn_sigtramp (struct alpha_extra_func_info *proc)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
if (tdep->dynamic_sigtramp_offset != NULL)
proc->pdr.isym = ALPHA_PROC_SIGTRAMP_MAGIC;
}
static alpha_extra_func_info_t
push_sigtramp_desc (CORE_ADDR low_addr)
{
struct linked_proc_info *link;
alpha_extra_func_info_t proc_desc;
link = (struct linked_proc_info *)
xmalloc (sizeof (struct linked_proc_info));
link->next = linked_proc_desc_table;
linked_proc_desc_table = link;
proc_desc = &link->info;
proc_desc->numargs = 0;
PROC_LOW_ADDR (proc_desc) = low_addr;
PROC_HIGH_ADDR (proc_desc) = low_addr + 3 * 4;
PROC_DUMMY_FRAME (proc_desc) = 0;
PROC_FRAME_OFFSET (proc_desc) = 0x298;
PROC_FRAME_REG (proc_desc) = SP_REGNUM;
PROC_REG_MASK (proc_desc) = 0xffff;
PROC_FREG_MASK (proc_desc) = 0xffff;
PROC_PC_REG (proc_desc) = 26;
PROC_LOCALOFF (proc_desc) = 0;
alpha_set_proc_desc_is_dyn_sigtramp (proc_desc);
return (proc_desc);
}
static const char *
alpha_register_name (int regno)
{
static char *register_names[] =
{
"v0", "t0", "t1", "t2", "t3", "t4", "t5", "t6",
"t7", "s0", "s1", "s2", "s3", "s4", "s5", "fp",
"a0", "a1", "a2", "a3", "a4", "a5", "t8", "t9",
"t10", "t11", "ra", "t12", "at", "gp", "sp", "zero",
"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
"f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
"f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
"f24", "f25", "f26", "f27", "f28", "f29", "f30", "fpcr",
"pc", "vfp",
};
if (regno < 0)
return (NULL);
if (regno >= (sizeof(register_names) / sizeof(*register_names)))
return (NULL);
return (register_names[regno]);
}
static int
alpha_cannot_fetch_register (int regno)
{
return (regno == FP_REGNUM || regno == ALPHA_ZERO_REGNUM);
}
static int
alpha_cannot_store_register (int regno)
{
return (regno == FP_REGNUM || regno == ALPHA_ZERO_REGNUM);
}
static int
alpha_register_convertible (int regno)
{
return (regno >= FP0_REGNUM && regno <= FP0_REGNUM + 31);
}
static struct type *
alpha_register_virtual_type (int regno)
{
return ((regno >= FP0_REGNUM && regno < (FP0_REGNUM+31))
? builtin_type_double : builtin_type_long);
}
static int
alpha_register_byte (int regno)
{
return (regno * 8);
}
static int
alpha_register_raw_size (int regno)
{
return 8;
}
static int
alpha_register_virtual_size (int regno)
{
return 8;
}
static CORE_ADDR
alpha_sigcontext_addr (struct frame_info *fi)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
if (tdep->sigcontext_addr)
return (tdep->sigcontext_addr (fi));
return (0);
}
static void
alpha_find_saved_regs (struct frame_info *frame)
{
int ireg;
CORE_ADDR reg_position;
unsigned long mask;
alpha_extra_func_info_t proc_desc;
int returnreg;
frame_saved_regs_zalloc (frame);
#ifndef SIGFRAME_PC_OFF
#define SIGFRAME_PC_OFF (2 * 8)
#define SIGFRAME_REGSAVE_OFF (4 * 8)
#define SIGFRAME_FPREGSAVE_OFF (SIGFRAME_REGSAVE_OFF + 32 * 8 + 8)
#endif
if ((get_frame_type (frame) == SIGTRAMP_FRAME))
{
CORE_ADDR sigcontext_addr;
sigcontext_addr = alpha_sigcontext_addr (frame);
if (sigcontext_addr == 0)
{
return;
}
for (ireg = 0; ireg < 32; ireg++)
{
reg_position = sigcontext_addr + SIGFRAME_REGSAVE_OFF + ireg * 8;
get_frame_saved_regs (frame)[ireg] = reg_position;
}
for (ireg = 0; ireg < 32; ireg++)
{
reg_position = sigcontext_addr + SIGFRAME_FPREGSAVE_OFF + ireg * 8;
get_frame_saved_regs (frame)[FP0_REGNUM + ireg] = reg_position;
}
get_frame_saved_regs (frame)[PC_REGNUM] = sigcontext_addr + SIGFRAME_PC_OFF;
return;
}
proc_desc = get_frame_extra_info (frame)->proc_desc;
if (proc_desc == NULL)
return;
reg_position = get_frame_base (frame) + PROC_REG_OFFSET (proc_desc);
mask = PROC_REG_MASK (proc_desc);
returnreg = PROC_PC_REG (proc_desc);
if (mask & (1 << returnreg))
{
get_frame_saved_regs (frame)[returnreg] = reg_position;
reg_position += 8;
mask &= ~(1 << returnreg);
}
for (ireg = 0; ireg <= 31; ++ireg)
if (mask & (1 << ireg))
{
get_frame_saved_regs (frame)[ireg] = reg_position;
reg_position += 8;
}
reg_position = get_frame_base (frame) + PROC_FREG_OFFSET (proc_desc);
mask = PROC_FREG_MASK (proc_desc);
for (ireg = 0; ireg <= 31; ++ireg)
if (mask & (1 << ireg))
{
get_frame_saved_regs (frame)[FP0_REGNUM + ireg] = reg_position;
reg_position += 8;
}
get_frame_saved_regs (frame)[PC_REGNUM] = get_frame_saved_regs (frame)[returnreg];
}
static void
alpha_frame_init_saved_regs (struct frame_info *fi)
{
if (get_frame_saved_regs (fi) == NULL)
alpha_find_saved_regs (fi);
get_frame_saved_regs (fi)[SP_REGNUM] = get_frame_base (fi);
}
static CORE_ADDR
alpha_init_frame_pc_first (int fromleaf, struct frame_info *prev)
{
return (fromleaf ? SAVED_PC_AFTER_CALL (get_next_frame (prev))
: get_next_frame (prev) ? FRAME_SAVED_PC (get_next_frame (prev))
: read_pc ());
}
static CORE_ADDR
read_next_frame_reg (struct frame_info *fi, int regno)
{
for (; fi; fi = get_next_frame (fi))
{
if (regno == SP_REGNUM && !(get_frame_type (fi) == SIGTRAMP_FRAME))
return get_frame_base (fi);
else
{
if (get_frame_saved_regs (fi) == NULL)
alpha_find_saved_regs (fi);
if (get_frame_saved_regs (fi)[regno])
return read_memory_integer (get_frame_saved_regs (fi)[regno], 8);
}
}
return read_register (regno);
}
static CORE_ADDR
alpha_frame_saved_pc (struct frame_info *frame)
{
alpha_extra_func_info_t proc_desc = get_frame_extra_info (frame)->proc_desc;
int pcreg = ((get_frame_type (frame) == SIGTRAMP_FRAME)
? PC_REGNUM
: get_frame_extra_info (frame)->pc_reg);
if (proc_desc && PROC_DESC_IS_DUMMY (proc_desc))
return read_memory_integer (get_frame_base (frame) - 8, 8);
return read_next_frame_reg (frame, pcreg);
}
static CORE_ADDR
alpha_saved_pc_after_call (struct frame_info *frame)
{
CORE_ADDR pc = get_frame_pc (frame);
CORE_ADDR tmp;
alpha_extra_func_info_t proc_desc;
int pcreg;
tmp = SKIP_TRAMPOLINE_CODE (pc);
if (tmp != 0)
pc = tmp;
proc_desc = find_proc_desc (pc, get_next_frame (frame));
pcreg = proc_desc ? PROC_PC_REG (proc_desc) : ALPHA_RA_REGNUM;
if ((get_frame_type (frame) == SIGTRAMP_FRAME))
return alpha_frame_saved_pc (frame);
else
return read_register (pcreg);
}
static struct alpha_extra_func_info temp_proc_desc;
static CORE_ADDR temp_saved_regs[ALPHA_NUM_REGS];
static int
alpha_about_to_return (CORE_ADDR pc)
{
return read_memory_integer (pc, 4) == 0x6bfa8001;
}
static CORE_ADDR
heuristic_proc_start (CORE_ADDR pc)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
CORE_ADDR start_pc = pc;
CORE_ADDR fence = start_pc - heuristic_fence_post;
if (start_pc == 0)
return 0;
if (heuristic_fence_post == UINT_MAX
|| fence < tdep->vm_min_address)
fence = tdep->vm_min_address;
for (start_pc -= 4;; start_pc -= 4)
if (start_pc < fence)
{
if (!stop_soon_quietly)
{
static int blurb_printed = 0;
if (fence == tdep->vm_min_address)
warning ("Hit beginning of text section without finding");
else
warning ("Hit heuristic-fence-post without finding");
warning ("enclosing function for address 0x%s", paddr_nz (pc));
if (!blurb_printed)
{
printf_filtered ("\
This warning occurs if you are debugging a function without any symbols\n\
(for example, in a stripped executable). In that case, you may wish to\n\
increase the size of the search with the `set heuristic-fence-post' command.\n\
\n\
Otherwise, you told GDB there was a function where there isn't one, or\n\
(more likely) you have encountered a bug in GDB.\n");
blurb_printed = 1;
}
}
return 0;
}
else if (alpha_about_to_return (start_pc))
break;
start_pc += 4;
return start_pc;
}
static alpha_extra_func_info_t
heuristic_proc_desc (CORE_ADDR start_pc, CORE_ADDR limit_pc,
struct frame_info *next_frame)
{
CORE_ADDR sp = read_next_frame_reg (next_frame, SP_REGNUM);
CORE_ADDR vfp = sp;
CORE_ADDR cur_pc;
int frame_size;
int has_frame_reg = 0;
unsigned long reg_mask = 0;
int pcreg = -1;
int regno;
if (start_pc == 0)
return NULL;
memset (&temp_proc_desc, '\0', sizeof (temp_proc_desc));
memset (&temp_saved_regs, '\0', SIZEOF_FRAME_SAVED_REGS);
PROC_LOW_ADDR (&temp_proc_desc) = start_pc;
if (start_pc + 200 < limit_pc)
limit_pc = start_pc + 200;
frame_size = 0;
for (cur_pc = start_pc; cur_pc < limit_pc; cur_pc += 4)
{
char buf[4];
unsigned long word;
int status;
status = read_memory_nobpt (cur_pc, buf, 4);
if (status)
memory_error (status, cur_pc);
word = extract_unsigned_integer (buf, 4);
if ((word & 0xffff0000) == 0x23de0000)
{
if (word & 0x8000)
{
if (frame_size == 0)
frame_size += (-word) & 0xffff;
}
else
break;
}
else if ((word & 0xfc1f0000) == 0xb41e0000
&& (word & 0xffff0000) != 0xb7fe0000)
{
int reg = (word & 0x03e00000) >> 21;
reg_mask |= 1 << reg;
temp_saved_regs[reg] = (short) word;
if (pcreg == -1
&& cur_pc < (start_pc + 80)
&& (reg == ALPHA_T7_REGNUM || reg == ALPHA_T9_REGNUM
|| reg == ALPHA_RA_REGNUM))
pcreg = reg;
}
else if ((word & 0xffe0ffff) == 0x6be08001)
pcreg = (word >> 16) & 0x1f;
else if (word == 0x47de040f || word == 0x47fe040f)
{
has_frame_reg = 1;
vfp = read_next_frame_reg (next_frame, ALPHA_GCC_FP_REGNUM);
}
}
if (pcreg == -1)
{
while (cur_pc < (limit_pc + 80) && cur_pc < (start_pc + 80))
{
char buf[4];
unsigned long word;
if (read_memory_nobpt (cur_pc, buf, 4))
break;
cur_pc += 4;
word = extract_unsigned_integer (buf, 4);
if ((word & 0xfc1f0000) == 0xb41e0000
&& (word & 0xffff0000) != 0xb7fe0000)
{
int reg = (word & 0x03e00000) >> 21;
if (reg == ALPHA_T7_REGNUM || reg == ALPHA_T9_REGNUM
|| reg == ALPHA_RA_REGNUM)
{
pcreg = reg;
break;
}
}
else if ((word & 0xffe0ffff) == 0x6be08001)
{
pcreg = (word >> 16) & 0x1f;
break;
}
}
}
if (has_frame_reg)
PROC_FRAME_REG (&temp_proc_desc) = ALPHA_GCC_FP_REGNUM;
else
PROC_FRAME_REG (&temp_proc_desc) = SP_REGNUM;
for (regno = 0; regno < NUM_REGS; regno++)
{
if (reg_mask & 1 << regno)
temp_saved_regs[regno] += vfp;
}
PROC_FRAME_OFFSET (&temp_proc_desc) = frame_size;
PROC_REG_MASK (&temp_proc_desc) = reg_mask;
PROC_PC_REG (&temp_proc_desc) = (pcreg == -1) ? ALPHA_RA_REGNUM : pcreg;
PROC_LOCALOFF (&temp_proc_desc) = 0;
return &temp_proc_desc;
}
static CORE_ADDR
after_prologue (CORE_ADDR pc, alpha_extra_func_info_t proc_desc)
{
struct symtab_and_line sal;
CORE_ADDR func_addr, func_end;
if (!proc_desc)
proc_desc = find_proc_desc (pc, NULL);
if (proc_desc)
{
if (alpha_proc_desc_is_dyn_sigtramp (proc_desc))
return PROC_LOW_ADDR (proc_desc);
if (PROC_FRAME_REG (proc_desc) == SP_REGNUM
&& PROC_FRAME_OFFSET (proc_desc) == 0)
return 0;
}
if (!find_pc_partial_function (pc, NULL, &func_addr, &func_end))
return 0;
sal = find_pc_line (func_addr, 0);
if (sal.end < func_end)
return sal.end;
return 0;
}
static int
alpha_in_prologue (CORE_ADDR pc, alpha_extra_func_info_t proc_desc)
{
CORE_ADDR after_prologue_pc;
after_prologue_pc = after_prologue (pc, proc_desc);
if (after_prologue_pc == 0
|| pc < after_prologue_pc)
return 1;
else
return 0;
}
static alpha_extra_func_info_t
find_proc_desc (CORE_ADDR pc, struct frame_info *next_frame)
{
alpha_extra_func_info_t proc_desc;
struct block *b;
struct symbol *sym;
CORE_ADDR startaddr;
if (DEPRECATED_PC_IN_CALL_DUMMY (pc, 0, 0))
{
struct linked_proc_info *link;
CORE_ADDR sp = read_next_frame_reg (next_frame, SP_REGNUM);
alpha_extra_func_info_t found_proc_desc = NULL;
long min_distance = LONG_MAX;
for (link = linked_proc_desc_table; link; link = link->next)
{
long distance = (CORE_ADDR) PROC_DUMMY_FRAME (&link->info) - sp;
if (distance > 0 && distance < min_distance)
{
min_distance = distance;
found_proc_desc = &link->info;
}
}
if (found_proc_desc != NULL)
return found_proc_desc;
}
b = block_for_pc (pc);
find_pc_partial_function (pc, NULL, &startaddr, NULL);
if (b == NULL)
sym = NULL;
else
{
if (startaddr > BLOCK_START (b))
sym = NULL;
else
sym = lookup_symbol (MIPS_EFI_SYMBOL_NAME, b, LABEL_NAMESPACE,
0, NULL);
}
if (sym && ((mips_extra_func_info_t) SYMBOL_VALUE (sym))->pdr.framereg == -1)
sym = NULL;
if (sym)
{
proc_desc = (alpha_extra_func_info_t) SYMBOL_VALUE (sym);
if (next_frame == NULL)
{
if (PROC_DESC_IS_DUMMY (proc_desc) || alpha_in_prologue (pc, proc_desc))
{
alpha_extra_func_info_t found_heuristic =
heuristic_proc_desc (PROC_LOW_ADDR (proc_desc),
pc, next_frame);
if (found_heuristic)
{
PROC_LOCALOFF (found_heuristic) =
PROC_LOCALOFF (proc_desc);
PROC_PC_REG (found_heuristic) = PROC_PC_REG (proc_desc);
proc_desc = found_heuristic;
}
}
}
}
else
{
long offset;
register struct linked_proc_info *link;
for (link = linked_proc_desc_table; link; link = link->next)
if (PROC_LOW_ADDR (&link->info) <= pc
&& PROC_HIGH_ADDR (&link->info) > pc)
return &link->info;
offset = alpha_dynamic_sigtramp_offset (pc);
if (offset >= 0)
return push_sigtramp_desc (pc - offset);
if (startaddr == 0 || heuristic_fence_post != 0)
startaddr = heuristic_proc_start (pc);
proc_desc =
heuristic_proc_desc (startaddr, pc, next_frame);
}
return proc_desc;
}
alpha_extra_func_info_t cached_proc_desc;
static CORE_ADDR
alpha_frame_chain (struct frame_info *frame)
{
alpha_extra_func_info_t proc_desc;
CORE_ADDR saved_pc = FRAME_SAVED_PC (frame);
if (saved_pc == 0 || inside_entry_file (saved_pc))
return 0;
proc_desc = find_proc_desc (saved_pc, frame);
if (!proc_desc)
return 0;
cached_proc_desc = proc_desc;
if (PROC_DESC_IS_DUMMY (proc_desc))
return (CORE_ADDR) PROC_DUMMY_FRAME (proc_desc);
if (PROC_FRAME_REG (proc_desc) == SP_REGNUM
&& PROC_FRAME_OFFSET (proc_desc) == 0
&& !(get_frame_type (frame) == SIGTRAMP_FRAME))
return alpha_frame_past_sigtramp_frame (frame, saved_pc);
else
return read_next_frame_reg (frame, PROC_FRAME_REG (proc_desc))
+ PROC_FRAME_OFFSET (proc_desc);
}
void
alpha_print_extra_frame_info (struct frame_info *fi)
{
if (fi
&& get_frame_extra_info (fi)
&& get_frame_extra_info (fi)->proc_desc
&& get_frame_extra_info (fi)->proc_desc->pdr.framereg < NUM_REGS)
printf_filtered (" frame pointer is at %s+%s\n",
REGISTER_NAME (get_frame_extra_info (fi)->proc_desc->pdr.framereg),
paddr_d (get_frame_extra_info (fi)->proc_desc->pdr.frameoffset));
}
static void
alpha_init_extra_frame_info (int fromleaf, struct frame_info *frame)
{
alpha_extra_func_info_t proc_desc =
get_next_frame (frame)
? cached_proc_desc
: find_proc_desc (get_frame_pc (frame), get_next_frame (frame));
frame_extra_info_zalloc (frame, sizeof (struct frame_extra_info));
get_frame_extra_info (frame)->localoff = 0;
get_frame_extra_info (frame)->pc_reg = ALPHA_RA_REGNUM;
get_frame_extra_info (frame)->proc_desc = proc_desc == &temp_proc_desc ? 0 : proc_desc;
if (proc_desc)
{
get_frame_extra_info (frame)->localoff = PROC_LOCALOFF (proc_desc);
get_frame_extra_info (frame)->pc_reg = PROC_PC_REG (proc_desc);
if (PROC_DESC_IS_DUMMY (proc_desc))
deprecated_update_frame_base_hack (frame, (CORE_ADDR) PROC_DUMMY_FRAME (proc_desc));
else if (get_frame_pc (frame) == PROC_LOW_ADDR (proc_desc)
&& !alpha_proc_desc_is_dyn_sigtramp (proc_desc))
deprecated_update_frame_base_hack (frame, read_next_frame_reg (get_next_frame (frame), SP_REGNUM));
else
deprecated_update_frame_base_hack (frame, read_next_frame_reg (get_next_frame (frame), PROC_FRAME_REG (proc_desc))
+ PROC_FRAME_OFFSET (proc_desc));
if (proc_desc == &temp_proc_desc)
{
char *name;
find_pc_partial_function (get_frame_pc (frame), &name,
(CORE_ADDR *) NULL, (CORE_ADDR *) NULL);
if (!PC_IN_SIGTRAMP (get_frame_pc (frame), name))
{
frame_saved_regs_zalloc (frame);
memcpy (get_frame_saved_regs (frame), temp_saved_regs,
SIZEOF_FRAME_SAVED_REGS);
get_frame_saved_regs (frame)[PC_REGNUM]
= get_frame_saved_regs (frame)[ALPHA_RA_REGNUM];
}
}
}
}
static CORE_ADDR
alpha_frame_locals_address (struct frame_info *fi)
{
return (get_frame_base (fi) - get_frame_extra_info (fi)->localoff);
}
static CORE_ADDR
alpha_frame_args_address (struct frame_info *fi)
{
return (get_frame_base (fi) - (ALPHA_NUM_ARG_REGS * 8));
}
struct frame_info *
alpha_setup_arbitrary_frame (int argc, CORE_ADDR *argv)
{
if (argc != 2)
error ("ALPHA frame specifications require two arguments: sp and pc");
return create_new_frame (argv[0], argv[1]);
}
static CORE_ADDR
alpha_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
int struct_return, CORE_ADDR struct_addr)
{
int i;
int accumulate_size = struct_return ? 8 : 0;
int arg_regs_size = ALPHA_NUM_ARG_REGS * 8;
struct alpha_arg
{
char *contents;
int len;
int offset;
};
struct alpha_arg *alpha_args =
(struct alpha_arg *) alloca (nargs * sizeof (struct alpha_arg));
register struct alpha_arg *m_arg;
char raw_buffer[sizeof (CORE_ADDR)];
int required_arg_regs;
for (i = 0, m_arg = alpha_args; i < nargs; i++, m_arg++)
{
struct value *arg = args[i];
struct type *arg_type = check_typedef (VALUE_TYPE (arg));
switch (TYPE_CODE (arg_type))
{
case TYPE_CODE_INT:
case TYPE_CODE_BOOL:
case TYPE_CODE_CHAR:
case TYPE_CODE_RANGE:
case TYPE_CODE_ENUM:
if (TYPE_LENGTH (arg_type) < TYPE_LENGTH (builtin_type_long))
{
arg_type = builtin_type_long;
arg = value_cast (arg_type, arg);
}
break;
default:
break;
}
m_arg->len = TYPE_LENGTH (arg_type);
m_arg->offset = accumulate_size;
accumulate_size = (accumulate_size + m_arg->len + 7) & ~7;
m_arg->contents = VALUE_CONTENTS (arg);
}
required_arg_regs = accumulate_size / 8;
if (required_arg_regs > ALPHA_NUM_ARG_REGS)
required_arg_regs = ALPHA_NUM_ARG_REGS;
if (accumulate_size < arg_regs_size)
accumulate_size = arg_regs_size;
sp -= accumulate_size;
sp &= ~15;
for (i = nargs; m_arg--, --i >= 0;)
write_memory (sp + m_arg->offset, m_arg->contents, m_arg->len);
if (struct_return)
{
store_address (raw_buffer, sizeof (CORE_ADDR), struct_addr);
write_memory (sp, raw_buffer, sizeof (CORE_ADDR));
}
for (i = 0; i < required_arg_regs; i++)
{
LONGEST val;
val = read_memory_integer (sp + i * 8, 8);
write_register (ALPHA_A0_REGNUM + i, val);
write_register (ALPHA_FPA0_REGNUM + i, val);
}
return sp + arg_regs_size;
}
static void
alpha_push_dummy_frame (void)
{
int ireg;
struct linked_proc_info *link;
alpha_extra_func_info_t proc_desc;
CORE_ADDR sp = read_register (SP_REGNUM);
CORE_ADDR save_address;
char raw_buffer[ALPHA_MAX_REGISTER_RAW_SIZE];
unsigned long mask;
link = (struct linked_proc_info *) xmalloc (sizeof (struct linked_proc_info));
link->next = linked_proc_desc_table;
linked_proc_desc_table = link;
proc_desc = &link->info;
#define MASK(i,j) ((((LONGEST)1 << ((j)+1)) - 1) ^ (((LONGEST)1 << (i)) - 1))
#define GEN_REG_SAVE_MASK (MASK(0,8) | MASK(16,29))
#define GEN_REG_SAVE_COUNT 24
#define FLOAT_REG_SAVE_MASK (MASK(0,1) | MASK(10,30))
#define FLOAT_REG_SAVE_COUNT 23
#define SPECIAL_REG_SAVE_COUNT 1
PROC_REG_MASK (proc_desc) = GEN_REG_SAVE_MASK;
PROC_FREG_MASK (proc_desc) = FLOAT_REG_SAVE_MASK;
PROC_REG_OFFSET (proc_desc) =
-((8 * (SPECIAL_REG_SAVE_COUNT
+ GEN_REG_SAVE_COUNT
+ FLOAT_REG_SAVE_COUNT)
+ 15) & ~15);
PROC_FREG_OFFSET (proc_desc) =
PROC_REG_OFFSET (proc_desc) + 8 * GEN_REG_SAVE_COUNT;
save_address = sp + PROC_REG_OFFSET (proc_desc);
store_address (raw_buffer, 8, read_register (ALPHA_RA_REGNUM));
write_memory (save_address, raw_buffer, 8);
save_address += 8;
mask = PROC_REG_MASK (proc_desc) & 0xffffffffL;
for (ireg = 0; mask; ireg++, mask >>= 1)
if (mask & 1)
{
if (ireg == ALPHA_RA_REGNUM)
continue;
store_address (raw_buffer, 8, read_register (ireg));
write_memory (save_address, raw_buffer, 8);
save_address += 8;
}
store_address (raw_buffer, 8, read_register (PC_REGNUM));
write_memory (sp - 8, raw_buffer, 8);
save_address = sp + PROC_FREG_OFFSET (proc_desc);
mask = PROC_FREG_MASK (proc_desc) & 0xffffffffL;
for (ireg = 0; mask; ireg++, mask >>= 1)
if (mask & 1)
{
store_address (raw_buffer, 8, read_register (ireg + FP0_REGNUM));
write_memory (save_address, raw_buffer, 8);
save_address += 8;
}
PROC_DUMMY_FRAME (proc_desc) = sp;
PROC_FRAME_REG (proc_desc) = FP_REGNUM;
PROC_FRAME_OFFSET (proc_desc) = 0;
sp += PROC_REG_OFFSET (proc_desc);
write_register (SP_REGNUM, sp);
PROC_LOW_ADDR (proc_desc) = CALL_DUMMY_ADDRESS ();
PROC_HIGH_ADDR (proc_desc) = PROC_LOW_ADDR (proc_desc) + 4;
SET_PROC_DESC_IS_DUMMY (proc_desc);
PROC_PC_REG (proc_desc) = ALPHA_RA_REGNUM;
}
static void
alpha_pop_frame (void)
{
register int regnum;
struct frame_info *frame = get_current_frame ();
CORE_ADDR new_sp = get_frame_base (frame);
alpha_extra_func_info_t proc_desc = get_frame_extra_info (frame)->proc_desc;
if (proc_desc == NULL)
proc_desc = find_proc_desc (get_frame_pc (frame), get_next_frame (frame));
write_register (PC_REGNUM, FRAME_SAVED_PC (frame));
if (get_frame_saved_regs (frame) == NULL)
alpha_find_saved_regs (frame);
if (proc_desc)
{
for (regnum = 32; --regnum >= 0;)
if (PROC_REG_MASK (proc_desc) & (1 << regnum))
write_register (regnum,
read_memory_integer (get_frame_saved_regs (frame)[regnum],
8));
for (regnum = 32; --regnum >= 0;)
if (PROC_FREG_MASK (proc_desc) & (1 << regnum))
write_register (regnum + FP0_REGNUM,
read_memory_integer (get_frame_saved_regs (frame)[regnum + FP0_REGNUM], 8));
}
write_register (SP_REGNUM, new_sp);
flush_cached_frames ();
if (proc_desc && (PROC_DESC_IS_DUMMY (proc_desc)
|| alpha_proc_desc_is_dyn_sigtramp (proc_desc)))
{
struct linked_proc_info *pi_ptr, *prev_ptr;
for (pi_ptr = linked_proc_desc_table, prev_ptr = NULL;
pi_ptr != NULL;
prev_ptr = pi_ptr, pi_ptr = pi_ptr->next)
{
if (&pi_ptr->info == proc_desc)
break;
}
if (pi_ptr == NULL)
error ("Can't locate dummy extra frame info\n");
if (prev_ptr != NULL)
prev_ptr->next = pi_ptr->next;
else
linked_proc_desc_table = pi_ptr->next;
xfree (pi_ptr);
}
}
static CORE_ADDR
alpha_skip_prologue_internal (CORE_ADDR pc, int lenient)
{
unsigned long inst;
int offset;
CORE_ADDR post_prologue_pc;
char buf[4];
if (target_read_memory (pc, buf, 4))
return pc;
post_prologue_pc = after_prologue (pc, NULL);
if (post_prologue_pc != 0)
return max (pc, post_prologue_pc);
for (offset = 0; offset < 100; offset += 4)
{
int status;
status = read_memory_nobpt (pc + offset, buf, 4);
if (status)
memory_error (status, pc + offset);
inst = extract_unsigned_integer (buf, 4);
if (lenient && 0)
continue;
if ((inst & 0xffff0000) == 0x27bb0000)
continue;
if ((inst & 0xffff0000) == 0x23bd0000)
continue;
if ((inst & 0xffff0000) == 0x23de0000)
continue;
if ((inst & 0xffe01fff) == 0x43c0153e)
continue;
if ((inst & 0xfc1f0000) == 0xb41e0000
&& (inst & 0xffff0000) != 0xb7fe0000)
continue;
if ((inst & 0xfc1f0000) == 0x9c1e0000
&& (inst & 0xffff0000) != 0x9ffe0000)
continue;
if (inst == 0x47de040f)
continue;
break;
}
return pc + offset;
}
static CORE_ADDR
alpha_skip_prologue (CORE_ADDR addr)
{
return (alpha_skip_prologue_internal (addr, 0));
}
#if 0
static int
alpha_in_lenient_prologue (CORE_ADDR startaddr, CORE_ADDR pc)
{
CORE_ADDR end_prologue = alpha_skip_prologue_internal (startaddr, 1);
return pc >= startaddr && pc < end_prologue;
}
#endif
static void
alpha_register_convert_to_virtual (int regnum, struct type *valtype,
char *raw_buffer, char *virtual_buffer)
{
if (TYPE_LENGTH (valtype) >= REGISTER_RAW_SIZE (regnum))
{
memcpy (virtual_buffer, raw_buffer, REGISTER_VIRTUAL_SIZE (regnum));
return;
}
if (TYPE_CODE (valtype) == TYPE_CODE_FLT)
{
double d = extract_floating (raw_buffer, REGISTER_RAW_SIZE (regnum));
store_floating (virtual_buffer, TYPE_LENGTH (valtype), d);
}
else if (TYPE_CODE (valtype) == TYPE_CODE_INT && TYPE_LENGTH (valtype) <= 4)
{
ULONGEST l;
l = extract_unsigned_integer (raw_buffer, REGISTER_RAW_SIZE (regnum));
l = ((l >> 32) & 0xc0000000) | ((l >> 29) & 0x3fffffff);
store_unsigned_integer (virtual_buffer, TYPE_LENGTH (valtype), l);
}
else
error ("Cannot retrieve value from floating point register");
}
static void
alpha_register_convert_to_raw (struct type *valtype, int regnum,
char *virtual_buffer, char *raw_buffer)
{
if (TYPE_LENGTH (valtype) >= REGISTER_RAW_SIZE (regnum))
{
memcpy (raw_buffer, virtual_buffer, REGISTER_RAW_SIZE (regnum));
return;
}
if (TYPE_CODE (valtype) == TYPE_CODE_FLT)
{
double d = extract_floating (virtual_buffer, TYPE_LENGTH (valtype));
store_floating (raw_buffer, REGISTER_RAW_SIZE (regnum), d);
}
else if (TYPE_CODE (valtype) == TYPE_CODE_INT && TYPE_LENGTH (valtype) <= 4)
{
ULONGEST l;
if (TYPE_UNSIGNED (valtype))
l = extract_unsigned_integer (virtual_buffer, TYPE_LENGTH (valtype));
else
l = extract_signed_integer (virtual_buffer, TYPE_LENGTH (valtype));
l = ((l & 0xc0000000) << 32) | ((l & 0x3fffffff) << 29);
store_unsigned_integer (raw_buffer, REGISTER_RAW_SIZE (regnum), l);
}
else
error ("Cannot store value in floating point register");
}
static const unsigned char *
alpha_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr)
{
static const unsigned char alpha_breakpoint[] =
{ 0x80, 0, 0, 0 };
*lenptr = sizeof(alpha_breakpoint);
return (alpha_breakpoint);
}
static void
alpha_extract_return_value (struct type *valtype,
char regbuf[ALPHA_REGISTER_BYTES], char *valbuf)
{
if (TYPE_CODE (valtype) == TYPE_CODE_FLT)
alpha_register_convert_to_virtual (FP0_REGNUM, valtype,
regbuf + REGISTER_BYTE (FP0_REGNUM),
valbuf);
else
memcpy (valbuf, regbuf + REGISTER_BYTE (ALPHA_V0_REGNUM),
TYPE_LENGTH (valtype));
}
static void
alpha_store_return_value (struct type *valtype, char *valbuf)
{
char raw_buffer[ALPHA_MAX_REGISTER_RAW_SIZE];
int regnum = ALPHA_V0_REGNUM;
int length = TYPE_LENGTH (valtype);
if (TYPE_CODE (valtype) == TYPE_CODE_FLT)
{
regnum = FP0_REGNUM;
length = REGISTER_RAW_SIZE (regnum);
alpha_register_convert_to_raw (valtype, regnum, valbuf, raw_buffer);
}
else
memcpy (raw_buffer, valbuf, length);
deprecated_write_register_bytes (REGISTER_BYTE (regnum), raw_buffer, length);
}
static void
reinit_frame_cache_sfunc (char *args, int from_tty, struct cmd_list_element *c)
{
reinit_frame_cache ();
}
CORE_ADDR
alpha_call_dummy_address (void)
{
CORE_ADDR entry;
struct minimal_symbol *sym;
entry = entry_point_address ();
if (entry != 0)
return entry;
sym = lookup_minimal_symbol ("_Prelude", NULL, symfile_objfile);
if (!sym || MSYMBOL_TYPE (sym) != mst_text)
return 0;
else
return SYMBOL_VALUE_ADDRESS (sym) + 4;
}
static 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 (ALPHA_RA_REGNUM, bp_address);
write_register (ALPHA_T12_REGNUM, fun);
}
LONGEST alpha_call_dummy_words[] = { 0 };
static int
alpha_use_struct_convention (int gcc_p, struct type *type)
{
return 1;
}
static void
alpha_store_struct_return (CORE_ADDR addr, CORE_ADDR sp)
{
}
static CORE_ADDR
alpha_extract_struct_value_address (char *regbuf)
{
return (extract_address (regbuf + REGISTER_BYTE (ALPHA_V0_REGNUM),
REGISTER_RAW_SIZE (ALPHA_V0_REGNUM)));
}
static int
alpha_get_longjmp_target (CORE_ADDR *pc)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
CORE_ADDR jb_addr;
char raw_buffer[ALPHA_MAX_REGISTER_RAW_SIZE];
jb_addr = read_register (ALPHA_A0_REGNUM);
if (target_read_memory (jb_addr + (tdep->jb_pc * tdep->jb_elt_size),
raw_buffer, tdep->jb_elt_size))
return 0;
*pc = extract_address (raw_buffer, tdep->jb_elt_size);
return 1;
}
static CORE_ADDR
alpha_next_pc (CORE_ADDR pc)
{
unsigned int insn;
unsigned int op;
int offset;
LONGEST rav;
insn = read_memory_unsigned_integer (pc, sizeof (insn));
op = (insn >> 26) & 0x3f;
if (op == 0x1a)
{
return (read_register ((insn >> 16) & 0x1f) & ~3);
}
if ((op & 0x30) == 0x30)
{
if (op == 0x30 ||
op == 0x34)
{
branch_taken:
offset = (insn & 0x001fffff);
if (offset & 0x00100000)
offset |= 0xffe00000;
offset *= 4;
return (pc + 4 + offset);
}
rav = (LONGEST) read_register ((insn >> 21) & 0x1f);
switch (op)
{
case 0x38:
if ((rav & 1) == 0)
goto branch_taken;
break;
case 0x3c:
if (rav & 1)
goto branch_taken;
break;
case 0x39:
if (rav == 0)
goto branch_taken;
break;
case 0x3d:
if (rav != 0)
goto branch_taken;
break;
case 0x3a:
if (rav < 0)
goto branch_taken;
break;
case 0x3b:
if (rav <= 0)
goto branch_taken;
break;
case 0x3f:
if (rav > 0)
goto branch_taken;
break;
case 0x3e:
if (rav >= 0)
goto branch_taken;
break;
}
}
return (pc + 4);
}
void
alpha_software_single_step (enum target_signal sig, int insert_breakpoints_p)
{
static CORE_ADDR next_pc;
typedef char binsn_quantum[BREAKPOINT_MAX];
static binsn_quantum break_mem;
CORE_ADDR pc;
if (insert_breakpoints_p)
{
pc = read_pc ();
next_pc = alpha_next_pc (pc);
target_insert_breakpoint (next_pc, break_mem);
}
else
{
target_remove_breakpoint (next_pc, break_mem);
write_pc (next_pc);
}
}
static struct gdbarch *
alpha_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
{
struct gdbarch_tdep *tdep;
struct gdbarch *gdbarch;
if (info.abfd != NULL && info.osabi == GDB_OSABI_UNKNOWN)
{
if (bfd_get_flavour (info.abfd) == bfd_target_ecoff_flavour)
info.osabi = GDB_OSABI_OSF1;
}
arches = gdbarch_list_lookup_by_info (arches, &info);
if (arches != NULL)
return arches->gdbarch;
tdep = xmalloc (sizeof (struct gdbarch_tdep));
gdbarch = gdbarch_alloc (&info, tdep);
tdep->vm_min_address = (CORE_ADDR) 0x120000000;
tdep->dynamic_sigtramp_offset = NULL;
tdep->skip_sigtramp_frame = NULL;
tdep->sigcontext_addr = NULL;
tdep->jb_pc = -1;
set_gdbarch_short_bit (gdbarch, 16);
set_gdbarch_int_bit (gdbarch, 32);
set_gdbarch_long_bit (gdbarch, 64);
set_gdbarch_long_long_bit (gdbarch, 64);
set_gdbarch_float_bit (gdbarch, 32);
set_gdbarch_double_bit (gdbarch, 64);
set_gdbarch_long_double_bit (gdbarch, 64);
set_gdbarch_ptr_bit (gdbarch, 64);
set_gdbarch_num_regs (gdbarch, ALPHA_NUM_REGS);
set_gdbarch_sp_regnum (gdbarch, ALPHA_SP_REGNUM);
set_gdbarch_fp_regnum (gdbarch, ALPHA_FP_REGNUM);
set_gdbarch_pc_regnum (gdbarch, ALPHA_PC_REGNUM);
set_gdbarch_fp0_regnum (gdbarch, ALPHA_FP0_REGNUM);
set_gdbarch_register_name (gdbarch, alpha_register_name);
set_gdbarch_register_size (gdbarch, ALPHA_REGISTER_SIZE);
set_gdbarch_register_bytes (gdbarch, ALPHA_REGISTER_BYTES);
set_gdbarch_register_byte (gdbarch, alpha_register_byte);
set_gdbarch_register_raw_size (gdbarch, alpha_register_raw_size);
set_gdbarch_max_register_raw_size (gdbarch, ALPHA_MAX_REGISTER_RAW_SIZE);
set_gdbarch_register_virtual_size (gdbarch, alpha_register_virtual_size);
set_gdbarch_max_register_virtual_size (gdbarch,
ALPHA_MAX_REGISTER_VIRTUAL_SIZE);
set_gdbarch_register_virtual_type (gdbarch, alpha_register_virtual_type);
set_gdbarch_cannot_fetch_register (gdbarch, alpha_cannot_fetch_register);
set_gdbarch_cannot_store_register (gdbarch, alpha_cannot_store_register);
set_gdbarch_register_convertible (gdbarch, alpha_register_convertible);
set_gdbarch_register_convert_to_virtual (gdbarch,
alpha_register_convert_to_virtual);
set_gdbarch_register_convert_to_raw (gdbarch, alpha_register_convert_to_raw);
set_gdbarch_skip_prologue (gdbarch, alpha_skip_prologue);
set_gdbarch_frame_num_args (gdbarch, frame_num_args_unknown);
set_gdbarch_frameless_function_invocation (gdbarch,
generic_frameless_function_invocation_not);
set_gdbarch_saved_pc_after_call (gdbarch, alpha_saved_pc_after_call);
set_gdbarch_frame_chain (gdbarch, alpha_frame_chain);
set_gdbarch_frame_saved_pc (gdbarch, alpha_frame_saved_pc);
set_gdbarch_frame_init_saved_regs (gdbarch, alpha_frame_init_saved_regs);
set_gdbarch_use_struct_convention (gdbarch, alpha_use_struct_convention);
set_gdbarch_deprecated_extract_return_value (gdbarch, alpha_extract_return_value);
set_gdbarch_store_struct_return (gdbarch, alpha_store_struct_return);
set_gdbarch_deprecated_store_return_value (gdbarch, alpha_store_return_value);
set_gdbarch_deprecated_extract_struct_value_address (gdbarch,
alpha_extract_struct_value_address);
set_gdbarch_deprecated_use_generic_dummy_frames (gdbarch, 0);
set_gdbarch_call_dummy_length (gdbarch, 0);
set_gdbarch_push_arguments (gdbarch, alpha_push_arguments);
set_gdbarch_pop_frame (gdbarch, alpha_pop_frame);
set_gdbarch_call_dummy_p (gdbarch, 1);
set_gdbarch_call_dummy_words (gdbarch, alpha_call_dummy_words);
set_gdbarch_sizeof_call_dummy_words (gdbarch, 0);
set_gdbarch_frame_args_address (gdbarch, alpha_frame_args_address);
set_gdbarch_frame_locals_address (gdbarch, alpha_frame_locals_address);
set_gdbarch_init_extra_frame_info (gdbarch, alpha_init_extra_frame_info);
set_gdbarch_call_dummy_address (gdbarch, alpha_call_dummy_address);
set_gdbarch_call_dummy_breakpoint_offset_p (gdbarch, 1);
set_gdbarch_call_dummy_breakpoint_offset (gdbarch, 0);
set_gdbarch_call_dummy_start_offset (gdbarch, 0);
set_gdbarch_deprecated_pc_in_call_dummy (gdbarch, deprecated_pc_in_call_dummy_at_entry_point);
set_gdbarch_call_dummy_stack_adjust_p (gdbarch, 0);
set_gdbarch_push_dummy_frame (gdbarch, alpha_push_dummy_frame);
set_gdbarch_fix_call_dummy (gdbarch, alpha_fix_call_dummy);
set_gdbarch_deprecated_init_frame_pc (gdbarch, init_frame_pc_noop);
set_gdbarch_deprecated_init_frame_pc_first (gdbarch, alpha_init_frame_pc_first);
set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
set_gdbarch_breakpoint_from_pc (gdbarch, alpha_breakpoint_from_pc);
set_gdbarch_decr_pc_after_break (gdbarch, 4);
set_gdbarch_function_start_offset (gdbarch, 0);
set_gdbarch_frame_args_skip (gdbarch, 0);
gdbarch_init_osabi (info, gdbarch);
if (tdep->jb_pc >= 0)
set_gdbarch_get_longjmp_target (gdbarch, alpha_get_longjmp_target);
return gdbarch;
}
static void
alpha_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
if (tdep == NULL)
return;
fprintf_unfiltered (file,
"alpha_dump_tdep: vm_min_address = 0x%lx\n",
(long) tdep->vm_min_address);
fprintf_unfiltered (file,
"alpha_dump_tdep: jb_pc = %d\n",
tdep->jb_pc);
fprintf_unfiltered (file,
"alpha_dump_tdep: jb_elt_size = %ld\n",
(long) tdep->jb_elt_size);
}
void
_initialize_alpha_tdep (void)
{
struct cmd_list_element *c;
gdbarch_register (bfd_arch_alpha, alpha_gdbarch_init, alpha_dump_tdep);
tm_print_insn = print_insn_alpha;
c = add_set_cmd ("heuristic-fence-post", class_support, var_zinteger,
(char *) &heuristic_fence_post,
"\
Set the distance searched for the start of a function.\n\
If you are debugging a stripped executable, GDB needs to search through the\n\
program for the start of a function. This command sets the distance of the\n\
search. The only need to set it is when debugging a stripped executable.",
&setlist);
set_cmd_sfunc (c, reinit_frame_cache_sfunc);
add_show_from_set (c, &showlist);
}