Re: [rfa/amd64] Zero fill 32-bit registers

Mark Kettenis
2004-02-28T20:26:02Z

Date: Sat, 28 Feb 2004 14:18:07 -0500
From: Andrew Cagney <cagney@gnu.org>

> I don't know enough about MIPS to be sure, but I really think AMD64 is
> different; the ISA doesn't magically extend 32-bit values to 64-bit
> values.

(That's why I zero extended).

The problem with MIPS is that the code, instead of always being locally
consistent, assume that problems like this were handled elsewhere - they
never were or were not handled consistently. Only when MIPS started
being locally consistent (and the mantra that addresses shall always be
sign extended) did the code become robust, and the bugs disappear. It
became possible to mix 'n' match 32-bit and 64-bit code.

The problem with MIPS is that it has far too many ABI's ;-).

Here amd64 has the same problem - all 32x64-bit code needs to ensure
that it is locally consistent. If asked to supply a 64-bit register,
supply the full 64-bits, and not hope something else is filling in the
upper 32-bits.

Hmm, actually the AMD64 Architecture Programmer's Manual explicitly
says that the 16 general purpose registers are "zero-extended for
32-bit operands", so I guess zero-extending makes sense here.

It doesn't say anthing about %rip, but that makes sense since you
can't change it directly. Zero-extending makes sense though.

I'm not sure about %eflags. Hmm, it should probably be named %rflags.
Its upper 32-bits are reserved, and read as zero. The manual says
that anything you write to the upper 32 bits is ignored. I get the
feeling that we should leave the upper bits alone, just in case they
ever get used for new processors.

The segment registers are wierd anyway, since they're 16-bit
regsisters in reality. Zero extending shouldn't be a problem here,
but these registers could pose a problem. See below.

> Short-term fix is probably to let fill_gregset() clear the register
> buffer before calling amd64_native_collect_gregset().
> store_inferior_registers() should call amd64_native_collect_gregset()
> then.

It doesn't address the underlying problem where fetching an individual
register leaves half the register field undefined. The code shouldn't
assume that other code has magically initialized the rest of that
register field.

OK, but you realize its the problem of the threads code, and *not* the
code amd64-nat.c?

> > Another problem with your patch is that I'd rather like avoid assuming
> > that the register buffer is an array of 8-byte registers.
>
> That code already assumems that, and that the values are little-endian.
>
> Yes it assumes little-endianness, but the assumptions on the size of
> the slots in the register buffer are weaker. The register buffer here
> corresponds to `struct reg' on the BSD's. It would be prefectly well
> possible for some of its members to be 4 bytes in size. The current
> code works for that case, whereas with your patch, it could thrash
> another member of the structure.

Do you know of any such an system?

Actually GNU/Linux x86-64 has a gregset_t where %cs, %fs and %gs are
stored in a short.

Could you live with just zero-extending the 16 general-purpose
registers and the instruction pointer? I'll implement it for you.

Mark