#define CANNOT_STORE_REGISTER(regno) 0
#endif
-static void write_register_gen PARAMS ((int, char *));
+void write_register_gen PARAMS ((int, char *));
-static int read_relative_register_raw_bytes_for_frame PARAMS ((int regnum, char *myaddr, struct frame_info * frame));
+static int
+read_relative_register_raw_bytes_for_frame PARAMS ((int regnum,
+ char *myaddr,
+ struct frame_info *frame));
/* Basic byte-swapping routines. GDB has needed these for a long time...
All extract a target-format integer at ADDR which is LEN bytes long. */
you lose
#endif
- LONGEST
-extract_signed_integer (addr, len)
- PTR addr;
- int len;
+LONGEST
+extract_signed_integer (void *addr, int len)
{
LONGEST retval;
unsigned char *p;
}
ULONGEST
-extract_unsigned_integer (addr, len)
- PTR addr;
- int len;
+extract_unsigned_integer (void *addr, int len)
{
ULONGEST retval;
unsigned char *p;
function returns 1 and sets *PVAL. Otherwise it returns 0. */
int
-extract_long_unsigned_integer (addr, orig_len, pval)
- PTR addr;
- int orig_len;
- LONGEST *pval;
+extract_long_unsigned_integer (void *addr, int orig_len, LONGEST *pval)
{
char *p, *first_addr;
int len;
return 0;
}
+
+/* Treat the LEN bytes at ADDR as a target-format address, and return
+ that address. ADDR is a buffer in the GDB process, not in the
+ inferior.
+
+ This function should only be used by target-specific code. It
+ assumes that a pointer has the same representation as that thing's
+ address represented as an integer. Some machines use word
+ addresses, or similarly munged things, for certain types of
+ pointers, so that assumption doesn't hold everywhere.
+
+ Common code should use extract_typed_address instead, or something
+ else based on POINTER_TO_ADDRESS. */
+
CORE_ADDR
-extract_address (addr, len)
- PTR addr;
- int len;
+extract_address (void *addr, int len)
{
/* Assume a CORE_ADDR can fit in a LONGEST (for now). Not sure
whether we want this to be true eventually. */
return (CORE_ADDR) extract_unsigned_integer (addr, len);
}
+
+/* Treat the bytes at BUF as a pointer of type TYPE, and return the
+ address it represents. */
+CORE_ADDR
+extract_typed_address (void *buf, struct type *type)
+{
+ if (TYPE_CODE (type) != TYPE_CODE_PTR
+ && TYPE_CODE (type) != TYPE_CODE_REF)
+ internal_error ("findvar.c (extract_typed_address): "
+ "type is not a pointer or reference");
+
+ return POINTER_TO_ADDRESS (type, buf);
+}
+
+
void
-store_signed_integer (addr, len, val)
- PTR addr;
- int len;
- LONGEST val;
+store_signed_integer (void *addr, int len, LONGEST val)
{
unsigned char *p;
unsigned char *startaddr = (unsigned char *) addr;
}
void
-store_unsigned_integer (addr, len, val)
- PTR addr;
- int len;
- ULONGEST val;
+store_unsigned_integer (void *addr, int len, ULONGEST val)
{
unsigned char *p;
unsigned char *startaddr = (unsigned char *) addr;
}
}
-/* Store the literal address "val" into
- gdb-local memory pointed to by "addr"
- for "len" bytes. */
+/* Store the address VAL as a LEN-byte value in target byte order at
+ ADDR. ADDR is a buffer in the GDB process, not in the inferior.
+
+ This function should only be used by target-specific code. It
+ assumes that a pointer has the same representation as that thing's
+ address represented as an integer. Some machines use word
+ addresses, or similarly munged things, for certain types of
+ pointers, so that assumption doesn't hold everywhere.
+
+ Common code should use store_typed_address instead, or something else
+ based on ADDRESS_TO_POINTER. */
void
-store_address (addr, len, val)
- PTR addr;
- int len;
- LONGEST val;
+store_address (void *addr, int len, LONGEST val)
{
store_unsigned_integer (addr, len, val);
}
-\f
-/* Swap LEN bytes at BUFFER between target and host byte-order. */
-#define SWAP_FLOATING(buffer,len) \
- do \
- { \
- if (TARGET_BYTE_ORDER != HOST_BYTE_ORDER) \
- { \
- char tmp; \
- char *p = (char *)(buffer); \
- char *q = ((char *)(buffer)) + len - 1; \
- for (; p < q; p++, q--) \
- { \
- tmp = *q; \
- *q = *p; \
- *p = tmp; \
- } \
- } \
- } \
- while (0)
+
+/* Store the address ADDR as a pointer of type TYPE at BUF, in target
+ form. */
+void
+store_typed_address (void *buf, struct type *type, CORE_ADDR addr)
+{
+ if (TYPE_CODE (type) != TYPE_CODE_PTR
+ && TYPE_CODE (type) != TYPE_CODE_REF)
+ internal_error ("findvar.c (store_typed_address): "
+ "type is not a pointer or reference");
+
+ ADDRESS_TO_POINTER (type, buf, addr);
+}
+
+
+
+\f
/* Extract a floating-point number from a target-order byte-stream at ADDR.
Returns the value as type DOUBLEST.
dirty work. */
DOUBLEST
-extract_floating (addr, len)
- PTR addr;
- int len;
+extract_floating (void *addr, int len)
{
DOUBLEST dretval;
- if (len == sizeof (float))
+ if (len * TARGET_CHAR_BIT == TARGET_FLOAT_BIT)
{
if (HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT)
{
else
floatformat_to_doublest (TARGET_FLOAT_FORMAT, addr, &dretval);
}
- else if (len == sizeof (double))
+ else if (len * TARGET_CHAR_BIT == TARGET_DOUBLE_BIT)
{
if (HOST_DOUBLE_FORMAT == TARGET_DOUBLE_FORMAT)
{
else
floatformat_to_doublest (TARGET_DOUBLE_FORMAT, addr, &dretval);
}
- else if (len == sizeof (DOUBLEST))
+ else if (len * TARGET_CHAR_BIT == TARGET_LONG_DOUBLE_BIT)
{
if (HOST_LONG_DOUBLE_FORMAT == TARGET_LONG_DOUBLE_FORMAT)
{
}
void
-store_floating (addr, len, val)
- PTR addr;
- int len;
- DOUBLEST val;
+store_floating (void *addr, int len, DOUBLEST val)
{
- if (len == sizeof (float))
+ if (len * TARGET_CHAR_BIT == TARGET_FLOAT_BIT)
{
if (HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT)
{
else
floatformat_from_doublest (TARGET_FLOAT_FORMAT, &val, addr);
}
- else if (len == sizeof (double))
+ else if (len * TARGET_CHAR_BIT == TARGET_DOUBLE_BIT)
{
if (HOST_DOUBLE_FORMAT == TARGET_DOUBLE_FORMAT)
{
else
floatformat_from_doublest (TARGET_DOUBLE_FORMAT, &val, addr);
}
- else if (len == sizeof (DOUBLEST))
+ else if (len * TARGET_CHAR_BIT == TARGET_LONG_DOUBLE_BIT)
{
if (HOST_LONG_DOUBLE_FORMAT == TARGET_LONG_DOUBLE_FORMAT)
memcpy (addr, &val, sizeof (val));
if (raw_buffer != NULL)
{
/* Put it back in target format. */
- store_address (raw_buffer, REGISTER_RAW_SIZE (regnum), (LONGEST) addr);
+ store_address (raw_buffer, REGISTER_RAW_SIZE (regnum),
+ (LONGEST) addr);
}
if (addrp != NULL)
*addrp = 0;
memcpy (VALUE_CONTENTS_RAW (reg_val), raw_buffer,
REGISTER_RAW_SIZE (regnum));
else
- fatal ("Register \"%s\" (%d) has conflicting raw (%d) and virtual (%d) size",
- REGISTER_NAME (regnum), regnum,
- REGISTER_RAW_SIZE (regnum), REGISTER_VIRTUAL_SIZE (regnum));
+ internal_error ("Register \"%s\" (%d) has conflicting raw (%d) and virtual (%d) size",
+ REGISTER_NAME (regnum),
+ regnum,
+ REGISTER_RAW_SIZE (regnum),
+ REGISTER_VIRTUAL_SIZE (regnum));
VALUE_LVAL (reg_val) = lval;
VALUE_ADDRESS (reg_val) = addr;
VALUE_REGNO (reg_val) = regnum;
register_valid[i] = 1;
}
-/* read_register_bytes and write_register_bytes are generally a *BAD* idea.
- They are inefficient because they need to check for partial updates, which
- can only be done by scanning through all of the registers and seeing if the
- bytes that are being read/written fall inside of an invalid register. [The
- main reason this is necessary is that register sizes can vary, so a simple
- index won't suffice.] It is far better to call read_register_gen if you
- want to get at the raw register contents, as it only takes a regno as an
- argument, and therefore can't do a partial register update. It would also
- be good to have a write_register_gen for similar reasons.
-
- Prior to the recent fixes to check for partial updates, both read and
- write_register_bytes always checked to see if any registers were stale, and
- then called target_fetch_registers (-1) to update the whole set. This
- caused really slowed things down for remote targets. */
+/* read_register_bytes and write_register_bytes are generally a *BAD*
+ idea. They are inefficient because they need to check for partial
+ updates, which can only be done by scanning through all of the
+ registers and seeing if the bytes that are being read/written fall
+ inside of an invalid register. [The main reason this is necessary
+ is that register sizes can vary, so a simple index won't suffice.]
+ It is far better to call read_register_gen and write_register_gen
+ if you want to get at the raw register contents, as it only takes a
+ regno as an argument, and therefore can't do a partial register
+ update.
+
+ Prior to the recent fixes to check for partial updates, both read
+ and write_register_bytes always checked to see if any registers
+ were stale, and then called target_fetch_registers (-1) to update
+ the whole set. This caused really slowed things down for remote
+ targets. */
/* Copy INLEN bytes of consecutive data from registers
starting with the INREGBYTE'th byte of register data
for (regno = 0; regno < NUM_REGS; regno++)
{
int regstart, regend;
- int startin, endin;
if (register_valid[regno])
continue;
regstart = REGISTER_BYTE (regno);
regend = regstart + REGISTER_RAW_SIZE (regno);
- startin = regstart >= inregbyte && regstart < inregend;
- endin = regend > inregbyte && regend <= inregend;
-
- if (!startin && !endin)
+ if (regend <= inregbyte || inregend <= regstart)
+ /* The range the user wants to read doesn't overlap with regno. */
continue;
/* We've found an invalid register where at least one byte will be read.
Update it from the target. */
-
target_fetch_registers (regno);
if (!register_valid[regno])
/* Write register REGNO at MYADDR to the target. MYADDR points at
REGISTER_RAW_BYTES(REGNO), which must be in target byte-order. */
-static void
+void
write_register_gen (regno, myaddr)
int regno;
char *myaddr;
for (regno = 0; regno < NUM_REGS; regno++)
{
int regstart, regend;
- int startin, endin;
- char regbuf[MAX_REGISTER_RAW_SIZE];
regstart = REGISTER_BYTE (regno);
regend = regstart + REGISTER_RAW_SIZE (regno);
- startin = regstart >= myregstart && regstart < myregend;
- endin = regend > myregstart && regend <= myregend;
+ /* Is this register completely outside the range the user is writing? */
+ if (myregend <= regstart || regend <= myregstart)
+ /* do nothing */ ;
- if (!startin && !endin)
- continue; /* Register is completely out of range */
+ /* Is this register completely within the range the user is writing? */
+ else if (myregstart <= regstart && regend <= myregend)
+ write_register_gen (regno, myaddr + (regstart - myregstart));
- if (startin && endin) /* register is completely in range */
+ /* The register partially overlaps the range being written. */
+ else
{
- write_register_gen (regno, myaddr + (regstart - myregstart));
- continue;
- }
+ char regbuf[MAX_REGISTER_RAW_SIZE];
+ /* What's the overlap between this register's bytes and
+ those the caller wants to write? */
+ int overlapstart = max (regstart, myregstart);
+ int overlapend = min (regend, myregend);
+
+ /* We may be doing a partial update of an invalid register.
+ Update it from the target before scribbling on it. */
+ read_register_gen (regno, regbuf);
- /* We may be doing a partial update of an invalid register. Update it
- from the target before scribbling on it. */
- read_register_gen (regno, regbuf);
-
- if (startin)
- memcpy (registers + regstart,
- myaddr + regstart - myregstart,
- myregend - regstart);
- else /* endin */
- memcpy (registers + myregstart,
- myaddr,
- regend - myregstart);
- target_store_registers (regno);
+ memcpy (registers + overlapstart,
+ myaddr + (overlapstart - myregstart),
+ overlapend - overlapstart);
+
+ target_store_registers (regno);
+ }
}
}
+
/* Return the raw contents of register REGNO, regarding it as an integer. */
/* This probably should be returning LONGEST rather than CORE_ADDR. */
if (!register_valid[regno])
target_fetch_registers (regno);
- return (CORE_ADDR) extract_address (®isters[REGISTER_BYTE (regno)],
- REGISTER_RAW_SIZE (regno));
+ return ((CORE_ADDR)
+ extract_unsigned_integer (®isters[REGISTER_BYTE (regno)],
+ REGISTER_RAW_SIZE (regno)));
}
CORE_ADDR
#endif
CORE_ADDR
-generic_target_read_pc (pid)
+generic_target_read_pc (int pid)
{
#ifdef PC_REGNUM
if (PC_REGNUM >= 0)
return pc_val;
}
#endif
- fatal ("generic_target_read_pc");
+ internal_error ("generic_target_read_pc");
return 0;
}
#ifdef PC_REGNUM
if (PC_REGNUM >= 0)
write_register_pid (PC_REGNUM, pc, pid);
-#ifdef NPC_REGNUM
if (NPC_REGNUM >= 0)
write_register_pid (NPC_REGNUM, pc + 4, pid);
-#ifdef NNPC_REGNUM
if (NNPC_REGNUM >= 0)
write_register_pid (NNPC_REGNUM, pc + 8, pid);
-#endif
-#endif
#else
- fatal ("generic_target_write_pc");
+ internal_error ("generic_target_write_pc");
#endif
}
if (SP_REGNUM >= 0)
return read_register (SP_REGNUM);
#endif
- fatal ("generic_target_read_sp");
+ internal_error ("generic_target_read_sp");
}
CORE_ADDR
return;
}
#endif
- fatal ("generic_target_write_sp");
+ internal_error ("generic_target_write_sp");
}
void
if (FP_REGNUM >= 0)
return read_register (FP_REGNUM);
#endif
- fatal ("generic_target_read_fp");
+ internal_error ("generic_target_read_fp");
}
CORE_ADDR
return;
}
#endif
- fatal ("generic_target_write_fp");
+ internal_error ("generic_target_write_fp");
}
void
{
TARGET_WRITE_FP (val);
}
+
+
+/* Given a pointer of type TYPE in target form in BUF, return the
+ address it represents. */
+CORE_ADDR
+generic_pointer_to_address (struct type *type, char *buf)
+{
+ return extract_address (buf, TYPE_LENGTH (type));
+}
+
+
+/* Given an address, store it as a pointer of type TYPE in target
+ format in BUF. */
+void
+generic_address_to_pointer (struct type *type, char *buf, CORE_ADDR addr)
+{
+ store_address (buf, TYPE_LENGTH (type), addr);
+}
+
\f
/* Will calling read_var_value or locate_var_value on SYM end
up caring what frame it is being evaluated relative to? SYM must
case LOC_LABEL:
/* Put the constant back in target format. */
if (overlay_debugging)
- store_address (VALUE_CONTENTS_RAW (v), len,
- (LONGEST) symbol_overlayed_address (SYMBOL_VALUE_ADDRESS (var),
- SYMBOL_BFD_SECTION (var)));
+ {
+ CORE_ADDR addr
+ = symbol_overlayed_address (SYMBOL_VALUE_ADDRESS (var),
+ SYMBOL_BFD_SECTION (var));
+ store_typed_address (VALUE_CONTENTS_RAW (v), type, addr);
+ }
else
- store_address (VALUE_CONTENTS_RAW (v), len,
- (LONGEST) SYMBOL_VALUE_ADDRESS (var));
+ store_typed_address (VALUE_CONTENTS_RAW (v), type,
+ SYMBOL_VALUE_ADDRESS (var));
VALUE_LVAL (v) = not_lval;
return v;
CHECK_TYPEDEF (type);
len = TYPE_LENGTH (type);
+ /* Pointers on D10V are really only 16 bits, but we lie to gdb elsewhere... */
+ if (GDB_TARGET_IS_D10V && TYPE_CODE (type) == TYPE_CODE_PTR)
+ len = 2;
+
VALUE_REGNO (v) = regnum;
num_storage_locs = (len > REGISTER_VIRTUAL_SIZE (regnum) ?
VALUE_ADDRESS (v) = first_addr;
}
else
- fatal ("value_from_register: Value not stored anywhere!");
+ internal_error ("value_from_register: Value not stored anywhere!");
VALUE_OPTIMIZED_OUT (v) = optim;
memcpy (VALUE_CONTENTS_RAW (v), raw_buffer + VALUE_OFFSET (v), len);
}
+ if (GDB_TARGET_IS_D10V
+ && TYPE_CODE (type) == TYPE_CODE_PTR
+ && TYPE_TARGET_TYPE (type)
+ && (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_FUNC))
+ {
+ /* pointer to function */
+ unsigned long num;
+ unsigned short snum;
+ snum = (unsigned short) extract_unsigned_integer (VALUE_CONTENTS_RAW (v), 2);
+ num = D10V_MAKE_IADDR (snum);
+ store_address (VALUE_CONTENTS_RAW (v), 4, num);
+ }
+ else if (GDB_TARGET_IS_D10V
+ && TYPE_CODE (type) == TYPE_CODE_PTR)
+ {
+ /* pointer to data */
+ unsigned long num;
+ unsigned short snum;
+ snum = (unsigned short) extract_unsigned_integer (VALUE_CONTENTS_RAW (v), 2);
+ num = D10V_MAKE_DADDR (snum);
+ store_address (VALUE_CONTENTS_RAW (v), 4, num);
+ }
+
return v;
}
\f
value_ptr val;
addr = VALUE_ADDRESS (lazy_value);
- val = value_from_longest (lookup_pointer_type (type), (LONGEST) addr);
+ val = value_from_pointer (lookup_pointer_type (type), addr);
VALUE_BFD_SECTION (val) = VALUE_BFD_SECTION (lazy_value);
return val;
}