Re: [RFC/mips] Problem with fetching/setting 32 bit registers

Daniel Jacobowitz
2005-03-24T04:26:11Z

On Wed, Mar 23, 2005 at 08:14:07PM -0800, Joel Brobecker wrote:
> What I found was that the problem was related to the fact that
> the FSR register is 32 bits. So the cooked register type was set
> to a 32 bits type, while underneath, the value provided by the
> kernel is located in a 64 bits buffer. And looking close, I found
> that we're reading and writing th wrong end of the buffer :-(.
>
> Here is the relevant code using when reading a pseudo register
> whose size is smaller than the size of the cooked register:
>
> else if (register_size (gdbarch, rawnum) >
> register_size (gdbarch, cookednum))
> {
> if (gdbarch_tdep (gdbarch)->mips64_transfers_32bit_regs_p
> || TARGET_BYTE_ORDER == BFD_ENDIAN_LITTLE)
> regcache_raw_read_part (regcache, rawnum, 0, 4, buf);
> else
> regcache_raw_read_part (regcache, rawnum, 4, 4, buf);
>
> In our case (mips-irix), we have a big-endian byte order, and
> therefore read the register value from the last 4 bytes, while
> I found out that they are actually in the first 4.

This appears to be a bug in your native support, at least relative to
the rest of the MIPS port.

> - || TARGET_BYTE_ORDER == BFD_ENDIAN_LITTLE)
> + || TARGET_BYTE_ORDER == BFD_ENDIAN_LITTLE
> + || gdbarch_osabi (current_gdbarch) == GDB_OSABI_IRIX)

> And it works very well. In fact, not only does it fix the problem
> exposed here, but it does help a lot in the testsuite as well
> (with function calls, and signal testcases).
>
> But I am hesitating a bit. It looks a bit like a hack to be specifying
> specifically IRIX here. I am afraid that there might be another way of
> fixing this more cleanly. But I don't see anything. One idea I had was
> to add yet another flag in the tdep part to say force the side where
> to look. But that wouldn't very practical either. So I'm left with
> the change above.

??? What I'm not getting from your explanation is what besides the FSR
is affected. It looks to me like you want to take this (irix5-nat.c):

/* FIXME, this is wrong for the N32 ABI which has 64 bit FP regs. */

for (regi = 0; regi < 32; regi++)
regcache_raw_supply (current_regcache, FP0_REGNUM + regi,
(char *) &fpregsetp->fp_r.fp_regs[regi]);

regcache_raw_supply (current_regcache,
mips_regnum (current_gdbarch)->fp_control_status,
(char *) &fpregsetp->fp_csr);

... and fix it.

The real funny bit of the whole story appears to be (mips-tdep.c):

else if (regnum < NUM_REGS)
{
/* The raw or ISA registers. These are all sized according to
the ISA regsize. */
if (mips_isa_regsize (gdbarch) == 4)
return builtin_type_int32;
else
return builtin_type_int64;
}

I don't know why the raw view of this register is 64-bit. That's
probably affecting the mips-linux port too. However, changing that
messes with the remote protocol, so we're probably stuck.

--
Daniel Jacobowitz
CodeSourcery, LLC