This is the mail archive of the gdb@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: read_register_byte can't work with pseudo-reg model


> > The only assumption is that if this is defined, then pseudos do not need 
> > unique entries in the regcache (ie they always map onto physical 
> > registers), so we can copy the regcache simply by iterating over 
> > 0..NUM_REGS.
> 
> So the [0..NUM_REGS) space is mapped 1:1, sounds good.

Yep, that's the idea.

> 
> Just resist the temptation to look under the following rock: 
> 0..NUM_REGS will include hardware registers save/restoring that probably 
> isn't a good idea.  Per other e-mail, it will eventually need to check 
> if the register should be saved/restored.

I think regcache_read() could be made to handle that easily enough.

> 
> I think I'll tweak that branch to, when restoring the cache and 
> register_write_p, not call write_register_bytes().
> 
> > I need to re-baseline my testsuite runs, but the results look pretty 
> > encouraging compared to previous runs.
> 

I ran into another problem last night.  The code to update a register value, say from

(gdb) set $f0 = 1.0

causes write_register_bytes to iterate over the entire
[0..NUM_REGS+NUM_PSEUDO_REGS), even though a start regno is given.  Since
this then calls through the write_register_gen() interface whenever
REGISTER_BYTE indicates an overlap we end up calling REGISTER_WRITE() with
a non-pseudo regno.  The ARM implementation of this code is designed to
fault when this occurs (since it shouldn't -- gdb-core should only be
accessing the pseudo view of the register).  Would the following tweak be
acceptable?  That is, only do the update if the register has a name.

  else if (REGISTER_NAME (regnum) != NULL && *REGISTER_NAME (regnum) != '\0')
    {
      /* Is this register completely within the range the user is writing?  */
      if (myregstart <= regstart && regend <= myregend)
        write_register_gen (regnum, myaddr + (regstart - myregstart));

      /* The register partially overlaps the range being written.  */
      else
        {
          char *regbuf = (char*) alloca (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 (regnum, regbuf);

          memcpy (registers + overlapstart,
                  myaddr + (overlapstart - myregstart),
                  overlapend - overlapstart);

          store_register (regnum);
        }
    }

Note that even with this change some weird multi-writing effects are going
to happen.  Consider a frag:

	+------------+------------+
	| PHYS S0 "" | PHYS S1 "" |  Physical regs in regbank
	+------------+------------+
	|    "S0"    |    "S1"    |  First pseudo view (single precision)
	+------------+------------+
        |          "D0"           |  Second pseudo view (double)
	+------------+------------+

Then with the existing code

(gdb) set $s0 = 1.0

will call write_register_gen for PHYS S0 (anonymous), then for "S0" the
pseudo view of S0, and finally it will read the whole of "D0", update part
of it and write all of "D0" back again.

My change would eliminate the update of PHYS S0, but not simplify the
remaining multi-updates.

R.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]