Bad MIPS address arithmetic

Paul Koning Paul_Koning@Dell.com
Tue May 11 01:11:00 GMT 2010


> Well things get tricky up there near the top of USEG.  That is why the
> Linux kernel never places the stack in that region.

Sure, I suppose it's possible to have the kernel work around the
assembler bug that way.  That's an interesting possibility.
 
> > It seems that daddu rather than addu should be used here, for O64
> (and
> > probably N32) ABIs.
> >
> 
> This is what I get:
> 
> $ cat koning.s
> foo:	ld	$v0,40000($sp)
> 	jr	$ra
> 
> $ mips64-linux-as --version
> GNU assembler (GNU Binutils) 2.20
> Copyright 2009 Free Software Foundation, Inc.
> This program is free software; you may redistribute it under the terms
> of
> the GNU General Public License version 3 or later.
> This program has absolutely no warranty.
> This assembler was configured for a target of `mips64-linux'.
> $ mips64-linux-as -o koning.o koning.s
> $ mips64-linux-objdump -d -r koning.o
> 
> koning.o:     file format elf32-ntradbigmips
> 
> 
> Disassembly of section .text:
> 
> 00000000 <foo>:
>     0:	3c020001 	lui	v0,0x1
>     4:	005d1021 	addu	v0,v0,sp
>     8:	03e00008 	jr	ra
>     c:	dc429c40 	ld	v0,-25536(v0)
> 
> $ mips64-linux-as -mabi=32 -o koning.o koning.s
> $ mips64-linux-objdump -d -r koning.o
> 
> koning.o:     file format elf32-tradbigmips
> 
> 
> Disassembly of section .text:
> 
> 00000000 <foo>:
>     0:	3c010001 	lui	at,0x1
>     4:	03a10821 	addu	at,sp,at
>     8:	8c229c40 	lw	v0,-25536(at)
>     c:	8c239c44 	lw	v1,-25532(at)
>    10:	03e00008 	jr	ra
>    14:	00000000 	nop
> 	...
> 
> $ mips64-linux-as -mabi=64 -o koning.o koning.s
> $ mips64-linux-objdump -d -r koning.o
> 
> koning.o:     file format elf64-tradbigmips
> 
> 
> Disassembly of section .text:
> 
> 0000000000000000 <foo>:
>     0:	3c020001 	lui	v0,0x1
>     4:	005d102d 	daddu	v0,v0,sp
>     8:	03e00008 	jr	ra
>     c:	dc429c40 	ld	v0,-25536(v0)
> 
> 
> 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.  

> Other
> ABIs do different things.  If you want code for n64, you should
specify
> that when invoking the assembler.  You can also add '.set nomacro' if
> you don't want it to do these weird things.
> 
> In MIPS assembly, what you think is an instruction often isn't, the
ABI
> and other things have a big influence.

Well, yes, that's an unfortunate and very serious design error dating
back to day 1 of the MIPS assemblers.

The big problem for me is that the code sequence in question comes out
of gcc (V3.3, which we're stuck with for now).  Essentially, what it
means is that a program with a stack frame bigger than 32k may crash in
bizarre ways.

Clearly addu is wrong here.  I believe the right answer is that daddu 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 the
current assumption.

I need to do some analysis to see if that theory is correct for ksegx
addresses.

	paul



More information about the Binutils mailing list