Re: [WIP/RFC] MIPS registers overhaul

Andrew Cagney
2003-05-16T04:00:06Z

> On May 10, 4:29pm, Andrew Cagney wrote:
>
>
>> > Problem 1 was solved by introducing a union type for floating point
>> > registers. When attempting to display a value using ``print'', you'll
>> > see (with my patch) something like this:
>> >
>> > (gdb) p $f20
>> > $1 = {i = 4621199872640208077, f = -107374184, d = 8.9000000000000004}
>> >
>> > (If someone can think of more meaningful, but still terse field names for
>> > the above, please let me know.)
>
>>
>> I'd try to be consistent with the other register unions, uint64 for
>> instance. As for the d/f, I don't know.
>
>
> I like Daniel's suggestion for the names: u64, flt, and dbl. (flt and dbl
> match the prefixes used by "info float".)

"flt" and "dbl" look ok, an alternative would be ieee754_{32,64} - ulgh.
"uint64", unlike "u64" is consistent with the existing convention.

>> > BTW, the raw floating point registers are still accessible. Doing
>> > "info registers raw" will display all of the raw registers. Or, if
>> > you know the names of the registers you want to display, you can do,
>> > e.g, "info registers raw_f20".
>
>>
>> Hmm, is this necessary? Confusing? ``maint print
>> {raw-,cooked-,}registers'' are already available and provide access to
>> the underlying values.
>
>
> Maybe we need to name the prefix something different than "raw_"?
>
> Whatever we call them, I think it's still useful to have names
> associated with them. E.g, you can do any of the following:
>
> print $raw_f20
> print/x ($raw_f20 >> 32)
> set $raw_f20=0xbadbeef

But how often will that actually happen?

I think a user debugging o32 on ISA64 still should expect to be
manipulating the full 64 bit register. Only on ISA32 should the
registers be restricted to their 32 bit values.

Even if the upper 32 bits of the FP registers are unpredictable, I think
they should still be displayed.

>> Should there be separate raw and cooked num structures?
>>
>
>> > +struct mips_regnums
>> > + {
>> > + int fp0_regnum; /* First floating point register. */
>> > + int fplast_regnum; /* Last floating point register. */
>> > + int last_arg_regnum; /* Last general purpose register used for
>> > + passing arguments. (a0_regnum is the
>> > + first.) */
>> > + int first_fp_arg_regnum; /* First floating point register used for
>> > + passing floating point arguments. */
>> > + int last_fp_arg_regnum; /* Last floating point register used for
>> > + passing floating point arguments. */
>> > + int zero_regnum; /* The zero register; read-only, always 0. */
>> > + int v0_regnum; /* Function return value. */
>> > + int a0_regnum; /* First GPR used for passing arguments. */
>> > + int t9_regnum; /* Contains address of callee in PIC code. */
>> > + int sp_regnum; /* Stack pointer. */
>> > + int ra_regnum; /* Return address. */
>> > + int ps_regnum; /* Processor status. */
>> > + int hi_regnum; /* High portion of internal multiply/divide
>> > + register. */
>> > + int lo_regnum; /* Low portion of internal multiply/divide
>> > + register. */
>> > + int badvaddr_regnum; /* Address associated with
>> > + addressing exception. */
>> > + int cause_regnum; /* Describes last exception. */
>> > + int pc_regnum; /* Program counter. */
>> > + int fcrcs_regnum; /* FP control/status. */
>> > + int fcrir_regnum; /* FP implementation/revision. */
>> > + int first_embed_regnum; /* First CP0 register for embedded use. */
>> > + int last_embed_regnum; /* Last CP0 register for embedded use. */
>> > + int prid_regnum; /* Processor ID. */
>> > + };
>> > +
>> > +const struct mips_regnums *mips_raw_regnums (struct gdbarch *gdbarch);
>> > +const struct mips_regnums *mips_cooked_regnums (struct gdbarch *gdbarch);
>
>>
>> or at least keep things like "last_arg_regnum" out this space (they only
>> belong in one of the two spaces). Having them appear in both makes it
>> too easy to do the wrong thing.
>
>
> Actually, I think it's useful for the layout raw and cooked regnum
> structs to be identical. When initializing the cooked regnum struct,
> we can do so via a single assignment:
>
> /* For many registers, the cooked and raw register numbers are the same. */
> tdep->cooked_regnums = tdep->raw_regnums;
>
> /* Cooked regnum initializations that differ follow... */
>
> The fact that the structs were identical made it easy and elegant to
> define the reg_name() function which is used twice by mips_register_name(),
> once for cooked register numbers, and a second time (assuming no suitable
> cooked name was found) for the raw numbers. If the layout of the cooked
> and raw structs were different, I'd need two separate functions with nearly
> identical functionality. Ditto for mips_dump_regnums().
>
> I think that you definitely want "last_arg_regnum" and
> "last_fp_arg_regnum" to appear in both structs. At the moment, the
> various MIPS *_push_argument() code uses the register names from the
> raw regnums struct. I think it may be desirable at some point to make
> this code use cooked regnums instead. (It will hopefully simplify a
> bunch of code that worries about shifting values to the correct
> position within a register.) For the floating point registers, where
> the cooked and raw numbers are actually different, we would like
> "first_fp_arg_regnum" and "last_fp_arg_regnum" to actually refer to
> numbers within this space.

The only code that should manipulate the raw register values
(regcache_raw_*) is:
- the cooked <-> raw mapping functions
- the target side code that supplies register values
The rest should use cooked values. Hence, I think the variables like
last_arg_regnum has a strictly cooked value (note that a cooked register
number can fall in the range [0 .. NUM_REGS).

>> How do you know that the raw register numbers were computed correctly?
>
>
> I just used the same values as the macros used to use. The user can see
> what they are via "maint print architecture".

I'm wondering how you know that the transformation from macro (defined
in .h files?) to variables worked?

Andrew