recent mips changes break mips-sgi-irix5.3 target (+patch)
scott snyder
snyder@d0sgif.fnal.gov
Thu Jan 22 14:36:00 GMT 1998
hi -
The recent mips changes seem to break gcc for a mips-sgi-irix5.3 target.
The following program, for example, produces a segv when run:
int xx = 42;
void bar () {}
main () { bar(); return xx; }
Here is the generated assembly code along with disassembled code
from the debugger:
.globl main
.ent main
main:
.frame $1,40,$31 # vars= 0, regs= 3/0, args= 16, extra= 8
.mask 0xd0000000,-8
.fmask 0x00000000,0
.set noreorder
.cpload $25
.set reorder
subu $sp,$sp,40
.cprestore 16
sw $31,32($sp)
sw $fp,28($sp)
sw $28,24($sp)
move $fp,$sp
la $25,bar
jal $31,$25
lw $3,xx
move $2,$3
j $L2
$L2:
move $sp,$fp
lw $31,32($sp)
lw $fp,28($sp)
addu $sp,$sp,40
j $31
.end main
Dump of assembler code for function main:
0x400a10 <main>: lui $gp,0xfc0
0x400a14 <main+4>: addiu $gp,$gp,30192
0x400a18 <main+8>: addu $gp,$gp,$t9
0x400a1c <main+12>: addiu $sp,$sp,-40
0x400a20 <main+16>: sw $gp,16($sp)
0x400a24 <main+20>: sw $ra,32($sp)
0x400a28 <main+24>: sw $s8,28($sp)
0x400a2c <main+28>: sw $gp,24($sp)
0x400a30 <main+32>: move $s8,$sp
0x400a34 <main+36>: lw $t9,-32748($gp)
0x400a38 <main+40>: nop
0x400a3c <main+44>: addiu $t9,$t9,2528
0x400a40 <main+48>: nop
0x400a44 <main+52>: jalr $t9
0x400a48 <main+56>: nop
0x400a4c <main+60>: lw $gp,16($at)
0x400a50 <main+64>: nop
0x400a54 <main+68>: lw $v1,-32680($gp)
0x400a58 <main+72>: nop
0x400a5c <main+76>: addiu $v1,$v1,0
0x400a60 <main+80>: lw $v1,0($v1)
0x400a64 <main+84>: nop
0x400a68 <main+88>: b 0x400a70 <main+96>
0x400a6c <main+92>: move $v0,$v1
0x400a70 <main+96>: move $sp,$s8
0x400a74 <main+100>: lw $ra,32($sp)
0x400a78 <main+104>: lw $s8,28($sp)
0x400a7c <main+108>: jr $ra
0x400a80 <main+112>: addiu $sp,$sp,40
End of assembler dump.
The `jal' assembly instruction is treated as a macro, and generates
the actuall call instruction plus an instruction to restore the $gp
register:
0x400a44 <main+52>: jalr $t9
0x400a48 <main+56>: nop
0x400a4c <main+60>: lw $gp,16($at)
But $at has never gets initialized, so this sequence corrupts $gp.
The program then crashes trying to access xx through $gp.
The base register used for restoring $gp is taken from the .frame
directive, which is $1 (= $at). Previous versions of egcs put
$fp there instead, which worked.
Looking in mips.c and mips.h, i see that the register used in .frame
is given by FRAME_POINTER_REGNUM. In this last round of changes,
FRAME_POINTER_REGNUM was changed from $30 to $1, and HARD_FRAME_POINTER_REGNUM
was introduced, which referenced $30. So i tried changing the
code which emits .frame to use HARD_FRAME_POINTER_REGNUM
instead of FRAME_POINTER_REGNUM. With this patch, at least the compiler
bootstraps ok...
sss
1998-01-22 scott snyder <snyder@d0sgif.fnal.gov>
* config/mips/mips.c (function_prologue): Use
HARD_FRAME_POINTER_REGNUM in .frame directive instead of
FRAME_POINTER_REGNUM.
Index: config/mips/mips.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/config/mips/mips.c,v
retrieving revision 1.13
diff -u -r1.13 mips.c
--- mips.c 1998/01/05 10:45:44 1.13
+++ mips.c 1998/01/22 22:33:23
@@ -6079,7 +6079,7 @@
if (!flag_inhibit_size_directive)
{
fprintf (file, "\t.frame\t%s,%d,%s\t\t# vars= %d, regs= %d/%d, args= %d, extra= %d\n",
- reg_names[ (frame_pointer_needed) ? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM ],
+ reg_names[ (frame_pointer_needed) ? HARD_FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM ],
tsize,
reg_names[31 + GP_REG_FIRST],
current_frame_info.var_size,
More information about the Gcc-bugs
mailing list