summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoraoliva <aoliva@138bc75d-0d04-0410-961f-82ee72b054a4>2000-09-02 03:28:47 +0000
committeraoliva <aoliva@138bc75d-0d04-0410-961f-82ee72b054a4>2000-09-02 03:28:47 +0000
commit0abf894c1fcf45f2a726011624d0a18b878ad214 (patch)
tree778c9a0d798070b0eff6fbf93318bc7e2b6452f4
parentd91f2122e6ec441dc2fff6302c869bba14f7443d (diff)
downloadgcc-0abf894c1fcf45f2a726011624d0a18b878ad214.tar.gz
* config/sh/t-elf, config/sh/crt1.asm, config/sh/crti.asm,
config/sh/crtn.asm: New files. * config/sh/t-sh (EXTRA_MULTILIB_PARTS): Set. (crt1.o, crti.o, crtn.o): New targets. * configure.in [sh-*-elf*, sh-*-rtemself*] (tmake_file): Added sh/t-elf. * configure: Rebuilt. * config/sh/sh.h (INIT_SECTION_ASM_OP, FINI_SECTION_ASM_OP, STARTFILE_SPEC, ENDFILE_SPEC, CRT_CALL_STATIC_FUNCTION): Define. * config/sh/elf.h (INIT_SECTION_ASM_OP, FINI_SECTION_ASM_OP): Undefine for config/elfos.h to redefine. (STARTFILE_SPEC, ENDFILE_SPEC): Redefine after config/elfos.h. * config/sh/sh-protos.h (nonpic_symbol_mentioned_p, legitimize_pic_address, output_pic_addr_const): Declare. * config/sh/sh.h (CONDITIONAL_REGISTER_USAGE): Fix PIC register. (PREFERGOT_BIT, TARGET_PREFERGOT): Likewise. (TARGET_SWITCHES): New switch -mprefergot. (OVERRIDE_OPTIONS): Set flag_no_function_cse unless -mprefergot. (PIC_OFFSET_TABLE_REGNUM): Define. (GOT_SYMBOL_TABLE): Likewise. (LEGITIMIZE_ADDRESS): Use legitimize_pic_address. (ENCODE_SECTION_INFO): Define. (FINALIZE_PIC): New macros. (LEGITIMATE_PIC_OPERAND_P, SYMBOLIC_CONST_P): New macro. (ASM_OUTPUT_INT, ASM_OUTPUT_SHORT): Use output_pic_addr_const. * config/sh/sh.c (print_operand_address): Use output_pic_addr_const. (prepare_move_operands): Call emit_pic_move or emit_pic_const_move if appropriate. (output_far_jump): For PIC, use braf and output long offset. (machine_dependent_reorg): (sh_expand_prologue): Save and initialize the PIC register. (sh_expand_epilogue): Restore it. (initial_elimination_offset): Account for it. (nonpic_symbol_mentioned_p): New function. (legitimize_pic_address): Likewise. (output_pic_addr_const): Likewise. * config/sh/sh.md (calli_pcrel, call_valuei_pcrel): New insns. (call, call_value): Use them. (GOTaddr2picreg, sym_label2reg, symGOT2reg, symGOTOFF2reg, symPLT_label2reg): New expands. * invoke.texi (SH Options): Document -mprefergot. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@36111 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog47
-rw-r--r--gcc/config/sh/crt1.asm107
-rw-r--r--gcc/config/sh/crti.asm101
-rw-r--r--gcc/config/sh/crtn.asm52
-rw-r--r--gcc/config/sh/elf.h18
-rw-r--r--gcc/config/sh/sh-protos.h3
-rw-r--r--gcc/config/sh/sh.c251
-rw-r--r--gcc/config/sh/sh.h94
-rw-r--r--gcc/config/sh/sh.md126
-rw-r--r--gcc/config/sh/t-elf9
-rw-r--r--gcc/config/sh/t-sh9
-rwxr-xr-xgcc/configure3
-rw-r--r--gcc/configure.in3
-rw-r--r--gcc/invoke.texi5
14 files changed, 812 insertions, 16 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 16fce73aed3..03a624c8f59 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,50 @@
+2000-09-02 Alexandre Oliva <aoliva@redhat.com>
+
+ * config/sh/t-elf, config/sh/crt1.asm, config/sh/crti.asm,
+ config/sh/crtn.asm: New files.
+ * config/sh/t-sh (EXTRA_MULTILIB_PARTS): Set.
+ (crt1.o, crti.o, crtn.o): New targets.
+ * configure.in [sh-*-elf*, sh-*-rtemself*] (tmake_file): Added
+ sh/t-elf.
+ * configure: Rebuilt.
+ * config/sh/sh.h (INIT_SECTION_ASM_OP, FINI_SECTION_ASM_OP,
+ STARTFILE_SPEC, ENDFILE_SPEC, CRT_CALL_STATIC_FUNCTION): Define.
+ * config/sh/elf.h (INIT_SECTION_ASM_OP, FINI_SECTION_ASM_OP):
+ Undefine for config/elfos.h to redefine.
+ (STARTFILE_SPEC, ENDFILE_SPEC): Redefine after config/elfos.h.
+
+2000-09-02 Alexandre Oliva <aoliva@redhat.com>, Niibe Yutaka <gniibe@m17n.org>, Kaz Kojima <kkojima@rr.iij4u.or.jp>
+
+ * config/sh/sh-protos.h (nonpic_symbol_mentioned_p,
+ legitimize_pic_address, output_pic_addr_const): Declare.
+ * config/sh/sh.h (CONDITIONAL_REGISTER_USAGE): Fix PIC register.
+ (PREFERGOT_BIT, TARGET_PREFERGOT): Likewise.
+ (TARGET_SWITCHES): New switch -mprefergot.
+ (OVERRIDE_OPTIONS): Set flag_no_function_cse unless -mprefergot.
+ (PIC_OFFSET_TABLE_REGNUM): Define.
+ (GOT_SYMBOL_TABLE): Likewise.
+ (LEGITIMIZE_ADDRESS): Use legitimize_pic_address.
+ (ENCODE_SECTION_INFO): Define.
+ (FINALIZE_PIC): New macros.
+ (LEGITIMATE_PIC_OPERAND_P, SYMBOLIC_CONST_P): New macro.
+ (ASM_OUTPUT_INT, ASM_OUTPUT_SHORT): Use output_pic_addr_const.
+ * config/sh/sh.c (print_operand_address): Use output_pic_addr_const.
+ (prepare_move_operands): Call emit_pic_move or
+ emit_pic_const_move if appropriate.
+ (output_far_jump): For PIC, use braf and output long offset.
+ (machine_dependent_reorg):
+ (sh_expand_prologue): Save and initialize the PIC register.
+ (sh_expand_epilogue): Restore it.
+ (initial_elimination_offset): Account for it.
+ (nonpic_symbol_mentioned_p): New function.
+ (legitimize_pic_address): Likewise.
+ (output_pic_addr_const): Likewise.
+ * config/sh/sh.md (calli_pcrel, call_valuei_pcrel): New insns.
+ (call, call_value): Use them.
+ (GOTaddr2picreg, sym_label2reg, symGOT2reg, symGOTOFF2reg,
+ symPLT_label2reg): New expands.
+ * invoke.texi (SH Options): Document -mprefergot.
+
2000-09-01 Alexandre Oliva <aoliva@redhat.com>
* rtl.h (ASM_OPERANDS_INPUT_CONSTRAINT_EXP): New macro.
diff --git a/gcc/config/sh/crt1.asm b/gcc/config/sh/crt1.asm
new file mode 100644
index 00000000000..a5eb4b4e7e5
--- /dev/null
+++ b/gcc/config/sh/crt1.asm
@@ -0,0 +1,107 @@
+/* Copyright (C) 2000 Free Software Foundation, Inc.
+ This file was pretty much copied from newlib.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+In addition to the permissions in the GNU General Public License, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file into combinations with other programs,
+and to distribute those combinations without any restriction coming
+from the use of this file. (The General Public License restrictions
+do apply in other respects; for example, they cover modification of
+the file, and distribution when not linked into a combine
+executable.)
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+ .section .text
+ .global start
+start:
+ mov.l stack_k,r15
+
+ ! zero out bss
+ mov.l edata_k,r0
+ mov.l end_k,r1
+ mov #0,r2
+start_l:
+ mov.l r2,@r0
+ add #4,r0
+ cmp/ge r0,r1
+ bt start_l
+
+#if defined (__SH3E__) || defined(__SH4_SINGLE__) || defined(__SH4__) || defined(__SH4_SINGLE_ONLY)
+ mov.l set_fpscr_k, r1
+ jsr @r1
+ mov #0,r4
+ lds r3,fpscr
+#endif /* defined (__SH3E__) || defined(__SH4_SINGLE__) || defined(__SH4__) || defined(__SH4_SINGLE_ONLY__) */
+
+ ! arrange for exit to call fini
+ mov.l atexit_k,r0
+ jsr @r0
+ mov.l fini_k,r4
+
+ ! call init
+ mov.l init_k,r0
+ jsr @r0
+ nop
+
+ ! call the mainline
+ mov.l main_k,r0
+ jsr @r0
+ nop
+
+ ! call exit
+ mov r0,r4
+ mov.l exit_k,r0
+ jsr @r0
+ nop
+
+ .align 2
+#if defined (__SH3E__) || defined(__SH4_SINGLE__) || defined(__SH4__) || defined(__SH4_SINGLE_ONLY__)
+set_fpscr_k:
+ .long ___set_fpscr
+#endif /* defined (__SH3E__) || defined(__SH4_SINGLE__) || defined(__SH4__) || defined(SH4_SINGLE_ONLY) */
+stack_k:
+ .long _stack
+edata_k:
+ .long _edata
+end_k:
+ .long _end
+main_k:
+ .long _main
+exit_k:
+ .long _exit
+atexit_k:
+ .long _atexit
+init_k:
+ .long _init
+fini_k:
+ .long _fini
+
+ ! supplied for backward compatibility only, in case of linking
+ ! code whose main() was compiled with an older version of GCC.
+ .global ___main
+___main:
+ rts
+ nop
+
+#ifdef __ELF__
+ .section .stack,"aw"
+#else
+ .section .stack
+#endif
+_stack: .long 0xdeaddead
diff --git a/gcc/config/sh/crti.asm b/gcc/config/sh/crti.asm
new file mode 100644
index 00000000000..ece86667e74
--- /dev/null
+++ b/gcc/config/sh/crti.asm
@@ -0,0 +1,101 @@
+/* Copyright (C) 2000 Free Software Foundation, Inc.
+ This file was adapted from glibc sources.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+In addition to the permissions in the GNU General Public License, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file into combinations with other programs,
+and to distribute those combinations without any restriction coming
+from the use of this file. (The General Public License restrictions
+do apply in other respects; for example, they cover modification of
+the file, and distribution when not linked into a combine
+executable.)
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* The code in sections .init and .fini is supposed to be a single
+ regular function. The function in .init is called directly from
+ start in crt1.asm. The function in .fini is atexit()ed in crt1.asm
+ too.
+
+ crti.asm contributes the prologue of a function to these sections,
+ and crtn.asm comes up the epilogue. STARTFILE_SPEC should list
+ crti.o before any other object files that might add code to .init
+ or .fini sections, and ENDFILE_SPEC should list crtn.o after any
+ such object files. */
+
+ .section .init
+/* The alignment below can't be smaller, otherwide the mova below
+ breaks. Yes, we might align just the label, but then we'd be
+ exchanging an alignment here for one there, since the code fragment
+ below ensures 4-byte alignment on __ELF__. */
+#ifdef __ELF__
+ .p2align 2
+#else
+ .p2align 1
+#endif
+ .global _init
+_init:
+#ifdef __ELF__
+ mov.l r12,@-r15
+ mova 0f,r0
+ mov.l 0f,r12
+#endif
+ mov.l r14,@-r15
+#ifdef __ELF__
+ add r0,r12
+#endif
+ sts.l pr,@-r15
+#ifdef __ELF__
+ bra 1f
+#endif
+ mov r15,r14
+#ifdef __ELF__
+0: .long _GLOBAL_OFFSET_TABLE_
+1:
+#endif
+
+ .section .fini
+/* The alignment below can't be smaller, otherwide the mova below
+ breaks. Yes, we might align just the label, but then we'd be
+ exchanging an alignment here for one there, since the code fragment
+ below ensures 4-byte alignment on __ELF__. */
+#ifdef __ELF__
+ .p2align 2
+#else
+ .p2align 1
+#endif
+ .global _fini
+_fini:
+#ifdef __ELF__
+ mov.l r12,@-r15
+ mova 0f,r0
+ mov.l 0f,r12
+#endif
+ mov.l r14,@-r15
+#ifdef __ELF__
+ add r0,r12
+#endif
+ sts.l pr,@-r15
+#ifdef __ELF__
+ bra 1f
+#endif
+ mov r15,r14
+#ifdef __ELF__
+0: .long _GLOBAL_OFFSET_TABLE_
+1:
+#endif
diff --git a/gcc/config/sh/crtn.asm b/gcc/config/sh/crtn.asm
new file mode 100644
index 00000000000..86a4ee3f976
--- /dev/null
+++ b/gcc/config/sh/crtn.asm
@@ -0,0 +1,52 @@
+/* Copyright (C) 2000 Free Software Foundation, Inc.
+ This file was adapted from glibc sources.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+In addition to the permissions in the GNU General Public License, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file into combinations with other programs,
+and to distribute those combinations without any restriction coming
+from the use of this file. (The General Public License restrictions
+do apply in other respects; for example, they cover modification of
+the file, and distribution when not linked into a combine
+executable.)
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* See an explanation about .init and .fini in crti.asm. */
+
+ .section .init
+ mov r15,r14
+ lds.l @r15+,pr
+ mov.l @r15+,r14
+ rts
+#ifdef __ELF__
+ mov.l @r15+,r12
+#else
+ nop
+#endif
+
+ .section .fini
+ mov r15,r14
+ lds.l @r15+,pr
+ mov.l @r15+,r14
+ rts
+#ifdef __ELF__
+ mov.l @r15+,r12
+#else
+ nop
+#endif
diff --git a/gcc/config/sh/elf.h b/gcc/config/sh/elf.h
index 9d9e0038995..148b6b973b1 100644
--- a/gcc/config/sh/elf.h
+++ b/gcc/config/sh/elf.h
@@ -43,6 +43,8 @@ Boston, MA 02111-1307, USA. */
#undef ASM_OUTPUT_DESTRUCTOR
#undef ASM_DECLARE_FUNCTION_NAME
#undef MAX_OFILE_ALIGNMENT
+#undef INIT_SECTION_ASM_OP
+#undef FINI_SECTION_ASM_OP
/* Be ELF-like. */
#include "svr4.h"
@@ -110,13 +112,15 @@ do { \
fprintf ((FILE), "\t.stabs \"\",%d,0,0,Letext\nLetext:\n", N_SO); \
} while (0)
-/* Arrange to call __main, rather than using crtbegin.o and crtend.o
- and relying on .init and .fini being executed at appropriate times. */
-#undef INIT_SECTION_ASM_OP
-#undef FINI_SECTION_ASM_OP
-#undef STARTFILE_SPEC
-#undef ENDFILE_SPEC
-
/* HANDLE_SYSV_PRAGMA (defined by svr4.h) takes precedence over HANDLE_PRAGMA.
We want to use the HANDLE_PRAGMA from sh.h. */
#undef HANDLE_SYSV_PRAGMA
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC \
+ "%{!shared: crt1.o%s} crti.o%s \
+ %{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}"
+
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC \
+ "%{!shared:crtend.o%s} %{shared:crtendS.o%s} crtn.o%s"
diff --git a/gcc/config/sh/sh-protos.h b/gcc/config/sh/sh-protos.h
index acc316ea376..375ade8b7d9 100644
--- a/gcc/config/sh/sh-protos.h
+++ b/gcc/config/sh/sh-protos.h
@@ -42,10 +42,13 @@ extern int fp_zero_operand PARAMS ((rtx));
extern int fp_one_operand PARAMS ((rtx));
extern int fp_int_operand PARAMS ((rtx));
extern rtx get_fpscr_rtx PARAMS ((void));
+extern rtx legitimize_pic_address PARAMS ((rtx, enum machine_mode, rtx));
+extern int nonpic_symbol_mentioned_p PARAMS ((rtx));
extern void emit_sf_insn PARAMS ((rtx));
extern void emit_df_insn PARAMS ((rtx));
extern void print_operand_address PARAMS ((FILE *, rtx));
extern void print_operand PARAMS ((FILE *, rtx, int));
+extern void output_pic_addr_const PARAMS ((FILE *, rtx));
extern int expand_block_move PARAMS ((rtx *));
extern int prepare_move_operands PARAMS ((rtx[], enum machine_mode mode));
extern void from_compare PARAMS ((rtx *, int));
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
index 9e2ced69ed0..930ff738b05 100644
--- a/gcc/config/sh/sh.c
+++ b/gcc/config/sh/sh.c
@@ -201,7 +201,7 @@ print_operand_address (stream, x)
break;
default:
- output_addr_const (stream, x);
+ output_pic_addr_const (stream, x);
break;
}
}
@@ -457,6 +457,31 @@ prepare_move_operands (operands, mode)
rtx operands[];
enum machine_mode mode;
{
+ if (mode == SImode && flag_pic)
+ {
+ rtx temp;
+ if (SYMBOLIC_CONST_P (operands[1]))
+ {
+ if (GET_CODE (operands[0]) == MEM)
+ operands[1] = force_reg (Pmode, operands[1]);
+ else
+ {
+ temp = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
+ operands[1] = legitimize_pic_address (operands[1], SImode, temp);
+ }
+ }
+ else if (GET_CODE (operands[1]) == CONST
+ && GET_CODE (XEXP (operands[1], 0)) == PLUS
+ && SYMBOLIC_CONST_P (XEXP (XEXP (operands[1], 0), 0)))
+ {
+ temp = legitimize_pic_address (XEXP (XEXP (operands[1], 0), 0),
+ SImode, gen_reg_rtx (Pmode));
+ operands[1] = expand_binop (SImode, add_optab, temp,
+ XEXP (XEXP (operands[1], 0), 1),
+ gen_reg_rtx (Pmode), 0, OPTAB_LIB_WIDEN);
+ }
+ }
+
if (! reload_in_progress && ! reload_completed)
{
/* Copy the source to a register if both operands aren't registers. */
@@ -702,7 +727,10 @@ output_far_jump (insn, op)
else
{
far = 1;
- jump = "mov.l %O0,%1;jmp @%1";
+ if (flag_pic)
+ jump = "mov.l %O0,%1;braf %1";
+ else
+ jump = "mov.l %O0,%1;jmp @%1";
}
/* If we have a scratch register available, use it. */
if (GET_CODE (PREV_INSN (insn)) == INSN
@@ -730,7 +758,10 @@ output_far_jump (insn, op)
output_asm_insn (".align 2", 0);
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (this.lab));
this.op = op;
- output_asm_insn (far ? ".long %O2" : ".word %O2-%O0", &this.lab);
+ if (far && flag_pic)
+ output_asm_insn (".long %O2-%O0", &this.lab);
+ else
+ output_asm_insn (far ? ".long %O2" : ".word %O2-%O0", &this.lab);
return "";
}
@@ -3214,6 +3245,19 @@ machine_dependent_reorg (first)
/* Remove the clobber of r0. */
XEXP (clobber, 0) = gen_rtx_SCRATCH (Pmode);
}
+ /* This is a mova needing a label. Create it. */
+ else if (GET_CODE (src) == CONST
+ && GET_CODE (XEXP (src, 0)) == UNSPEC
+ && XINT (XEXP (src, 0), 1) == 1
+ && GET_CODE (XVECEXP (XEXP (src, 0),
+ 0, 0)) == CONST)
+ {
+ lab = add_constant (XVECEXP (XEXP (src, 0),
+ 0, 0), mode, 0);
+ newsrc = gen_rtx_LABEL_REF (VOIDmode, lab);
+ newsrc = gen_rtx_UNSPEC (VOIDmode,
+ gen_rtvec (1, newsrc), 1);
+ }
else
{
lab = add_constant (src, mode, 0);
@@ -3874,7 +3918,20 @@ sh_expand_prologue ()
that already happens to be at the function start into the prologue. */
if (target_flags != save_flags)
emit_insn (gen_toggle_sz ());
+ if (flag_pic && (current_function_uses_pic_offset_table
+ || regs_ever_live[PIC_OFFSET_TABLE_REGNUM]))
+ {
+ if ((live_regs_mask & (1 << PIC_OFFSET_TABLE_REGNUM)) != 0)
+ abort ();
+ d += UNITS_PER_WORD;
+ live_regs_mask |= (1 << PIC_OFFSET_TABLE_REGNUM);
+ }
push_regs (live_regs_mask, live_regs_mask2);
+
+ if (flag_pic && (current_function_uses_pic_offset_table
+ || regs_ever_live[PIC_OFFSET_TABLE_REGNUM]))
+ emit_insn (gen_GOTaddr2picreg ());
+
if (target_flags != save_flags)
emit_insn (gen_toggle_sz ());
@@ -3926,6 +3983,8 @@ sh_expand_epilogue ()
if (target_flags != save_flags)
emit_insn (gen_toggle_sz ());
+ if (flag_pic && current_function_uses_pic_offset_table)
+ live_regs_mask |= (1 << PIC_OFFSET_TABLE_REGNUM);
if (live_regs_mask & (1 << PR_REG))
pop (PR_REG);
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
@@ -4329,6 +4388,11 @@ initial_elimination_offset (from, to)
int live_regs_mask, live_regs_mask2;
live_regs_mask = calc_live_regs (&regs_saved, &live_regs_mask2);
+ if (flag_pic && current_function_uses_pic_offset_table)
+ {
+ regs_saved++;
+ live_regs_mask |= (1 << PIC_OFFSET_TABLE_REGNUM);
+ }
total_auto_space = rounded_frame_size (regs_saved);
target_flags = save_flags;
@@ -5189,3 +5253,184 @@ sh_insn_length_adjustment (insn)
}
return 0;
}
+
+/* Return TRUE if X references a SYMBOL_REF whose symbol doesn't have
+ @GOT or @GOTOFF. */
+int
+nonpic_symbol_mentioned_p (x)
+ rtx x;
+{
+ register const char *fmt;
+ register int i;
+
+ if (GET_CODE (x) == SYMBOL_REF)
+ return 1;
+
+ if (GET_CODE (x) == UNSPEC
+ && (XINT (x, 1) >= 6 && XINT (x, 1) <= 9))
+ return 0;
+
+ fmt = GET_RTX_FORMAT (GET_CODE (x));
+ for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
+ {
+ if (fmt[i] == 'E')
+ {
+ register int j;
+
+ for (j = XVECLEN (x, i) - 1; j >= 0; j--)
+ if (nonpic_symbol_mentioned_p (XVECEXP (x, i, j)))
+ return 1;
+ }
+ else if (fmt[i] == 'e' && nonpic_symbol_mentioned_p (XEXP (x, i)))
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Convert a non-PIC address in `orig' to a PIC address using @GOT or
+ @GOTOFF in `reg'. */
+rtx
+legitimize_pic_address (orig, mode, reg)
+ rtx orig;
+ enum machine_mode mode;
+ rtx reg;
+{
+ if (GET_CODE (orig) == LABEL_REF
+ || (GET_CODE (orig) == SYMBOL_REF
+ && (CONSTANT_POOL_ADDRESS_P (orig)
+ /* SYMBOL_REF_FLAG is set on static symbols. */
+ || SYMBOL_REF_FLAG (orig))))
+ {
+ if (reg == 0)
+ reg = gen_reg_rtx (Pmode);
+
+ emit_insn (gen_symGOTOFF2reg (reg, orig));
+ return reg;
+ }
+ else if (GET_CODE (orig) == SYMBOL_REF)
+ {
+ if (reg == 0)
+ reg = gen_reg_rtx (Pmode);
+
+ emit_insn (gen_symGOT2reg (reg, orig));
+ return reg;
+ }
+ return orig;
+}
+
+/* Like output_addr_const(), but recognize PIC unspecs and special
+ expressions. */
+void
+output_pic_addr_const (file, x)
+ FILE *file;
+ rtx x;
+{
+ char buf[256];
+
+ switch (GET_CODE (x))
+ {
+ case PC:
+ if (flag_pic)
+ putc ('.', file);
+ else
+ abort ();
+ break;
+
+ case SYMBOL_REF:
+ assemble_name (file, XSTR (x, 0));
+ break;
+
+ case LABEL_REF:
+ x = XEXP (x, 0);
+ /* FALLTHRU */
+ case CODE_LABEL:
+ ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
+ assemble_name (asm_out_file, buf);
+ break;
+
+ case CONST:
+ output_pic_addr_const (file, XEXP (x, 0));
+ break;
+
+ case CONST_INT:
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
+ break;
+
+ case CONST_DOUBLE:
+ if (GET_MODE (x) == VOIDmode)
+ {
+ /* We can use %d if the number is <32 bits and positive. */
+ if (CONST_DOUBLE_HIGH (x) || CONST_DOUBLE_LOW (x) < 0)
+ fprintf (file, "0x%lx%08lx",
+ (unsigned long) CONST_DOUBLE_HIGH (x),
+ (unsigned long) CONST_DOUBLE_LOW (x));
+ else
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC, CONST_DOUBLE_LOW (x));
+ }
+ else
+ /* We can't handle floating point constants;
+ PRINT_OPERAND must handle them. */
+ output_operand_lossage ("floating constant misused");
+ break;
+
+ case PLUS:
+ /* Some assemblers need integer constants to appear first. */
+ if (GET_CODE (XEXP (x, 0)) == CONST_INT)
+ {
+ output_pic_addr_const (file, XEXP (x, 0));
+ fprintf (file, "+");
+ output_pic_addr_const (file, XEXP (x, 1));
+ }
+ else if (GET_CODE (XEXP (x, 1)) == CONST_INT
+ || GET_CODE (XEXP (x, 0)) == PC)
+ {
+ output_pic_addr_const (file, XEXP (x, 1));
+ fprintf (file, "+");
+ output_pic_addr_const (file, XEXP (x, 0));
+ }
+ else
+ abort ();
+ break;
+
+ case MINUS:
+ output_pic_addr_const (file, XEXP (x, 0));
+ fprintf (file, "-");
+ if (GET_CODE (XEXP (x, 1)) == CONST)
+ {
+ putc ('(', file);
+ output_pic_addr_const (file, XEXP (x, 1));
+ putc (')', file);
+ }
+ else
+ output_pic_addr_const (file, XEXP (x, 1));
+ break;
+
+ case UNSPEC:
+ if ((XVECLEN (x, 0)) > 3)
+ abort ();
+ output_pic_addr_const (file, XVECEXP (x, 0, 0));
+ switch (XINT (x, 1))
+ {
+ case 6:
+ /* GLOBAL_OFFSET_TABLE or local symbols, no suffix. */
+ break;
+ case 7:
+ fputs ("@GOT", file);
+ break;
+ case 8:
+ fputs ("@GOTOFF", file);
+ break;
+ case 9:
+ fputs ("@PLT", file);
+ break;
+ default:
+ output_operand_lossage ("invalid UNSPEC as operand");
+ break;
+ }
+ break;
+
+ default:
+ output_operand_lossage ("invalid expression as operand");
+ }
+}
diff --git a/gcc/config/sh/sh.h b/gcc/config/sh/sh.h
index 1ea39d673b0..82b56b55f04 100644
--- a/gcc/config/sh/sh.h
+++ b/gcc/config/sh/sh.h
@@ -78,6 +78,11 @@ extern int code_for_indirect_jump_scratch;
} \
} \
} \
+ if (flag_pic) \
+ { \
+ fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1; \
+ call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1; \
+ } \
/* Hitachi saves and restores mac registers on call. */ \
if (TARGET_HITACHI && ! TARGET_NOMACSAVE) \
{ \
@@ -106,6 +111,7 @@ extern int target_flags;
#define RELAX_BIT (1<<15)
#define HITACHI_BIT (1<<22)
#define NOMACSAVE_BIT (1<<23)
+#define PREFERGOT_BIT (1<<24)
#define PADSTRUCT_BIT (1<<28)
#define LITTLE_ENDIAN_BIT (1<<29)
#define IEEE_BIT (1<<30)
@@ -178,6 +184,9 @@ extern int target_flags;
/* Nonzero if generating code for a little endian SH. */
#define TARGET_LITTLE_ENDIAN (target_flags & LITTLE_ENDIAN_BIT)
+/* Nonzero if we should prefer @GOT calls when generating PIC. */
+#define TARGET_PREFERGOT (target_flags & PREFERGOT_BIT)
+
#define TARGET_SWITCHES \
{ {"1", SH1_BIT}, \
{"2", SH2_BIT}, \
@@ -198,6 +207,7 @@ extern int target_flags;
{"l", LITTLE_ENDIAN_BIT}, \
{"no-ieee", -IEEE_BIT}, \
{"padstruct", PADSTRUCT_BIT}, \
+ {"prefergot", PREFERGOT_BIT}, \
{"relax", RELAX_BIT}, \
{"space", SPACE_BIT}, \
SUBTARGET_SWITCHES \
@@ -256,6 +266,9 @@ do { \
else \
flag_omit_frame_pointer = 0; \
\
+ if (! TARGET_PREFERGOT) \
+ flag_no_function_cse = 1; \
+ \
/* Never run scheduling before reload, since that can \
break global alloc, and generates slower code anyway due \
to the pressure on R0. */ \
@@ -538,6 +551,12 @@ do { \
current function's return address. */
#define RETURN_ADDRESS_POINTER_REGNUM 23
+/* Register to hold the addressing base for position independent
+ code access to data items. */
+#define PIC_OFFSET_TABLE_REGNUM 12
+
+#define GOT_SYMBOL_NAME "*_GLOBAL_OFFSET_TABLE_"
+
/* Value should be nonzero if functions must have frame pointers.
Zero means the frame pointer need not be set up (and parms may be accessed
via the stack pointer) in functions that seem suitable. */
@@ -1400,6 +1419,8 @@ extern int current_function_anonymous_args;
#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \
{ \
+ if (flag_pic) \
+ (X) = legitimize_pic_address (OLDX, MODE, NULL_RTX); \
if (GET_CODE (X) == PLUS \
&& (GET_MODE_SIZE (MODE) == 4 \
|| GET_MODE_SIZE (MODE) == 8) \
@@ -1708,6 +1729,44 @@ extern int current_function_anonymous_args;
&& GET_CODE (PATTERN (X)) != CLOBBER \
&& get_attr_is_sfunc (X)))
+
+/* Position Independent Code. */
+/* Define this macro if references to a symbol must be treated
+ differently depending on something about the variable or function
+ named by the symbol (such as what section it is in).
+
+ On SH, if using PIC, mark a SYMBOL_REF for a non-global symbol
+ so that we may access it using GOTOFF instead of GOT. */
+
+#define ENCODE_SECTION_INFO(DECL) \
+do \
+ { \
+ if (flag_pic) \
+ { \
+ rtx rtl = (TREE_CODE_CLASS (TREE_CODE (DECL)) != 'd' \
+ ? TREE_CST_RTL (DECL) : DECL_RTL (DECL)); \
+ \
+ SYMBOL_REF_FLAG (XEXP (rtl, 0)) = \
+ (TREE_CODE_CLASS (TREE_CODE (DECL)) != 'd' \
+ || ! TREE_PUBLIC (DECL)); \
+ } \
+ } \
+while (0)
+
+#define FINALIZE_PIC \
+ current_function_uses_pic_offset_table |= profile_flag | profile_block_flag
+
+/* We can't directly access anything that contains a symbol,
+ nor can we indirect via the constant pool. */
+#define LEGITIMATE_PIC_OPERAND_P(X) \
+ (! nonpic_symbol_mentioned_p (X) \
+ && (! CONSTANT_POOL_ADDRESS_P (X) \
+ || ! nonpic_symbol_mentioned_p (get_pool_constant (X))))
+
+#define SYMBOLIC_CONST_P(X) \
+((GET_CODE (X) == SYMBOL_REF || GET_CODE (X) == LABEL_REF) \
+ && nonpic_symbol_mentioned_p (X))
+
/* Compute the cost of an address. For the SH, all valid addresses are
the same cost. */
/* ??? Perhaps we should make reg+reg addresses have higher cost because
@@ -2003,12 +2062,12 @@ do { char dstr[30]; \
#define ASM_OUTPUT_INT(STREAM, EXP) \
(fprintf ((STREAM), "\t.long\t"), \
- output_addr_const ((STREAM), (EXP)), \
+ output_pic_addr_const ((STREAM), (EXP)), \
fputc ('\n', (STREAM)))
#define ASM_OUTPUT_SHORT(STREAM, EXP) \
(fprintf ((STREAM), "\t.short\t"), \
- output_addr_const ((STREAM), (EXP)), \
+ output_pic_addr_const ((STREAM), (EXP)), \
fputc ('\n', (STREAM)))
#define ASM_OUTPUT_CHAR(STREAM, EXP) \
@@ -2279,3 +2338,34 @@ do { \
fpscr_set_from_mem ((MODE), (HARD_REGS_LIVE))
#define DWARF_LINE_MIN_INSTR_LENGTH 2
+
+#undef INIT_SECTION_ASM_OP
+#define INIT_SECTION_ASM_OP ".section\t.init"
+#undef FINI_SECTION_ASM_OP
+#define FINI_SECTION_ASM_OP ".section\t.fini"
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC \
+ "crt1.o%s crti.o%s crtbegin.o%s"
+
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC \
+ "crtend.o%s crtn.o%s"
+
+/* SH constant pool breaks the devices in crtstuff.c to control section
+ in where code resides. We have to write it as asm code. */
+#define CRT_CALL_STATIC_FUNCTION(func) \
+ if (0) \
+ /* This avoids warnings about the static function being unused. */ \
+ func (); \
+ else \
+ /* We should be passing FUNC to the asm statement as an asm input \
+ operand, but this breaks with -fPIC. FIXME. */ \
+ asm \
+ ("mov.l 1f,r1\n\
+ mova 2f,r0\n\
+ braf r1\n\
+ lds r0,pr\n\
+0: .p2align 2\n\
+1: .long " USER_LABEL_PREFIX #func " - 0b\n\
+2:")
diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md
index fc306849124..9ac6436d189 100644
--- a/gcc/config/sh/sh.md
+++ b/gcc/config/sh/sh.md
@@ -3295,6 +3295,22 @@
(const_string "single") (const_string "double")))
(set_attr "needs_delay_slot" "yes")])
+;; This is a pc-rel call, using bsrf, for use with PIC.
+
+(define_insn "calli_pcrel"
+ [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
+ (match_operand 1 "" ""))
+ (use (reg:SI 48))
+ (use (match_operand 2 "" ""))
+ (clobber (reg:SI 17))]
+ ""
+ "bsrf %0\\n%O2:%#"
+ [(set_attr "type" "call")
+ (set (attr "fp_mode")
+ (if_then_else (eq_attr "fpu_single" "yes")
+ (const_string "single") (const_string "double")))
+ (set_attr "needs_delay_slot" "yes")])
+
(define_insn "call_valuei"
[(set (match_operand 0 "" "=rf")
(call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
@@ -3309,13 +3325,44 @@
(const_string "single") (const_string "double")))
(set_attr "needs_delay_slot" "yes")])
+(define_insn "call_valuei_pcrel"
+ [(set (match_operand 0 "" "=rf")
+ (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
+ (match_operand 2 "" "")))
+ (use (reg:SI 48))
+ (use (match_operand 3 "" ""))
+ (clobber (reg:SI 17))]
+ ""
+ "bsrf %1\\n%O3:%#"
+ [(set_attr "type" "call")
+ (set (attr "fp_mode")
+ (if_then_else (eq_attr "fpu_single" "yes")
+ (const_string "single") (const_string "double")))
+ (set_attr "needs_delay_slot" "yes")])
+
(define_expand "call"
[(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
(match_operand 1 "" ""))
(use (reg:SI 48))
(clobber (reg:SI 17))])]
""
- "operands[0] = force_reg (SImode, XEXP (operands[0], 0));")
+ "
+if (flag_pic && ! TARGET_SH1 && ! flag_unroll_loops
+ && GET_CODE (operands[0]) == MEM
+ && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
+ {
+ rtx reg = gen_reg_rtx (SImode), lab = gen_label_rtx ();
+
+ if (SYMBOL_REF_FLAG (XEXP (operands[0], 0)))
+ emit_insn (gen_sym_label2reg (reg, XEXP (operands[0], 0), lab));
+ else
+ emit_insn (gen_symPLT_label2reg (reg, XEXP (operands[0], 0), lab));
+ operands[0] = reg;
+ emit_call_insn (gen_calli_pcrel (operands[0], operands[1], lab));
+ DONE;
+ }
+else
+ operands[0] = force_reg (SImode, XEXP (operands[0], 0));")
(define_expand "call_value"
[(parallel [(set (match_operand 0 "arith_reg_operand" "")
@@ -3324,7 +3371,24 @@
(use (reg:SI 48))
(clobber (reg:SI 17))])]
""
- "operands[1] = force_reg (SImode, XEXP (operands[1], 0));")
+ "
+if (flag_pic && ! TARGET_SH1 && ! flag_unroll_loops
+ && GET_CODE (operands[1]) == MEM
+ && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
+ {
+ rtx reg = gen_reg_rtx (SImode), lab = gen_label_rtx ();
+
+ if (SYMBOL_REF_FLAG (XEXP (operands[1], 0)))
+ emit_insn (gen_sym_label2reg (reg, XEXP (operands[1], 0), lab));
+ else
+ emit_insn (gen_symPLT_label2reg (reg, XEXP (operands[1], 0), lab));
+ operands[1] = reg;
+ emit_call_insn (gen_call_valuei_pcrel (operands[0], operands[1],
+ operands[2], lab));
+ DONE;
+ }
+else
+ operands[1] = force_reg (SImode, XEXP (operands[1], 0));")
(define_insn "indirect_jump"
[(set (pc)
@@ -3418,6 +3482,58 @@
[(set_attr "in_delay_slot" "no")
(set_attr "type" "arith")])
+(define_expand "GOTaddr2picreg"
+ [(set (reg:SI 0) (const (unspec [(const (unspec [(match_dup 1)] 6))] 1)))
+ (set (match_dup 0) (const (unspec [(match_dup 1)] 6)))
+ (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI 0)))]
+ "" "
+{
+ operands[0] = pic_offset_table_rtx;
+ current_function_uses_pic_offset_table = 1;
+ operands[1] = gen_rtx_SYMBOL_REF (VOIDmode, GOT_SYMBOL_NAME);
+}
+")
+
+(define_expand "sym_label2reg"
+ [(set (match_operand:SI 0 "" "")
+ (const (minus:SI
+ (unspec [(match_operand:SI 1 "" "")] 6)
+ (const (plus:SI (label_ref (match_operand:SI 2 "" ""))
+ (const_int 2))))))]
+ "" "")
+
+(define_expand "symGOT2reg"
+ [(set (match_operand:SI 0 "" "")
+ (const (unspec [(match_operand:SI 1 "" "")] 7)))
+ (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 2)))
+ (set (match_dup 0) (mem:SI (match_dup 0)))]
+ ""
+ "
+{
+ operands[2] = pic_offset_table_rtx;
+ current_function_uses_pic_offset_table = 1;
+}")
+
+(define_expand "symGOTOFF2reg"
+ [(set (match_operand:SI 0 "" "")
+ (const (unspec [(match_operand:SI 1 "" "")] 8)))
+ (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 2)))]
+ ""
+ "
+{
+ operands[2] = pic_offset_table_rtx;
+ current_function_uses_pic_offset_table = 1;
+}")
+
+(define_expand "symPLT_label2reg"
+ [(set (match_operand:SI 0 "" "")
+ (const (minus:SI
+ (plus:SI (pc)
+ (unspec [(match_operand:SI 1 "" "")] 9))
+ (const (plus:SI (label_ref (match_operand:SI 2 "" ""))
+ (const_int 2))))))]
+ "" "")
+
;; case instruction for switch statements.
;; Operand 0 is index
@@ -3912,6 +4028,9 @@
{
operands[1] = get_fpscr_rtx ();
operands[2] = gen_rtx_SYMBOL_REF (SImode, \"__fpscr_values\");
+ if (flag_pic)
+ operands[2] = legitimize_pic_address (operands[2], SImode,
+ no_new_pseudos ? operands[0] : 0);
}")
(define_expand "fpu_switch1"
@@ -3923,6 +4042,9 @@
{
operands[1] = get_fpscr_rtx ();
operands[2] = gen_rtx_SYMBOL_REF (SImode, \"__fpscr_values\");
+ if (flag_pic)
+ operands[2] = legitimize_pic_address (operands[2], SImode,
+ no_new_pseudos ? operands[0] : 0);
operands[3] = no_new_pseudos ? operands[0] : gen_reg_rtx (SImode);
}")
diff --git a/gcc/config/sh/t-elf b/gcc/config/sh/t-elf
new file mode 100644
index 00000000000..29807d79c24
--- /dev/null
+++ b/gcc/config/sh/t-elf
@@ -0,0 +1,9 @@
+EXTRA_MULTILIB_PARTS= crt1.o crti.o crtn.o \
+ crtbegin.o crtend.o crtbeginS.o crtendS.o
+
+# Compile crtbeginS.o and crtendS.o with pic.
+CRTSTUFF_T_CFLAGS_S = -fPIC
+
+# Don't compile libgcc with -fpic for now. It's unlikely that we'll
+# build shared libraries for embedded SH.
+# TARGET_LIBGCC2_CFLAGS = -fpic
diff --git a/gcc/config/sh/t-sh b/gcc/config/sh/t-sh
index cb187aa855c..99ae929d0f0 100644
--- a/gcc/config/sh/t-sh
+++ b/gcc/config/sh/t-sh
@@ -27,3 +27,12 @@ MULTILIB_MATCHES = m2=m3 m2=m4-nofpu
LIBGCC = stmp-multilib
INSTALL_LIBGCC = install-multilib
+
+$(T)crt1.o: $(srcdir)/config/sh/crt1.asm $(GCC_PASSES)
+ $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -c -o $(T)crt1.o -x assembler-with-cpp $(srcdir)/config/sh/crt1.asm
+$(T)crti.o: $(srcdir)/config/sh/crti.asm $(GCC_PASSES)
+ $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/sh/crti.asm
+$(T)crtn.o: $(srcdir)/config/sh/crtn.asm $(GCC_PASSES)
+ $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/sh/crtn.asm
+
+EXTRA_MULTILIB_PARTS= crt1.o crti.o crtn.o crtbegin.o crtend.o
diff --git a/gcc/configure b/gcc/configure
index 15e7109d0bd..ed7f32a6872 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -6308,11 +6308,12 @@ for machine in $build $host $target; do
use_collect2=yes
;;
sh-*-elf*)
+ tmake_file="sh/t-sh sh/t-elf"
tm_file="sh/sh.h sh/elf.h"
float_format=sh
;;
sh-*-rtemself*)
- tmake_file="sh/t-sh t-rtems"
+ tmake_file="sh/t-sh sh/t-elf t-rtems"
tm_file="sh/sh.h sh/elf.h sh/rtemself.h"
float_format=sh
;;
diff --git a/gcc/configure.in b/gcc/configure.in
index 213f8dc5502..bee31c06437 100644
--- a/gcc/configure.in
+++ b/gcc/configure.in
@@ -3344,11 +3344,12 @@ changequote([,])dnl
use_collect2=yes
;;
sh-*-elf*)
+ tmake_file="sh/t-sh sh/t-elf"
tm_file="sh/sh.h sh/elf.h"
float_format=sh
;;
sh-*-rtemself*)
- tmake_file="sh/t-sh t-rtems"
+ tmake_file="sh/t-sh sh/t-elf t-rtems"
tm_file="sh/sh.h sh/elf.h sh/rtemself.h"
float_format=sh
;;
diff --git a/gcc/invoke.texi b/gcc/invoke.texi
index b68b14c1a40..523c320253d 100644
--- a/gcc/invoke.texi
+++ b/gcc/invoke.texi
@@ -418,6 +418,7 @@ in the following sections.
-mb -ml -mdalign -mrelax
-mbigtable -mfmovd -mhitachi -mnomacsave
-misize -mpadstruct -mspace
+-mprefergot
@emph{System V Options}
-Qy -Qn -YP,@var{paths} -Ym,@var{dir}
@@ -6713,6 +6714,10 @@ which is incompatible with the SH ABI.
@item -mspace
Optimize for space instead of speed. Implied by @code{-Os}.
+
+@item -mprefergot
+When generating position-independent code, emit function calls using
+the Global Offset Table instead of the Procedure Linkage Table.
@end table
@node System V Options