This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Re: mips 64-bit address generation is broken.
- From: cgd at broadcom dot com
- To: "Maciej W. Rozycki" <macro at ds2 dot pg dot gda dot pl>
- Cc: ica2_ts at csv dot ica dot uni-stuttgart dot de,binutils at sources dot redhat dot com
- Date: 18 Feb 2002 10:32:53 -0800
- Subject: Re: mips 64-bit address generation is broken.
- References: <Pine.GSO.3.96.1020218143742.13485H-100000@delta.ds2.pg.gda.pl>
At Mon, 18 Feb 2002 14:52:24 +0100 (MET), Maciej W. Rozycki wrote:
> On 17 Feb 2002 cgd@broadcom.com wrote:
> > (2) If you have 32-bit addresses, they need to behave (potentially --
> > depending on the exact calculation involved) differently,
> > depending on the addresses involved. Obviously, e.g. loads of
> > pointers should be done as 32-bit loads, but then the subsequent
> > operations (e.g. adding offsets) need to be done as 64-bit ops.
>
> Why? An offsetted 32-bit address is 32-bit as well, so you don't want
> 64-bit operations. For a proper result you need to sign-extend low 32
> bits of the 64-bit offset, though.
If you say 'dla' though, you want a 64-bit address.
The way I see this, the address size in the object format is something
that you have to cope with, rather than something to be cherished.
You have the following choices:
* 32-bit object-file address format and 'la'. Easy enough: do
32-bit load and subsequent operations as 32-bit.
* 64-bit object-file address format and 'la' or 'dla':
64-bit load and subsequent operations as 64-bit.
* 32-bit object-file address format and 'dla'. The result
should be a 64-bit address. you have to do a 32-bit load
(sign-extending) from the object format, but then do
subsequent ops as 64-bit operations.
Go back to the original example function which is mis-compiled.
The complete example is:
/* Verify that the compiler uses 'dla' to load 64-bit addresses (leadi
pattern in mips.md). */
/* { dg-do run { target mips64*-*-elf } } */
/* { dg-options "-O2 -mlong64" } */
extern void abort (void);
extern void exit (int);
void pointer_test(void);
extern void exit(int);
static char *p, *q;
void pointer_test(void)
{
if ((unsigned long)p > (unsigned long)(q + 0x20000))
exit (1);
}
int main(void)
{
p = (char *) 0x0000000100000000UL;
q = p;
pointer_test();
exit (0);
}
Then see the original pointer_test disassembly that you get with 'dla'
if you do a 32-bit add, and you'll see why that loses.
cgd