+CORE_ADDR
+address_from_register (int regnum, struct frame_info *frame)
+{
+ struct gdbarch *gdbarch = get_frame_arch (frame);
+ struct type *type = builtin_type (gdbarch)->builtin_data_ptr;
+ struct value *value;
+ CORE_ADDR result;
+ int regnum_max_excl = (gdbarch_num_regs (gdbarch)
+ + gdbarch_num_pseudo_regs (gdbarch));
+
+ if (regnum < 0 || regnum >= regnum_max_excl)
+ error (_("Invalid register #%d, expecting 0 <= # < %d"), regnum,
+ regnum_max_excl);
+
+ /* This routine may be called during early unwinding, at a time
+ where the ID of FRAME is not yet known. Calling value_from_register
+ would therefore abort in get_frame_id. However, since we only need
+ a temporary value that is never used as lvalue, we actually do not
+ really need to set its VALUE_FRAME_ID. Therefore, we re-implement
+ the core of value_from_register, but use the null_frame_id. */
+
+ /* Some targets require a special conversion routine even for plain
+ pointer types. Avoid constructing a value object in those cases. */
+ if (gdbarch_convert_register_p (gdbarch, regnum, type))
+ {
+ gdb_byte *buf = (gdb_byte *) alloca (TYPE_LENGTH (type));
+ int optim, unavail, ok;
+
+ ok = gdbarch_register_to_value (gdbarch, frame, regnum, type,
+ buf, &optim, &unavail);
+ if (!ok)
+ {
+ /* This function is used while computing a location expression.
+ Complain about the value being optimized out, rather than
+ letting value_as_address complain about some random register
+ the expression depends on not being saved. */
+ error_value_optimized_out ();
+ }