Re: WIP: Register doco

Jim Blandy
2002-07-20T03:11:31Z

I'm not saying the questions below couldn't be worked out by examining
the whole document carefully. But ideally, a document makes sense in
the first read-through.

Andrew Cagney <ac131313@ges.redhat.com> writes:
> @table @emph
> @item cooked
> @itemize @bullet
> @item
> manipulated by core @value{GDBN}
> @item
> correspond to user level, or abi registers

Don't you mean "ISA" here, not "ABI"? If I disassemble some code and
see an instruction that refers to r12, then I should be able to see
that register's value by saying "print $r12". The ABI in use has
nothing to do with it.

> @end itemize
> @item raw
> @itemize @bullet
> @item
> manipulated by target backends
> @item
> correspond to physical registers

I think you're introducing a new term here, "physical", which doesn't
do anything for you. When I see "physical", I think of actual
flip-flops. But that's clearly not what you're talking about: GDB has
no idea how many ports these registers have, whether they get renamed
for speculative execution, etc.

In effect, all that phrase does is define "raw" in terms of another
undefined term, "physical".

By "raw", do you really mean the registers as presented by the
underlying protocol GDB uses to examine the inferior (be it remote,
/proc, or ptrace)? I dunno.

> @subsection Raw Registers
>
> The raw register space, containing @code{NUM_REGS}
> @c index NUM_REGS
> raw registers, abstracts the instruction set architectures physical
> register set. @value{GDBN}'s register cache contains raw registers.
> Each raw register is mapped, one-to-one, onto a corresponding physical
> register. For instance:
>
> @itemize @bullet
>
> @item
> For 64 bit architecture that has 32 general purpose registers, the
> register cache, and the raw register space would include space for those
> 32 registers.
>
> @item
> For an architectures that has register banks, the register cache, and
> raw register space would contain space for registers from all banks.
> The one-to-one relationship between the raw registers and the
> architecture's physical registers being preserved.
>
> @item
> For a 64 bit architecture that is running in 32 bit mode, the register
> cache and raw register space would contain the 64 bit hardware
> registers. The raw register space would not include cut down 32 bit
> registers.

By "32 bit mode", do you mean that there's an actual bit on the
processor that makes shift, divide, etc. instructions behave as if
there were only 32 bits? Or do you mean an ABI that simply only uses
the lower 32 bits of the registers?

> @item
> For an architecture that determines the program-counter by examining the
> value of severaal hardware registers, the register cache and raw
> register space will contain the separate hardware values. The raw
> register space would not include the program-counter.
>
> @item
> For an architecture that has memory mapped registers, those registers
> are not be part of the register cache or raw register space (there is no
> corresponding hardware register).

I think it would be nice to use the IA-64's arrangement as an example
here. I assume the raw registers would include the unrotated register
file, and the registers that determine how they're rotated at the
current point. Whereas the cooked registers would be numbered the way
they appear in the machine instructions.

> @end itemize
>
> @emph{Maintainer note: Old architectures, since they didn't know better,
> broke all of the above rules, sigh!}
>
> The raw registers are not necessarily directly visible to the user.
>
> @emph{Maintainer note: There should be be a @samp{maint info registers}
> command so that the raw register cache is visible.}
>
> @section Cooked Registers
>
> The core of @value{GDBN} manipulates registers in the cooked register
> space. Any external or user visible register is mapped onto the cooked
> register space, in particular:
>
> @itemize @bullet
> @item
> registers refered to by debug information
> @item
> user visible registers (specified by name)
> @item
> mode dependant registers (e.g., a 64 bit architecture in 32 bit mode may
> need to manipulate the 32 bits of 64 bit registers)
> @item
> memory mapped registers
> space.
> @item
> state dependant registers (e.g., bank registers)
> @end itemize
>
> Architecture methods then map the @code{NUM_REGS + NUM_PSEUDO_REGS}
> cooked registers onto raw registers or memory.

So pseudo registers are different from cooked registers? Or are they
the same? If they're the same, then distinguishing NUM_REGS and
NUM_PSEUDO_REGS sort of implies that NUM_REGS corresponds to the
number of raw registers. But that shouldn't be visible to the outside
at all.

> While arbitrary mappings
> are possible, the first @code{NUM_REGS} registers should be be mapped
> direct to the raw registers. The remaining @code{NUM_PSEUDO_REGS then
> having more arbitrary mappings. That is:
>
> @smallexample
> cooked: [0..NUM_REGS) [..NUM_REGS+NUM_PSEUDO_REGS)
> | / |
> | / |
> | / |
> | / |
> raw: RAW REGISTERS MEMORY
> @end smallexample

One of the problems with this explanation is that we have a real
menagerie of different kinds of registers:

- raw registers
- cooked registers
- pseudo registers
- whatever you call a cooked register that isn't a pseudo register

This is a big source of confusion --- for me, at least.

Why can't we just have "cooked" and "raw" registers, and draw the
picture like this?

> cooked: [0..NUM_REGS)
> | \
> | \
> | \
> | \
> raw: RAW REGISTERS MEMORY

In other words, given that we're allowing cooked registers to be
computed arbitrarily from raw registers and memory contents, why not
dispense with pseudo registers altogether?

> @section The Register Cache
>
> @value{GDBN} stores the target register state in a register cache
> (@code{struct regcache}).
>
> The register cache has three separate interfaces:
>
> @itemize @bullet
> @item
> cooked
> @item
> raw
> @item
> target
> @end itemize
>
> Core @value{GDBN} manipulates the register cache using the cooked
> interfaces:
>
> @deftypefun void regcache_cooked_read (struct regcache
> *@var{regcache}, int @var{regnum}, void *@var{buf})
> Read a cooked register value from the register cache (or memory).
> @end deftypefun
> @deftypefun void regcache_cooked_write (struct regcache
> *@var{regcache}, int @var{regnum}, const void *@var{buf})
> Write a cooked register value to the register cache (or memory).
> @end deftypefun
>
> These methods then use corresponding architecture methods to map the
> cooked registers onto either raw registers or memory:
>
> @deftypefun void gdbarch_cooked_register_read (struct gdbarch
> *@var{gdbarch}, struct regcache *@var{regcache}, int @var{regnum},
> void *@var{buf})
> Read the specified @var{regnum} register value from the @var{regcache}
> (or memory for memory mapped registers).
> @end deftypefun
> @deftypefun void gdbarch_cooked_register_write (struct gdbarch
> *@var{gdbarch}, struct regcache *@var{regcache}, int @var{regnum},
> const void *@var{buf})
> Write the specified @var{regnum} register value into the @var{regcache}
> (or memory for memory mapped registers).
> @end deftypefun
>
> The raw register values being manipulated using:
>
> @deftypefun void regcache_raw_read (struct regcache *@var{regcache},
> int @var{regnum}, void *@var{buf})
> Read a cooked register value from the register cache (or memory).
> @end deftypefun
> @deftypefun void regcache_raw_write (struct regcache *@var{regcache},
> int @var{regnum}, const void *@var{buf})
> Write a raw register value to the register cache (or memory).
> @end deftypefun
>
> When a raw register read or write needs to go through to the target (the
> value isn't yet in the cache or a modification needs to be written to
> the target) the register cache state is then manipulated by the target
> using the methods:
>
> @deftypefun regcache_collect (struct regcache *@var{regcache}, int
> @var{regnum}, void *@var{buf})
> @end deftypefun
> @deftypefun regcache_supply (struct regcache *@var{regcache}, int
> @var{regnum}, const void *@var{buf})
> @end deftypefun