summaryrefslogtreecommitdiff
path: root/gnu/usr.bin
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2006-10-06 20:58:18 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2006-10-06 20:58:18 +0000
commitb50063e7723d8a96f3eaeb641e59f7f161dcd917 (patch)
tree912a3440a1bc70d7ac987e099524134196c40874 /gnu/usr.bin
parentbf3a6255750ff2254e0357e9e01506962b1f316f (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-wrapper4
-rw-r--r--gnu/usr.bin/binutils/bfd/config.bfd2
-rw-r--r--gnu/usr.bin/binutils/gas/configure1
-rw-r--r--gnu/usr.bin/binutils/gas/configure.in1
-rw-r--r--gnu/usr.bin/binutils/gdb/configure.tgt2
-rw-r--r--gnu/usr.bin/binutils/gdb/sh-tdep.c14
-rw-r--r--gnu/usr.bin/binutils/ld/configure.tgt2
-rw-r--r--gnu/usr.bin/gcc/gcc/config.gcc7
-rw-r--r--gnu/usr.bin/gcc/gcc/config/sh/openbsd.h106
-rw-r--r--gnu/usr.bin/gcc/gcc/config/sh/sh-protos.h7
-rw-r--r--gnu/usr.bin/gcc/gcc/config/sh/sh.c164
-rw-r--r--gnu/usr.bin/gcc/gcc/config/sh/sh.h6
-rw-r--r--gnu/usr.bin/gcc/gcc/config/sh/t-openbsd19
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=