+ ret = ia64_find_unwind_table (sec->objfile, ip, &di, &buf);
+ if (ret < 0)
+ return ret;
+
+ if (gdbarch_debug >= 1)
+ fprintf_unfiltered (gdb_stdlog, "ia64_find_proc_info_x: 0x%s -> "
+ "(name=`%s',segbase=0x%s,start=0x%s,end=0x%s,gp=0x%s,"
+ "length=%s,data=0x%s)\n",
+ paddr_nz (ip), (char *)di.u.rti.name_ptr,
+ paddr_nz (di.u.rti.segbase),
+ paddr_nz (di.start_ip), paddr_nz (di.end_ip),
+ paddr_nz (di.gp),
+ paddr_u (di.u.rti.table_len),
+ paddr_nz (di.u.rti.table_data));
+ }
+
+ ret = libunwind_search_unwind_table (&as, ip, &di, pi, need_unwind_info,
+ arg);
+
+ /* We no longer need the dyn info storage so free it. */
+ xfree (buf);
+
+ return ret;
+}
+
+/* Libunwind callback accessor function for cleanup. */
+static void
+ia64_put_unwind_info (unw_addr_space_t as,
+ unw_proc_info_t *pip, void *arg)
+{
+ /* Nothing required for now. */
+}
+
+/* Libunwind callback accessor function to get head of the dynamic
+ unwind-info registration list. */
+static int
+ia64_get_dyn_info_list (unw_addr_space_t as,
+ unw_word_t *dilap, void *arg)
+{
+ struct obj_section *text_sec;
+ struct objfile *objfile;
+ unw_word_t ip, addr;
+ unw_dyn_info_t di;
+ int ret;
+
+ if (!libunwind_is_initialized ())
+ return -UNW_ENOINFO;
+
+ for (objfile = object_files; objfile; objfile = objfile->next)
+ {
+ void *buf = NULL;
+
+ text_sec = objfile->sections + SECT_OFF_TEXT (objfile);
+ ip = text_sec->addr;
+ ret = ia64_find_unwind_table (objfile, ip, &di, &buf);
+ if (ret >= 0)
+ {
+ addr = libunwind_find_dyn_list (as, &di, arg);
+ /* We no longer need the dyn info storage so free it. */
+ xfree (buf);
+
+ if (addr)
+ {
+ if (gdbarch_debug >= 1)
+ fprintf_unfiltered (gdb_stdlog,
+ "dynamic unwind table in objfile %s "
+ "at 0x%s (gp=0x%s)\n",
+ bfd_get_filename (objfile->obfd),
+ paddr_nz (addr), paddr_nz (di.gp));
+ *dilap = addr;
+ return 0;
+ }
+ }
+ }
+ return -UNW_ENOINFO;
+}
+
+
+/* Frame interface functions for libunwind. */
+
+static void
+ia64_libunwind_frame_this_id (struct frame_info *next_frame, void **this_cache,
+ struct frame_id *this_id)
+{
+ char buf[8];
+ CORE_ADDR bsp;
+ struct frame_id id;
+
+ libunwind_frame_this_id (next_frame, this_cache, &id);
+
+ /* We must add the bsp as the special address for frame comparison purposes. */
+ frame_unwind_register (next_frame, IA64_BSP_REGNUM, buf);
+ bsp = extract_unsigned_integer (buf, 8);
+
+ (*this_id) = frame_id_build_special (id.stack_addr, id.code_addr, bsp);
+
+ if (gdbarch_debug >= 1)
+ fprintf_unfiltered (gdb_stdlog,
+ "libunwind frame id: code 0x%s, stack 0x%s, special 0x%s, next_frame %p\n",
+ paddr_nz (id.code_addr), paddr_nz (id.stack_addr),
+ paddr_nz (bsp), next_frame);
+}
+
+static void
+ia64_libunwind_frame_prev_register (struct frame_info *next_frame,
+ void **this_cache,
+ int regnum, int *optimizedp,
+ enum lval_type *lvalp, CORE_ADDR *addrp,
+ int *realnump, void *valuep)
+{
+ int reg = regnum;
+
+ if (VP0_REGNUM <= regnum && regnum <= VP63_REGNUM)
+ reg = IA64_PR_REGNUM;
+ else if (IA64_NAT0_REGNUM <= regnum && regnum <= IA64_NAT127_REGNUM)
+ reg = IA64_UNAT_REGNUM;
+
+ /* Let libunwind do most of the work. */
+ libunwind_frame_prev_register (next_frame, this_cache, reg,
+ optimizedp, lvalp, addrp, realnump, valuep);
+
+ /* No more to do if the value is not supposed to be supplied. */
+ if (!valuep)
+ return;
+
+ if (VP0_REGNUM <= regnum && regnum <= VP63_REGNUM)
+ {
+ ULONGEST prN_val;
+
+ if (VP16_REGNUM <= regnum && regnum <= VP63_REGNUM)
+ {
+ int rrb_pr = 0;
+ ULONGEST cfm;
+ unsigned char buf[MAX_REGISTER_SIZE];
+
+ /* Fetch predicate register rename base from current frame
+ marker for this frame. */
+ frame_unwind_register (next_frame, IA64_CFM_REGNUM, buf);
+ cfm = extract_unsigned_integer (buf, 8);
+ rrb_pr = (cfm >> 32) & 0x3f;
+
+ /* Adjust the register number to account for register rotation. */
+ regnum = VP16_REGNUM
+ + ((regnum - VP16_REGNUM) + rrb_pr) % 48;
+ }
+ prN_val = extract_bit_field ((unsigned char *) valuep,
+ regnum - VP0_REGNUM, 1);
+ store_unsigned_integer (valuep, register_size (current_gdbarch, regnum), prN_val);
+ }
+ else if (IA64_NAT0_REGNUM <= regnum && regnum <= IA64_NAT127_REGNUM)
+ {
+ ULONGEST unatN_val;
+
+ unatN_val = extract_bit_field ((unsigned char *) valuep,
+ regnum - IA64_NAT0_REGNUM, 1);
+ store_unsigned_integer (valuep, register_size (current_gdbarch, regnum),
+ unatN_val);
+ }
+ else if (regnum == IA64_BSP_REGNUM)
+ {
+ char cfm_valuep[MAX_REGISTER_SIZE];
+ int cfm_optim;
+ int cfm_realnum;
+ enum lval_type cfm_lval;
+ CORE_ADDR cfm_addr;
+ CORE_ADDR bsp, prev_cfm, prev_bsp;
+
+ /* We want to calculate the previous bsp as the end of the previous register stack frame.
+ This corresponds to what the hardware bsp register will be if we pop the frame
+ back which is why we might have been called. We know that libunwind will pass us back
+ the beginning of the current frame so we should just add sof to it. */
+ prev_bsp = extract_unsigned_integer (valuep, 8);
+ libunwind_frame_prev_register (next_frame, this_cache, IA64_CFM_REGNUM,
+ &cfm_optim, &cfm_lval, &cfm_addr, &cfm_realnum, cfm_valuep);
+ prev_cfm = extract_unsigned_integer (cfm_valuep, 8);
+ prev_bsp = rse_address_add (prev_bsp, (prev_cfm & 0x7f));
+
+ store_unsigned_integer (valuep, register_size (current_gdbarch, regnum),
+ prev_bsp);
+ }
+
+ if (gdbarch_debug >= 1)
+ fprintf_unfiltered (gdb_stdlog,
+ "libunwind prev register <%s> is 0x%s\n",
+ (((unsigned) regnum <= IA64_NAT127_REGNUM)
+ ? ia64_register_names[regnum] : "r??"),
+ paddr_nz (extract_unsigned_integer (valuep, 8)));
+}
+
+static const struct frame_unwind ia64_libunwind_frame_unwind =
+{
+ NORMAL_FRAME,
+ ia64_libunwind_frame_this_id,
+ ia64_libunwind_frame_prev_register
+};
+
+static const struct frame_unwind *
+ia64_libunwind_frame_sniffer (struct frame_info *next_frame)
+{
+ if (libunwind_is_initialized () && libunwind_frame_sniffer (next_frame))
+ return &ia64_libunwind_frame_unwind;
+
+ return NULL;
+}
+
+/* Set of libunwind callback acccessor functions. */
+static unw_accessors_t ia64_unw_accessors =
+{
+ ia64_find_proc_info_x,
+ ia64_put_unwind_info,
+ ia64_get_dyn_info_list,
+ ia64_access_mem,
+ ia64_access_reg,
+ ia64_access_fpreg,
+ /* resume */
+ /* get_proc_name */
+};
+
+/* Set of ia64 gdb libunwind-frame callbacks and data for generic libunwind-frame code to use. */
+static struct libunwind_descr ia64_libunwind_descr =
+{
+ ia64_gdb2uw_regnum,
+ ia64_uw2gdb_regnum,
+ ia64_is_fpreg,
+ &ia64_unw_accessors,
+};
+
+#endif /* HAVE_LIBUNWIND_IA64_H */
+
+/* Should we use DEPRECATED_EXTRACT_STRUCT_VALUE_ADDRESS instead of
+ EXTRACT_RETURN_VALUE? GCC_P is true if compiled with gcc and TYPE
+ is the type (which is known to be struct, union or array). */
+int
+ia64_use_struct_convention (int gcc_p, struct type *type)
+{
+ struct type *float_elt_type;
+
+ /* HFAs are structures (or arrays) consisting entirely of floating
+ point values of the same length. Up to 8 of these are returned
+ in registers. Don't use the struct convention when this is the
+ case. */
+ float_elt_type = is_float_or_hfa_type (type);
+ if (float_elt_type != NULL
+ && TYPE_LENGTH (type) / TYPE_LENGTH (float_elt_type) <= 8)
+ return 0;
+
+ /* Other structs of length 32 or less are returned in r8-r11.
+ Don't use the struct convention for those either. */
+ return TYPE_LENGTH (type) > 32;
+}
+
+void
+ia64_extract_return_value (struct type *type, struct regcache *regcache, void *valbuf)
+{
+ struct type *float_elt_type;
+
+ float_elt_type = is_float_or_hfa_type (type);
+ if (float_elt_type != NULL)
+ {
+ char from[MAX_REGISTER_SIZE];
+ int offset = 0;
+ int regnum = IA64_FR8_REGNUM;
+ int n = TYPE_LENGTH (type) / TYPE_LENGTH (float_elt_type);