This fixes / works-around the wrong-code PR57583 on M68K, caused by overflowing the 16-bit jump table offsets the backend uses.
Ideally the backend should define CASE_VECTOR_SHORTEN_MODE, but that AFAIK needs insn length attributes, which the backend only has for CF but not for classic M68K. Instead this patch adds an -mlong-jump-table-offsets option, and adjusts the code for emitting and using jump table offsets to handle both short and long offsets. As long as the option is not selected, the backend behaves exactly as before. John Paul Adrian Glaubitz tested this patch by compiling "mednafen" with it, which previously failed; I also tested earlier versions. Is this Ok for trunk? /Mikael gcc/ 2017-01-06 Mikael Pettersson <mikpeli...@gmail.com> PR target/57583 * config/m68k/m68k.opt (LONG_JUMP_TABLE_OFFSETS): New option. * config/m68k/linux.h (ASM_RETURN_CASE_JUMP): Handle TARGET_LONG_JUMP_TABLE_OFFSETS. * config/m68k/m68kelf.h (ASM_RETURN_CASE_JUMP): Likewise. * config/m68k/netbsd-elf.h (ASM_RETURN_CASE_JUMP): Likewise. * config/m68k/m68k.h (CASE_VECTOR_MODE): Likewise. (ASM_OUTPUT_ADDR_DIFF_ELF): Likewise. * config/m68k/m68k.md (tablejump expander): Likewise. (*tablejump_pcrel_hi): Renamed from unnamed insn, reject TARGET_LONG_JUMP_TABLE_OFFSETS. (*tablejump_pcrel_si): New insn, handle TARGET_LONG_JUMP_TABLE_OFFSETS. * doc/invoke.texi (M68K options): Add -mlong-jump-table-offsets. --- gcc-7-20170101/gcc/config/m68k/linux.h.~1~ 2017-01-01 13:07:43.000000000 +0100 +++ gcc-7-20170101/gcc/config/m68k/linux.h 2017-01-06 14:36:37.366245875 +0100 @@ -98,9 +98,13 @@ along with GCC; see the file COPYING3. { \ if (ADDRESS_REG_P (operands[0])) \ return "jmp %%pc@(2,%0:l)"; \ + else if (TARGET_LONG_JUMP_TABLE_OFFSETS) \ + return "jmp %%pc@(2,%0:l)"; \ else \ return "ext%.l %0\n\tjmp %%pc@(2,%0:l)"; \ } \ + else if (TARGET_LONG_JUMP_TABLE_OFFSETS) \ + return "jmp %%pc@(2,%0:l)"; \ else \ return "jmp %%pc@(2,%0:w)"; \ } while (0) --- gcc-7-20170101/gcc/config/m68k/m68k.h.~1~ 2017-01-01 13:07:43.000000000 +0100 +++ gcc-7-20170101/gcc/config/m68k/m68k.h 2017-01-06 14:36:37.366245875 +0100 @@ -675,7 +675,7 @@ __transfer_from_trampoline () \ /* This address is OK as it stands. */ #define PIC_CASE_VECTOR_ADDRESS(index) index -#define CASE_VECTOR_MODE HImode +#define CASE_VECTOR_MODE (TARGET_LONG_JUMP_TABLE_OFFSETS ? SImode : HImode) #define CASE_VECTOR_PC_RELATIVE 1 #define DEFAULT_SIGNED_CHAR 1 @@ -857,7 +857,11 @@ do { if (cc_prev_status.flags & CC_IN_68 asm_fprintf (FILE, "\t.long %LL%d\n", VALUE) #define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ - asm_fprintf (FILE, "\t.word %LL%d-%LL%d\n", VALUE, REL) + asm_fprintf (FILE, \ + TARGET_LONG_JUMP_TABLE_OFFSETS \ + ? "\t.long %LL%d-%LL%d\n" \ + : "\t.word %LL%d-%LL%d\n", \ + VALUE, REL) /* We don't have a way to align to more than a two-byte boundary, so do the best we can and don't complain. */ --- gcc-7-20170101/gcc/config/m68k/m68k.md.~1~ 2017-01-01 13:07:43.000000000 +0100 +++ gcc-7-20170101/gcc/config/m68k/m68k.md 2017-01-06 14:36:37.366245875 +0100 @@ -6695,7 +6695,9 @@ (define_expand "tablejump" { #if CASE_VECTOR_PC_RELATIVE operands[0] = gen_rtx_PLUS (SImode, pc_rtx, - gen_rtx_SIGN_EXTEND (SImode, operands[0])); + TARGET_LONG_JUMP_TABLE_OFFSETS + ? operands[0] + : gen_rtx_SIGN_EXTEND (SImode, operands[0])); #endif }) @@ -6710,12 +6712,36 @@ (define_insn "*tablejump_internal" [(set_attr "type" "jmp")]) ;; Jump to variable address from dispatch table of relative addresses. -(define_insn "" +(define_insn "*tablejump_pcrel_si" + [(set (pc) + (plus:SI (pc) + (match_operand:SI 0 "register_operand" "r"))) + (use (label_ref (match_operand 1 "" "")))] + "TARGET_LONG_JUMP_TABLE_OFFSETS" +{ +#ifdef ASM_RETURN_CASE_JUMP + ASM_RETURN_CASE_JUMP; +#else + if (TARGET_COLDFIRE) + { + if (ADDRESS_REG_P (operands[0])) + return MOTOROLA ? "jmp (2,pc,%0.l)" : "jmp pc@(2,%0:l)"; + else if (MOTOROLA) + return "jmp (2,pc,%0.l)"; + else + return "jmp pc@(2,%0:l)"; + } + else + return MOTOROLA ? "jmp (2,pc,%0.l)" : "jmp pc@(2,%0:l)"; +#endif +}) + +(define_insn "*tablejump_pcrel_hi" [(set (pc) (plus:SI (pc) (sign_extend:SI (match_operand:HI 0 "register_operand" "r")))) (use (label_ref (match_operand 1 "" "")))] - "" + "!TARGET_LONG_JUMP_TABLE_OFFSETS" { #ifdef ASM_RETURN_CASE_JUMP ASM_RETURN_CASE_JUMP; --- gcc-7-20170101/gcc/config/m68k/m68k.opt.~1~ 2017-01-01 13:07:43.000000000 +0100 +++ gcc-7-20170101/gcc/config/m68k/m68k.opt 2017-01-06 14:45:19.305434346 +0100 @@ -142,6 +142,10 @@ mid-shared-library Target Report Mask(ID_SHARED_LIBRARY) Enable ID based shared library. +mlong-jump-table-offsets +Target Report RejectNegative Mask(LONG_JUMP_TABLE_OFFSETS) +Use 32-bit offsets in jump tables rather than 16-bit offsets. + mnobitfield Target RejectNegative InverseMask(BITFIELD) Do not use the bit-field instructions. --- gcc-7-20170101/gcc/config/m68k/m68kelf.h.~1~ 2017-01-01 13:07:43.000000000 +0100 +++ gcc-7-20170101/gcc/config/m68k/m68kelf.h 2017-01-06 14:36:37.366245875 +0100 @@ -58,9 +58,13 @@ along with GCC; see the file COPYING3. { \ if (ADDRESS_REG_P (operands[0])) \ return "jmp %%pc@(2,%0:l)"; \ + else if (TARGET_LONG_JUMP_TABLE_OFFSETS) \ + return "jmp %%pc@(2,%0:l)"; \ else \ return "ext%.l %0\n\tjmp %%pc@(2,%0:l)"; \ } \ + else if (TARGET_LONG_JUMP_TABLE_OFFSETS) \ + return "jmp %%pc@(2,%0:l)"; \ else \ return "jmp %%pc@(2,%0:w)"; \ } while (0) --- gcc-7-20170101/gcc/config/m68k/netbsd-elf.h.~1~ 2017-01-01 13:07:43.000000000 +0100 +++ gcc-7-20170101/gcc/config/m68k/netbsd-elf.h 2017-01-06 14:36:37.366245875 +0100 @@ -136,9 +136,13 @@ while (0) { \ if (ADDRESS_REG_P (operands[0])) \ return "jmp %%pc@(2,%0:l)"; \ + else if (TARGET_LONG_JUMP_TABLE_OFFSETS) \ + return "jmp %%pc@(2,%0:l)"; \ else \ return "ext%.l %0\n\tjmp %%pc@(2,%0:l)"; \ } \ + else if (TARGET_LONG_JUMP_TABLE_OFFSETS) \ + return "jmp %%pc@(2,%0:l)"; \ else \ return "jmp %%pc@(2,%0:w)"; \ } while (0) --- gcc-7-20170101/gcc/doc/invoke.texi.~1~ 2017-01-01 13:07:43.000000000 +0100 +++ gcc-7-20170101/gcc/doc/invoke.texi 2017-01-06 15:32:04.101803458 +0100 @@ -837,7 +837,7 @@ Objective-C and Objective-C++ Dialects}. -mno-short -mhard-float -m68881 -msoft-float -mpcrel @gol -malign-int -mstrict-align -msep-data -mno-sep-data @gol -mshared-library-id=n -mid-shared-library -mno-id-shared-library @gol --mxgot -mno-xgot} +-mxgot -mno-xgot -mlong-jump-table-offsets} @emph{MCore Options} @gccoptlist{-mhardlit -mno-hardlit -mdiv -mno-div -mrelax-immediates @gol @@ -18460,6 +18460,11 @@ object file that accesses more than 8192 These options have no effect unless GCC is generating position-independent code. +@item -mlong-jump-table-offsets +@opindex mlong-jump-table-offsets +Use 32-bit offsets in @code{switch} tables. The default is to use +16-bit offsets. + @end table @node MCore Options