t-elf, [...]: New files.

* 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.

From-SVN: r36111
This commit is contained in:
Alexandre Oliva 2000-09-02 03:28:47 +00:00 committed by Alexandre Oliva
parent 6462bb432f
commit 1a66cd67e2
14 changed files with 812 additions and 16 deletions

View File

@ -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.

107
gcc/config/sh/crt1.asm Normal file
View File

@ -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

101
gcc/config/sh/crti.asm Normal file
View File

@ -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

52
gcc/config/sh/crtn.asm Normal file
View File

@ -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

View File

@ -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"

View File

@ -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));

View File

@ -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");
}
}

View File

@ -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:")

View File

@ -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);
}")

9
gcc/config/sh/t-elf Normal file
View File

@ -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

View File

@ -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

3
gcc/configure vendored
View File

@ -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
;;

View File

@ -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
;;

View File

@ -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