- int local_regnum;
- int mem_stor = 0, reg_stor = 0;
- int mem_tracking = 1;
- CORE_ADDR last_addr = 0;
- CORE_ADDR first_addr = 0;
- int first_realnum = regnum;
- int len = TYPE_LENGTH (type);
- int value_bytes_copied;
- int optimized = 0;
- char *value_bytes = (char *) alloca (len + MAX_REGISTER_SIZE);
-
- /* Copy all of the data out, whereever it may be. */
- for (local_regnum = regnum, value_bytes_copied = 0;
- value_bytes_copied < len;
- (value_bytes_copied += register_size (current_gdbarch, local_regnum),
- ++local_regnum))
- {
- int realnum;
- int optim;
- enum lval_type lval;
- CORE_ADDR addr;
- frame_register (frame, local_regnum, &optim, &lval, &addr,
- &realnum, value_bytes + value_bytes_copied);
- optimized += optim;
- if (register_cached (local_regnum) == -1)
- return NULL; /* register value not available */
-
- if (regnum == local_regnum)
- {
- first_addr = addr;
- first_realnum = realnum;
- }
- if (lval == lval_register)
- reg_stor++;
- else
- {
- mem_stor++;
-
- mem_tracking = (mem_tracking
- && (regnum == local_regnum
- || addr == last_addr));
- }
- last_addr = addr;
- }
-
- /* FIXME: cagney/2003-06-04: Shouldn't this always use
- lval_reg_frame_relative? If it doesn't and the register's
- location changes (say after a resume) then this value is
- going to have wrong information. */
- if ((reg_stor && mem_stor)
- || (mem_stor && !mem_tracking))
- /* Mixed storage; all of the hassle we just went through was
- for some good purpose. */
- {
- VALUE_LVAL (v) = lval_reg_frame_relative;
- VALUE_FRAME_ID (v) = get_frame_id (frame);
- VALUE_FRAME_REGNUM (v) = regnum;
- }
- else if (mem_stor)
- {
- VALUE_LVAL (v) = lval_memory;
- VALUE_ADDRESS (v) = first_addr;
- }
- else if (reg_stor)
- {
- VALUE_LVAL (v) = lval_register;
- VALUE_ADDRESS (v) = first_addr;
- VALUE_REGNO (v) = first_realnum;
- }
- else
- internal_error (__FILE__, __LINE__,
- "value_from_register: Value not stored anywhere!");
-
- VALUE_OPTIMIZED_OUT (v) = optimized;
-
- /* Any structure stored in more than one register will always be
- an integral number of registers. Otherwise, you need to do
- some fiddling with the last register copied here for little
- endian machines. */
- if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
- && len < register_size (current_gdbarch, regnum))
- /* Big-endian, and we want less than full size. */
- VALUE_OFFSET (v) = register_size (current_gdbarch, regnum) - len;
- else
- VALUE_OFFSET (v) = 0;
- memcpy (VALUE_CONTENTS_RAW (v), value_bytes + VALUE_OFFSET (v), len);