https://gcc.gnu.org/bugzilla/show_bug.cgi?id=74563
Bug ID: 74563 Summary: [5 regression] Classic MIPS16 (non-MIPS16e) function return broken Product: gcc Version: 6.1.1 Status: UNCONFIRMED Severity: major Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: ma...@linux-mips.org CC: matthew.fortune at imgtec dot com Target Milestone: --- Target: mips-mti-linux-gnu This is a regression from GCC 5, present in GCC 6 and in current trunk. Non-leaf classic MIPS16 (non-MIPS16e) function epilogue uses $7 as the return register, because there is no hardware instruction available to load $31 directly from the stack. This used to work up to GCC 5, but now function epilogue still loads $7 with the return address, however it then uses JR $31 to attempt a function return. This obviously cannot work as in a non-leaf function typically $31 does not hold the return address anymore. To reproduce this simple program can be used: $ cat jal16.c void f2(void); void f1(void) { f2(); } $ gcc -mips1 -mips16 -O2 -S jal16.c $ cat jal16.s With GCC 5 I get this correct result: .file 1 "jal16.c" .section .mdebug.abi32 .previous .nan legacy .module fp=32 .module nooddspreg .abicalls .option pic0 .text .align 2 .globl f1 .set mips16 .set nomicromips .ent f1 .type f1, @function f1: .frame $sp,32,$31 # vars= 0, regs= 1/0, args= 16, gp= 8 .mask 0x80000000,-4 .fmask 0x00000000,0 addiu $sp,-32 sw $31,28($sp) jal f2 lw $7,28($sp) .set noreorder .set nomacro j $7 addiu $sp,32 .set macro .set reorder .end f1 .size f1, .-f1 .ident "GCC: (GNU) 5.4.1 20160810" With GCC 6 I get this bad one instead: .file 1 "jal16.c" .section .mdebug.abi32 .previous .nan legacy .module fp=32 .module nooddspreg .abicalls .option pic0 .text .align 2 .globl f1 .set mips16 .set nomicromips .ent f1 .type f1, @function f1: .frame $sp,32,$31 # vars= 0, regs= 1/0, args= 16, gp= 8 .mask 0x80000000,-4 .fmask 0x00000000,0 addiu $sp,-32 sw $31,28($sp) jal f2 lw $7,28($sp) .set noreorder .set nomacro jr $31 addiu $sp,32 .set macro .set reorder .end f1 .size f1, .-f1 .ident "GCC: (GNU) 6.1.1 20160810" Notice the difference: --- jal16-gcc5.s 2016-08-11 14:22:24.996749000 +0100 +++ jal16-gcc6.s 2016-08-11 18:59:38.472543000 +0100 @@ -23,11 +23,11 @@ lw $7,28($sp) .set noreorder .set nomacro - j $7 + jr $31 addiu $sp,32 .set macro .set reorder .end f1 .size f1, .-f1 - .ident "GCC: (GNU) 5.4.1 20160810" + .ident "GCC: (GNU) 6.1.1 20160810" This is a fatal bug making the MIPS16 compiler unusable and therefore requiring hightened attention, although only affecting an ISA level which is not as important these days anymore, so setting severity to major rather than critical/blocker.