This is the mail archive of the
gdb@sources.redhat.com
mailing list for the GDB project.
Re: The regcache abstraction (Was Re: PATCH ARM initial support for different floating-point models)
- From: Andrew Cagney <ac131313 at cygnus dot com>
- To: Richard dot Earnshaw at arm dot com
- Cc: gdb at sources dot redhat dot com
- Date: Wed, 20 Feb 2002 13:49:07 -0500
- Subject: Re: The regcache abstraction (Was Re: PATCH ARM initial support for different floating-point models)
- References: <200202201644.QAA09255@cam-mail2.cambridge.arm.com>
Richard what follows is the short obscure answer (sorry). I'll try to
do the long (add to documentation answer, in about a week - this really
does need to be documented.
> retrieving revision 1.47
>> > diff -p -r1.47 arm-tdep.c
>> > *** arm-tdep.c 2002/02/19 13:57:35 1.47
>> > --- arm-tdep.c 2002/02/19 19:14:40
>> > *************** arm_extract_return_value (struct type *t
>> > *** 2139,2145 ****
>> > char *valbuf)
>> > {
>> > if (TYPE_CODE_FLT == TYPE_CODE (type))
>> > ! convert_from_extended (®buf[REGISTER_BYTE (ARM_F0_REGNUM)], valbuf);
>> > else
>> > memcpy (valbuf, ®buf[REGISTER_BYTE (ARM_A1_REGNUM)],
>> > TYPE_LENGTH (type));
>
>>
>> Here, unfortunatly, directly pokeing around the regcache buffer (a
>> parameter) is still the only way to do this.
>
>
> Yep, this is awful, but that's what it has always done there (you quote
> the old code).
Yes, I figured you're intended modifications were just re-aranging the
existing code.
For the above case it isn't possible to do any better. Fixing the
problem requires further changes to the regcache interface - perhaphs a
mechanism for saving/restoring the regcache or better the ``target
register state''.
> And you quote the old code again here.
>
>
>> Need to be careful though. If the code is assuming a floating point
>> value should be stored across multiple adjacent registers then the code
>> will need to be broken down into separate explicit writes.
>
>
> I desperately need a high-level overview of how the regcache interface is
> *supposed* to work in the brave new world (ie without all the legacy
> interfaces lying around). Let me start by trying to draw a little diagram
> to explain how I think it might work; then we can expand on that, or
> re-draw it as appropriate.
>
> Lets start the model with four main units. The inferior, the regcache,
> the MI routines and the tdep support. The interfaces are then as follows:
>
> +--------------------------------+
> | Inferior |
> +--------------------------------+
> ^ |
> | | A
> | v
> +--------------------------------+
> | Regcache |
> +--------------------------------+
> ^ | ^ |
> | | B | | C
> | v | v
> +-------------+ +-------------+
> | MI |<==>| Tdep |
> +-------------+ D +-------------+
>
> That gives us three potential interfaces to the regcache, A, B and C. In
> addition, there is an interface D, which is effectively the gdbarch vector.
>
> Now, as I understand it, interface A is quite straight-forward and
> consists of three functions:
>
> supply_register()
> collect_register()
> set_register_cached()
>
> [The last of these is needed because a target may be unable to recover
> some registers at certain times, and may need to tell the regcache that.]
Yes. In a ``pure'' new model the regcache only contains raw values.
> This interface is used by the 'nat' code or anything else that talks to a
> target machine (ie it lies at the callee side of a target_ops vector).
>
> However, after that it starts to become fuzzy. The first problem is that
> it isn't completely clear whether the regcache should contain a raw cache
> of the physical registers, or some munged view of them.
>
> I'd be inclined to argue the regcache should be pretty much a raw cache of
> the machine registers, and that interface B is therefore bogus (since it
> can't know how to interpret the information); therefore all accesses to
> the regcache by MI code should be, at least conceptually, via the tdep
> code using interface D.
>
> Of course, it may be that many targets will have near identical routines
> for mapping D<->C and there's no reason why that shouldn't be extracted
> out so that the gdbarch vector can handle it cleanly.
>
> So my questions are: Do we have interface B? If so, why? what functions
> comprise C? and what functions comprise D?
(core gdb is safer than MI, although core GDB still has problems).
In theory the call pattern is:
core-gdb
-> read_register_gen
-> gdbarch_register_read()
-> regcache_read() OR -> memory_read()
-> get value from raw regcache.
All accesses to the regcache are ment to go via gdbarch_register_read()
which your architecture controls.
If a register is really in memory, register_read() can fetch it from
memory. If a register is a composite of several raw registers,
register_read() can compose it (on the fly) from the sub registers.
Conversely for writes. gdbarch_register_write() can scatter the
register's value to the correct raw register and memory locations.
The theory breaks down on two fronts:
Core code still uses read_register_bytes() to do things like extract
struct values from two or more registers assuming they are adjacent.
That code is broken since, for instance, when a 64 bit architecture is
executing 32 bit compat code - structs are across 32 and not 64 bit
registers.
Core code still uses read_register_bytes() to save the register cache
and to apply operations on a saved register set (eg extract return
value). That code is broken since it saves/restores all registers and
not just the registers (and memory) relevant to the ABI.
Andrew