https://gcc.gnu.org/g:2588ef7423a135427c5d343461da092cbedbe194

commit r16-1049-g2588ef7423a135427c5d343461da092cbedbe194
Author: Stafford Horne <sho...@gmail.com>
Date:   Mon May 12 21:47:21 2025 +0100

    or1k: Support long jump offsets with -mcmodel=large
    
    The -mcmodel=large option was originally added to handle generation of
    large binaries with large PLTs.  However, when compiling the Linux
    kernel with allyesconfig the output binary is so large that the jump
    instruction 26-bit immediate is not large enough to store the jump
    offset to some symbols when linking.  Example error:
    
      relocation truncated to fit: R_OR1K_INSN_REL_26 against symbol 
`do_fpe_trap' defined in .text section in arch/openrisc/kernel/traps.o
    
    We fix this by forcing jump offsets to registers when -mcmodel=large.
    
    Note, to get the Linux kernel allyesconfig config to work with OpenRISC,
    this patch is needed along with some other patches to the Linux hand
    coded assembly bits.
    
    gcc/ChangeLog:
    
            * config/or1k/predicates.md (call_insn_operand): Add condition
            to not allow symbol_ref operands with TARGET_CMODEL_LARGE.
            * config/or1k/or1k.opt: Document new -mcmodel=large
            implications.
            * doc/invoke.texi: Likewise.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.target/or1k/call-1.c: New test.
            * gcc.target/or1k/got-1.c: New test.

Diff:
---
 gcc/config/or1k/or1k.opt               |  4 ++--
 gcc/config/or1k/predicates.md          |  3 ++-
 gcc/doc/invoke.texi                    |  7 ++++---
 gcc/testsuite/gcc.target/or1k/call-1.c | 22 ++++++++++++++++++++++
 gcc/testsuite/gcc.target/or1k/got-1.c  | 18 ++++++++++++++++++
 5 files changed, 48 insertions(+), 6 deletions(-)

diff --git a/gcc/config/or1k/or1k.opt b/gcc/config/or1k/or1k.opt
index 00c556033006..d252de082041 100644
--- a/gcc/config/or1k/or1k.opt
+++ b/gcc/config/or1k/or1k.opt
@@ -69,8 +69,8 @@ are used to perform unordered floating point compare and set 
flag operations.
 mcmodel=
 Target RejectNegative Joined Enum(or1k_cmodel_type) Var(or1k_code_model) 
Init(CMODEL_SMALL)
 Specify the code model used for accessing memory addresses.  Specifying large
-enables generating binaries with large global offset tables.  By default the
-value is small.
+enables generating binaries with large global offset tables and calling
+functions anywhere in an executable.  By default the value is small.
 
 Enum
 Name(or1k_cmodel_type) Type(enum or1k_cmodel_type)
diff --git a/gcc/config/or1k/predicates.md b/gcc/config/or1k/predicates.md
index 11bb5181436f..144f4d7b5778 100644
--- a/gcc/config/or1k/predicates.md
+++ b/gcc/config/or1k/predicates.md
@@ -61,7 +61,8 @@
         (match_test "TARGET_ROR"))))
 
 (define_predicate "call_insn_operand"
-  (ior (match_code "symbol_ref")
+  (ior (and (match_code "symbol_ref")
+           (match_test "!TARGET_CMODEL_LARGE"))
        (match_operand 0 "register_operand")))
 
 (define_predicate "high_operand"
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 0150ad088798..8de00854a05e 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -30911,12 +30911,13 @@ to store the immediate to a register first.
 @opindex mcmodel=
 @opindex mcmodel=small
 @item -mcmodel=small
-Generate OpenRISC code for the small model: The GOT is limited to 64k. This is
-the default model.
+Generate OpenRISC code for the small model: The GOT is limited to 64k and
+function call jumps are limited to 64M offsets. This is the default model.
 
 @opindex mcmodel=large
 @item -mcmodel=large
-Generate OpenRISC code for the large model: The GOT may grow up to 4G in size.
+Generate OpenRISC code for the large model: The GOT may grow up to 4G in size
+and function call jumps can target the full 4G address space.
 
 
 @end table
diff --git a/gcc/testsuite/gcc.target/or1k/call-1.c 
b/gcc/testsuite/gcc.target/or1k/call-1.c
new file mode 100644
index 000000000000..593e402d21c6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/or1k/call-1.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mcmodel=large" } */
+
+/* Generate local and global function calls. */
+
+extern int geti (void);
+
+__attribute__ ((noinline)) int
+calc (int a, int b)
+{
+  return a * b + 255;
+}
+
+int
+main (void)
+{
+  return geti () + calc (3, 4);
+}
+
+/* Ensure the 2 calls use register not immediate jumps.  */
+/* { dg-final { scan-assembler-times "l.movhi\\s+" 2 } } */
+/* { dg-final { scan-assembler-times "l.jalr\\s+" 2 } } */
diff --git a/gcc/testsuite/gcc.target/or1k/got-1.c 
b/gcc/testsuite/gcc.target/or1k/got-1.c
new file mode 100644
index 000000000000..5357096421dc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/or1k/got-1.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fPIC -mcmodel=large" } */
+
+/* Generate references to the GOT. */
+
+extern int geti (void);
+extern int j;
+
+int
+calc (int a)
+{
+  return a * j + geti ();
+}
+
+/* Ensure the 2 references use gotha relocations and that the function call 
does
+   not use an immediate jump instruction.  */
+/* { dg-final { scan-assembler-times "gotha" 2 } } */
+/* { dg-final { scan-assembler "l.jalr\\s+" } } */

Reply via email to