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