#include "frame.h"
#include "frame-unwind.h"
#include "frame-base.h"
+#include "dwarf2-frame.h"
#include "inferior.h"
#include "symtab.h"
#include "value.h"
return 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)
+alpha_register_type (struct gdbarch *gdbarch, int regno)
{
if (regno == ALPHA_SP_REGNUM || regno == ALPHA_GP_REGNUM)
return builtin_type_void_data_ptr;
if (REGISTER_NAME (regnum) == NULL || *REGISTER_NAME (regnum) == '\0')
return 0;
- /* Since we implement no pseudo registers, save/restore is equal to all. */
- if (group == all_reggroup
- || group == save_reggroup
- || group == restore_reggroup)
+ if (group == all_reggroup)
+ return 1;
+
+ /* Zero should not be saved or restored. Technically it is a general
+ register (just as $f31 would be a float if we represented it), but
+ there's no point displaying it during "info regs", so leave it out
+ of all groups except for "all". */
+ if (regnum == ALPHA_ZERO_REGNUM)
+ return 0;
+
+ /* All other registers are saved and restored. */
+ if (group == save_reggroup || group == restore_reggroup)
return 1;
/* All other groups are non-overlapping. */
return 8;
}
-/* The alpha needs a conversion between register and memory format if the
- register is a floating point register and memory format is float, as the
- register format must be double or memory format is an integer with 4
- bytes or less, as the representation of integers in floating point
- registers is different. */
+/* The following represents exactly the conversion performed by
+ the LDS instruction. This applies to both single-precision
+ floating point and 32-bit integers. */
static void
-alpha_convert_flt_dbl (void *out, const void *in)
+alpha_lds (void *out, const void *in)
{
- DOUBLEST d = extract_typed_floating (in, builtin_type_ieee_single_little);
- store_typed_floating (out, builtin_type_ieee_double_little, d);
-}
+ ULONGEST mem = extract_unsigned_integer (in, 4);
+ ULONGEST frac = (mem >> 0) & 0x7fffff;
+ ULONGEST sign = (mem >> 31) & 1;
+ ULONGEST exp_msb = (mem >> 30) & 1;
+ ULONGEST exp_low = (mem >> 23) & 0x7f;
+ ULONGEST exp, reg;
+
+ exp = (exp_msb << 10) | exp_low;
+ if (exp_msb)
+ {
+ if (exp_low == 0x7f)
+ exp = 0x7ff;
+ }
+ else
+ {
+ if (exp_low != 0x00)
+ exp |= 0x380;
+ }
-static void
-alpha_convert_dbl_flt (void *out, const void *in)
-{
- DOUBLEST d = extract_typed_floating (in, builtin_type_ieee_double_little);
- store_typed_floating (out, builtin_type_ieee_single_little, d);
+ reg = (sign << 63) | (exp << 52) | (frac << 29);
+ store_unsigned_integer (out, 8, reg);
}
+/* Similarly, this represents exactly the conversion performed by
+ the STS instruction. */
+
static void
-alpha_register_convert_to_virtual (int regnum, struct type *valtype,
- char *raw_buffer, char *virtual_buffer)
+alpha_sts (void *out, const void *in)
{
- if (TYPE_LENGTH (valtype) >= ALPHA_REGISTER_SIZE)
- {
- memcpy (virtual_buffer, raw_buffer, ALPHA_REGISTER_SIZE);
- return;
- }
+ ULONGEST reg, mem;
- /* Note that everything below is less than 8 bytes long. */
+ reg = extract_unsigned_integer (in, 8);
+ mem = ((reg >> 32) & 0xc0000000) | ((reg >> 29) & 0x3fffffff);
+ store_unsigned_integer (out, 4, mem);
+}
- if (TYPE_CODE (valtype) == TYPE_CODE_FLT)
- alpha_convert_dbl_flt (virtual_buffer, raw_buffer);
- else if (TYPE_CODE (valtype) == TYPE_CODE_INT)
- {
- ULONGEST l;
- l = extract_unsigned_integer (raw_buffer, ALPHA_REGISTER_SIZE);
- 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");
+/* The alpha needs a conversion between register and memory format if the
+ register is a floating point register and memory format is float, as the
+ register format must be double or memory format is an integer with 4
+ bytes or less, as the representation of integers in floating point
+ registers is different. */
+
+static int
+alpha_convert_register_p (int regno, struct type *type)
+{
+ return (regno >= ALPHA_FP0_REGNUM && regno < ALPHA_FP0_REGNUM + 31);
}
static void
-alpha_register_convert_to_raw (struct type *valtype, int regnum,
- char *virtual_buffer, char *raw_buffer)
+alpha_register_to_value (struct frame_info *frame, int regnum,
+ struct type *valtype, void *out)
{
- if (TYPE_LENGTH (valtype) >= ALPHA_REGISTER_SIZE)
+ char in[MAX_REGISTER_SIZE];
+ frame_register_read (frame, regnum, in);
+ switch (TYPE_LENGTH (valtype))
{
- memcpy (raw_buffer, virtual_buffer, ALPHA_REGISTER_SIZE);
- return;
+ case 4:
+ alpha_sts (out, in);
+ break;
+ case 8:
+ memcpy (out, in, 8);
+ break;
+ default:
+ error ("Cannot retrieve value from floating point register");
}
+}
- /* Note that everything below is less than 8 bytes long. */
-
- if (TYPE_CODE (valtype) == TYPE_CODE_FLT)
- alpha_convert_flt_dbl (raw_buffer, virtual_buffer);
- else if (TYPE_CODE (valtype) == TYPE_CODE_INT)
+static void
+alpha_value_to_register (struct frame_info *frame, int regnum,
+ struct type *valtype, const void *in)
+{
+ char out[MAX_REGISTER_SIZE];
+ switch (TYPE_LENGTH (valtype))
{
- ULONGEST l = unpack_long (valtype, virtual_buffer);
- l = ((l & 0xc0000000) << 32) | ((l & 0x3fffffff) << 29);
- store_unsigned_integer (raw_buffer, ALPHA_REGISTER_SIZE, l);
+ case 4:
+ alpha_lds (out, in);
+ break;
+ case 8:
+ memcpy (out, in, 8);
+ break;
+ default:
+ error ("Cannot store value in floating point register");
}
- else
- error ("Cannot store value in floating point register");
+ put_frame_register (frame, regnum, out);
}
\f
};
struct alpha_arg *alpha_args
= (struct alpha_arg *) alloca (nargs * sizeof (struct alpha_arg));
- register struct alpha_arg *m_arg;
+ struct alpha_arg *m_arg;
char arg_reg_buffer[ALPHA_REGISTER_SIZE * ALPHA_NUM_ARG_REGS];
int required_arg_regs;
{
case 4:
regcache_cooked_read (regcache, ALPHA_FP0_REGNUM, raw_buffer);
- alpha_convert_dbl_flt (valbuf, raw_buffer);
+ alpha_sts (valbuf, raw_buffer);
break;
case 8:
switch (length)
{
case 4:
- alpha_convert_flt_dbl (raw_buffer, valbuf);
+ alpha_lds (raw_buffer, valbuf);
regcache_cooked_write (regcache, ALPHA_FP0_REGNUM, raw_buffer);
break;
}
}
-static int
-alpha_use_struct_convention (int gcc_p, struct type *type)
-{
- /* Structures are returned by ref in extra arg0. */
- return 1;
-}
-
\f
static const unsigned char *
alpha_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr)
return info;
}
-/* Return the address of REGNO in a sigtramp frame. Since this is all
- arithmetic, it doesn't seem worthwhile to cache it. */
-
-#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
+/* Return the address of REGNUM in a sigtramp frame. Since this is
+ all arithmetic, it doesn't seem worthwhile to cache it. */
static CORE_ADDR
-alpha_sigtramp_register_address (CORE_ADDR sigcontext_addr, unsigned int regno)
+alpha_sigtramp_register_address (CORE_ADDR sigcontext_addr, int regnum)
{
- if (regno < 32)
- return sigcontext_addr + SIGFRAME_REGSAVE_OFF + regno * 8;
- if (regno >= ALPHA_FP0_REGNUM && regno < ALPHA_FP0_REGNUM + 32)
- return sigcontext_addr + SIGFRAME_FPREGSAVE_OFF + regno * 8;
- if (regno == ALPHA_PC_REGNUM)
- return sigcontext_addr + SIGFRAME_PC_OFF;
+ struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+
+ if (regnum >= 0 && regnum < 32)
+ return sigcontext_addr + tdep->sc_regs_offset + regnum * 8;
+ else if (regnum >= ALPHA_FP0_REGNUM && regnum < ALPHA_FP0_REGNUM + 32)
+ return sigcontext_addr + tdep->sc_fpregs_offset + regnum * 8;
+ else if (regnum == ALPHA_PC_REGNUM)
+ return sigcontext_addr + tdep->sc_pc_offset;
return 0;
}
/* The stack address is trivially read from the sigcontext. */
stack_addr = alpha_sigtramp_register_address (info->sigcontext_addr,
ALPHA_SP_REGNUM);
- stack_addr = read_memory_unsigned_integer (stack_addr, ALPHA_REGISTER_SIZE);
+ stack_addr = get_frame_memory_unsigned (next_frame, stack_addr,
+ ALPHA_REGISTER_SIZE);
*this_id = frame_id_build (stack_addr, code_addr);
}
*addrp = addr;
*realnump = -1;
if (bufferp != NULL)
- read_memory (addr, bufferp, ALPHA_REGISTER_SIZE);
+ get_frame_memory (next_frame, addr, bufferp, ALPHA_REGISTER_SIZE);
return;
}
}
};
static const struct frame_unwind *
-alpha_sigtramp_frame_p (CORE_ADDR pc)
+alpha_sigtramp_frame_sniffer (struct frame_info *next_frame)
{
+ CORE_ADDR pc = frame_pc_unwind (next_frame);
char *name;
/* We shouldn't even bother to try if the OSABI didn't register
struct alpha_heuristic_unwind_cache *info
= alpha_heuristic_frame_unwind_cache (next_frame, this_prologue_cache, 0);
- /* This is meant to halt the backtrace at "_start". Make sure we
- don't halt it at a generic dummy frame. */
- if (inside_entry_file (info->start_pc))
- return;
-
*this_id = frame_id_build (info->vfp, info->start_pc);
}
*addrp = info->saved_regs[regnum];
*realnump = -1;
if (bufferp != NULL)
- read_memory (*addrp, bufferp, ALPHA_REGISTER_SIZE);
+ get_frame_memory (next_frame, *addrp, bufferp, ALPHA_REGISTER_SIZE);
return;
}
};
static const struct frame_unwind *
-alpha_heuristic_frame_p (CORE_ADDR pc)
+alpha_heuristic_frame_sniffer (struct frame_info *next_frame)
{
return &alpha_heuristic_frame_unwind;
}
int offset;
LONGEST rav;
- insn = read_memory_unsigned_integer (pc, sizeof (insn));
+ insn = alpha_read_insn (pc);
/* Opcode is top 6 bits. */
op = (insn >> 26) & 0x3f;
tdep->dynamic_sigtramp_offset = NULL;
tdep->sigcontext_addr = NULL;
+ tdep->sc_pc_offset = 2 * 8;
+ tdep->sc_regs_offset = 4 * 8;
+ tdep->sc_fpregs_offset = tdep->sc_regs_offset + 32 * 8 + 8;
tdep->jb_pc = -1; /* longjmp support not enabled by default */
set_gdbarch_fp0_regnum (gdbarch, ALPHA_FP0_REGNUM);
set_gdbarch_register_name (gdbarch, alpha_register_name);
- set_gdbarch_register_byte (gdbarch, alpha_register_byte);
- set_gdbarch_register_raw_size (gdbarch, alpha_register_raw_size);
- set_gdbarch_register_virtual_size (gdbarch, alpha_register_virtual_size);
- set_gdbarch_register_virtual_type (gdbarch, alpha_register_virtual_type);
+ set_gdbarch_deprecated_register_byte (gdbarch, alpha_register_byte);
+ set_gdbarch_deprecated_register_raw_size (gdbarch, alpha_register_raw_size);
+ set_gdbarch_deprecated_register_virtual_size (gdbarch, alpha_register_virtual_size);
+ set_gdbarch_register_type (gdbarch, alpha_register_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_convert_register_p (gdbarch, alpha_convert_register_p);
+ set_gdbarch_register_to_value (gdbarch, alpha_register_to_value);
+ set_gdbarch_value_to_register (gdbarch, alpha_value_to_register);
set_gdbarch_register_reggroup_p (gdbarch, alpha_register_reggroup_p);
set_gdbarch_print_insn (gdbarch, print_insn_alpha);
/* Call info. */
- set_gdbarch_frame_num_args (gdbarch, frame_num_args_unknown);
set_gdbarch_frameless_function_invocation (gdbarch,
generic_frameless_function_invocation_not);
- set_gdbarch_use_struct_convention (gdbarch, alpha_use_struct_convention);
+ set_gdbarch_use_struct_convention (gdbarch, always_use_struct_convention);
set_gdbarch_extract_return_value (gdbarch, alpha_extract_return_value);
set_gdbarch_store_return_value (gdbarch, alpha_store_return_value);
set_gdbarch_extract_struct_value_address (gdbarch,
/* Methods for saving / extracting a dummy frame's ID. */
set_gdbarch_unwind_dummy_id (gdbarch, alpha_unwind_dummy_id);
- set_gdbarch_save_dummy_frame_tos (gdbarch, generic_save_dummy_frame_tos);
/* Return the unwound PC value. */
set_gdbarch_unwind_pc (gdbarch, alpha_unwind_pc);
if (tdep->jb_pc >= 0)
set_gdbarch_get_longjmp_target (gdbarch, alpha_get_longjmp_target);
- frame_unwind_append_predicate (gdbarch, alpha_sigtramp_frame_p);
- frame_unwind_append_predicate (gdbarch, alpha_heuristic_frame_p);
+ frame_unwind_append_sniffer (gdbarch, alpha_sigtramp_frame_sniffer);
+ frame_unwind_append_sniffer (gdbarch, alpha_heuristic_frame_sniffer);
frame_base_set_default (gdbarch, &alpha_heuristic_frame_base);
return gdbarch;
}
+void
+alpha_dwarf2_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+ frame_unwind_append_sniffer (gdbarch, dwarf2_frame_sniffer);
+ frame_base_append_sniffer (gdbarch, dwarf2_frame_base_sniffer);
+}
+
+extern initialize_file_ftype _initialize_alpha_tdep; /* -Wmissing-prototypes */
+
void
_initialize_alpha_tdep (void)
{