Browse Source
* findvar.c (_initialize_findvar, build_findvar, write_fp, read_fp,
generic_target_write_fp, generic_target_read_fp, write_sp, read_sp,
generic_target_write_sp, generic_target_read_sp, write_pc, read_pc,
generic_target_write_pc, generic_target_read_pc, write_pc_pid,
read_pc_pid, supply_register, write_register_pid, write_register,
read_register_pid, read_register, write_register_bytes,
read_register_bytes, write_register_gen, read_register_gen,
registers_fetched, registers_changed, find_saved_register,
read_relative_register_raw_bytes, default_get_saved_register,
read_relative_register_raw_bytes_for_frame, get_saved_register):
Move from this file into new file regcache.c.
(register_valid, registers_pid, registers): Ditto.
* regcache.c: New file to hold the register cache.
(register_cached): New function to read register_valid array.
* value.h (register_cached): Declare.
* defs.h (default_get_saved_register): Delete decl of static function.
* Makefile.in: Add regcache module.
binutils-2_11-branch
6 changed files with 875 additions and 822 deletions
@ -0,0 +1,840 @@ |
|||
/* Cache and manage the values of registers for GDB, the GNU debugger.
|
|||
Copyright 1986, 87, 89, 91, 94, 95, 96, 1998, 2000 |
|||
Free Software Foundation, Inc. |
|||
|
|||
This file is part of GDB. |
|||
|
|||
This program is free software; you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation; either version 2 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
This program is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with this program; if not, write to the Free Software |
|||
Foundation, Inc., 59 Temple Place - Suite 330, |
|||
Boston, MA 02111-1307, USA. */ |
|||
|
|||
#include "defs.h" |
|||
#include "frame.h" |
|||
#include "inferior.h" |
|||
#include "target.h" |
|||
#include "gdbarch.h" |
|||
|
|||
/*
|
|||
* DATA STRUCTURE |
|||
* |
|||
* Here is the actual register cache. |
|||
*/ |
|||
|
|||
/* NOTE: this is a write-back cache. There is no "dirty" bit for
|
|||
recording if the register values have been changed (eg. by the |
|||
user). Therefore all registers must be written back to the |
|||
target when appropriate. */ |
|||
|
|||
/* REGISTERS contains the cached register values (in target byte order). */ |
|||
|
|||
char *registers; |
|||
|
|||
/* REGISTER_VALID is 0 if the register needs to be fetched,
|
|||
1 if it has been fetched, and |
|||
-1 if the register value was not available. |
|||
"Not available" means don't try to fetch it again. */ |
|||
|
|||
signed char *register_valid; |
|||
|
|||
/* The thread/process associated with the current set of registers.
|
|||
For now, -1 is special, and means `no current process'. */ |
|||
|
|||
static int registers_pid = -1; |
|||
|
|||
/*
|
|||
* FUNCTIONS: |
|||
*/ |
|||
|
|||
/* REGISTER_CACHED()
|
|||
|
|||
Returns 0 if the value is not in the cache (needs fetch). |
|||
>0 if the value is in the cache. |
|||
<0 if the value is permanently unavailable (don't ask again). */ |
|||
|
|||
int |
|||
register_cached (int regnum) |
|||
{ |
|||
return register_valid[regnum]; |
|||
} |
|||
|
|||
/* FIND_SAVED_REGISTER ()
|
|||
|
|||
Return the address in which frame FRAME's value of register REGNUM |
|||
has been saved in memory. Or return zero if it has not been saved. |
|||
If REGNUM specifies the SP, the value we return is actually |
|||
the SP value, not an address where it was saved. */ |
|||
|
|||
CORE_ADDR |
|||
find_saved_register (struct frame_info *frame, int regnum) |
|||
{ |
|||
register struct frame_info *frame1 = NULL; |
|||
register CORE_ADDR addr = 0; |
|||
|
|||
if (frame == NULL) /* No regs saved if want current frame */ |
|||
return 0; |
|||
|
|||
#ifdef HAVE_REGISTER_WINDOWS |
|||
/* We assume that a register in a register window will only be saved
|
|||
in one place (since the name changes and/or disappears as you go |
|||
towards inner frames), so we only call get_frame_saved_regs on |
|||
the current frame. This is directly in contradiction to the |
|||
usage below, which assumes that registers used in a frame must be |
|||
saved in a lower (more interior) frame. This change is a result |
|||
of working on a register window machine; get_frame_saved_regs |
|||
always returns the registers saved within a frame, within the |
|||
context (register namespace) of that frame. */ |
|||
|
|||
/* However, note that we don't want this to return anything if
|
|||
nothing is saved (if there's a frame inside of this one). Also, |
|||
callers to this routine asking for the stack pointer want the |
|||
stack pointer saved for *this* frame; this is returned from the |
|||
next frame. */ |
|||
|
|||
if (REGISTER_IN_WINDOW_P (regnum)) |
|||
{ |
|||
frame1 = get_next_frame (frame); |
|||
if (!frame1) |
|||
return 0; /* Registers of this frame are active. */ |
|||
|
|||
/* Get the SP from the next frame in; it will be this
|
|||
current frame. */ |
|||
if (regnum != SP_REGNUM) |
|||
frame1 = frame; |
|||
|
|||
FRAME_INIT_SAVED_REGS (frame1); |
|||
return frame1->saved_regs[regnum]; /* ... which might be zero */ |
|||
} |
|||
#endif /* HAVE_REGISTER_WINDOWS */ |
|||
|
|||
/* Note that this next routine assumes that registers used in
|
|||
frame x will be saved only in the frame that x calls and |
|||
frames interior to it. This is not true on the sparc, but the |
|||
above macro takes care of it, so we should be all right. */ |
|||
while (1) |
|||
{ |
|||
QUIT; |
|||
frame1 = get_prev_frame (frame1); |
|||
if (frame1 == 0 || frame1 == frame) |
|||
break; |
|||
FRAME_INIT_SAVED_REGS (frame1); |
|||
if (frame1->saved_regs[regnum]) |
|||
addr = frame1->saved_regs[regnum]; |
|||
} |
|||
|
|||
return addr; |
|||
} |
|||
|
|||
/* DEFAULT_GET_SAVED_REGISTER ()
|
|||
|
|||
Find register number REGNUM relative to FRAME and put its (raw, |
|||
target format) contents in *RAW_BUFFER. Set *OPTIMIZED if the |
|||
variable was optimized out (and thus can't be fetched). Set *LVAL |
|||
to lval_memory, lval_register, or not_lval, depending on whether |
|||
the value was fetched from memory, from a register, or in a strange |
|||
and non-modifiable way (e.g. a frame pointer which was calculated |
|||
rather than fetched). Set *ADDRP to the address, either in memory |
|||
on as a REGISTER_BYTE offset into the registers array. |
|||
|
|||
Note that this implementation never sets *LVAL to not_lval. But |
|||
it can be replaced by defining GET_SAVED_REGISTER and supplying |
|||
your own. |
|||
|
|||
The argument RAW_BUFFER must point to aligned memory. */ |
|||
|
|||
static void |
|||
default_get_saved_register (char *raw_buffer, |
|||
int *optimized, |
|||
CORE_ADDR *addrp, |
|||
struct frame_info *frame, |
|||
int regnum, |
|||
enum lval_type *lval) |
|||
{ |
|||
CORE_ADDR addr; |
|||
|
|||
if (!target_has_registers) |
|||
error ("No registers."); |
|||
|
|||
/* Normal systems don't optimize out things with register numbers. */ |
|||
if (optimized != NULL) |
|||
*optimized = 0; |
|||
addr = find_saved_register (frame, regnum); |
|||
if (addr != 0) |
|||
{ |
|||
if (lval != NULL) |
|||
*lval = lval_memory; |
|||
if (regnum == SP_REGNUM) |
|||
{ |
|||
if (raw_buffer != NULL) |
|||
{ |
|||
/* Put it back in target format. */ |
|||
store_address (raw_buffer, REGISTER_RAW_SIZE (regnum), |
|||
(LONGEST) addr); |
|||
} |
|||
if (addrp != NULL) |
|||
*addrp = 0; |
|||
return; |
|||
} |
|||
if (raw_buffer != NULL) |
|||
target_read_memory (addr, raw_buffer, REGISTER_RAW_SIZE (regnum)); |
|||
} |
|||
else |
|||
{ |
|||
if (lval != NULL) |
|||
*lval = lval_register; |
|||
addr = REGISTER_BYTE (regnum); |
|||
if (raw_buffer != NULL) |
|||
read_register_gen (regnum, raw_buffer); |
|||
} |
|||
if (addrp != NULL) |
|||
*addrp = addr; |
|||
} |
|||
|
|||
#if !defined (GET_SAVED_REGISTER) |
|||
#define GET_SAVED_REGISTER(raw_buffer, optimized, addrp, frame, regnum, lval) \ |
|||
default_get_saved_register(raw_buffer, optimized, addrp, frame, regnum, lval) |
|||
#endif |
|||
|
|||
void |
|||
get_saved_register (char *raw_buffer, |
|||
int *optimized, |
|||
CORE_ADDR *addrp, |
|||
struct frame_info *frame, |
|||
int regnum, |
|||
enum lval_type *lval) |
|||
{ |
|||
GET_SAVED_REGISTER (raw_buffer, optimized, addrp, frame, regnum, lval); |
|||
} |
|||
|
|||
/* READ_RELATIVE_REGISTER_RAW_BYTES_FOR_FRAME
|
|||
|
|||
Copy the bytes of register REGNUM, relative to the input stack frame, |
|||
into our memory at MYADDR, in target byte order. |
|||
The number of bytes copied is REGISTER_RAW_SIZE (REGNUM). |
|||
|
|||
Returns 1 if could not be read, 0 if could. */ |
|||
|
|||
/* FIXME: This function increases the confusion between FP_REGNUM
|
|||
and the virtual/pseudo-frame pointer. */ |
|||
|
|||
static int |
|||
read_relative_register_raw_bytes_for_frame (int regnum, |
|||
char *myaddr, |
|||
struct frame_info *frame) |
|||
{ |
|||
int optim; |
|||
if (regnum == FP_REGNUM && frame) |
|||
{ |
|||
/* Put it back in target format. */ |
|||
store_address (myaddr, REGISTER_RAW_SIZE (FP_REGNUM), |
|||
(LONGEST) FRAME_FP (frame)); |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
get_saved_register (myaddr, &optim, (CORE_ADDR *) NULL, frame, |
|||
regnum, (enum lval_type *) NULL); |
|||
|
|||
if (register_valid[regnum] < 0) |
|||
return 1; /* register value not available */ |
|||
|
|||
return optim; |
|||
} |
|||
|
|||
/* READ_RELATIVE_REGISTER_RAW_BYTES
|
|||
|
|||
Copy the bytes of register REGNUM, relative to the current stack |
|||
frame, into our memory at MYADDR, in target byte order. |
|||
The number of bytes copied is REGISTER_RAW_SIZE (REGNUM). |
|||
|
|||
Returns 1 if could not be read, 0 if could. */ |
|||
|
|||
int |
|||
read_relative_register_raw_bytes (int regnum, char *myaddr) |
|||
{ |
|||
return read_relative_register_raw_bytes_for_frame (regnum, myaddr, |
|||
selected_frame); |
|||
} |
|||
|
|||
|
|||
/* Low level examining and depositing of registers.
|
|||
|
|||
The caller is responsible for making sure that the inferior is |
|||
stopped before calling the fetching routines, or it will get |
|||
garbage. (a change from GDB version 3, in which the caller got the |
|||
value from the last stop). */ |
|||
|
|||
/* REGISTERS_CHANGED ()
|
|||
|
|||
Indicate that registers may have changed, so invalidate the cache. */ |
|||
|
|||
void |
|||
registers_changed (void) |
|||
{ |
|||
int i; |
|||
int numregs = ARCH_NUM_REGS; |
|||
|
|||
registers_pid = -1; |
|||
|
|||
/* Force cleanup of any alloca areas if using C alloca instead of
|
|||
a builtin alloca. This particular call is used to clean up |
|||
areas allocated by low level target code which may build up |
|||
during lengthy interactions between gdb and the target before |
|||
gdb gives control to the user (ie watchpoints). */ |
|||
alloca (0); |
|||
|
|||
for (i = 0; i < numregs; i++) |
|||
register_valid[i] = 0; |
|||
|
|||
if (registers_changed_hook) |
|||
registers_changed_hook (); |
|||
} |
|||
|
|||
/* REGISTERS_FETCHED ()
|
|||
|
|||
Indicate that all registers have been fetched, so mark them all valid. */ |
|||
|
|||
|
|||
void |
|||
registers_fetched (void) |
|||
{ |
|||
int i; |
|||
int numregs = ARCH_NUM_REGS; |
|||
|
|||
for (i = 0; i < numregs; i++) |
|||
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 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 |
|||
into memory at MYADDR. */ |
|||
|
|||
void |
|||
read_register_bytes (int inregbyte, char *myaddr, int inlen) |
|||
{ |
|||
int inregend = inregbyte + inlen; |
|||
int regno; |
|||
|
|||
if (registers_pid != inferior_pid) |
|||
{ |
|||
registers_changed (); |
|||
registers_pid = inferior_pid; |
|||
} |
|||
|
|||
/* See if we are trying to read bytes from out-of-date registers. If so,
|
|||
update just those registers. */ |
|||
|
|||
for (regno = 0; regno < NUM_REGS; regno++) |
|||
{ |
|||
int regstart, regend; |
|||
|
|||
if (register_valid[regno]) |
|||
continue; |
|||
|
|||
if (REGISTER_NAME (regno) == NULL || *REGISTER_NAME (regno) == '\0') |
|||
continue; |
|||
|
|||
regstart = REGISTER_BYTE (regno); |
|||
regend = regstart + REGISTER_RAW_SIZE (regno); |
|||
|
|||
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]) |
|||
error ("read_register_bytes: Couldn't update register %d.", regno); |
|||
} |
|||
|
|||
if (myaddr != NULL) |
|||
memcpy (myaddr, ®isters[inregbyte], inlen); |
|||
} |
|||
|
|||
/* Read register REGNO into memory at MYADDR, which must be large
|
|||
enough for REGISTER_RAW_BYTES (REGNO). Target byte-order. If the |
|||
register is known to be the size of a CORE_ADDR or smaller, |
|||
read_register can be used instead. */ |
|||
|
|||
void |
|||
read_register_gen (int regno, char *myaddr) |
|||
{ |
|||
if (registers_pid != inferior_pid) |
|||
{ |
|||
registers_changed (); |
|||
registers_pid = inferior_pid; |
|||
} |
|||
|
|||
if (!register_valid[regno]) |
|||
target_fetch_registers (regno); |
|||
memcpy (myaddr, ®isters[REGISTER_BYTE (regno)], |
|||
REGISTER_RAW_SIZE (regno)); |
|||
} |
|||
|
|||
/* Write register REGNO at MYADDR to the target. MYADDR points at
|
|||
REGISTER_RAW_BYTES(REGNO), which must be in target byte-order. */ |
|||
|
|||
/* Registers we shouldn't try to store. */ |
|||
#if !defined (CANNOT_STORE_REGISTER) |
|||
#define CANNOT_STORE_REGISTER(regno) 0 |
|||
#endif |
|||
|
|||
void |
|||
write_register_gen (int regno, char *myaddr) |
|||
{ |
|||
int size; |
|||
|
|||
/* On the sparc, writing %g0 is a no-op, so we don't even want to
|
|||
change the registers array if something writes to this register. */ |
|||
if (CANNOT_STORE_REGISTER (regno)) |
|||
return; |
|||
|
|||
if (registers_pid != inferior_pid) |
|||
{ |
|||
registers_changed (); |
|||
registers_pid = inferior_pid; |
|||
} |
|||
|
|||
size = REGISTER_RAW_SIZE (regno); |
|||
|
|||
/* If we have a valid copy of the register, and new value == old value,
|
|||
then don't bother doing the actual store. */ |
|||
|
|||
if (register_valid[regno] |
|||
&& memcmp (®isters[REGISTER_BYTE (regno)], myaddr, size) == 0) |
|||
return; |
|||
|
|||
target_prepare_to_store (); |
|||
|
|||
memcpy (®isters[REGISTER_BYTE (regno)], myaddr, size); |
|||
|
|||
register_valid[regno] = 1; |
|||
|
|||
target_store_registers (regno); |
|||
} |
|||
|
|||
/* Copy INLEN bytes of consecutive data from memory at MYADDR
|
|||
into registers starting with the MYREGSTART'th byte of register data. */ |
|||
|
|||
void |
|||
write_register_bytes (int myregstart, char *myaddr, int inlen) |
|||
{ |
|||
int myregend = myregstart + inlen; |
|||
int regno; |
|||
|
|||
target_prepare_to_store (); |
|||
|
|||
/* Scan through the registers updating any that are covered by the
|
|||
range myregstart<=>myregend using write_register_gen, which does |
|||
nice things like handling threads, and avoiding updates when the |
|||
new and old contents are the same. */ |
|||
|
|||
for (regno = 0; regno < NUM_REGS; regno++) |
|||
{ |
|||
int regstart, regend; |
|||
|
|||
regstart = REGISTER_BYTE (regno); |
|||
regend = regstart + REGISTER_RAW_SIZE (regno); |
|||
|
|||
/* Is this register completely outside the range the user is writing? */ |
|||
if (myregend <= regstart || regend <= myregstart) |
|||
/* do nothing */ ; |
|||
|
|||
/* Is this register completely within the range the user is writing? */ |
|||
else if (myregstart <= regstart && regend <= myregend) |
|||
write_register_gen (regno, myaddr + (regstart - myregstart)); |
|||
|
|||
/* The register partially overlaps the range being written. */ |
|||
else |
|||
{ |
|||
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); |
|||
|
|||
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. */ |
|||
|
|||
CORE_ADDR |
|||
read_register (int regno) |
|||
{ |
|||
if (registers_pid != inferior_pid) |
|||
{ |
|||
registers_changed (); |
|||
registers_pid = inferior_pid; |
|||
} |
|||
|
|||
if (!register_valid[regno]) |
|||
target_fetch_registers (regno); |
|||
|
|||
return ((CORE_ADDR) |
|||
extract_unsigned_integer (®isters[REGISTER_BYTE (regno)], |
|||
REGISTER_RAW_SIZE (regno))); |
|||
} |
|||
|
|||
CORE_ADDR |
|||
read_register_pid (int regno, int pid) |
|||
{ |
|||
int save_pid; |
|||
CORE_ADDR retval; |
|||
|
|||
if (pid == inferior_pid) |
|||
return read_register (regno); |
|||
|
|||
save_pid = inferior_pid; |
|||
|
|||
inferior_pid = pid; |
|||
|
|||
retval = read_register (regno); |
|||
|
|||
inferior_pid = save_pid; |
|||
|
|||
return retval; |
|||
} |
|||
|
|||
/* Store VALUE, into the raw contents of register number REGNO. */ |
|||
|
|||
void |
|||
write_register (int regno, LONGEST val) |
|||
{ |
|||
PTR buf; |
|||
int size; |
|||
|
|||
/* On the sparc, writing %g0 is a no-op, so we don't even want to
|
|||
change the registers array if something writes to this register. */ |
|||
if (CANNOT_STORE_REGISTER (regno)) |
|||
return; |
|||
|
|||
if (registers_pid != inferior_pid) |
|||
{ |
|||
registers_changed (); |
|||
registers_pid = inferior_pid; |
|||
} |
|||
|
|||
size = REGISTER_RAW_SIZE (regno); |
|||
buf = alloca (size); |
|||
store_signed_integer (buf, size, (LONGEST) val); |
|||
|
|||
/* If we have a valid copy of the register, and new value == old value,
|
|||
then don't bother doing the actual store. */ |
|||
|
|||
if (register_valid[regno] |
|||
&& memcmp (®isters[REGISTER_BYTE (regno)], buf, size) == 0) |
|||
return; |
|||
|
|||
target_prepare_to_store (); |
|||
|
|||
memcpy (®isters[REGISTER_BYTE (regno)], buf, size); |
|||
|
|||
register_valid[regno] = 1; |
|||
|
|||
target_store_registers (regno); |
|||
} |
|||
|
|||
void |
|||
write_register_pid (int regno, CORE_ADDR val, int pid) |
|||
{ |
|||
int save_pid; |
|||
|
|||
if (pid == inferior_pid) |
|||
{ |
|||
write_register (regno, val); |
|||
return; |
|||
} |
|||
|
|||
save_pid = inferior_pid; |
|||
|
|||
inferior_pid = pid; |
|||
|
|||
write_register (regno, val); |
|||
|
|||
inferior_pid = save_pid; |
|||
} |
|||
|
|||
/* SUPPLY_REGISTER()
|
|||
|
|||
Record that register REGNO contains VAL. This is used when the |
|||
value is obtained from the inferior or core dump, so there is no |
|||
need to store the value there. |
|||
|
|||
If VAL is a NULL pointer, then it's probably an unsupported register. |
|||
We just set it's value to all zeros. We might want to record this |
|||
fact, and report it to the users of read_register and friends. */ |
|||
|
|||
void |
|||
supply_register (int regno, char *val) |
|||
{ |
|||
#if 1 |
|||
if (registers_pid != inferior_pid) |
|||
{ |
|||
registers_changed (); |
|||
registers_pid = inferior_pid; |
|||
} |
|||
#endif |
|||
|
|||
register_valid[regno] = 1; |
|||
if (val) |
|||
memcpy (®isters[REGISTER_BYTE (regno)], val, |
|||
REGISTER_RAW_SIZE (regno)); |
|||
else |
|||
memset (®isters[REGISTER_BYTE (regno)], '\000', |
|||
REGISTER_RAW_SIZE (regno)); |
|||
|
|||
/* On some architectures, e.g. HPPA, there are a few stray bits in
|
|||
some registers, that the rest of the code would like to ignore. */ |
|||
|
|||
#ifdef CLEAN_UP_REGISTER_VALUE |
|||
CLEAN_UP_REGISTER_VALUE (regno, ®isters[REGISTER_BYTE (regno)]); |
|||
#endif |
|||
} |
|||
|
|||
/* read_pc, write_pc, read_sp, write_sp, read_fp, write_fp, etc.
|
|||
Special handling for registers PC, SP, and FP. */ |
|||
|
|||
/* This routine is getting awfully cluttered with #if's. It's probably
|
|||
time to turn this into READ_PC and define it in the tm.h file. |
|||
Ditto for write_pc. |
|||
|
|||
1999-06-08: The following were re-written so that it assumes the |
|||
existance of a TARGET_READ_PC et.al. macro. A default generic |
|||
version of that macro is made available where needed. |
|||
|
|||
Since the ``TARGET_READ_PC'' et.al. macro is going to be controlled |
|||
by the multi-arch framework, it will eventually be possible to |
|||
eliminate the intermediate read_pc_pid(). The client would call |
|||
TARGET_READ_PC directly. (cagney). */ |
|||
|
|||
#ifndef TARGET_READ_PC |
|||
#define TARGET_READ_PC generic_target_read_pc |
|||
#endif |
|||
|
|||
CORE_ADDR |
|||
generic_target_read_pc (int pid) |
|||
{ |
|||
#ifdef PC_REGNUM |
|||
if (PC_REGNUM >= 0) |
|||
{ |
|||
CORE_ADDR pc_val = ADDR_BITS_REMOVE ((CORE_ADDR) read_register_pid (PC_REGNUM, pid)); |
|||
return pc_val; |
|||
} |
|||
#endif |
|||
internal_error ("generic_target_read_pc"); |
|||
return 0; |
|||
} |
|||
|
|||
CORE_ADDR |
|||
read_pc_pid (int pid) |
|||
{ |
|||
int saved_inferior_pid; |
|||
CORE_ADDR pc_val; |
|||
|
|||
/* In case pid != inferior_pid. */ |
|||
saved_inferior_pid = inferior_pid; |
|||
inferior_pid = pid; |
|||
|
|||
pc_val = TARGET_READ_PC (pid); |
|||
|
|||
inferior_pid = saved_inferior_pid; |
|||
return pc_val; |
|||
} |
|||
|
|||
CORE_ADDR |
|||
read_pc (void) |
|||
{ |
|||
return read_pc_pid (inferior_pid); |
|||
} |
|||
|
|||
#ifndef TARGET_WRITE_PC |
|||
#define TARGET_WRITE_PC generic_target_write_pc |
|||
#endif |
|||
|
|||
void |
|||
generic_target_write_pc (CORE_ADDR pc, int pid) |
|||
{ |
|||
#ifdef PC_REGNUM |
|||
if (PC_REGNUM >= 0) |
|||
write_register_pid (PC_REGNUM, pc, pid); |
|||
if (NPC_REGNUM >= 0) |
|||
write_register_pid (NPC_REGNUM, pc + 4, pid); |
|||
if (NNPC_REGNUM >= 0) |
|||
write_register_pid (NNPC_REGNUM, pc + 8, pid); |
|||
#else |
|||
internal_error ("generic_target_write_pc"); |
|||
#endif |
|||
} |
|||
|
|||
void |
|||
write_pc_pid (CORE_ADDR pc, int pid) |
|||
{ |
|||
int saved_inferior_pid; |
|||
|
|||
/* In case pid != inferior_pid. */ |
|||
saved_inferior_pid = inferior_pid; |
|||
inferior_pid = pid; |
|||
|
|||
TARGET_WRITE_PC (pc, pid); |
|||
|
|||
inferior_pid = saved_inferior_pid; |
|||
} |
|||
|
|||
void |
|||
write_pc (CORE_ADDR pc) |
|||
{ |
|||
write_pc_pid (pc, inferior_pid); |
|||
} |
|||
|
|||
/* Cope with strage ways of getting to the stack and frame pointers */ |
|||
|
|||
#ifndef TARGET_READ_SP |
|||
#define TARGET_READ_SP generic_target_read_sp |
|||
#endif |
|||
|
|||
CORE_ADDR |
|||
generic_target_read_sp (void) |
|||
{ |
|||
#ifdef SP_REGNUM |
|||
if (SP_REGNUM >= 0) |
|||
return read_register (SP_REGNUM); |
|||
#endif |
|||
internal_error ("generic_target_read_sp"); |
|||
} |
|||
|
|||
CORE_ADDR |
|||
read_sp (void) |
|||
{ |
|||
return TARGET_READ_SP (); |
|||
} |
|||
|
|||
#ifndef TARGET_WRITE_SP |
|||
#define TARGET_WRITE_SP generic_target_write_sp |
|||
#endif |
|||
|
|||
void |
|||
generic_target_write_sp (CORE_ADDR val) |
|||
{ |
|||
#ifdef SP_REGNUM |
|||
if (SP_REGNUM >= 0) |
|||
{ |
|||
write_register (SP_REGNUM, val); |
|||
return; |
|||
} |
|||
#endif |
|||
internal_error ("generic_target_write_sp"); |
|||
} |
|||
|
|||
void |
|||
write_sp (CORE_ADDR val) |
|||
{ |
|||
TARGET_WRITE_SP (val); |
|||
} |
|||
|
|||
#ifndef TARGET_READ_FP |
|||
#define TARGET_READ_FP generic_target_read_fp |
|||
#endif |
|||
|
|||
CORE_ADDR |
|||
generic_target_read_fp (void) |
|||
{ |
|||
#ifdef FP_REGNUM |
|||
if (FP_REGNUM >= 0) |
|||
return read_register (FP_REGNUM); |
|||
#endif |
|||
internal_error ("generic_target_read_fp"); |
|||
} |
|||
|
|||
CORE_ADDR |
|||
read_fp (void) |
|||
{ |
|||
return TARGET_READ_FP (); |
|||
} |
|||
|
|||
#ifndef TARGET_WRITE_FP |
|||
#define TARGET_WRITE_FP generic_target_write_fp |
|||
#endif |
|||
|
|||
void |
|||
generic_target_write_fp (CORE_ADDR val) |
|||
{ |
|||
#ifdef FP_REGNUM |
|||
if (FP_REGNUM >= 0) |
|||
{ |
|||
write_register (FP_REGNUM, val); |
|||
return; |
|||
} |
|||
#endif |
|||
internal_error ("generic_target_write_fp"); |
|||
} |
|||
|
|||
void |
|||
write_fp (CORE_ADDR val) |
|||
{ |
|||
TARGET_WRITE_FP (val); |
|||
} |
|||
|
|||
static void |
|||
build_regcache (void) |
|||
{ |
|||
/* We allocate some extra slop since we do a lot of memcpy's around
|
|||
`registers', and failing-soft is better than failing hard. */ |
|||
int sizeof_registers = REGISTER_BYTES + /* SLOP */ 256; |
|||
int sizeof_register_valid = NUM_REGS * sizeof (*register_valid); |
|||
registers = xmalloc (sizeof_registers); |
|||
memset (registers, 0, sizeof_registers); |
|||
register_valid = xmalloc (sizeof_register_valid); |
|||
memset (register_valid, 0, sizeof_register_valid); |
|||
} |
|||
|
|||
void |
|||
_initialize_regcache (void) |
|||
{ |
|||
build_regcache (); |
|||
|
|||
register_gdbarch_swap (®isters, sizeof (registers), NULL); |
|||
register_gdbarch_swap (®ister_valid, sizeof (register_valid), NULL); |
|||
register_gdbarch_swap (NULL, 0, build_regcache); |
|||
} |
|||
Loading…
Reference in new issue