This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils 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: mips 64-bit address generation is broken.


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


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