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

Reply via email to