+2000-06-06 James E. Wilson <wilson@cygnus.com>
+
+ * frame.h (struct unwind_info_ptr): Collapse version, flags, and length
+ fields into header field.
+ (IA64_UNW_HDR_LENGTH, IA64_UNW_HDR_FLAGS, IA64_UNW_HDR_VERSION): New
+ macros to access length, flags, and version info from header field.
+ * config/ia64/crtbegin.asm (__do_frame_setup_aux): Delete here.
+ * config/ia64/crtend.asm (__do_frame_setup_aux): Add here.
+ (__do_global_ctors_aux): Fix caller.
+ * config/ia64/frame-ia64.c (get_unwind_record): Change parameter
+ prologue_flag to header. Pass to read_P_record.
+ (read_P_record): New argument header. Implement P4 format.
+ Multiply P7_T_SIZE by 16.
+ (execute_one_ia64_descriptor): New static local region_header. Pass to
+ get_unwind_record. Copy r to region_header if r is a header record.
+ (print_all_records): Likewise.
+ (__build_ia64_frame_state): Use IA64_UNW_HDR_LENGTH.
+ (__get_personality, __get_except_table): Likewise.
+ * config/ia64/ia64.c (process_set): Do not divide offsets by 4.
+
2000-06-06 Philipp Thomas <pthomas@suse.de>
* configure.in (AC_C_INLINE): Added.
.section .init,"ax","progbits"
{ .mlx
- // __do_frame_setup_aux is in crtbegin.asm
movl r2 = @gprel(__do_frame_setup_aux#)
;;
}
;;
mov b6 = r2
}
- { .mib
- // __do_frame_setup_aux needs the address of __EH_FRAME_END__,
- // so we pass it in r16. This is rather evil, but we have no
- // output registers.
- addl r16 = @ltoff(__EH_FRAME_END__#), gp
+ { .bbb
br.call.sptk.many b0 = b6
;;
}
+.text
+ .align 16
+ .proc __do_frame_setup_aux#
+__do_frame_setup_aux:
+ /*
+ if (__register_frame_info_aux)
+ __register_frame_info_aux(__EH_FRAME_END__)
+ */
+ alloc loc0 = ar.pfs, 0, 3, 1, 0
+ addl r14 = @ltoff(@fptr(__register_frame_info_aux#)), gp
+ mov loc1 = b0
+ ;;
+ ld8 r15 = [r14]
+ addl r16 = @ltoff(__EH_FRAME_END__#), gp
+ mov loc2 = gp
+ ;;
+ cmp.eq p6, p7 = 0, r15
+ (p6) br.cond.dptk 1f
+ ld8 r8 = [r15], 8
+ ld8 out0 = [r16]
+ ;;
+ ld8 gp = [r15]
+ mov b6 = r8
+ ;;
+ br.call.sptk.many b0 = b6
+ ;;
+1:
+ mov gp = loc2
+ mov ar.pfs = loc0
+ mov b0 = loc1
+ br.ret.sptk.many b0
+ .endp __do_frame_setup_aux#
+
+.weak __register_frame_info_aux#
static unsigned char *read_R_record (unwind_record *, unsigned char, unsigned char *);
static unsigned char *read_X_record (unwind_record *, unsigned char, unsigned char *);
static unsigned char *read_B_record (unwind_record *, unsigned char, unsigned char *);
-static unsigned char *read_P_record (unwind_record *, unsigned char, unsigned char *);
+static unsigned char *read_P_record (unwind_record *, unsigned char, unsigned char *, unwind_record *);
/* This routine will determine what type of record the memory pointer
is refering to, and fill in the appropriate fields for that record type.
- PROLOGUE_FLAG is TRUE if we are currently processing a PROLOGUE
- body.
+ HEADER is a pointer to the last region header unwind record.
DATA is a pointer to an unwind record which will be filled in.
PTR is a pointer to the current location in the unwind table where we
will read the next record from.
The return value is the start of the next record. */
extern unsigned char *
-get_unwind_record (prologue_flag, data, ptr)
- int prologue_flag;
- unwind_record *data;
- unsigned char *ptr;
+get_unwind_record (header, data, ptr)
+ unwind_record *header;
+ unwind_record *data;
+ unsigned char *ptr;
{
unsigned char val = *ptr++;
if (val == UNW_X1 || val == UNW_X2 || val == UNW_X3 || val == UNW_X4)
return read_X_record (data, val, ptr);
- if (prologue_flag)
- return read_P_record (data, val, ptr);
+ if (header->type != body)
+ return read_P_record (data, val, ptr, header);
else
return read_B_record (data, val, ptr);
}
static unsigned char *
-read_P_record (data, val, ptr)
+read_P_record (data, val, ptr, header)
unwind_record *data;
unsigned char val;
unsigned char *ptr;
+ unwind_record *header;
{
if ((val & 0xe0) == 0x80)
{
if (val == UNW_P4)
{
- /* P4 format. Currently unimplemented. */
- int len = 0; /* TODO.. get prologue rlen. */
- int size = (len * 2 + 7) / 8;
+ /* P4 format. */
+ int size = (header->record.r.rlen * 2 + 7) / 8;
data->type = spill_mask;
data->record.p.imask = (unsigned char *) malloc (size);
- /* memcpy (data->record.p.imask, ptr, size); */
+ memcpy (data->record.p.imask, ptr, size);
return ptr+size;
}
{
case P7_T_SIZE:
data->record.p.t = read_uleb128 (&ptr);
- data->record.p.size = read_uleb128 (&ptr);
+ data->record.p.size = read_uleb128 (&ptr) << 4;
break;
case P7_T:
data->record.p.t = read_uleb128 (&ptr);
long *len;
{
unwind_record r;
+ /* The last region_header. Needed to distinguish between prologue and body
+ descriptors. Also needed for length of P4 format. */
+ static unwind_record region_header;
ia64_reg_loc *loc_ptr = NULL;
int grmask = 0, frmask = 0;
*len = -1;
- addr = get_unwind_record (1, &r, addr);
+ addr = get_unwind_record (®ion_header, &r, addr);
/* process it in 2 phases, the first phase will either do the work,
or set up a pointer to the records we care about
case prologue:
case body:
*len = r.record.r.rlen;
+ memcpy (®ion_header, &r, sizeof (unwind_record));
break;
case prologue_gr:
{
frame->pr.loc_type = IA64_UNW_LOC_TYPE_GR;
frame->pr.l.regno = reg++;
}
+ memcpy (®ion_header, &r, sizeof (unwind_record));
break;
}
case mem_stack_f:
start_pc = pc_base + entry->start_offset;
unw_info_ptr = ((struct unwind_info_ptr *)(pc_base + entry->unwind_offset));
addr = unw_info_ptr->unwind_descriptors;
- end = addr + unw_info_ptr->length * 8;
+ end = addr + IA64_UNW_HDR_LENGTH (unw_info_ptr->header) * 8;
pc_offset = (pc - start_pc) / 16 * 3;
init_ia64_unwind_frame (frame);
unwind_info_ptr *ptr;
{
void **p;
- p = (void **) (ptr->unwind_descriptors + ptr->length * 8);
+ p = (void **) (ptr->unwind_descriptors
+ + IA64_UNW_HDR_LENGTH (ptr->header) * 8);
return *p;
}
unwind_info_ptr *ptr;
{
void **p, *table;
- p = (void **) (ptr->unwind_descriptors + ptr->length * 8);
+ p = (void **) (ptr->unwind_descriptors
+ + IA64_UNW_HDR_LENGTH (ptr->header) * 8);
/* If there is no personality, there is no handler data. */
if (*p == 0)
return 0;
- table = (void *) (ptr->unwind_descriptors + ptr->length * 8 + 8);
+ table = (void *) (ptr->unwind_descriptors
+ + IA64_UNW_HDR_LENGTH (ptr->header) * 8 + 8);
return table;
}
{
unsigned char *end = mem + size;
unwind_record r;
+ static unwind_record region_header;
fprintf (f, "UNWIND IMAGE:\n");
while (mem < end)
{
- mem = get_unwind_record (1, &r, mem);
+ mem = get_unwind_record (®ion_header, &r, mem);
print_record (f, &r);
+ switch (r.type)
+ {
+ case prologue:
+ case body:
+ case prologue_gr:
+ memcpy (region_header, r, sizeof (unwind_record));
+ break;
+ default:
+ break;
+ }
}
fprintf (f, "--end unwind image--\n\n");
}