diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2006-10-06 20:58:18 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2006-10-06 20:58:18 +0000 |
commit | b50063e7723d8a96f3eaeb641e59f7f161dcd917 (patch) | |
tree | 912a3440a1bc70d7ac987e099524134196c40874 /gnu/usr.bin | |
parent | bf3a6255750ff2254e0357e9e01506962b1f316f (diff) |
Early bits for a 32-bit SuperH toolchain, currently for little-endian
systems only; more work is necessary in ld land.
Diffstat (limited to 'gnu/usr.bin')
-rw-r--r-- | gnu/usr.bin/binutils/Makefile.bsd-wrapper | 4 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/bfd/config.bfd | 2 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/gas/configure | 1 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/gas/configure.in | 1 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/gdb/configure.tgt | 2 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/gdb/sh-tdep.c | 14 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/ld/configure.tgt | 2 | ||||
-rw-r--r-- | gnu/usr.bin/gcc/gcc/config.gcc | 7 | ||||
-rw-r--r-- | gnu/usr.bin/gcc/gcc/config/sh/openbsd.h | 106 | ||||
-rw-r--r-- | gnu/usr.bin/gcc/gcc/config/sh/sh-protos.h | 7 | ||||
-rw-r--r-- | gnu/usr.bin/gcc/gcc/config/sh/sh.c | 164 | ||||
-rw-r--r-- | gnu/usr.bin/gcc/gcc/config/sh/sh.h | 6 | ||||
-rw-r--r-- | gnu/usr.bin/gcc/gcc/config/sh/t-openbsd | 19 |
13 files changed, 309 insertions, 26 deletions
diff --git a/gnu/usr.bin/binutils/Makefile.bsd-wrapper b/gnu/usr.bin/binutils/Makefile.bsd-wrapper index 969af582b82..b41d7e0e272 100644 --- a/gnu/usr.bin/binutils/Makefile.bsd-wrapper +++ b/gnu/usr.bin/binutils/Makefile.bsd-wrapper @@ -1,6 +1,6 @@ -# $OpenBSD: Makefile.bsd-wrapper,v 1.66 2006/07/12 23:00:07 espie Exp $ +# $OpenBSD: Makefile.bsd-wrapper,v 1.67 2006/10/06 20:58:17 miod Exp $ -NEW_BINUTILS=alpha amd64 arm hppa hppa64 i386 mips64 powerpc sparc sparc64 +NEW_BINUTILS=alpha amd64 arm hppa hppa64 i386 mips64 powerpc sh sparc sparc64 .for _arch in ${MACHINE_ARCH} . if !empty(NEW_BINUTILS:M${_arch}) diff --git a/gnu/usr.bin/binutils/bfd/config.bfd b/gnu/usr.bin/binutils/bfd/config.bfd index a3bdcb9b886..e5edb3d7705 100644 --- a/gnu/usr.bin/binutils/bfd/config.bfd +++ b/gnu/usr.bin/binutils/bfd/config.bfd @@ -1080,7 +1080,7 @@ case "${targ}" in ;; #endif - sh*l*-*-netbsdelf*) + sh*-*-openbsd* | sh*l*-*-netbsdelf*) targ_defvec=bfd_elf32_shlnbsd_vec targ_selvecs="bfd_elf32_shnbsd_vec shcoff_vec shlcoff_vec" #ifdef BFD64 diff --git a/gnu/usr.bin/binutils/gas/configure b/gnu/usr.bin/binutils/gas/configure index a35663d3dd0..58a39d85960 100644 --- a/gnu/usr.bin/binutils/gas/configure +++ b/gnu/usr.bin/binutils/gas/configure @@ -4510,6 +4510,7 @@ echo "$as_me: error: Solaris must be configured little endian" >&2;} sh5*-*-netbsd*) fmt=elf em=nbsd ;; sh64*-*-netbsd*) fmt=elf em=nbsd ;; sh*-*-netbsdelf*) fmt=elf em=nbsd ;; + sh*-*-openbsd*) fmt=elf em=nbsd endian=little ;; sh-*-elf*) fmt=elf ;; sh-*-coff*) fmt=coff ;; sh-*-nto*) fmt=elf ;; diff --git a/gnu/usr.bin/binutils/gas/configure.in b/gnu/usr.bin/binutils/gas/configure.in index f28993a30c3..60a0369904a 100644 --- a/gnu/usr.bin/binutils/gas/configure.in +++ b/gnu/usr.bin/binutils/gas/configure.in @@ -465,6 +465,7 @@ changequote([,])dnl sh5*-*-netbsd*) fmt=elf em=nbsd ;; sh64*-*-netbsd*) fmt=elf em=nbsd ;; sh*-*-netbsdelf*) fmt=elf em=nbsd ;; + sh*-*-openbsd*) fmt=elf em=nbsd endian=little ;; sh-*-elf*) fmt=elf ;; sh-*-coff*) fmt=coff ;; sh-*-nto*) fmt=elf ;; diff --git a/gnu/usr.bin/binutils/gdb/configure.tgt b/gnu/usr.bin/binutils/gdb/configure.tgt index ea0ef9da4cf..ad260433386 100644 --- a/gnu/usr.bin/binutils/gdb/configure.tgt +++ b/gnu/usr.bin/binutils/gdb/configure.tgt @@ -178,7 +178,7 @@ sh-*-elf*) gdb_target=embed ;; sh-*-linux*) gdb_target=linux build_gdbserver=yes ;; -sh*-*-netbsdelf* | sh*-*-knetbsd*-gnu) +sh*-*-netbsdelf* | sh*-*-knetbsd*-gnu | sh*-*-openbsd*) gdb_target=nbsd ;; sh-*-nto*) gdb_target=nto ;; sh*) gdb_target=embed ;; diff --git a/gnu/usr.bin/binutils/gdb/sh-tdep.c b/gnu/usr.bin/binutils/gdb/sh-tdep.c index 48e994d4e2e..327454fd875 100644 --- a/gnu/usr.bin/binutils/gdb/sh-tdep.c +++ b/gnu/usr.bin/binutils/gdb/sh-tdep.c @@ -161,6 +161,7 @@ sh_sh2e_register_name (int reg_nr) return register_names[reg_nr]; } +#ifdef notyet static const char * sh_sh2a_register_name (int reg_nr) { @@ -240,6 +241,7 @@ sh_sh2a_nofpu_register_name (int reg_nr) return NULL; return register_names[reg_nr]; } +#endif static const char * sh_sh_dsp_register_name (int reg_nr) @@ -1402,6 +1404,7 @@ sh2e_show_regs (void) printf_filtered (("FP8-FP15 %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n"), (long) read_register (FP0_REGNUM + 8), (long) read_register (FP0_REGNUM + 9), (long) read_register (FP0_REGNUM + 10), (long) read_register (FP0_REGNUM + 11), (long) read_register (FP0_REGNUM + 12), (long) read_register (FP0_REGNUM + 13), (long) read_register (FP0_REGNUM + 14), (long) read_register (FP0_REGNUM + 15)); } +#ifdef notyet static void sh2a_show_regs (void) { @@ -1536,6 +1539,7 @@ sh2a_nofpu_show_regs (void) (long) read_register (R0_BANK0_REGNUM + 18), (long) read_register (R0_BANK0_REGNUM + 19)); } +#endif static void sh3e_show_regs (void) @@ -1758,6 +1762,7 @@ sh_show_regs_command (char *args, int from_tty) (*sh_show_regs) (); } +#ifdef notyet static struct type * sh_sh2a_register_type (struct gdbarch *gdbarch, int reg_nr) { @@ -1769,6 +1774,7 @@ sh_sh2a_register_type (struct gdbarch *gdbarch, int reg_nr) else return builtin_type_int; } +#endif /* Return the GDB type object for the "standard" data type of data in register N. */ @@ -2210,6 +2216,7 @@ sh_dsp_register_sim_regno (int nr) return nr; } +#ifdef notyet static int sh_sh2a_register_sim_regno (int nr) { @@ -2238,6 +2245,7 @@ sh_sh2a_register_sim_regno (int nr) } return legacy_register_sim_regno (nr); } +#endif static struct sh_frame_cache * sh_alloc_frame_cache (void) @@ -2495,6 +2503,7 @@ sh_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc) inst = read_memory_unsigned_integer (addr - 2, 2); } +#ifdef notyet /* On SH2a check if the previous instruction was perhaps a MOVI20. That's allowed for the epilogue. */ if ((gdbarch_bfd_arch_info (gdbarch)->mach == bfd_mach_sh2a @@ -2502,6 +2511,7 @@ sh_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc) && addr > func_addr + 6 && IS_MOVI20 (read_memory_unsigned_integer (addr - 4, 2))) addr -= 4; +#endif if (pc >= addr) return 1; @@ -2522,12 +2532,14 @@ sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) case bfd_mach_sh2e: sh_show_regs = sh2e_show_regs; break; +#ifdef notyet case bfd_mach_sh2a: sh_show_regs = sh2a_show_regs; break; case bfd_mach_sh2a_nofpu: sh_show_regs = sh2a_nofpu_show_regs; break; +#endif case bfd_mach_sh_dsp: sh_show_regs = sh_dsp_show_regs; break; @@ -2638,6 +2650,7 @@ sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_push_dummy_call (gdbarch, sh_push_dummy_call_fpu); break; +#ifdef notyet case bfd_mach_sh2a: set_gdbarch_register_name (gdbarch, sh_sh2a_register_name); set_gdbarch_register_type (gdbarch, sh_sh2a_register_type); @@ -2659,6 +2672,7 @@ sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_pseudo_register_read (gdbarch, sh_pseudo_register_read); set_gdbarch_pseudo_register_write (gdbarch, sh_pseudo_register_write); break; +#endif case bfd_mach_sh_dsp: set_gdbarch_register_name (gdbarch, sh_sh_dsp_register_name); diff --git a/gnu/usr.bin/binutils/ld/configure.tgt b/gnu/usr.bin/binutils/ld/configure.tgt index c8a620f7f52..6692e3e26ee 100644 --- a/gnu/usr.bin/binutils/ld/configure.tgt +++ b/gnu/usr.bin/binutils/ld/configure.tgt @@ -334,7 +334,7 @@ sh64-*-netbsd*) targ_emul=shelf64_nbsd targ_extra_emuls="shlelf64_nbsd shelf32_nbsd shlelf32_nbsd shelf_nbsd shlelf_nbsd" ;; -sh*l*-*-netbsdelf*) +sh*l*-*-netbsdelf*|sh*-*-openbsd*) targ_emul=shlelf_nbsd targ_extra_emuls=shelf_nbsd ;; diff --git a/gnu/usr.bin/gcc/gcc/config.gcc b/gnu/usr.bin/gcc/gcc/config.gcc index 0c1867549a3..b9f8c13897f 100644 --- a/gnu/usr.bin/gcc/gcc/config.gcc +++ b/gnu/usr.bin/gcc/gcc/config.gcc @@ -2412,6 +2412,13 @@ sh-*-netbsdelf* | shl*-*-netbsdelf* | sh5-*-netbsd* | sh5l*-*-netbsd* | \ ;; esac ;; +sh-*-openbsd*) + tm_file="sh/little.h dbxelf.h sh/sh.h elfos.h sh/elf.h ${tm_file}" + tmake_file="${tmake_file} sh/t-sh sh/t-elf" + # SH3, software floating point + target_cpu_default="SH1_BIT|SH2_BIT|SH3_BIT" + tmake_file="${tmake_file} sh/t-openbsd" + ;; sh-*-*) tm_file="${tm_file} sh/coff.h" ;; diff --git a/gnu/usr.bin/gcc/gcc/config/sh/openbsd.h b/gnu/usr.bin/gcc/gcc/config/sh/openbsd.h new file mode 100644 index 00000000000..4b133319fed --- /dev/null +++ b/gnu/usr.bin/gcc/gcc/config/sh/openbsd.h @@ -0,0 +1,106 @@ +/* Definitions for SH running OpenBSD using ELF + Copyright (C) 2002, 2006 Free Software Foundation, Inc. + Adapted from the NetBSD configuration contributed by Wasabi Systems, Inc. + +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. + +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. */ + +#define OBSD_NO_DYNAMIC_LIBRARIES + +/* Get generic OpenBSD definitions. */ +#include <openbsd.h> + +#undef TARGET_DEFAULT +#define TARGET_DEFAULT \ + (TARGET_CPU_DEFAULT | USERMODE_BIT | TARGET_ENDIAN_DEFAULT) + +#define TARGET_OS_CPP_BUILTINS() OPENBSD_OS_CPP_BUILTINS_ELF() + +/* Layout of source language data types */ + +/* This must agree with <machine/_types.h> */ +#undef SIZE_TYPE +#define SIZE_TYPE "long unsigned int" + +#undef PTRDIFF_TYPE +#define PTRDIFF_TYPE "long int" + +#undef WCHAR_TYPE +#define WCHAR_TYPE "int" + +#undef WCHAR_TYPE_SIZE +#define WCHAR_TYPE_SIZE 32 + +#undef LINK_DEFAULT_CPU_EMUL +#define LINK_DEFAULT_CPU_EMUL "" + +#undef SUBTARGET_LINK_EMUL_SUFFIX +#define SUBTARGET_LINK_EMUL_SUFFIX "_nbsd" + +#undef SUBTARGET_LINK_SPEC +#define SUBTARGET_LINK_SPEC LINK_SPEC + +#undef LINK_SPEC +#define LINK_SPEC SH_LINK_SPEC + +/* As an elf system, we need crtbegin/crtend stuff. */ +#undef STARTFILE_SPEC +#define STARTFILE_SPEC "\ + %{!shared: %{pg:gcrt0%O%s} %{!pg:%{p:gcrt0%O%s} %{!p:crt0%O%s}} \ + crtbegin%O%s} %{shared:crtbeginS%O%s}" +#undef ENDFILE_SPEC +#define ENDFILE_SPEC "%{!shared:crtend%O%s} %{shared:crtendS%O%s}" + +#undef PREFERRED_DEBUGGING_TYPE +#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG + +/* Provide a CPP_SPEC appropriate for OpenBSD. */ +#undef SUBTARGET_CPP_SPEC +#define SUBTARGET_CPP_SPEC OBSD_CPP_SPEC + +/* Define because we use the label and we do not need them. */ +#define NO_PROFILE_COUNTERS + +#undef FUNCTION_PROFILER +#define FUNCTION_PROFILER(STREAM,LABELNO) \ +do \ + { \ + if (TARGET_SHMEDIA32) \ + { \ + /* FIXME */ \ + abort (); \ + } \ + else if (TARGET_SHMEDIA64) \ + { \ + /* FIXME */ \ + abort (); \ + } \ + else \ + { \ + fprintf((STREAM), "\tmov.l\t%sLP%d,r1\n", \ + LOCAL_LABEL_PREFIX, (LABELNO)); \ + fprintf((STREAM), "\tmova\t%sLP%dr,r0\n", \ + LOCAL_LABEL_PREFIX, (LABELNO)); \ + fprintf((STREAM), "\tjmp\t@r1\n"); \ + fprintf((STREAM), "\tnop\n"); \ + fprintf((STREAM), "\t.align\t2\n"); \ + fprintf((STREAM), "%sLP%d:\t.long\t__mcount\n", \ + LOCAL_LABEL_PREFIX, (LABELNO)); \ + fprintf((STREAM), "%sLP%dr:\n", LOCAL_LABEL_PREFIX, (LABELNO)); \ + } \ + } \ +while (0) diff --git a/gnu/usr.bin/gcc/gcc/config/sh/sh-protos.h b/gnu/usr.bin/gcc/gcc/config/sh/sh-protos.h index 70d0ade0787..475ab9dadfc 100644 --- a/gnu/usr.bin/gcc/gcc/config/sh/sh-protos.h +++ b/gnu/usr.bin/gcc/gcc/config/sh/sh-protos.h @@ -1,5 +1,5 @@ /* Definitions of target machine for GNU compiler for Hitachi / SuperH SH. - Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000 + Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2004 Free Software Foundation, Inc. Contributed by Steve Chamberlain (sac@cygnus.com). Improved by Jim Wilson (wilson@cygnus.com). @@ -118,7 +118,7 @@ extern struct rtx_def *get_fpscr_rtx PARAMS ((void)); extern void output_file_start PARAMS ((FILE *)); extern int sh_media_register_for_return PARAMS ((void)); extern void sh_expand_prologue PARAMS ((void)); -extern void sh_expand_epilogue PARAMS ((void)); +extern void sh_expand_epilogue PARAMS ((bool)); extern int sh_need_epilogue PARAMS ((void)); extern int initial_elimination_offset PARAMS ((int, int)); extern int fldi_ok PARAMS ((void)); @@ -131,6 +131,7 @@ extern bool sh_cannot_change_mode_class extern void sh_mark_label PARAMS ((rtx, int)); extern int sh_register_move_cost PARAMS ((enum machine_mode mode, enum reg_class, enum reg_class)); +extern int check_use_sfunc_addr PARAMS ((rtx, rtx)); #ifdef HARD_CONST extern void fpscr_set_from_mem PARAMS ((int, HARD_REG_SET)); @@ -142,4 +143,6 @@ extern void sh_pr_trapa PARAMS ((cpp_reader *)); extern void sh_pr_nosave_low_regs PARAMS ((cpp_reader *)); #endif +extern rtx sh_get_pr_initial_val PARAMS ((void)); + #endif /* ! GCC_SH_PROTOS_H */ diff --git a/gnu/usr.bin/gcc/gcc/config/sh/sh.c b/gnu/usr.bin/gcc/gcc/config/sh/sh.c index 237c78d90c0..883380d6047 100644 --- a/gnu/usr.bin/gcc/gcc/config/sh/sh.c +++ b/gnu/usr.bin/gcc/gcc/config/sh/sh.c @@ -1,6 +1,6 @@ /* Output routines for GCC for Hitachi / SuperH SH. - Copyright (C) 1993, 1994, 1995, 1997, 1997, 1998, 1999, 2000, 2001, 2002 - Free Software Foundation, Inc. + Copyright (C) 1993, 1994, 1995, 1997, 1997, 1998, 1999, 2000, 2001, 2002, + 2004 Free Software Foundation, Inc. Contributed by Steve Chamberlain (sac@cygnus.com). Improved by Jim Wilson (wilson@cygnus.com). @@ -3065,6 +3065,14 @@ gen_block_redirect (jump, addr, need_block) else if (recog_memoized (prev) == CODE_FOR_block_branch_redirect) need_block = 0; } + if (GET_CODE (PATTERN (jump)) == RETURN) + { + if (! need_block) + return prev; + /* Reorg even does nasty things with return insns that cause branches + to go out of range - see find_end_label and callers. */ + return emit_insn_before (gen_block_branch_redirect (GEN_INT (0)) , jump); + } /* We can't use JUMP_LABEL here because it might be undefined when not optimizing. */ dest = XEXP (SET_SRC (PATTERN (jump)), 0); @@ -3233,11 +3241,16 @@ gen_far_branch (bp) JUMP_LABEL (jump) = bp->far_label; if (! invert_jump (insn, label, 1)) abort (); - (emit_insn_after - (gen_stuff_delay_slot - (GEN_INT (INSN_UID (XEXP (SET_SRC (PATTERN (jump)), 0))), - GEN_INT (recog_memoized (insn) == CODE_FOR_branch_false)), - insn)); + /* If we are branching around a jump (rather than a return), prevent + reorg from using an insn from the jump target as the delay slot insn - + when reorg did this, it pessimized code (we rather hide the delay slot) + and it could cause branches to go out of range. */ + if (bp->far_label) + (emit_insn_after + (gen_stuff_delay_slot + (GEN_INT (INSN_UID (XEXP (SET_SRC (PATTERN (jump)), 0))), + GEN_INT (recog_memoized (insn) == CODE_FOR_branch_false)), + insn)); /* Prevent reorg from undoing our splits. */ gen_block_redirect (jump, bp->address += 2, 2); } @@ -4264,7 +4277,55 @@ output_stack_adjust (size, reg, temp, emit_fn) register to MACL. However, there is currently no need to handle this case, so just abort when we see it. */ if (temp < 0) - abort (); + { + /* If we reached here, the most likely case is the (sibcall) + epilogue for non SHmedia. Put a special push/pop sequence + for such case as the last resort. This looks lengthy but + would not be problem because it seems to be very rare. */ + if (! TARGET_SHMEDIA && (emit_fn != frame_insn)) + { + rtx adj_reg, tmp_reg, mem; + + /* ??? There is still the slight possibility that r4 or r5 + have been reserved as fixed registers or assigned as + global registers, and they change during an interrupt. + There are possible ways to handle this: + - If we are adjusting the frame pointer (r14), we can do + with a single temp register and an ordinary push / pop + on the stack. + - Grab any call-used or call-saved registers (i.e. not + fixed or globals) for the temps we need. We might + also grab r14 if we are adjusting the stack pointer. + If we can't find enough available registers, issue + a diagnostic and abort - the user must have reserved + way too many registers. + But since all this is rather unlikely to happen and + would require extra testing, we just abort if r4 / r5 + are not available. */ + if (fixed_regs[4] || fixed_regs[5] + || global_regs[4] || global_regs[5]) + abort (); + + adj_reg = gen_rtx_REG (GET_MODE (reg), 4); + tmp_reg = gen_rtx_REG (GET_MODE (reg), 5); + emit_move_insn (gen_rtx_MEM (Pmode, reg), adj_reg); + emit_insn (GEN_MOV (adj_reg, GEN_INT (size))); + emit_insn (GEN_ADD3 (adj_reg, adj_reg, reg)); + mem = gen_rtx_MEM (Pmode, gen_rtx_PRE_DEC (Pmode, adj_reg)); + emit_move_insn (mem, tmp_reg); + emit_move_insn (tmp_reg, gen_rtx_MEM (Pmode, reg)); + mem = gen_rtx_MEM (Pmode, gen_rtx_PRE_DEC (Pmode, adj_reg)); + emit_move_insn (mem, tmp_reg); + emit_move_insn (reg, adj_reg); + mem = gen_rtx_MEM (Pmode, gen_rtx_POST_INC (Pmode, reg)); + emit_move_insn (adj_reg, mem); + mem = gen_rtx_MEM (Pmode, gen_rtx_POST_INC (Pmode, reg)); + emit_move_insn (tmp_reg, mem); + return; + } + else + abort (); + } const_reg = gen_rtx_REG (GET_MODE (reg), temp); /* If SIZE is negative, subtract the positive value. @@ -4518,6 +4579,7 @@ sh_expand_prologue () int d, i; int d_rounding = 0; int save_flags = target_flags; + int size; current_function_interrupt = sh_cfun_interrupt_handler_p (); @@ -4811,7 +4873,12 @@ sh_expand_prologue () target_flags = save_flags; - output_stack_adjust (-rounded_frame_size (d) + d_rounding, + size = rounded_frame_size (d); + + if (warn_stack_larger_than && size > stack_larger_than_size) + warning ("stack usage is %d bytes", size); + + output_stack_adjust (-size + d_rounding, stack_pointer_rtx, TARGET_SH5 ? 0 : 1, frame_insn); if (frame_pointer_needed) @@ -4830,7 +4897,7 @@ sh_expand_prologue () } void -sh_expand_epilogue () +sh_expand_epilogue (bool sibcall_p) { HOST_WIDE_INT live_regs_mask[(FIRST_PSEUDO_REGISTER + 31) / 32]; int d, i; @@ -4838,9 +4905,22 @@ sh_expand_epilogue () int save_flags = target_flags; int frame_size; + int temp; calc_live_regs (&d, live_regs_mask); + if (! sibcall_p) + temp = 7; + else if (TARGET_SHMEDIA) + temp = 1; + else + { + for (i = FIRST_GENERAL_REG; i <= LAST_GENERAL_REG; i++) + if (TEST_HARD_REG_BIT (live_regs_mask, i)) + break; + temp = (i <= LAST_GENERAL_REG) ? i : -1; + } + if (TARGET_SH5 && d % (STACK_BOUNDARY / BITS_PER_UNIT)) d_rounding = ((STACK_BOUNDARY / BITS_PER_UNIT) - d % (STACK_BOUNDARY / BITS_PER_UNIT)); @@ -4849,7 +4929,7 @@ sh_expand_epilogue () if (frame_pointer_needed) { - output_stack_adjust (frame_size, frame_pointer_rtx, 7, emit_insn); + output_stack_adjust (frame_size, frame_pointer_rtx, temp, emit_insn); /* We must avoid moving the stack pointer adjustment past code which reads from the local frame, else an interrupt could @@ -4865,7 +4945,7 @@ sh_expand_epilogue () occur after the SP adjustment and clobber data in the local frame. */ emit_insn (gen_blockage ()); - output_stack_adjust (frame_size, stack_pointer_rtx, 7, emit_insn); + output_stack_adjust (frame_size, stack_pointer_rtx, temp, emit_insn); } if (SHMEDIA_REGS_STACK_ADJUST ()) @@ -5041,7 +5121,7 @@ sh_expand_epilogue () output_stack_adjust (extra_push + current_function_pretend_args_size + d + d_rounding + current_function_args_info.stack_regs * 8, - stack_pointer_rtx, 7, emit_insn); + stack_pointer_rtx, (sibcall_p ? -1 : temp), emit_insn); /* Switch back to the normal stack if necessary. */ if (sp_switch) @@ -5065,7 +5145,7 @@ sh_need_epilogue () rtx epilogue; start_sequence (); - sh_expand_epilogue (); + sh_expand_epilogue (0); epilogue = get_insns (); end_sequence (); sh_need_epilogue_known = (epilogue == NULL ? -1 : 1); @@ -5238,7 +5318,7 @@ sh_build_va_list () if (TARGET_SH5 || (! TARGET_SH3E && ! TARGET_SH4) || TARGET_HITACHI) return ptr_type_node; - record = make_node (RECORD_TYPE); + record = (*lang_hooks.types.make_type) (RECORD_TYPE); f_next_o = build_decl (FIELD_DECL, get_identifier ("__va_next_o"), ptr_type_node); @@ -7857,4 +7937,58 @@ sh_register_operand (op, mode) return register_operand (op, mode); } +rtx +sh_get_pr_initial_val (void) +{ + return + get_hard_reg_initial_val (Pmode, TARGET_SHMEDIA ? PR_MEDIA_REG : PR_REG); +} + +/* INSN is an sfunc; return the rtx that describes the address used. */ +static rtx +extract_sfunc_addr (rtx insn) +{ + rtx pattern, part = NULL_RTX; + int len, i; + + pattern = PATTERN (insn); + len = XVECLEN (pattern, 0); + for (i = 0; i < len; i++) + { + part = XVECEXP (pattern, 0, i); + if (GET_CODE (part) == USE && GET_MODE (XEXP (part, 0)) == Pmode + && GENERAL_REGISTER_P (true_regnum (XEXP (part, 0)))) + return XEXP (part, 0); + } + if (GET_CODE (XVECEXP (pattern, 0, 0)) == UNSPEC_VOLATILE) + return XVECEXP (XVECEXP (pattern, 0, 0), 0, 1); + abort (); +} + +/* Verify that the register in use_sfunc_addr still agrees with the address + used in the sfunc. This prevents fill_slots_from_thread from changing + use_sfunc_addr. + INSN is the use_sfunc_addr instruction, and REG is the register it + guards. */ +int +check_use_sfunc_addr (rtx insn, rtx reg) +{ + /* Search for the sfunc. It should really come right after INSN. */ + while ((insn = NEXT_INSN (insn))) + { + if (GET_CODE (insn) == CODE_LABEL || GET_CODE (insn) == JUMP_INSN) + break; + if (! INSN_P (insn)) + continue; + + if (GET_CODE (PATTERN (insn)) == SEQUENCE) + insn = XVECEXP (PATTERN (insn), 0, 0); + if (GET_CODE (PATTERN (insn)) != PARALLEL + || get_attr_type (insn) != TYPE_SFUNC) + continue; + return rtx_equal_p (extract_sfunc_addr (insn), reg); + } + abort (); +} + #include "gt-sh.h" diff --git a/gnu/usr.bin/gcc/gcc/config/sh/sh.h b/gnu/usr.bin/gcc/gcc/config/sh/sh.h index 14667794e20..e8310502d34 100644 --- a/gnu/usr.bin/gcc/gcc/config/sh/sh.h +++ b/gnu/usr.bin/gcc/gcc/config/sh/sh.h @@ -2140,9 +2140,7 @@ while (0) can ignore COUNT. */ #define RETURN_ADDR_RTX(COUNT, FRAME) \ - (((COUNT) == 0) \ - ? get_hard_reg_initial_val (Pmode, TARGET_SHMEDIA ? PR_MEDIA_REG : PR_REG) \ - : (rtx) 0) + (((COUNT) == 0) ? sh_get_pr_initial_val () : (rtx) 0) /* A C expression whose value is RTL representing the location of the incoming return address at the beginning of any function, before the @@ -2989,7 +2987,7 @@ while (0) #define ASM_OUTPUT_LABELREF(FILE, NAME) \ do \ { \ - char * lname; \ + const char * lname; \ \ STRIP_DATALABEL_ENCODING (lname, (NAME)); \ if (lname[0] == '*') \ diff --git a/gnu/usr.bin/gcc/gcc/config/sh/t-openbsd b/gnu/usr.bin/gcc/gcc/config/sh/t-openbsd new file mode 100644 index 00000000000..408530f7ec7 --- /dev/null +++ b/gnu/usr.bin/gcc/gcc/config/sh/t-openbsd @@ -0,0 +1,19 @@ +#TARGET_LIBGCC2_CFLAGS = -fpic +TARGET_LIBGCC2_CFLAGS = +LIB1ASMFUNCS_CACHE = _ic_invalidate + +LIB2FUNCS_EXTRA= + +EXTRA_MULTILIB_PARTS= + +# OpenBSD's C library includes a fast software FP library that +# has support for setting/setting the rounding mode, exception +# mask, etc. Therefore, we don't want to include software FP +# in libgcc. +FPBIT = +DPBIT = + +MULTILIB_OPTIONS += m3e/m4 +MULTILIB_DIRNAMES= +MULTILIB_MATCHES = +MULTILIB_EXCEPTIONS= |