Bad MIPS address arithmetic

Paul Koning
Tue May 11 11:03:00 GMT 2010

> >> So I think it is working as it was intended.  For the default n32
> ABI,
> >> the ADDU is the proper instruction to use for pointer arithmetic.
> >
> > I don't agree.  Clearly it is flat out wrong in the test case.
> >
> You never said what your criteria for correctness were.  For your two
> line assembly file you are not getting the results you want for some
> specific values of $sp.

That's true.
> If you expand your horizons a little so that they include the code gcc
> will emit for all different types of n32 pointer arithmetic, then I
> think it is not so black and white.

Maybe so.  Maybe not.  I think the issue has to do with instruction
sequences that mix 32 bit sign extended operations with 64 bit
operations.  If you're all one or all the other, the results are always
correct; if you mix then the results can be wrong near the boundaries,
as in this case.

> >
> > Clearly addu is wrong here.  I believe the right answer is that
> is
> > correct for address arithmetic whenever 64 bit registers are used,
> i.e.,
> > O64, N32, N64.  In other words, not only for N64 as appears to be
> > current assumption.
> >
> I dissagree, it has nothing to do with the width of the registers.  It
> is the width of the data type that is important.  If your pointers are
> 32-bits wide, you should use the corresponding 32-bit instructions to
> manipulate them.  Doing otherwise can result in undefined behavior.
> This is what gcc and binutils are doing.  If you use daddu, you can
> generate register values where the upper 32-bits are non-uniform (not
> all 0 or all 1).  Once you do that, you enter into the world of truly
> undefined behavior.

Undefined if you mix 32 and 64 bit operations, yes; that's what the MIPS
book says.

In fact, that is the problem right now.  The current code is the one
that mixes operation sizes.  Specifically, on a machine with 64 bit
registers, effective address arithmetic in load and store (base register
content plus offset) is done in 64 bits, NOT in 32 bits.  So on such
machines, if you add something to a pointer register with an addu, and
then subtract from it with a register offset in a load or store, you
have a mixed operation: 32 bits in the first, 64 in the second.

So I still believe daddu is the right instruction for any 64 bit
register machine.  But changing the address space is probably the
easiest solution so I'll look at that first.


More information about the Binutils mailing list