diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/config/picflag.m4 gcc-4.8.2-or1k-rtems/config/picflag.m4 --- gcc-4.8.2/config/picflag.m4 2012-01-23 08:25:28.000000000 +0200 +++ gcc-4.8.2-or1k-rtems/config/picflag.m4 2014-03-17 04:22:39.605043272 +0200 @@ -39,6 +39,9 @@ mips-sgi-irix6*) # PIC is the default. ;; + or1k-*-*) + $1=-fPIC + ;; rs6000-ibm-aix* | powerpc-ibm-aix*) # All AIX code is PIC. ;; diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/config.guess gcc-4.8.2-or1k-rtems/config.guess --- gcc-4.8.2/config.guess 2013-01-09 00:46:38.000000000 +0200 +++ gcc-4.8.2-or1k-rtems/config.guess 2014-03-17 09:14:15.665104892 +0200 @@ -957,8 +957,11 @@ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } ;; - or32:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + or1k:Linux:*:*) + echo or1k-unknown-linux-gnu + exit ;; + or1knd:Linux:*:*) + echo or1knd-unknown-linux-gnu exit ;; padre:Linux:*:*) echo sparc-unknown-linux-gnu diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/config.sub gcc-4.8.2-or1k-rtems/config.sub --- gcc-4.8.2/config.sub 2013-01-11 15:02:58.000000000 +0200 +++ gcc-4.8.2-or1k-rtems/config.sub 2014-03-17 09:09:36.721103909 +0200 @@ -300,7 +300,7 @@ | nios | nios2 \ | ns16k | ns32k \ | open8 \ - | or32 \ + | or1k | or1knd \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ | pyramid \ @@ -922,9 +922,12 @@ basic_machine=hppa1.1-oki os=-proelf ;; - openrisc | openrisc-*) - basic_machine=or32-unknown + or1k | or1k-*) + basic_machine=or1k-unknown ;; + or1knd | or1knd-*) + basic_machine=or1knd-unknown + ;; os400) basic_machine=powerpc-ibm os=-os400 @@ -1593,7 +1596,10 @@ mips*-*) os=-elf ;; - or32-*) + or1k-*) + os=-coff + ;; + or1knd-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/common/config/or1k/or1k-common.c gcc-4.8.2-or1k-rtems/gcc/common/config/or1k/or1k-common.c --- gcc-4.8.2/gcc/common/config/or1k/or1k-common.c 1970-01-01 02:00:00.000000000 +0200 +++ gcc-4.8.2-or1k-rtems/gcc/common/config/or1k/or1k-common.c 2014-03-14 07:27:49.000000000 +0200 @@ -0,0 +1,61 @@ +/* Common hooks for OR1K. + Copyright (C) 2011 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC 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 3, or (at your option) + any later version. + + GCC 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 GCC; see the file COPYING3. If not see + . */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tm.h" +#include "common/common-target.h" +#include "common/common-target-def.h" +#include "opts.h" +#include "flags.h" + +/* Implement TARGET_OPTION_OPTIMIZATION_TABLE. */ +static const struct default_options or1k_option_optimization_table[] = + { + { OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1 }, + { OPT_LEVELS_NONE, 0, NULL, 0 } + }; + +/* Implement TARGET_EXCEPT_UNWIND_INFO. */ +static enum unwind_info_type +or1k_except_unwind_info (struct gcc_options *opts) +{ + /* Honor the --enable-sjlj-exceptions configure switch. */ +#ifdef CONFIG_SJLJ_EXCEPTIONS + if (CONFIG_SJLJ_EXCEPTIONS) + return UI_SJLJ; +#endif + + if (DWARF2_UNWIND_INFO) + return UI_DWARF2; + + return UI_SJLJ; +} + +#undef TARGET_EXCEPT_UNWIND_INFO +#define TARGET_EXCEPT_UNWIND_INFO or1k_except_unwind_info + +#undef TARGET_OPTION_OPTIMIZATION_TABLE +#define TARGET_OPTION_OPTIMIZATION_TABLE or1k_option_optimization_table + +#undef TARGET_DEFAULT_TARGET_FLAGS +#define TARGET_DEFAULT_TARGET_FLAGS (MASK_HARD_MUL) + +struct gcc_targetm_common targetm_common = TARGETM_COMMON_INITIALIZER; diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/config/or1k/constraints.md gcc-4.8.2-or1k-rtems/gcc/config/or1k/constraints.md --- gcc-4.8.2/gcc/config/or1k/constraints.md 1970-01-01 02:00:00.000000000 +0200 +++ gcc-4.8.2-or1k-rtems/gcc/config/or1k/constraints.md 2014-03-14 07:27:49.000000000 +0200 @@ -0,0 +1,59 @@ +;; Copyright (C) 2010 Embecosm Limited +;; +;; Contributed by Joern Rennecke in 2010 +;; +;; This file is part of GCC. +;; +;; GCC 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 3, or (at your option) +;; any later version. +;; +;; GCC 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 GCC; see the file COPYING3. If not see +;; . + +(define_constraint "I" + "" + (and (match_code "const_int") + (match_test "ival >= -32768 && ival <= 32767"))) + +(define_constraint "J" + "" + (and (match_code "const_int") + (match_test "ival == 0"))) + +(define_constraint "K" + "" + (and (match_code "const_int") + (match_test "ival >= 0 && ival <= 65535"))) + +(define_constraint "L" + "" + (and (match_code "const_int") + (match_test "ival >= 0 && ival <= 31"))) + +(define_constraint "M" + "" + (and (match_code "const_int") + (match_test "(ival & 0xffff) == 0"))) + +(define_constraint "N" + "" + (and (match_code "const_int") + (match_test "ival >= -33554432 && ival <= 33554431"))) + +(define_constraint "O" + "" + (and (match_code "const_int") + (match_test "ival == 0"))) + +(define_constraint "C" + "" + (match_code "const_double")) + diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/config/or1k/elf.h gcc-4.8.2-or1k-rtems/gcc/config/or1k/elf.h --- gcc-4.8.2/gcc/config/or1k/elf.h 1970-01-01 02:00:00.000000000 +0200 +++ gcc-4.8.2-or1k-rtems/gcc/config/or1k/elf.h 2014-04-28 18:11:06.181280553 +0200 @@ -0,0 +1,31 @@ +/* Definitions for rtems targeting an OpenRisc OR1K using COFF + ??? this is for OR1K, but the rest of the above seems bogus. + Copyright (C) 1996, 1997, 2005 Free Software Foundation, Inc. + Contributed by Joel Sherrill (joel@OARcorp.com). + +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 GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* Use ELF */ +#undef OBJECT_FORMAT_ELF +#define OBJECT_FORMAT_ELF + +/* or1k debug info support is controlled by tm.h header files we include: + dbxelf.h enables optional stabs debug info. + elfos.h sets PREFERRED_DEBUGGING_TYPE to DWARF2_DEBUG . */ + +#define DRIVER_SELF_SPECS "%{!mno-newlib:-mnewlib}" diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/config/or1k/elf.h.rej gcc-4.8.2-or1k-rtems/gcc/config/or1k/elf.h.rej --- gcc-4.8.2/gcc/config/or1k/elf.h.rej 1970-01-01 02:00:00.000000000 +0200 +++ gcc-4.8.2-or1k-rtems/gcc/config/or1k/elf.h.rej 2014-04-28 18:10:09.429312182 +0200 @@ -0,0 +1,34 @@ +--- gcc/config/or1k/elf.h 2014-04-28 10:45:18.320114849 -0500 ++++ gcc/config/or1k/elf.h 1969-12-31 18:00:00.000000000 -0600 +@@ -1,31 +0,0 @@ +-/* Definitions for rtems targeting an OpenRisc OR1K using COFF +- ??? this is for OR1K, but the rest of the above seems bogus. +- Copyright (C) 1996, 1997, 2005 Free Software Foundation, Inc. +- Contributed by Joel Sherrill (joel@OARcorp.com). +- +-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 GNU CC; see the file COPYING. If not, write to +-the Free Software Foundation, 59 Temple Place - Suite 330, +-Boston, MA 02111-1307, USA. */ +- +-/* Use ELF */ +-#undef OBJECT_FORMAT_ELF +-#define OBJECT_FORMAT_ELF +- +-/* or1k debug info support is controlled by tm.h header files we include: +- dbxelf.h enables optional stabs debug info. +- elfos.h sets PREFERRED_DEBUGGING_TYPE to DWARF2_DEBUG . */ +- +-#define DRIVER_SELF_SPECS "%{!mno-newlib:-mnewlib}" diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/config/or1k/linux-elf.h gcc-4.8.2-or1k-rtems/gcc/config/or1k/linux-elf.h --- gcc-4.8.2/gcc/config/or1k/linux-elf.h 1970-01-01 02:00:00.000000000 +0200 +++ gcc-4.8.2-or1k-rtems/gcc/config/or1k/linux-elf.h 2014-03-14 07:27:49.000000000 +0200 @@ -0,0 +1,97 @@ +/* Definitions for or1k running Linux-based GNU systems using ELF + Copyright (C) 2002, 2005 + Free Software Foundation, Inc. + Contributed by Marko Mlinar + +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. */ + +/* elfos.h should have already been included. Now just override + any conflicting definitions and add any extras. */ + +/* Do not assume anything about header files. */ +#define NO_IMPLICIT_EXTERN_C + +/* This is how we tell the assembler that two symbols have the same value. */ +#define ASM_OUTPUT_DEF(FILE, NAME1, NAME2) \ + do \ + { \ + assemble_name (FILE, NAME1); \ + fputs (" = ", FILE); \ + assemble_name (FILE, NAME2); \ + fputc ('\n', FILE); \ + } \ + while (0) + + +#if 0 +/* Node: Label Output */ + +#define SET_ASM_OP "\t.set\t" + +#define ASM_OUTPUT_EXTERNAL_LIBCALL(FILE, FUN) \ + (*targetm.asm_out.globalize_label) (FILE, XSTR (FUN, 0)) + +#define ASM_WEAKEN_LABEL(FILE, NAME) \ + do \ + { \ + fputs ("\t.weak\t", (FILE)); \ + assemble_name ((FILE), (NAME)); \ + fputc ('\n', (FILE)); \ + } \ + while (0) + +#endif + +/* The GNU C++ standard library requires that these macros be defined. */ +#undef CPLUSPLUS_CPP_SPEC +#define CPLUSPLUS_CPP_SPEC "-D_GNU_SOURCE %(cpp)" + +#undef DRIVER_SELF_SPECS +#define DRIVER_SELF_SPECS "" + +#define GLIBC_DYNAMIC_LINKER "/lib/ld.so.1" + +/* Define a set of Linux builtins. This is copied from linux.h. We can't + include the whole file for now, because that causes configure to require ld + to support --eh-frame-header, which it currently doesn't */ +#define LINUX_TARGET_OS_CPP_BUILTINS() \ + do { \ + builtin_define ("__gnu_linux__"); \ + builtin_define_std ("linux"); \ + builtin_define_std ("unix"); \ + builtin_assert ("system=linux"); \ + builtin_assert ("system=unix"); \ + builtin_assert ("system=posix"); \ + } while (0) + +#define TARGET_OS_CPP_BUILTINS() \ + do { \ + LINUX_TARGET_OS_CPP_BUILTINS(); \ + if (OPTION_UCLIBC) \ + builtin_define ("__UCLIBC__"); \ + /* The GNU C++ standard library requires this. */ \ + if (c_dialect_cxx ()) \ + builtin_define ("_GNU_SOURCE"); \ + } while (0) + +#undef LINK_SPEC +#define LINK_SPEC "%{mnewlib:-entry 0x100} \ + -dynamic-linker " GNU_USER_DYNAMIC_LINKER " \ + %{static:-static} \ + %{shared:-shared}" + diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/config/or1k/linux-gas.h gcc-4.8.2-or1k-rtems/gcc/config/or1k/linux-gas.h --- gcc-4.8.2/gcc/config/or1k/linux-gas.h 1970-01-01 02:00:00.000000000 +0200 +++ gcc-4.8.2-or1k-rtems/gcc/config/or1k/linux-gas.h 2014-03-14 07:27:49.000000000 +0200 @@ -0,0 +1,37 @@ +/* Definitions of target machine for GNU compiler. + Or32 Linux-based GNU systems version. + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + Contributed by Marko Mlinar + +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. */ + +/* Unsigned chars produces much better code than signed. */ +#undef DEFAULT_SIGNED_CHAR +#define DEFAULT_SIGNED_CHAR 1 + +/* Make gcc agree with */ + +#define SIZE_TYPE "unsigned int" +#define PTRDIFF_TYPE "int" +#define WCHAR_TYPE "unsigned int" +#define WCHAR_TYPE_SIZE 32 + + +/* Clear the instruction cache from `beg' to `end'. This makes an + inline system call to SYS_cacheflush. */ +#define CLEAR_INSN_CACHE(BEG, END) /* Do something here !!! */ diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/config/or1k/or1k.c gcc-4.8.2-or1k-rtems/gcc/config/or1k/or1k.c --- gcc-4.8.2/gcc/config/or1k/or1k.c 1970-01-01 02:00:00.000000000 +0200 +++ gcc-4.8.2-or1k-rtems/gcc/config/or1k/or1k.c 2014-03-14 07:27:49.000000000 +0200 @@ -0,0 +1,2263 @@ +/* Subroutines for insn-output.c for GNU compiler. OpenRISC 1000 version. + Copyright (C) 1987, 1992, 1997, 1999, 2000, 2001, 2002, 2003, 2004, + 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc + Copyright (C) 2010 Embecosm Limited + + Contributed by Damjan Lampret in 1999. + Major optimizations by Matjaz Breskvar in 2005. + Updated for GCC 4.5 by Jeremy Bennett + and Joern Rennecke in 2010. + + This file is part of GNU CC. + + This program 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 3 of the License, or (at your option) + any later version. + + This program 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. If not, see . */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tm.h" +#include "rtl.h" +#include "tree.h" +#include "obstack.h" +#include "regs.h" +#include "hard-reg-set.h" +#include "real.h" +#include "insn-config.h" +#include "conditions.h" +#include "output.h" +#include "insn-attr.h" +#include "flags.h" +#include "reload.h" +#include "function.h" +#include "expr.h" +#include "toplev.h" +#include "recog.h" +#include "ggc.h" +#include "except.h" +#include "tm_p.h" +#include "target.h" +#include "target-def.h" +#include "debug.h" +#include "langhooks.h" +#include "df.h" +#include "dwarf2.h" +#include "ansidecl.h" + +/* ========================================================================== */ +/* Local macros */ + +/* Construct a l.movhi instruction for the given reg and value */ +#define OR1K_MOVHI(rd, k) \ + ((0x6 << 26) | ((rd) << 21) | (k)) + +/* Construct a l.ori instruction for the given two regs and value */ +#define OR1K_ORI(rd, ra, k) \ + ((0x2a << 26) | ((rd) << 21) | ((ra) << 16) | (k)) + +/* Construct a l.lwz instruction for the given two registers and offset */ +#define OR1K_LWZ(rd, ra, i) \ + ((0x21 << 26) | ((rd) << 21) | ((ra) << 16) | (i)) + +/* Construct a l.jr instruction for the given register */ +#define OR1K_JR(rb) \ + ((0x11 << 26) | ((rb) << 11)) + +#define OR1K_NOP \ + (0x15 << 24) + +/* ========================================================================== */ +/* Static variables (i.e. global to this file only. */ + + +/*!Stack layout we use for pushing and poping saved registers */ +static struct +{ + bool save_lr_p; + int lr_save_offset; + bool save_fp_p; + int fp_save_offset; + int gpr_size; + int gpr_offset; + int total_size; + int vars_size; + int args_size; + int gpr_frame; + int late_frame; + HOST_WIDE_INT mask; +} frame_info; + + +/* ========================================================================== */ +/* Local (i.e. static) utility functions */ + +/* -------------------------------------------------------------------------- */ +/*!Must the current function save a register? + + @param[in] regno The register to consider. + + @return Non-zero (TRUE) if current function must save "regno", zero + (FALSE) otherwise. */ +/* -------------------------------------------------------------------------- */ +static bool +or1k_save_reg_p (int regno) +{ + /* No need to save the faked cc0 register. */ + if (regno == OR1K_FLAGS_REG) + return false; + + /* Check call-saved registers. */ + if (df_regs_ever_live_p(regno) && !call_used_regs[regno]) + return true; + + /* We need to save the old frame pointer before setting up a new + one. */ + if (regno == HARD_FRAME_POINTER_REGNUM && frame_pointer_needed) + return true; + + /* Save the stack pointer for DWARF2 for now. + * AFAIK, DWARF should be able to unwind using only the current stack + * register and the CFA offset, but I never got that to work. */ + if (regno == STACK_POINTER_REGNUM && !frame_pointer_needed) + return true; + + /* We need to save the incoming return address if it is ever clobbered + within the function. */ + if (regno == LINK_REGNUM + && (df_regs_ever_live_p(regno) || crtl->uses_pic_offset_table + || cfun->machine->force_lr_save)) + return true; + + if(crtl->calls_eh_return) + { + unsigned int i; + for (i = 0; EH_RETURN_DATA_REGNO (i) != INVALID_REGNUM; i++) + { + if ((unsigned int)regno == EH_RETURN_DATA_REGNO (i)) + return true; + } + } + + return false; + +} /* or1k_save_reg_p () */ + +bool +or1k_save_reg_p_cached (int regno) +{ + return (frame_info.mask & ((HOST_WIDE_INT) 1 << regno)) != 0; +} + +/* N.B. contrary to the ISA documentation, the stack includes the outgoing + arguments. */ +/* -------------------------------------------------------------------------- */ +/*!Compute full frame size and layout. + + Store information in "frame_info". + + @param[in] size The size of the function's local variables. + + @return Total size of stack frame. */ +/* -------------------------------------------------------------------------- */ +static HOST_WIDE_INT +or1k_compute_frame_size (HOST_WIDE_INT size) +{ + HOST_WIDE_INT args_size; + HOST_WIDE_INT vars_size; + HOST_WIDE_INT stack_offset; + HOST_WIDE_INT save_size; + bool interrupt_p = false; + int regno; + + args_size = crtl->outgoing_args_size; + vars_size = OR1K_ALIGN (size, 4); + + frame_info.args_size = args_size; + frame_info.vars_size = vars_size; + frame_info.gpr_frame = interrupt_p ? or1k_redzone : 0; + + /* If the function has local variables, we're committed to + allocating it anyway. Otherwise reclaim it here. */ + /* FIXME: Verify this. Got if from the MIPS port. */ + if (vars_size == 0 && crtl->is_leaf) + args_size = 0; + + stack_offset = 0; + + /* Save link register right at the bottom. */ + if (or1k_save_reg_p (LINK_REGNUM)) + { + stack_offset = stack_offset - UNITS_PER_WORD; + frame_info.lr_save_offset = stack_offset; + frame_info.save_lr_p = true; + } + else + frame_info.save_lr_p = false; + + /* HACK: In PIC mode we need to save the PIC reg and the link reg in + in case the function is doing references through the got or plt, + but this information is not necessarily available when the initial + elimination offset is calculated, so we always reserve the space even + if it is not used... */ + if (!frame_info.save_lr_p && flag_pic) + stack_offset = stack_offset - UNITS_PER_WORD; + + /* Save frame pointer right after possible link register. */ + if (frame_pointer_needed) + { + stack_offset = stack_offset - UNITS_PER_WORD; + frame_info.fp_save_offset = stack_offset; + frame_info.save_fp_p = true; + } + else + frame_info.save_fp_p = false; + + frame_info.gpr_size = 0; + frame_info.mask = 0; + + for (regno = 0; regno <= OR1K_LAST_ACTUAL_REG; regno++) + { + if (regno == LINK_REGNUM + || (frame_pointer_needed && regno == HARD_FRAME_POINTER_REGNUM)) + /* These have already been saved if so needed. */ + continue; + + if (or1k_save_reg_p (regno)) + { + frame_info.gpr_size += UNITS_PER_WORD; + frame_info.mask |= ((HOST_WIDE_INT) 1 << regno); + } + } + + if (!or1k_save_reg_p (PIC_OFFSET_TABLE_REGNUM) + && (crtl->uses_pic_offset_table || (flag_pic && frame_info.save_lr_p))) + { + frame_info.gpr_size += UNITS_PER_WORD; + frame_info.mask |= ((HOST_WIDE_INT) 1 << PIC_OFFSET_TABLE_REGNUM); + } + else if (flag_pic && !or1k_save_reg_p (PIC_OFFSET_TABLE_REGNUM)) + frame_info.gpr_size += UNITS_PER_WORD; + + save_size = (frame_info.gpr_size + + (frame_info.save_fp_p ? UNITS_PER_WORD : 0) + + (frame_info.save_lr_p || flag_pic ? UNITS_PER_WORD : 0)); + frame_info.total_size = save_size + vars_size + args_size; + gcc_assert (PROLOGUE_TMP != STATIC_CHAIN_REGNUM); + if (frame_info.total_size > 32767 && interrupt_p) + { + int n_extra + = (!!(~frame_info.mask && 1 << PROLOGUE_TMP) + + !!(~frame_info.mask & 1 << EPILOGUE_TMP)) * UNITS_PER_WORD; + + save_size += n_extra; + frame_info.gpr_size += n_extra; + frame_info.total_size += n_extra; + frame_info.mask |= (1 << PROLOGUE_TMP) | (1 << EPILOGUE_TMP); + } + + stack_offset -= frame_info.gpr_size; + frame_info.gpr_offset = stack_offset; + frame_info.late_frame = frame_info.total_size; + + if (save_size > or1k_redzone + || (frame_info.gpr_frame + && (frame_info.gpr_frame + frame_info.late_frame <= 32767))) + { + if (frame_info.gpr_frame + frame_info.late_frame <= 32767) + save_size = frame_info.total_size; + frame_info.gpr_frame += save_size; + frame_info.lr_save_offset += save_size; + frame_info.fp_save_offset += save_size; + frame_info.gpr_offset += save_size; + frame_info.late_frame -= save_size; + /* FIXME: check in TARGET_OVERRIDE_OPTIONS for invalid or1k_redzone. */ + gcc_assert (frame_info.gpr_frame <= 32767); + gcc_assert ((frame_info.gpr_frame & 3) == 0); + } + + return frame_info.total_size; + +} /* or1k_compute_frame_size () */ + + +/* -------------------------------------------------------------------------- */ +/*!Emit a frame related insn. + + Same as emit_insn, but sets RTX_FRAME_RELATED_P to one. Getting this right + will matter for DWARF 2 output, if prologues are handled via the "prologue" + pattern rather than target hooks. + + @param[in] insn The insn to emit. + + @return The RTX for the emitted insn. */ +/* -------------------------------------------------------------------------- */ +static rtx +emit_frame_insn (rtx insn) +{ + insn = emit_insn (insn); + RTX_FRAME_RELATED_P (insn) = 1; + return (insn); + +} /* emit_frame_insn () */ + + +/* -------------------------------------------------------------------------- */ +/* Generate a RTX for the indexed memory address based on stack_pointer_rtx + and a displacement + + @param[in] disp The displacement + + @return The RTX for the generated address. */ +/* -------------------------------------------------------------------------- */ +static rtx +stack_disp_mem (HOST_WIDE_INT disp) +{ + return gen_frame_mem (Pmode, plus_constant (Pmode, stack_pointer_rtx, disp)); +} + +enum machine_mode +or1k_select_cc_mode (enum rtx_code op) +{ + switch (op) { + case EQ: return CCEQmode; + case NE: return CCNEmode; + case GEU: return CCGEUmode; + case GTU: return CCGTUmode; + case LTU: return CCLTUmode; + case LEU: return CCLEUmode; + case GE: return CCGEmode; + case LT: return CCLTmode; + case GT: return CCGTmode; + case LE: return CCLEmode; + default: gcc_unreachable (); + } +} + +/* -------------------------------------------------------------------------- */ +/*!Generate insn patterns to do an integer compare of operands. + + @param[in] code RTX for the condition code. + @param[in] op0 RTX for the first operand. + @param[in] op1 RTX for the second operand. + + @return RTX for the comparison. */ +/* -------------------------------------------------------------------------- */ +static rtx +or1k_expand_int_compare (enum rtx_code code, + rtx op0, + rtx op1) +{ + enum machine_mode cmpmode; + rtx tmp, flags; + + cmpmode = or1k_select_cc_mode (code); + flags = gen_rtx_REG (cmpmode, OR1K_FLAGS_REG); + + /* This is very simple, but making the interface the same as in the + FP case makes the rest of the code easier. */ + tmp = gen_rtx_COMPARE (cmpmode, op0, op1); + emit_insn (gen_rtx_SET (VOIDmode, flags, tmp)); + + /* Return the test that should be put into the flags user, i.e. + the bcc, scc, or cmov instruction. */ + return gen_rtx_fmt_ee (code, VOIDmode, flags, const0_rtx); + +} /* or1k_expand_int_compare () */ + + +/* -------------------------------------------------------------------------- */ +/*!Generate insn patterns to do an integer compare of operands. + + We only deal with the case where the comparison is an integer + comparison. This wrapper function potentially allows reuse for non-integer + comparison in the future. + + @param[in] code RTX for the condition code. + @param[in] op0 RTX for the first operand. + @param[in] op1 RTX for the second operand. + + @return RTX for the comparison. */ +/* -------------------------------------------------------------------------- */ +static rtx +or1k_expand_compare (enum rtx_code code, rtx op0, rtx op1) +{ + return or1k_expand_int_compare (code, op0, op1); + +} /* or1k_expand_compare () */ + + +/* -------------------------------------------------------------------------- */ +/*!Emit insns to use the l.cmov instruction + + Emit a compare and then cmov. Only works for integer first operand. + + @param[in] dest RTX for the destination operand. + @param[in] op RTX for the comparison operation + @param[in] true_cond RTX to move to dest if condition is TRUE. + @param[in] false_cond RTX to move to dest if condition is FALSE. + + @return Non-zero (TRUE) if insns were emitted, zero (FALSE) otherwise. */ +/* -------------------------------------------------------------------------- */ +static int +or1k_emit_int_cmove (rtx dest, + rtx op, + rtx true_cond, + rtx false_cond) +{ + rtx condition_rtx, cr; + rtx op0 = XEXP (op, 0); + rtx op1 = XEXP (op, 1); + + if ((GET_MODE (op0) != SImode) && + (GET_MODE (op0) != HImode) && + (GET_MODE (op0) != QImode)) + { + return 0; + } + + /* We still have to do the compare, because cmov doesn't do a compare, it + just looks at the FLAG bit set by a previous compare instruction. */ + condition_rtx = or1k_expand_compare (GET_CODE (op), op0, op1); + + cr = XEXP (condition_rtx, 0); + + emit_insn (gen_cmov (dest, condition_rtx, true_cond, false_cond, cr)); + + return 1; + +} /* or1k_emit_int_cmove () */ + + +static void +or1k_print_operand_address (FILE *stream, rtx addr) +{ + rtx offset; + + switch (GET_CODE (addr)) + { + case MEM: + if (GET_CODE (XEXP (addr, 0)) == REG) + fprintf (stream, "%s", reg_names[REGNO (addr)]); + else + abort (); + break; + + case REG: + fprintf (stream, "0(%s)", reg_names[REGNO (addr)]); + break; + + case PLUS: + offset = 0; + + if (GET_CODE (XEXP (addr, 0)) == REG) + { + offset = XEXP (addr, 1); + addr = XEXP (addr, 0); + } + else if (GET_CODE (XEXP (addr, 1)) == REG) + { + offset = XEXP (addr, 0); + addr = XEXP (addr, 1); + } + output_address (offset); + fprintf (stream, "(%s)", reg_names[REGNO (addr)]); + break; + + case SYMBOL_REF: + if (SYMBOL_REF_DECL (addr)) + assemble_external (SYMBOL_REF_DECL (addr)); + + if (XSTR (addr, 0)[0] == '*') + fputs (&XSTR (addr, 0)[1], stream); + else + { + asm_fprintf (stream, "%U%s", XSTR (addr, 0)); + } + break; + + default: + output_addr_const (stream, addr); + } +} + +/* -------------------------------------------------------------------------- */ +/*!Is this a value suitable for an OR1K address displacement? + + Must be an integer (signed) which fits into 16-bits. If the result is a + double word, we had better also check that we can also get at the second + word. + + @param[in] mode Mode of the result for which this displacement will be + used. + @param[in] x RTX for an expression. + + @return Non-zero (TRUE) if this is a valid 16-bit offset, zero (FALSE) + otherwise. */ +/* -------------------------------------------------------------------------- */ +static int +or1k_legitimate_displacement_p (enum machine_mode mode, + rtx x) +{ + if (CONST_INT == GET_CODE(x)) + { + HOST_WIDE_INT disp = INTVAL (x); + + /* Allow for a second access 4 bytes further on if double. */ + if ((DFmode == mode) || (DImode == mode)) + { + return (-32768 < disp) && (disp <= 32763); + } + else + { + return (-32768 < disp) && (disp <= 32767); + } + } + else + { + return 0; + } +} /* or1k_legitimate_displacement_p () */ + + +/* -------------------------------------------------------------------------- */ +/*!Can this register be used as a base register? + + We need a strict version, for which the register must either be a hard + register, or already renumbered to a hard register. + + For the non-strict version, any register (other than the flag register will + do). + + @todo The code from the old port does not allow r0 as a base when strict, + and does when non-strict. Surely it is always a valid register? + + @param[in] regno The register to test + @param[in] strict Non-zero (TRUE) if this is a strict check, zero (FALSE) + otherwise. + + @return Non-zero (TRUE) if this register can be used as a base register, + zero (FALSE) otherwise. */ +/* -------------------------------------------------------------------------- */ +static bool +or1k_regnum_ok_for_base_p (HOST_WIDE_INT num, + bool strict) +{ + if (strict) + { + return (num < FIRST_PSEUDO_REGISTER) + ? (num > 0) && (num <= OR1K_LAST_INT_REG) + : (reg_renumber[num] > 0) && (reg_renumber[num] <= OR1K_LAST_INT_REG); + } + else + { + return (num <= OR1K_LAST_INT_REG) || (num >= FIRST_PSEUDO_REGISTER); + } +} /* or1k_regnum_ok_for_base_p () */ + +int +or1k_legitimate_pic_operand_p (rtx x) +{ + if (GET_CODE (x) == CONST + && GET_CODE (XEXP (x, 0)) == PLUS + && ((GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF + && (!SYMBOL_REF_LOCAL_P (XEXP (XEXP (x, 0), 0)) + || SYMBOL_REF_WEAK (XEXP (XEXP (x, 0), 0)))) + || GET_CODE (XEXP (XEXP (x, 0), 0)) == LABEL_REF) + && CONST_INT_P (XEXP (XEXP (x, 0), 1))) + return or1k_legitimate_displacement_p (SImode, XEXP (XEXP (x, 0), 1)); + + return 1; +} + +static bool +or1k_expand_pic_symbol_ref (enum machine_mode mode ATTRIBUTE_UNUSED, + rtx operands[]) +{ + if (GET_CODE (operands[1]) == LABEL_REF + || (GET_CODE (operands[1]) == SYMBOL_REF + && SYMBOL_REF_LOCAL_P (operands[1]) + && !SYMBOL_REF_WEAK (operands[1]))) + { + crtl->uses_pic_offset_table = 1; + emit_insn (gen_movsi_gotoffhi (operands[0], operands[1])); + emit_insn (gen_movsi_gotofflo (operands[0], operands[0], + operands[1])); + emit_insn (gen_add3_insn(operands[0], operands[0], + pic_offset_table_rtx)); + return true; + } + else if (GET_CODE (operands[1]) == SYMBOL_REF) + { + crtl->uses_pic_offset_table = 1; + emit_insn (gen_movsi_got (operands[0], operands[1])); + return true; + } + else if (GET_CODE (operands[1]) == CONST + && GET_CODE (XEXP (operands[1], 0)) == PLUS + && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == SYMBOL_REF + && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == CONST_INT) + { + rtx symbolref = XEXP (XEXP (operands[1], 0), 0); + crtl->uses_pic_offset_table = 1; + + if (SYMBOL_REF_LOCAL_P (symbolref) + && !SYMBOL_REF_WEAK (symbolref)) + { + emit_insn (gen_movsi_gotoffhi (operands[0], operands[1])); + emit_insn (gen_movsi_gotofflo (operands[0], operands[0], + operands[1])); + emit_insn (gen_add3_insn(operands[0], operands[0], + pic_offset_table_rtx)); + } + else + { + rtx const_int = XEXP (XEXP (operands[1], 0), 1); + + /* Expand the constant into a register if it doesn't + fit directly as an 16-bit immediate in the add below. + Note that the reg allocation is allowed here since + we are guarded by LEGITIMATE_PIC_OPERAND_P. */ + if (!or1k_legitimate_displacement_p (mode, const_int)) + { + rtx scratch = gen_reg_rtx (mode); + + or1k_emit_set_const32 (scratch, const_int); + const_int = scratch; + } + + emit_insn (gen_movsi_got (operands[0], symbolref)); + emit_insn (gen_add3_insn(operands[0], operands[0], const_int)); + } + return true; + } + return false; +} + +/* Return the TLS type for TLS symbols, 0 otherwise. */ +enum tls_model +or1k_tls_symbolic_operand (rtx op) +{ + if (GET_CODE (op) == CONST) + { + rtx sym, addend; + split_const (op, &sym, &addend); + if (GET_CODE (sym) == SYMBOL_REF) + return SYMBOL_REF_TLS_MODEL (sym); + } + else if (GET_CODE (op) == SYMBOL_REF) + return SYMBOL_REF_TLS_MODEL (op); + + return TLS_MODEL_NONE; +} + +static GTY(()) rtx gen_tls_tga; + +/* Get reference to the '__tls_get_addr' symbol */ +static rtx +gen_tls_get_addr (void) +{ + if (!gen_tls_tga) + gen_tls_tga = init_one_libfunc ("__tls_get_addr"); + return gen_tls_tga; +} + +/* Emit call to '__tls_get_addr' */ +static void +or1k_tls_call (rtx arg) +{ + emit_library_call_value (gen_tls_get_addr(), arg, + LCT_CONST, Pmode, 1, arg, Pmode); +} + +bool +or1k_expand_symbol_ref(enum machine_mode mode, rtx operands[]) +{ + if (mode == Pmode) + { + rtx op0, op1; + enum tls_model tls_kind; + + op0 = operands[0]; + op1 = operands[1]; + + if ((tls_kind = or1k_tls_symbolic_operand (op1)) != TLS_MODEL_NONE) + { + rtx tp; + tp = gen_rtx_REG(Pmode, THREAD_PTR_REGNUM); + switch (tls_kind) + { + case TLS_MODEL_GLOBAL_DYNAMIC: + case TLS_MODEL_LOCAL_DYNAMIC: + /* TODO: For now, treat LD as GD */ + crtl->uses_pic_offset_table = 1; + emit_insn (gen_movsi_tlsgdhi (op0, op1)); + emit_insn (gen_movsi_tlsgdlo (op0, op0, op1)); + emit_insn (gen_add3_insn (op0, op0, pic_offset_table_rtx)); + or1k_tls_call (op0); + break; + + case TLS_MODEL_INITIAL_EXEC: + crtl->uses_pic_offset_table = 1; + emit_insn (gen_movsi_gottpoffhi (op0, op1)); + emit_insn (gen_movsi_gottpofflo (op0, op0, op1)); + emit_insn (gen_add3_insn (op0, op0, pic_offset_table_rtx)); + emit_insn (gen_load_gottpoff (op0, op0)); + emit_insn (gen_add3_insn (op0, op0, tp)); + break; + + case TLS_MODEL_LOCAL_EXEC: + emit_insn (gen_movsi_tpoffhi (op0, op1)); + emit_insn (gen_movsi_tpofflo (op0, op0, op1)); + emit_insn (gen_add3_insn (op0, op0, tp)); + break; + + default: + gcc_unreachable (); + } + + return true; + } + } + + if (flag_pic && or1k_expand_pic_symbol_ref(mode, operands)) + return true; + + return false; +} + +bool +or1k_expand_move (enum machine_mode mode, rtx operands[]) +{ + if (can_create_pseudo_p ()) + { + if (GET_CODE (operands[0]) == MEM + || (GET_CODE (operands[0]) == SUBREG + && GET_CODE (SUBREG_REG (operands[0])) == MEM)) + { + /* Source operand for store must be in a register. */ + operands[1] = force_reg (SImode, operands[1]); + } + } + + if (or1k_expand_symbol_ref (mode, operands)) + return true; + + /* Working with CONST_INTs is easier, so convert + a double if needed. */ + + if (GET_CODE (operands[1]) == CONST_DOUBLE) { + operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1])); + } + + /* Handle sets of MEM first. */ + if (GET_CODE (operands[0]) == MEM) + { + if (register_operand(operands[1], SImode) + || (operands[1] == const0_rtx)) + goto movsi_is_ok; + + if (! reload_in_progress) + { + operands[0] = validize_mem (operands[0]); + operands[1] = force_reg (SImode, operands[1]); + } + } + + /* This makes sure we will not get rematched due to splittage. */ + if (! CONSTANT_P (operands[1]) || input_operand (operands[1], SImode)) + ; + else if (CONSTANT_P (operands[1]) + && GET_CODE (operands[1]) != HIGH + && GET_CODE (operands[1]) != LO_SUM) + { + or1k_emit_set_const32 (operands[0], operands[1]); + return true; + } + movsi_is_ok: + ; + + return false; +} + +/* -------------------------------------------------------------------------- */ +/*!Emit a move from SRC to DEST. + + Assume that the move expanders can handle all moves if !can_create_pseudo_p + (). The distinction is important because, unlike emit_move_insn, the move + expanders know how to force Pmode objects into the constant pool even when + the constant pool address is not itself legitimate. + + @param[in] dest Destination of the move. + @param[in] src Source for the move. + + @return RTX for the move. */ +/* -------------------------------------------------------------------------- */ +static rtx +or1k_emit_move (rtx dest, rtx src) +{ + return (can_create_pseudo_p () + ? emit_move_insn (dest, src) + : emit_move_insn_1 (dest, src)); + +} /* or1k_emit_move () */ + + +/* -------------------------------------------------------------------------- */ +/*!Emit an instruction of the form (set TARGET (CODE OP0 OP1)). + + @param[in] code The code for the operation. + @param[in] target Destination for the set operation. + @param[in] op0 First operand. + @param[in] op1 Second operand. */ +/* -------------------------------------------------------------------------- */ +static void +or1k_emit_binary (enum rtx_code code, + rtx target, + rtx op0, + rtx op1) +{ + emit_insn (gen_rtx_SET (VOIDmode, target, + gen_rtx_fmt_ee (code, GET_MODE (target), op0, op1))); + +} /* or1k_emit_binary () */ + + +/* -------------------------------------------------------------------------- */ +/*!Compute the result of an operation into a new register. + + Compute ("code" "op0" "op1") and store the result in a new register of mode + "mode". + + @param[in] mode Mode of the result + @parma[in] code RTX for the operation to perform + @param[in] op0 RTX for the first operand + @param[in] op1 RTX for the second operand + + @return The RTX for the new register. */ +/* -------------------------------------------------------------------------- */ +static rtx +or1k_force_binary (enum machine_mode mode, + enum rtx_code code, + rtx op0, + rtx op1) +{ + rtx reg; + + reg = gen_reg_rtx (mode); + or1k_emit_binary (code, reg, op0, op1); + + return reg; + +} /* or1k_force_binary () */ + + +/* ========================================================================== */ +/* Global support functions */ + +static int +or1k_trampoline_code_words (void) +{ + int words = 5; + + /* need one more word in TARGET_DELAY_COMPAT mode to hold l.nop in delay slot */ + if (TARGET_DELAY_COMPAT) + words++; + + return words; +} + +/* -------------------------------------------------------------------------- */ +/* Return the size in bytes of the trampoline code. + + Padded to TRAMPOLINE_ALIGNMENT bits. The code sequence is documented in + or1k_trampoline_init (). + + This is just the code size. the static chain pointer and target function + address immediately follow. + + @return The size of the trampoline code in bytes. */ +/* -------------------------------------------------------------------------- */ +int +or1k_trampoline_code_size (void) +{ + const int TRAMP_BYTE_ALIGN = TRAMPOLINE_ALIGNMENT / 8; + + return (or1k_trampoline_code_words() * 4 + TRAMP_BYTE_ALIGN - 1) / TRAMP_BYTE_ALIGN * TRAMP_BYTE_ALIGN; + +} /* or1k_trampoline_code_size () */ + + +/* ========================================================================== */ +/* Functions to support the Machine Description */ + + +/* -------------------------------------------------------------------------- */ +/*!Expand a prologue pattern. + + Called after register allocation to add any instructions needed for the + prologue. Using a prologue insn is favored compared to putting all of the + instructions in output_function_prologue(), since it allows the scheduler + to intermix instructions with the saves of the caller saved registers. In + some cases, it might be necessary to emit a barrier instruction as the last + insn to prevent such scheduling. */ +/* -------------------------------------------------------------------------- */ +void +or1k_expand_prologue (void) +{ + int total_size = or1k_compute_frame_size (get_frame_size ()); + rtx insn; + + if (!total_size) + /* No frame needed. */ + return; + + gcc_assert (!frame_info.save_lr_p || !frame_info.save_fp_p + || frame_info.lr_save_offset != frame_info.fp_save_offset); + + if (frame_info.gpr_frame) + emit_frame_insn (gen_add2_insn (stack_pointer_rtx, + GEN_INT (-frame_info.gpr_frame))); + if (frame_info.save_fp_p) + { + emit_frame_insn (gen_rtx_SET (Pmode, + stack_disp_mem (frame_info.fp_save_offset), + hard_frame_pointer_rtx)); + + emit_frame_insn + (gen_add3_insn (hard_frame_pointer_rtx, stack_pointer_rtx, const0_rtx)); + } + if (frame_info.save_lr_p) + { + emit_frame_insn + (gen_rtx_SET (Pmode, stack_disp_mem (frame_info.lr_save_offset), + gen_rtx_REG (Pmode, LINK_REGNUM))); + } + if (frame_info.gpr_size) + { + int offset = 0; + int regno; + + for (regno = 0; regno <= OR1K_LAST_ACTUAL_REG; regno++) + { + if (!(frame_info.mask & ((HOST_WIDE_INT) 1 << regno))) + continue; + + /* Check that the offsets aren't stepping on lr/fp slots */ + gcc_assert (!frame_info.save_lr_p + || ((frame_info.gpr_offset + offset) + != frame_info.lr_save_offset)); + gcc_assert (!frame_info.save_fp_p + || ((frame_info.gpr_offset + offset) + != frame_info.fp_save_offset)); + + emit_frame_insn + (gen_rtx_SET (Pmode, + stack_disp_mem (frame_info.gpr_offset + offset), + gen_rtx_REG (Pmode, regno))); + offset = offset + UNITS_PER_WORD; + } + } + + /* Update the stack pointer to reflect frame size. */ + total_size = frame_info.late_frame; + insn = gen_add2_insn (stack_pointer_rtx, GEN_INT (-total_size)); + if (total_size > 32768) + { + rtx note = insn; + rtx value_rtx = gen_rtx_REG (Pmode, PROLOGUE_TMP); + + or1k_emit_set_const32 (value_rtx, GEN_INT (-total_size)); + if (frame_info.save_fp_p) + insn = gen_frame_alloc_fp (value_rtx); + else + insn = gen_add2_insn (stack_pointer_rtx, value_rtx); + insn = emit_frame_insn (insn); + add_reg_note (insn, REG_FRAME_RELATED_EXPR, note); + } + else if (total_size) + { + if (frame_info.save_fp_p) + emit_frame_insn (gen_frame_alloc_fp (GEN_INT (-total_size))); + else + emit_frame_insn (insn); + } + /* Emit got pointer acquiring if there are any got references or + this function has calls */ + if (crtl->uses_pic_offset_table || (flag_pic && frame_info.save_lr_p)) + { + SET_REGNO (pic_offset_table_rtx, PIC_OFFSET_TABLE_REGNUM); + emit_insn (gen_set_got (pic_offset_table_rtx)); + } + +} /* or1k_expand_prologue () */ + + +/* -------------------------------------------------------------------------- */ +/*!Expand an epilogue pattern. + + Called after register allocation to add any instructions needed for the + epilogue. Using an epilogue insn is favored compared to putting all of the + instructions in output_function_epilogue(), since it allows the scheduler + to intermix instructions with the restores of the caller saved registers. + In some cases, it might be necessary to emit a barrier instruction as the + first insn to prevent such scheduling. */ +/* -------------------------------------------------------------------------- */ +void +or1k_expand_epilogue (void) +{ + int total_size = or1k_compute_frame_size (get_frame_size ()); + + if (frame_info.save_fp_p) + { + emit_insn (gen_frame_dealloc_fp ()); + emit_insn + (gen_rtx_SET (Pmode, hard_frame_pointer_rtx, + stack_disp_mem (frame_info.fp_save_offset))); + } + else + { + rtx value_rtx; + + total_size = frame_info.late_frame; + if (total_size > 32767) + { + value_rtx = gen_rtx_REG (Pmode, EPILOGUE_TMP); + or1k_emit_set_const32 (value_rtx, GEN_INT (total_size)); + } + else if (frame_info.late_frame) + value_rtx = GEN_INT (total_size); + if (total_size) + emit_insn (gen_frame_dealloc_sp (value_rtx)); + } + + /* eh_return sets the LR, do not overwrite it */ + if (frame_info.save_lr_p && !crtl->calls_eh_return) + { + emit_insn + (gen_rtx_SET (Pmode, gen_rtx_REG (Pmode, LINK_REGNUM), + stack_disp_mem (frame_info.lr_save_offset))); + } + + if (frame_info.gpr_size) + { + int offset = 0; + int regno; + + for (regno = 0; regno <= OR1K_LAST_ACTUAL_REG; regno++) + { + if (!(frame_info.mask & ((HOST_WIDE_INT) 1 << regno))) + continue; + + if (regno != FIRST_PSEUDO_REGISTER) + emit_insn + (gen_rtx_SET (Pmode, gen_rtx_REG (Pmode, regno), + stack_disp_mem (frame_info.gpr_offset + offset))); + offset = offset + UNITS_PER_WORD; + } + } + + if (crtl->calls_eh_return) + emit_insn (gen_add2_insn (stack_pointer_rtx, EH_RETURN_STACKADJ_RTX)); + + if (frame_info.gpr_frame) + emit_insn (gen_add2_insn (stack_pointer_rtx, + GEN_INT (frame_info.gpr_frame))); + emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode, 9))); + +} /* or1k_expand_epilogue () */ + + + +/* -------------------------------------------------------------------------- */ +/*!Generate assembler code for a movdi/movdf pattern + + @param[in] operands Operands to the movdx pattern. + + @return The assembler string to output (always "", since we've done the + output here). */ +/* -------------------------------------------------------------------------- */ +const char * +or1k_output_move_double (rtx *operands) +{ + rtx xoperands[3]; + + switch (GET_CODE (operands[0])) + { + case REG: + if (GET_CODE (operands[1]) == REG) + { + if (REGNO (operands[0]) == REGNO (operands[1]) + 1) + { + output_asm_insn ("\tl.or \t%H0, %H1, r0", operands); + output_asm_insn ("\tl.or \t%0, %1, r0", operands); + return ""; + } + else + { + output_asm_insn ("\tl.or \t%0, %1, r0", operands); + output_asm_insn ("\tl.or \t%H0, %H1, r0", operands); + return ""; + } + } + else if (GET_CODE (operands[1]) == MEM) + { + xoperands[1] = XEXP (operands[1], 0); + if (GET_CODE (xoperands[1]) == REG) + { + xoperands[0] = operands[0]; + if (REGNO (xoperands[0]) == REGNO (xoperands[1])) + { + output_asm_insn ("\tl.lwz \t%H0, 4(%1)", xoperands); + output_asm_insn ("\tl.lwz \t%0, 0(%1)", xoperands); + return ""; + } + else + { + output_asm_insn ("\tl.lwz \t%0, 0(%1)", xoperands); + output_asm_insn ("\tl.lwz \t%H0, 4(%1)", xoperands); + return ""; + } + } + else if (GET_CODE (xoperands[1]) == PLUS) + { + if (GET_CODE (xoperands[2] = XEXP (xoperands[1], 1)) == REG) + { + xoperands[0] = operands[0]; + xoperands[1] = XEXP (xoperands[1], 0); + if (REGNO (xoperands[0]) == REGNO (xoperands[2])) + { + output_asm_insn ("\tl.lwz \t%H0, %1+4(%2)", + xoperands); + output_asm_insn ("\tl.lwz \t%0, %1(%2)", xoperands); + return ""; + } + else + { + output_asm_insn ("\tl.lwz \t%0, %1(%2)", xoperands); + output_asm_insn ("\tl.lwz \t%H0, %1+4(%2)", + xoperands); + return ""; + } + } + else if (GET_CODE (xoperands[2] = XEXP (xoperands[1], 0)) == + REG) + { + xoperands[0] = operands[0]; + xoperands[1] = XEXP (xoperands[1], 1); + if (REGNO (xoperands[0]) == REGNO (xoperands[2])) + { + output_asm_insn ("\tl.lwz \t%H0, %1+4(%2)", + xoperands); + output_asm_insn ("\tl.lwz \t%0, %1(%2)", xoperands); + return ""; + } + else + { + output_asm_insn ("\tl.lwz \t%0, %1(%2)", xoperands); + output_asm_insn ("\tl.lwz \t%H0, %1+4(%2)", + xoperands); + return ""; + } + } + else + abort (); + } + else + abort (); + } + else + abort (); + case MEM: + xoperands[0] = XEXP (operands[0], 0); + if (GET_CODE (xoperands[0]) == REG) + { + xoperands[1] = operands[1]; + output_asm_insn ("\tl.sw \t0(%0), %1", xoperands); + output_asm_insn ("\tl.sw \t4(%0), %H1", xoperands); + return ""; + } + else if (GET_CODE (xoperands[0]) == PLUS) + { + if (GET_CODE (xoperands[1] = XEXP (xoperands[0], 1)) == REG) + { + xoperands[0] = XEXP (xoperands[0], 0); + xoperands[2] = operands[1]; + output_asm_insn ("\tl.sw \t%0(%1), %2", xoperands); + output_asm_insn ("\tl.sw \t%0+4(%1), %H2", xoperands); + return ""; + } + else if (GET_CODE (xoperands[1] = XEXP (xoperands[0], 0)) == REG) + { + xoperands[0] = XEXP (xoperands[0], 1); + xoperands[2] = operands[1]; + output_asm_insn ("\tl.sw \t%0(%1), %2", xoperands); + output_asm_insn ("\tl.sw \t%0+4(%1), %H2", xoperands); + return ""; + } + else + abort (); + } + else + { + fprintf (stderr, " O/p error %s\n", + GET_RTX_NAME (GET_CODE (xoperands[0]))); + return ""; + /* abort (); */ + } + default: + abort (); + } +} /* or1k_output_move_double () */ + + +/* -------------------------------------------------------------------------- */ +/*!Expand a conditional branch + + @param[in] operands Operands to the branch. + @param[in] mode Mode of the comparison. */ +/* -------------------------------------------------------------------------- */ +void +or1k_expand_conditional_branch (rtx *operands, + enum machine_mode mode) +{ + rtx tmp; + enum rtx_code test_code = GET_CODE(operands[0]); + + switch (mode) + { + case SImode: + tmp = or1k_expand_compare (test_code, operands[1], operands[2]); + tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, + tmp, + gen_rtx_LABEL_REF (VOIDmode, operands[3]), + pc_rtx); + emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp)); + return; + + case SFmode: + tmp = or1k_expand_compare (test_code, operands[1], operands[2]); + tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, + tmp, + gen_rtx_LABEL_REF (VOIDmode, operands[3]), + pc_rtx); + emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp)); + return; + + default: + abort (); + } + +} /* or1k_expand_conditional_branch () */ + + +/* -------------------------------------------------------------------------- */ +/*!Emit a conditional move + + move "true_cond" to "dest" if "op" of the operands of the last comparison + is nonzero/true, "false_cond" if it is zero/false. + + @param[in] dest RTX for the destination operand. + @param[in] op RTX for the comparison operation + @param[in] true_cond RTX to move to dest if condition is TRUE. + @param[in] false_cond RTX to move to dest if condition is FALSE. + + @return Non-zero (TRUE) if the hardware supports such an operation, zero + (FALSE) otherwise. */ +/* -------------------------------------------------------------------------- */ +int +or1k_emit_cmove (rtx dest, + rtx op, + rtx true_cond, + rtx false_cond) +{ + enum machine_mode result_mode = GET_MODE (dest); + + if (GET_MODE (true_cond) != result_mode) + return 0; + + if (GET_MODE (false_cond) != result_mode) + return 0; + + /* First, work out if the hardware can do this at all */ + return or1k_emit_int_cmove (dest, op, true_cond, false_cond); + +} /* or1k_emit_cmove () */ + + +/* -------------------------------------------------------------------------- */ +/*!Output the assembler for a branch on flag instruction. + + @param[in] operands Operands to the branch. + + @return The assembler string to use. */ +/* -------------------------------------------------------------------------- */ +const char * +or1k_output_bf (rtx * operands) +{ + enum rtx_code code; + enum machine_mode mode_calc, mode_got; + + code = GET_CODE (operands[1]); + mode_calc = or1k_select_cc_mode (code); + mode_got = GET_MODE (operands[2]); + + if (mode_calc != mode_got) + return "l.bnf\t%l0%("; + else + return "l.bf\t%l0%("; +} /* or1k_output_bf () */ + + +/* -------------------------------------------------------------------------- */ +/*!Output the assembler for a conditional move instruction. + + @param[in] operands Operands to the conditional move. + + @return The assembler string to use. */ +/* -------------------------------------------------------------------------- */ +const char * +or1k_output_cmov (rtx * operands) +{ + enum rtx_code code; + enum machine_mode mode_calc, mode_got; + + code = GET_CODE (operands[1]); + mode_calc = or1k_select_cc_mode (code); + mode_got = GET_MODE (operands[4]); + + if (mode_calc != mode_got) + return "l.cmov\t%0,%3,%2"; /* reversed */ + else + return "l.cmov\t%0,%2,%3"; + +} /* or1k_output_cmov () */ + +/* -------------------------------------------------------------------------- */ +/*!Load a 32-bit constant. + + We know it can't be done in one insn when we get here, the movsi expander + guarantees this. + + @param[in] op0 RTX for the destination. + @param[in] op1 RTX for the (constant) source. */ +/* -------------------------------------------------------------------------- */ +void +or1k_emit_set_const32 (rtx op0, + rtx op1) +{ + enum machine_mode mode = GET_MODE (op0); + rtx temp; + + /* Sanity check that we really can't do it in one instruction. I.e that we + don't have a 16-bit constant. */ + if (GET_CODE (op1) == CONST_INT) + { + HOST_WIDE_INT val = INTVAL (op1) & GET_MODE_MASK (mode); + + if ((-32768 <= val) && (val <= 32767)) + { + abort (); + } + } + + /* Full 2-insn decomposition is needed. */ + if (reload_in_progress || reload_completed) + temp = op0; + else + temp = gen_reg_rtx (mode); + + if (GET_CODE (op1) == CONST_INT) + { + /* Emit them as real moves instead of a HIGH/LO_SUM, + this way CSE can see everything and reuse intermediate + values if it wants. */ + emit_insn (gen_rtx_SET (VOIDmode, temp, + GEN_INT (INTVAL (op1) + & ~(HOST_WIDE_INT) 0xffff))); + + emit_insn (gen_rtx_SET (VOIDmode, + op0, + gen_rtx_IOR (mode, temp, + GEN_INT (INTVAL (op1) & 0xffff)))); + } + else + { + /* since or1k bfd can not deal with relocs that are not of type + OR1K_CONSTH_RELOC + OR1K_CONST_RELOC (ie move high must be + followed by exactly one lo_sum) + */ + emit_insn (gen_movsi_insn_big (op0, op1)); + } +} /* or1k_emit_set_const32 () */ + + +/* ========================================================================== */ +/* Target hook functions. + + These are initialized at the end of this file, to avoid having to + predeclare all the functions. They are only needed here, so are static. */ + + + + +/* -------------------------------------------------------------------------- */ +/*!Define where a function returns values. + + Define this to return an RTX representing the place where a function + returns or receives a value of data type ret type, a tree node representing + a data type. "func" is a tree node representing FUNCTION_DECL or + FUNCTION_TYPE of a function being called. If "outgoing" is false, the hook + should compute the register in which the caller will see the return + value. Otherwise, the hook should return an RTX representing the place + where a function returns a value. + + On many machines, only TYPE_MODE ("ret_type") is relevant. (Actually, on + most machines, scalar values are returned in the same place regardless of + mode.) The value of the expression is usually a reg RTX for the hard + register where the return value is stored. The value can also be a parallel + RTX, if the return value is in multiple places. See FUNCTION_ARG for an + explanation of the parallel form. Note that the callee will populate every + location specified in the parallel, but if the first element of the + parallel contains the whole return value, callers will use that element as + the canonical location and ignore the others. The m68k port uses this type + of parallel to return pointers in both ‘%a0’ (the canonical location) and + ‘%d0’. + + If TARGET_PROMOTE_FUNCTION_RETURN returns true, you must apply the same + promotion rules specified in PROMOTE_MODE if valtype is a scalar type. + + If the precise function being called is known, "func" is a tree node + (FUNCTION_DECL) for it; otherwise, "func" is a null pointer. This makes it + possible to use a different value-returning convention for specific + functions when all their calls are known. + + Some target machines have "register windows" so that the register in which + a function returns its value is not the same as the one in which the caller + sees the value. For such machines, you should return different RTX + depending on outgoing. + + TARGET_FUNCTION_VALUE is not used for return values with aggregate data + types, because these are returned in another way. See + TARGET_STRUCT_VALUE_RTX and related macros. + + For the OR1K, we can just use the result of LIBCALL_VALUE, since all + functions return their result in the same place (register rv = r11). + + JPB 30-Aug-10: What about 64-bit scalar returns (long long int, double), + which also use rvh (=r12)? + + @param[in] ret_type The return type of the function. + @param[in] func Tree representing function being called. + @param[in] outgoing Non-zero (TRUE) if the result represents where the + function places the results, zero (FALSE) if the + result represents where the caller sees the result. + + @return A RTX representing where the result can be found. */ +/* -------------------------------------------------------------------------- */ +static rtx +or1k_function_value (const_tree ret_type, + const_tree func ATTRIBUTE_UNUSED, + bool outgoing ATTRIBUTE_UNUSED) +{ + return LIBCALL_VALUE (TYPE_MODE(ret_type)); + +} /* or1k_function_value () */ + + +/* -------------------------------------------------------------------------- */ +/*!Check if a function is suitable for tail call optimization. + + True if it is OK to do sibling call optimization for the specified call + expression "exp". "decl" will be the called function, or NULL if this is an + indirect call. + + It is not uncommon for limitations of calling conventions to prevent tail + calls to functions outside the current unit of translation, or during PIC + compilation. The hook is used to enforce these restrictions, as the sibcall + md pattern can not fail, or fall over to a “normal” call. The criteria for + successful sibling call optimization may vary greatly between different + architectures. + + For the OR1K, we currently don't allow sibcalls. + + @param[in] decl The function for which we may optimize + @param[in] exp The call expression which is candidate for optimization. + + @return Non-zero (TRUE) if sibcall optimization is permitted, zero (FALSE) + otherwise. */ +/* -------------------------------------------------------------------------- */ +static bool +or1k_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED, + tree exp ATTRIBUTE_UNUSED) +{ + return 0; +} /* or1k_function_ok_for_sibcall () */ + + +/* -------------------------------------------------------------------------- */ +/*!Should an argument be passed by reference. + + This target hook should return true if an argument at the position + indicated by "cum" should be passed by reference. This predicate is queried + after target independent reasons for being passed by reference, such as + TREE_ADDRESSABLE ("type"). + + If the hook returns TRUE, a copy of that argument is made in memory and a + pointer to the argument is passed instead of the argument itself. The + pointer is passed in whatever way is appropriate for passing a pointer to + that type. + + For the OR1K, all aggregates and arguments greater than 8 bytes are passed + this way. + + @param[in] cum Position of argument under consideration. + @param[in[ mode Not sure what this relates to. + @param[in] type Type of the argument. + @param[in] named Not sure what this relates to. + + @return Non-zero (TRUE) if the argument should be passed by reference, + zero (FALSE) otherwise. */ +/* -------------------------------------------------------------------------- */ +static bool +or1k_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED, + enum machine_mode mode ATTRIBUTE_UNUSED, + const_tree type, + bool named ATTRIBUTE_UNUSED) +{ + return (type && (AGGREGATE_TYPE_P (type) || int_size_in_bytes (type) > 8)); + +} /* or1k_pass_by_reference () */ + + +int +or1k_initial_elimination_offset(int from, int to) +{ + or1k_compute_frame_size (get_frame_size ()); + return ((from == FRAME_POINTER_REGNUM + ? frame_info.gpr_offset : frame_info.gpr_frame) + + (to == STACK_POINTER_REGNUM ? frame_info.late_frame : 0)); +} + + +/* -------------------------------------------------------------------------- */ +/*!How many bytes at the beginning of an argument must be put into registers. + + This target hook returns the number of bytes at the beginning of an + argument that must be put in registers. The value must be zero for + arguments that are passed entirely in registers or that are entirely pushed + on the stack. + + On some machines, certain arguments must be passed partially in registers + and partially in memory. On these machines, typically the first few words + of arguments a re passed in registers, and the rest on the stack. If a + multi-word argument (a double or a structure) crosses that boundary, its + first few words must be passed in registers and the rest must be + pushed. This macro tells the compiler when this occurs, and how many bytes + should go in registers. + + FUNCTION_ARG for these arguments should return the first register to be + used by the caller for this argument; likewise FUNCTION_INCOMING_ARG, for + the called function. + + On the OR1K we never split argumetns between registers and memory. + + JPB 30-Aug-10: Is this correct? Surely we should allow this. The ABI spec + is incomplete on this point. + + @param[in] cum Position of argument under consideration. + @param[in[ mode Not sure what this relates to. + @param[in] type Type of the argument. + @param[in] named Not sure what this relates to. + + @return The number of bytes of the argument to go into registers */ +/* -------------------------------------------------------------------------- */ +static int +or1k_arg_partial_bytes (cumulative_args_t cum ATTRIBUTE_UNUSED, + enum machine_mode mode ATTRIBUTE_UNUSED, + tree type ATTRIBUTE_UNUSED, + bool named ATTRIBUTE_UNUSED) +{ + return 0; + +} /* or1k_arg_partial_bytes () */ + + +/* -------------------------------------------------------------------------- */ +/*!Promote the mode of a function's arguments/return value. + + Like PROMOTE_MODE, but it is applied to outgoing function arguments or + function return values. The target hook should return the new mode and + possibly change "*punsignedp" if the promotion should change + signedness. This function is called only for scalar or pointer types. + + "for_return" allows to distinguish the promotion of arguments and return + values. If it is 1, a return value is being promoted and + TARGET_FUNCTION_VALUE must perform the same promotions done here. If it is + 2, the returned mode should be that of the register in which an incoming + parameter is copied, or the outgoing result is computed; then the hook + should return the same mode as PROMOTE_MODE, though the signedness may be + different. + + The default is to not promote arguments and return values. You can also + define the hook to "default_promote_function_mode_always_promote" if you + would like to apply the same rules given by PROMOTE_MODE. + + For the OR1K, if the size of the mode is integral and less than 4, we + promote to SImode, otherwise we return the mode we are supplied. + + @param[in] type Not sure. Type of the argument? + @param[in] mode The mode of argument/return value to consider. + @param[out] punsignedp Signedness of the value. + @param[in] fntype Not sure. Type of the function? + @param[in] for_return 1 if a return value, 2 if an incoming value. + + @return The new mode. */ +/* -------------------------------------------------------------------------- */ +static enum machine_mode +or1k_promote_function_mode (const_tree type ATTRIBUTE_UNUSED, + enum machine_mode mode, + int *punsignedp ATTRIBUTE_UNUSED, + const_tree fntype ATTRIBUTE_UNUSED, + int for_return ATTRIBUTE_UNUSED) +{ + return ( (GET_MODE_CLASS (mode) == MODE_INT) + && (GET_MODE_SIZE (mode) < 4)) ? SImode : mode; + +} /* or1k_promote_function_mode () */ + + +/* -------------------------------------------------------------------------- */ +/*!Is this a legitimate address? + + A function that returns whether x (an RTX) is a legitimate memory address on + the target machine for a memory operand of mode mode. + + Legitimate addresses are defined in two variants: a strict variant and a + non-strict one. The strict parameter chooses which variant is desired by + the caller. + + The strict variant is used in the reload pass. It must be defined so that + any pseudo- register that has not been allocated a hard register is + considered a memory reference. This is because in contexts where some kind + of register is required, a pseudo-register with no hard register must be + rejected. For non-hard registers, the strict variant should look up the + reg_renumber array; it should then proceed using the hard register number in + the array, or treat the pseudo as a memory reference if the array holds -1. + + The non-strict variant is used in other passes. It must be defined to accept + all pseudo-registers in every context where some kind of register is + required. + + Normally, constant addresses which are the sum of a symbol_ref and an + integer are stored inside a const RTX to mark them as constant. Therefore, + there is no need to recognize such sums specifically as legitimate + addresses. Normally you would simply recognize any const as legitimate. + + Usually PRINT_OPERAND_ADDRESS is not prepared to handle constant sums that + are not marked with const. It assumes that a naked plus indicates + indexing. If so, then you must reject such naked constant sums as + illegitimate addresses, so that none of them will be given to + PRINT_OPERAND_ADDRESS. + + On some machines, whether a symbolic address is legitimate depends on the + section that the address refers to. On these machines, define the target + hook TARGET_ENCODE_ SECTION_INFO to store the information into the + symbol_ref, and then check for it here. When you see a const, you will have + to look inside it to find the symbol_ref in order to determine the + section. See the internals manual section on "Assembler Format" for more + info. + + Some ports are still using a deprecated legacy substitute for this hook, the + GO_IF_LEGITIMATE_ADDRESS macro. This macro has this syntax: + + #define GO_IF_LEGITIMATE_ADDRESS (mode, x, label ) + + and should goto label if the address x is a valid address on the target + machine for a memory operand of mode mode. Whether the strict or non-strict + variants are desired is defined by the REG_OK_STRICT macro introduced + earlier in this section. Using the hook is usually simpler because it limits + the number of files that are recompiled when changes are made. + + The OR1K only has a single addressing mode, which is a base register with + 16-bit displacement. We can accept just 16-bit constants as addresses (they + can use r0 as base address, and we can accept plain registers as addresses + (they can use a displacement of zero). + + @param[in] mode The mode of the address + @param[in] x The address (RTX) + @param[in] strict Non-zero (TRUE) if we are in "strict" mode, zero (FALSE) + otherwise. + + @return Non-zero (TRUE) if this is a legitimate address, zero (FALSE) + otherwise. */ +/* -------------------------------------------------------------------------- */ +static bool +or1k_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED, + rtx x, + bool strict) +{ + /* You might think 16-bit constants are suitable. They can be built into + addresses using r0 as the base. However this seems to lead to defective + code. So for now this is a placeholder, and this code is not used. + + if (or1k_legitimate_displacement_p (mode, x)) + { + return 1; + } + */ + /* Addresses consisting of a register and 16-bit displacement are also + suitable. We need the mode, since for double words, we had better be + able to address the full 8 bytes. */ + if (GET_CODE(x) == PLUS) + { + rtx reg = XEXP(x,0); + + /* If valid register... */ + if ((GET_CODE(reg) == REG) + && or1k_regnum_ok_for_base_p (REGNO (reg), strict)) + { + rtx offset = XEXP(x,1); + + /* ...and valid offset */ + if (or1k_legitimate_displacement_p (mode, offset)) + { + return 1; + } + } + } + + /* Addresses consisting of just a register are OK. They can be built into + addresses using an offset of zero (and an offset of four if double + word). */ + if (GET_CODE(x) == REG + && or1k_regnum_ok_for_base_p(REGNO(x),strict)) { + return 1; + } + + return 0; +} + +/* -------------------------------------------------------------------------- */ +/*!Initialize a trampoline for nested functions. + + A nested function is defined by *two* pieces of information, the address of + the function (like any other function) and a pointer to the frame of the + enclosing function. The latter is required to allow the nested function to + access local variables in the enclosing function's frame. + + This represents a problem, since a function in C is represented as an + address that can be held in a single variable as a pointer. Requiring two + pointers will not fit. + + The solution is documented in "Lexical Closures for C++" by Thomas + M. Breuel (USENIX C++ Conference Proceedings, October 17-21, 1988). The + nested function is represented by a small block of code and data on the + enclosing function's stack frame, which sets up a pointer to the enclosing + function's stack frame (the static chain pointer) in a register defined by + the ABI, and then jumps to the code of the function proper. + + The function can be represented as a single pointer to this block of code, + known as a trampoline, which when called generates both pointers + needed. The nested function (which knows it is a nested function at compile + time) can then generate code to access the enclosing frame via the static + chain register. + + There is a catch that the trampoline is set up as data, but executed as + instructions. The former will be via the data cache, the latter via the + instruction cache. There is a risk that a later trampoline will not be seen + by the instruction cache, so the wrong code will be executed. So the + instruction cache should be flushed for the trampoline address range. + + This hook is called to initialize a trampoline. "m_tramp" is an RTX for the + memory block for the trampoline; "fndecl" is the FUNCTION_DECL for the + nested function; "static_chain" is an RTX for the static chain value that + should be passed to the function when it is called. + + If the target defines TARGET_ASM_TRAMPOLINE_TEMPLATE, then the first thing + this hook should do is emit a block move into "m_tramp" from the memory + block returned by assemble_trampoline_template. Note that the block move + need only cover the constant parts of the trampoline. If the target + isolates the variable parts of the trampoline to the end, not all + TRAMPOLINE_SIZE bytes need be copied. + + If the target requires any other actions, such as flushing caches or + enabling stack execution, these actions should be performed after + initializing the trampoline proper. + + For the OR1K, no static chain register is used. We choose to use the return + value (rv) register. The code is based on that for MIPS. + The trampoline code is: + + l.movhi r11,hi(end_addr) + l.ori r11,lo(end_addr) + l.lwz r13,4(r11) + l.jr r13 + l.lwz r11,0(r11) + end_addr: + .word + .word + + @note For the OR1K we need to flush the instruction cache, which is a + privileged operation. Needs fixing. + + @param[in] m_tramp The lowest address of the trampoline on the stack. + @param[in] fndecl Declaration of the enclosing function. + @param[in] chain_value Static chain pointer to pass to the nested + function. */ +/* -------------------------------------------------------------------------- */ +static void +or1k_trampoline_init (rtx m_tramp, + tree fndecl, + rtx chain_value) +{ + rtx addr; /* Start address of the trampoline */ + rtx end_addr; /* End address of the code block */ + + rtx high; /* RTX for the high part of end_addr */ + rtx low; /* RTX for the low part of end_addr */ + rtx opcode; /* RTX for generated opcodes */ + rtx mem; /* RTX for trampoline memory */ + + rtx *trampoline; /* The trampoline code */ + + unsigned int i; /* Index into trampoline */ + unsigned int j; /* General counter */ + + HOST_WIDE_INT end_addr_offset; /* Offset to end of code */ + HOST_WIDE_INT static_chain_offset; /* Offset to stack chain word */ + HOST_WIDE_INT target_function_offset; /* Offset to func address word */ + + /* Work out the offsets of the pointers from the start of the trampoline + code. */ + trampoline = (rtx*) alloca (or1k_trampoline_code_words() * sizeof(rtx)); + end_addr_offset = or1k_trampoline_code_size (); + static_chain_offset = end_addr_offset; + target_function_offset = static_chain_offset + GET_MODE_SIZE (ptr_mode); + + /* Get pointers in registers to the beginning and end of the code block. */ + addr = force_reg (Pmode, XEXP (m_tramp, 0)); + end_addr = or1k_force_binary (Pmode, PLUS, addr, GEN_INT (end_addr_offset)); + + /* Build up the code in TRAMPOLINE. + + l.movhi r11,hi(end_addr) + l.ori r11,lo(end_addr) + l.lwz r13,4(r11) + l.jr r13 + l.lwz r11,0(r11) + end_addr: + */ + + i = 0; + + /* Break out the high and low parts of the end_addr */ + high = expand_simple_binop (SImode, LSHIFTRT, end_addr, GEN_INT (16), + NULL, false, OPTAB_WIDEN); + low = convert_to_mode (SImode, gen_lowpart (HImode, end_addr), true); + + /* Emit the l.movhi, adding an operation to OR in the high bits from the + RTX. */ + opcode = gen_int_mode (OR1K_MOVHI (11, 0), SImode); + trampoline[i++] = expand_simple_binop (SImode, IOR, opcode, high, NULL, + false, OPTAB_WIDEN); + + /* Emit the l.ori, adding an operations to OR in the low bits from the + RTX. */ + opcode = gen_int_mode (OR1K_ORI (11, 11, 0), SImode); + trampoline[i++] = expand_simple_binop (SImode, IOR, opcode, low, NULL, + false, OPTAB_WIDEN); + + /* Emit the l.lwz of the function address. No bits to OR in here, so we can + do the opcode directly. */ + trampoline[i++] = + gen_int_mode (OR1K_LWZ (13, 11, target_function_offset - end_addr_offset), + SImode); + + if (TARGET_DELAY_ON) { + /* Emit the l.jr of the function. No bits to OR in here, so we can do the + opcode directly. */ + trampoline[i++] = gen_int_mode (OR1K_JR (13), SImode); + + /* Emit the l.lwz of the static chain. No bits to OR in here, so we can + do the opcode directly. */ + trampoline[i++] = + gen_int_mode (OR1K_LWZ (STATIC_CHAIN_REGNUM, 11, + static_chain_offset - end_addr_offset), SImode); + } else { + trampoline[i++] = + gen_int_mode (OR1K_LWZ (STATIC_CHAIN_REGNUM, 11, + static_chain_offset - end_addr_offset), SImode); + trampoline[i++] = gen_int_mode (OR1K_JR (13), SImode); + if (TARGET_DELAY_COMPAT) + trampoline[i++] = gen_int_mode (OR1K_NOP, SImode); + } + + /* Copy the trampoline code. Leave any padding uninitialized. */ + for (j = 0; j < i; j++) + { + mem = adjust_address (m_tramp, SImode, j * GET_MODE_SIZE (SImode)); + or1k_emit_move (mem, trampoline[j]); + } + + /* Set up the static chain pointer field. */ + mem = adjust_address (m_tramp, ptr_mode, static_chain_offset); + or1k_emit_move (mem, chain_value); + + /* Set up the target function field. */ + mem = adjust_address (m_tramp, ptr_mode, target_function_offset); + or1k_emit_move (mem, XEXP (DECL_RTL (fndecl), 0)); + + /* Flushing the trampoline from the instruction cache needs to be done + here. */ + +} /* or1k_trampoline_init () */ + + +/* -------------------------------------------------------------------------- */ +/*!Provide support for DW_AT_calling_convention + + Define this to enable the dwarf attribute DW_AT_calling_convention to be + emitted for each function. Instead of an integer return the enum value for + the DW_CC_ tag. + + To support optional call frame debugging information, you must also define + INCOMING_RETURN_ADDR_RTX and either set RTX_FRAME_RELATED_P on the prologue + insns if you use RTL for the prologue, or call "dwarf2out_def_cfa" and + "dwarf2out_reg_save" as appropriate from TARGET_ASM_FUNCTION_PROLOGUE if + you don’t. + + For the OR1K, it should be sufficient to return DW_CC_normal in all cases. + + @param[in] function The function requiring debug information + + @return The enum of the DW_CC tag. */ +/* -------------------------------------------------------------------------- */ +static int +or1k_dwarf_calling_convention (const_tree function ATTRIBUTE_UNUSED) +{ + return DW_CC_normal; + +} /* or1k_dwarf_calling_convention () */ + +/* ========================================================================== */ +/* Target hook initialization. + + In most cases these use the static functions declared above. They have + defaults, so must be undefined first, before being redefined. + + The description of what they do is found with the function above, unless it + is a standard function or a constant, in which case it is defined here (as + with TARGET_ASM_NAMED_SECTION). + + The final declaration is of the global "targetm" structure. */ + +/* Output assembly directives to switch to section name. The section should + have attributes as specified by flags, which is a bit mask of the SECTION_* + flags defined in ‘output.h’. If decl is non-NULL, it is the VAR_DECL or + FUNCTION_DECL with which this section is associated. + + For OR1K, we use the default ELF sectioning. */ +#undef TARGET_ASM_NAMED_SECTION +#define TARGET_ASM_NAMED_SECTION default_elf_asm_named_section + +#undef TARGET_FUNCTION_VALUE +#define TARGET_FUNCTION_VALUE or1k_function_value + +#undef TARGET_FUNCTION_OK_FOR_SIBCALL +#define TARGET_FUNCTION_OK_FOR_SIBCALL or1k_function_ok_for_sibcall + +#undef TARGET_PASS_BY_REFERENCE +#define TARGET_PASS_BY_REFERENCE or1k_pass_by_reference + +#undef TARGET_ARG_PARTIAL_BYTES +#define TARGET_ARG_PARTIAL_BYTES or1k_arg_partial_bytes + +#undef TARGET_OPTION_OVERRIDE +#define TARGET_OPTION_OVERRIDE or1k_option_override + +#undef TARGET_ASM_FILE_START +#define TARGET_ASM_FILE_START or1k_asm_file_start + +/* This target hook returns TRUE if an argument declared in a prototype as an + integral type smaller than int should actually be passed as an int. In + addition to avoiding errors in certain cases of mismatch, it also makes for + better code on certain machines. + + The default is to not promote prototypes. + + For the OR1K we do require this, so use a utility hook, which always + returns TRUE. */ +#undef TARGET_PROMOTE_PROTOTYPES +#define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true + +#undef TARGET_PROMOTE_FUNCTION_MODE +#define TARGET_PROMOTE_FUNCTION_MODE or1k_promote_function_mode + +#undef TARGET_LEGITIMATE_ADDRESS_P +#define TARGET_LEGITIMATE_ADDRESS_P or1k_legitimate_address_p + +#undef TARGET_TRAMPOLINE_INIT +#define TARGET_TRAMPOLINE_INIT or1k_trampoline_init + +#undef TARGET_DWARF_CALLING_CONVENTION +#define TARGET_DWARF_CALLING_CONVENTION or1k_dwarf_calling_convention + +/* uClibc has some instances where (non-coforming to ISO C) a non-varargs + prototype is in scope when calling that function which is implemented + as varargs. We want this to work at least where none of the anonymous + arguments are used. I.e. we want the last named argument to be known + as named so it can be passed in a register, varars funtion or not. */ +#undef TARGET_STRICT_ARGUMENT_NAMING +#define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true + +/* Is this suitable for an immediate operand. + + JPB 1-Sep-10: Is this correct. We can only do 16-bit immediates directly. */ +static bool +or1k_legitimate_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x) +{ + return GET_CODE(x) != CONST_DOUBLE || (GET_MODE (x) == VOIDmode && !flag_pic); +} +#undef TARGET_LEGITIMATE_CONSTANT_P +#define TARGET_LEGITIMATE_CONSTANT_P or1k_legitimate_constant_p + +/* On the OR1K, no functions pop their arguments. + JPB 29-Aug-10: Is this really correct? */ +static int +or1k_return_pops_args (tree ARG_UNUSED(fundecl), tree ARG_UNUSED(funtype), int ARG_UNUSED(size)) +{ + return 0; +} +#undef TARGET_RETURN_POPS_ARGS +#define TARGET_RETURN_POPS_ARGS or1k_return_pops_args + +/* Determine where to put an argument to a function. Value is zero to push + the argument on the stack, or a hard register in which to store the + argument. + + "mode" is the argument's machine mode. + + "type" is the data type of the argument (as a tree). This is null for + libcalls where that information may not be available. + + "cum" is a variable of type CUMULATIVE_ARGS which gives info about the + preceding args and about the function being called. + + "named" is nonzero if this argument is a named parameter (otherwise it is + an extra parameter matching an ellipsis). + + On the ARC the first MAX_ARC_PARM_REGS args are normally in registers and + the rest are pushed. */ +static rtx +or1k_function_arg (cumulative_args_t cum, enum machine_mode mode, + const_tree type, bool named) +{ + CUMULATIVE_ARGS *cum_pnt = get_cumulative_args (cum); + + if (OR1K_PASS_IN_REG_P (*cum_pnt, mode, type, named)) + return gen_rtx_REG (mode, OR1K_ROUND_ADVANCE_CUM (*cum_pnt, mode, type) + + GP_ARG_MIN_REG); + else + return 0; +} +#undef TARGET_FUNCTION_ARG +#define TARGET_FUNCTION_ARG or1k_function_arg +/* Update the data in "cum" to advance over an argument of mode "mode" and + data type "type". ("type" is null for libcalls where that information may + not be available.) */ +static void +or1k_function_arg_advance (cumulative_args_t cum, enum machine_mode mode, + const_tree type, bool ARG_UNUSED(named)) +{ + CUMULATIVE_ARGS *cum_pnt = get_cumulative_args (cum); + + *cum_pnt = OR1K_ROUND_ADVANCE_CUM (*cum_pnt, mode, type) + + OR1K_ROUND_ADVANCE_ARG (mode, type); +} + +#undef TARGET_FUNCTION_ARG_ADVANCE +#define TARGET_FUNCTION_ARG_ADVANCE or1k_function_arg_advance + +#undef TARGET_PRINT_OPERAND_ADDRESS +#define TARGET_PRINT_OPERAND_ADDRESS or1k_print_operand_address + +/* Trampoline stubs are yet to be written. */ +/* #define TARGET_ASM_TRAMPOLINE_TEMPLATE */ +/* #define TARGET_TRAMPOLINE_INIT */ + +/* Lay out structs with increased alignment so that they can be accessed + more efficiently. But don't increase the size of one or two byte + structs. */ +int +or1k_struct_alignment (tree t) +{ + unsigned HOST_WIDE_INT total = 0; + int default_align_fields = 0; + int special_align_fields = 0; + tree field; + unsigned max_align + = maximum_field_alignment ? maximum_field_alignment : BIGGEST_ALIGNMENT; + bool struct_p; + + switch (TREE_CODE (t)) + { + case RECORD_TYPE: + struct_p = true; break; + case UNION_TYPE: case QUAL_UNION_TYPE: + struct_p = false; break; + default: gcc_unreachable (); + } + /* Skip all non field decls */ + for (field = TYPE_FIELDS (t); field; field = TREE_CHAIN (field)) + { + unsigned HOST_WIDE_INT field_size; + + if (TREE_CODE (field) != FIELD_DECL || + TREE_TYPE (field) == error_mark_node) + continue; + /* If this is a field in a non-qualified union, or the sole field in + a struct, and the alignment was set by the user, don't change the + alignment. + If the field is a struct/union in a non-qualified union, we already + had sufficient opportunity to pad it - if we didn't, that'd be + because the alignment was set as above. + Likewise if the field is a struct/union and the sole field in a + struct. */ + if (DECL_USER_ALIGN (field) + || TYPE_USER_ALIGN (TREE_TYPE (field)) + || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE + || TREE_CODE (TREE_TYPE (field)) == QUAL_UNION_TYPE + || TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE) + { + if (TREE_CODE (t) == UNION_TYPE) + return 0; + special_align_fields++; + } + else if (DECL_PACKED (field)) + special_align_fields++; + else + default_align_fields++; + if (!host_integerp (DECL_SIZE (field), 1)) + field_size = max_align; + else + field_size = tree_low_cst (DECL_SIZE (field), 1); + if (field_size >= BIGGEST_ALIGNMENT) + total = max_align; + if (struct_p) + total += field_size; + else + total = MAX (total, field_size); + } + + if (!default_align_fields + && (TREE_CODE (t) != RECORD_TYPE || special_align_fields <= 1)) + return 0; + return total < max_align ? (1U << ceil_log2 (total)) : max_align; +} + +/* Increase the alignment of objects so that they are easier to copy. + Note that this can cause more struct copies to be inlined, so code + size might increase, but so should perfromance. */ +int +or1k_data_alignment (tree t, int align) +{ + if (align < FASTEST_ALIGNMENT && TREE_CODE (t) == ARRAY_TYPE) + { + int size = int_size_in_bytes (t); + + return (size > 0 && size < FASTEST_ALIGNMENT / BITS_PER_UNIT + ? (1 << floor_log2 (size)) * BITS_PER_UNIT + : FASTEST_ALIGNMENT); + } + return align; +} + +static void +or1k_option_override (void) +{ + if (!TARGET_DELAY_ON) + flag_delayed_branch = FALSE; +} + +static void +or1k_asm_file_start(void) +{ + default_file_start(); + + if (TARGET_DELAY_OFF) { + fprintf(asm_out_file, "\t.nodelay\n"); + } +} + +/* Implement EH_RETURN_HANDLER_RTX. + * Make eh_return use the link register. Epilogue LR restore + * is suppressed for eh_return. */ +rtx +or1k_eh_return_handler_rtx (void) +{ + return INCOMING_RETURN_ADDR_RTX; +} + +/* Implement RETURN_ADDR_RTX. + * We do not support moving back to a previous frame. */ +rtx +or1k_return_addr_rtx (int count, rtx frame ATTRIBUTE_UNUSED) +{ + if (count != 0) + return const0_rtx; + + /* We don't know if LR is going to be saved or if we're going to + * be clobbering it with the GOT instruction. + * Therefore the safest bet is to force a save of LR and use that. + * Assume it's going to be first in the stack. */ + + cfun->machine->force_lr_save = true; + return gen_rtx_MEM (Pmode, plus_constant (Pmode, arg_pointer_rtx, + -UNITS_PER_WORD)); +} + +/* Implement TARGET_FRAME_POINTER_REQUIRED. + * We want frame pointer in eh_return and when alloca is used */ +static bool +or1k_frame_pointer_required (void) +{ + return crtl->calls_eh_return || cfun->calls_alloca; +} + +/* Functions to save and restore machine-specific function data. */ +static struct machine_function * +or1k_init_machine_status (void) +{ + return ggc_alloc_cleared_machine_function (); +} + +void +or1k_init_expanders (void) +{ + /* Arrange to initialize and mark the machine per-function + * status. */ + init_machine_status = or1k_init_machine_status; + + if (cfun && cfun->machine) + { + cfun->machine->force_lr_save = false; + } +} + +#undef TARGET_FRAME_POINTER_REQUIRED +#define TARGET_FRAME_POINTER_REQUIRED or1k_frame_pointer_required + +/* Initialize the GCC target structure. */ +struct gcc_target targetm = TARGET_INITIALIZER; + +#include "gt-or1k.h" diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/config/or1k/or1k.h gcc-4.8.2-or1k-rtems/gcc/config/or1k/or1k.h --- gcc-4.8.2/gcc/config/or1k/or1k.h 1970-01-01 02:00:00.000000000 +0200 +++ gcc-4.8.2-or1k-rtems/gcc/config/or1k/or1k.h 2014-03-14 07:27:49.000000000 +0200 @@ -0,0 +1,1210 @@ +/* Definitions of target machine for GNU compiler. OpenRISC 1000 version. + Copyright (C) 1987, 1988, 1992, 1995, 1996, 1999, 2000, 2001, 2002, + 2003, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2010 Embecosm Limited + Contributed by Damjan Lampret in 1999. + Major optimizations by Matjaz Breskvar in 2005. + +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 1, 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 GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#ifndef _OR1K_H_ +#define _OR1K_H_ + +#include "config/or1k/or1k-opts.h" + +/* Target CPU builtins */ +#define TARGET_CPU_CPP_BUILTINS() \ + do \ + { \ + if (TARGET_DELAY_OFF) { \ + builtin_define ("__OR1KND__"); \ + builtin_define ("__or1knd__"); \ + builtin_assert ("cpu=or1knd"); \ + builtin_assert ("machine=or1knd"); \ + } else { \ + builtin_define ("__OR1K__"); \ + builtin_define ("__or1k__"); \ + builtin_assert ("cpu=or1k"); \ + builtin_assert ("machine=or1k"); \ + } \ + if (TARGET_DELAY_ON) { \ + builtin_define ("__OR1K_DELAY__"); \ + } else if (TARGET_DELAY_OFF) { \ + builtin_define ("__OR1K_NODELAY__"); \ + } else if (TARGET_DELAY_COMPAT) { \ + builtin_define ("__OR1K_DELAY_COMPAT__"); \ + } \ + } \ + while (0) + +#undef CPP_SPEC +#define CPP_SPEC \ + "%{!mnewlib:%{pthread:-D_XOPEN_SOURCE=700}}" + +/* Make sure we pick up the crti.o, crtbegin.o, crtend.o and crtn.o files. */ +#undef STARTFILE_SPEC +#define STARTFILE_SPEC \ + "%{!shared:%{pie:Scrt0.o%s;:crt0.o%s}} crti.o%s \ + %{static:crtbeginT.o%s;shared|pie:crtbeginS.o%s;:crtbegin.o%s}" + +#undef ENDFILE_SPEC +#define ENDFILE_SPEC "%{shared|pie:crtendS.o%s;:crtend.o%s} crtn.o%s" + +#undef LINK_SPEC +#define LINK_SPEC "%{mnewlib:-entry 0x100} %{static:-static} %{shared:-shared}" + +/* Override previous definitions (linux.h). Newlib doesn't have a profiling + version of the library, but it does have a debugging version (libg.a) */ +#undef LIB_SPEC +#define LIB_SPEC "%{!mnewlib:%{pthread:-lpthread} \ + %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}}" \ + "%{mnewlib:%{!g:-lc} %{g:-lg} -lor1k \ + %{mboard=*:-lboard-%*} %{!mboard=*:-lboard-or1ksim} \ + %{!g:-lc} %{g:-lg} \ + }" + +/* Target machine storage layout */ + +/* Define this if most significant bit is lowest numbered + in instructions that operate on numbered bit-fields. + This is not true on the or1k. */ +#define BITS_BIG_ENDIAN 0 + +/* Define this if most significant byte of a word is the lowest numbered. */ +#define BYTES_BIG_ENDIAN 1 + +/* Define this if most significant word of a multiword number is numbered. */ +#define WORDS_BIG_ENDIAN 1 + +/* Number of bits in an addressable storage unit */ +#define BITS_PER_UNIT 8 + +#define BITS_PER_WORD 32 +#define SHORT_TYPE_SIZE 16 +#define INT_TYPE_SIZE 32 +#define LONG_TYPE_SIZE 32 +#define LONG_LONG_TYPE_SIZE 64 +#define FLOAT_TYPE_SIZE 32 +#define DOUBLE_TYPE_SIZE 64 +#define LONG_DOUBLE_TYPE_SIZE 64 + +/* Width of a word, in units (bytes). */ +#define UNITS_PER_WORD 4 + +/* Width in bits of a pointer. + See also the macro `Pmode' defined below. */ +#define POINTER_SIZE 32 + +/* Allocation boundary (in *bits*) for storing pointers in memory. */ +#define POINTER_BOUNDARY 32 + +/* Allocation boundary (in *bits*) for storing arguments in argument list. */ +#define PARM_BOUNDARY 32 + +/* Boundary (in *bits*) on which stack pointer should be aligned. */ +#define STACK_BOUNDARY 32 + +/* Allocation boundary (in *bits*) for the code of a function. */ +#define FUNCTION_BOUNDARY 32 + +/* Alignment of field after `int : 0' in a structure. */ +#define EMPTY_FIELD_BOUNDARY 8 + +/* Every structure's size must be a multiple of this. */ +#define STRUCTURE_SIZE_BOUNDARY (TARGET_PADSTRUCT ? 32 : 8) + +/* A bitfield declared as `int' forces `int' alignment for the struct. */ +#define PCC_BITFIELD_TYPE_MATTERS 1 + +/* No data type wants to be aligned rounder than this. */ +#define BIGGEST_ALIGNMENT 32 + +/* The best alignment to use in cases where we have a choice. */ +#define FASTEST_ALIGNMENT 32 + +#define ROUND_TYPE_ALIGN(STRUCT, COMPUTED, SPECIFIED) \ + ((TREE_CODE (STRUCT) == RECORD_TYPE \ + || TREE_CODE (STRUCT) == UNION_TYPE \ + || TREE_CODE (STRUCT) == QUAL_UNION_TYPE) \ + && !TYPE_PACKED (STRUCT) \ + && TYPE_FIELDS (STRUCT) != 0 \ + ? MAX (MAX ((COMPUTED), (SPECIFIED)), or1k_struct_alignment (STRUCT)) \ + : MAX ((COMPUTED), (SPECIFIED))) \ + +/* Make strings word-aligned so strcpy from constants will be faster. */ +/* +#define CONSTANT_ALIGNMENT(EXP, ALIGN) \ + ((TREE_CODE (EXP) == STRING_CST || TREE_CODE (EXP) == CONSTRUCTOR) \ + && (ALIGN) < FASTEST_ALIGNMENT \ + ? FASTEST_ALIGNMENT : (ALIGN)) +*/ + +/* One use of this macro is to increase alignment of medium-size + data to make it all fit in fewer cache lines. Another is to + cause character arrays to be word-aligned so that `strcpy' calls + that copy constants to character arrays can be done inline. */ +/* +#define DATA_ALIGNMENT(TYPE, ALIGN) \ + ((((ALIGN) < FASTEST_ALIGNMENT) \ + && (TREE_CODE (TYPE) == ARRAY_TYPE \ + || TREE_CODE (TYPE) == UNION_TYPE \ + || TREE_CODE (TYPE) == RECORD_TYPE)) ? FASTEST_ALIGNMENT : (ALIGN)) +*/ /* CHECK - btw code gets bigger with this one */ +#define DATA_ALIGNMENT(TYPE, ALIGN) \ + ((ALIGN) < FASTEST_ALIGNMENT \ + ? or1k_data_alignment ((TYPE), (ALIGN)) : (ALIGN)) + +#define LOCAL_ALIGNMENT(TYPE, ALIGN) \ + ((ALIGN) < FASTEST_ALIGNMENT \ + ? or1k_data_alignment ((TYPE), (ALIGN)) : (ALIGN)) + +/* Define this if move instructions will actually fail to work + when given unaligned data. */ +#define STRICT_ALIGNMENT 1 /* CHECK */ + +/* Align an address */ +#define OR1K_ALIGN(n,a) (((n) + (a) - 1) & ~((a) - 1)) + +/* Define if operations between registers always perform the operation + on the full register even if a narrower mode is specified. */ +#define WORD_REGISTER_OPERATIONS /* CHECK */ + + +/* Define if loading in MODE, an integral mode narrower than BITS_PER_WORD + will either zero-extend or sign-extend. The value of this macro should + be the code that says which one of the two operations is implicitly + done, NIL if none. */ +#define LOAD_EXTEND_OP(MODE) ZERO_EXTEND + +/* Define this macro if it is advisable to hold scalars in registers + in a wider mode than that declared by the program. In such cases, + the value is constrained to be within the bounds of the declared + type, but kept valid in the wider mode. The signedness of the + extension may differ from that of the type. */ +#define PROMOTE_MODE(MODE, UNSIGNEDP, TYPE) \ + if (GET_MODE_CLASS (MODE) == MODE_INT \ + && GET_MODE_SIZE (MODE) < UNITS_PER_WORD) \ + (MODE) = SImode; + /* CHECK */ + + +/* + * brings 0.4% improvment in static size for linux + * +#define PROMOTE_FOR_CALL_ONLY +*/ + +/* Define this macro if it is as good or better to call a constant + function address than to call an address kept in a register. */ +#define NO_FUNCTION_CSE 1 /* check */ + +/* Standard register usage. */ + +/* Number of actual hardware registers. + The hardware registers are assigned numbers for the compiler + from 0 to just below FIRST_PSEUDO_REGISTER. + All registers that the compiler knows about must be given numbers, + even those that are not normally considered general registers. */ + +#define OR1K_LAST_ACTUAL_REG 31 +#define ARG_POINTER_REGNUM (OR1K_LAST_ACTUAL_REG + 1) +#define FRAME_POINTER_REGNUM (ARG_POINTER_REGNUM + 1) +#define OR1K_LAST_INT_REG FRAME_POINTER_REGNUM +#define OR1K_FLAGS_REG (OR1K_LAST_INT_REG + 1) +#define FIRST_PSEUDO_REGISTER (OR1K_FLAGS_REG + 1) + +/* 1 for registers that have pervasive standard uses + and are not available for the register allocator. + On the or1k, these are r1 as stack pointer and + r2 as frame/arg pointer. r9 is link register, r0 + is zero, r10 is linux thread and r16 is got pointer */ +#define FIXED_REGISTERS { \ + 1, 1, 0, 0, 0, 0, 0, 0, \ + 0, 1, 1, 0, 0, 0, 0, 0, \ + 1, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1 } +/* 1 for registers not available across function calls. + These must include the FIXED_REGISTERS and also any + registers that can be used without being saved. + The latter must include the registers where values are returned + and the register where structure-value addresses are passed. + Aside from that, you can include as many other registers as you like. */ +#define CALL_USED_REGISTERS { \ + 1, 1, 0, 1, 1, 1, 1, 1, \ + 1, 1, 1, 1, 1, 1, 0, 1, \ + 1, 1, 0, 1, 0, 1, 0, 1, \ + 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1} + +/* stack pointer: must be FIXED and CALL_USED */ +/* hard frame pointer: must be call saved. */ +/* soft frame pointer / arg pointer: must be FIXED and CALL_USED */ + +/* Return number of consecutive hard regs needed starting at reg REGNO + to hold something of mode MODE. + This is ordinarily the length in words of a value of mode MODE + but can be less for certain modes in special long registers. + On the or1k, all registers are one word long. */ +#define HARD_REGNO_NREGS(REGNO, MODE) \ + ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) + +/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. */ +#define HARD_REGNO_MODE_OK(REGNO, MODE) 1 + +/* Value is 1 if it is a good idea to tie two pseudo registers + when one has mode MODE1 and one has mode MODE2. + If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2, + for any hard reg, then this must be 0 for correct output. */ +#define MODES_TIEABLE_P(MODE1, MODE2) 1 + +/* A C expression for the cost of moving data of mode mode from a register in + class "from" to one in class "to". The classes are expressed using the + enumeration values such as GENERAL_REGS. A value of 2 is the default; other + values are interpreted relative to that. + + It is not required that the cost always equal 2 when "from" is the same as + "to"; on some machines it is expensive to move between registers if they are + not general registers. + + If reload sees an insn consisting of a single set between two hard + registers, and if REGISTER_MOVE_COST applied to their classes returns a + value of 2, reload does not check to ensure that the constraints of the + insn are met. Setting a cost of other than 2 will allow reload to verify + that the constraints are met. You should do this if the "movm" pattern's + constraints do not allow such copying. + + JPB 31-Aug-10: This is just the default. */ +#define REGISTER_MOVE_COST(mode, from, to) 2 + +/* A C expression for the cost of moving data of mode mode between a register + of class "class" and memory; "in" is zero if the value is to be written to + memory, nonzero if it is to be read in. This cost is relative to those in + REGISTER_MOVE_COST. If moving between registers and memory is more + expensive than between two registers, you should define this macro to + express the relative cost. + + If you do not define this macro, GCC uses a default cost of 4 plus the cost + of copying via a secondary reload register, if one is needed. If your + machine requires a secondary reload register to copy between memory and a + register of class but the reload mechanism is more complex than copying via + an intermediate, define this macro to reflect the actual cost of the move. + + GCC defines the function "memory_move_secondary_cost" if secondary reloads + are needed. It computes the costs due to copying via a secondary + register. If your machine copies from memory using a secondary register in + the conventional way but the default base value of 4 is not correct for + your machine, define this macro to add some other value to the result of + that function. The arguments to that function are the same as to this + macro. + + JPB 31-Aug-10. Is this really correct? I suppose the OR1K only takes one + cycle, notionally, to access memory, but surely that will + often stall the pipeline. Needs more investigation. */ +#define MEMORY_MOVE_COST(mode, class, in) 2 + +/* A C expression for the cost of a branch instruction. A value of 1 is the + default; other values are interpreted relative to that. Parameter "speed_p" + is TRUE when the branch in question should be optimized for speed. When it + is FALSE, BRANCH_COST should be returning value optimal for code size + rather then performance considerations. "predictable_p" is true for well + predictable branches. On many architectures the BRANCH_COST can be reduced + then. + + JPB 31-Aug-10. The original code had the comment that "... this should + specify the cost of a branch insn; roughly the number of + extra insns that should be added to avoid a branch. + + Set this to 3 on the or1k since that is roughly the average + cost of an unscheduled conditional branch. + + Cost of 2 and 3 give equal and ~0.7% bigger binaries + respectively." + + This seems ad-hoc. Probably we need some experiments. */ +#define BRANCH_COST(speed_p, predictable_p) 2 + +/* Specify the registers used for certain standard purposes. + The values of these macros are register numbers. */ + +/* Register to use for pushing function arguments. */ +#define STACK_POINTER_REGNUM 1 + +/* Base register for access to local variables of the function. */ +#define HARD_FRAME_POINTER_REGNUM 2 + +/* Link register. */ +#define LINK_REGNUM 9 + +/* Register in which static-chain is passed to a function. */ + +#define STATIC_CHAIN_REGNUM 11 + +#define PROLOGUE_TMP 13 +#define EPILOGUE_TMP 3 + +/* Register in which address to store a structure value + is passed to a function. */ +/*#define STRUCT_VALUE_REGNUM 0*/ + +/* Pass address of result struct to callee as "invisible" first argument */ +#define STRUCT_VALUE 0 + +/* -----------------------[ PHX start ]-------------------------------- */ + +/* Define the classes of registers for register constraints in the + machine description. Also define ranges of constants. + + One of the classes must always be named ALL_REGS and include all hard regs. + If there is more than one class, another class must be named NO_REGS + and contain no registers. + + The name GENERAL_REGS must be the name of a class (or an alias for + another name such as ALL_REGS). This is the class of registers + that is allowed by "g" or "r" in a register constraint. + Also, registers outside this class are allocated only when + instructions express preferences for them. + + GENERAL_REGS and BASE_REGS classess are the same on or1k. + + The classes must be numbered in nondecreasing order; that is, + a larger-numbered class must never be contained completely + in a smaller-numbered class. + + For any two classes, it is very desirable that there be another + class that represents their union. */ + +/* The or1k has only one kind of registers, so NO_REGS, GENERAL_REGS + and ALL_REGS are the only classes. */ +/* JPB 26-Aug-10: Based on note from Mikhael (mirekez@gmail.com), we don't + need CR_REGS and it is in the wrong place for later things! */ +enum reg_class +{ + NO_REGS, + GENERAL_REGS, + ALL_REGS, + LIM_REG_CLASSES +}; + +#define N_REG_CLASSES (int) LIM_REG_CLASSES + +/* Give names of register classes as strings for dump file. */ +#define REG_CLASS_NAMES \ +{ \ + "NO_REGS", \ + "GENERAL_REGS", \ + "ALL_REGS" \ +} + +/* Define which registers fit in which classes. This is an initializer for a + vector of HARD_REG_SET of length N_REG_CLASSES. + + An initializer containing the contents of the register classes, as integers + which are bit masks. The Nth integer specifies the contents of class N. + The way the integer MASK is interpreted is that register R is in the class + if `MASK & (1 << R)' is 1. + + When the machine has more than 32 registers, an integer does not suffice. + Then the integers are replaced by sub-initializers, braced groupings + containing several integers. Each sub-initializer must be suitable as an + initializer for the type `HARD_REG_SET' which is defined in + `hard-reg-set.h'. + + For the OR1K we have the minimal set. GENERAL_REGS is all except r0, which + it permanently zero. */ +#define REG_CLASS_CONTENTS \ + { \ + { 0x00000000, 0x00000000 }, /* NO_REGS */ \ + { 0xffffffff, 0x00000003 }, /* GENERAL_REGS */ \ + { 0xffffffff, 0x00000007 } /* ALL_REGS */ \ + } + +/* The same information, inverted: + + Return the class number of the smallest class containing reg number REGNO. + This could be a conditional expression or could index an array. + + ??? 0 is not really a register, but a constant. */ +#define REGNO_REG_CLASS(regno) \ + ((0 == regno) ? ALL_REGS : ((1 <= regno) && (regno <= OR1K_LAST_INT_REG)) \ + ? GENERAL_REGS : NO_REGS) + +/* The class value for index registers, and the one for base regs. */ +#define INDEX_REG_CLASS GENERAL_REGS +#define BASE_REG_CLASS GENERAL_REGS + +/* Given an rtx X being reloaded into a reg required to be in class CLASS, + return the class of reg to actually use. In general this is just CLASS; + but on some machines in some cases it is preferable to use a more + restrictive class. */ +#define PREFERRED_RELOAD_CLASS(X,CLASS) (CLASS) + +/* Return the maximum number of consecutive registers needed to represent mode + MODE in a register of class CLASS. + + On the or1k, this is always the size of MODE in words, since all registers + are the same size. */ +#define CLASS_MAX_NREGS(CLASS, MODE) \ + ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) + + +/* -------------------------------------------------------------------------- */ +/* Stack layout; function entry, exit and calling. */ + +/* Define this if pushing a word on the stack makes the stack pointer a + smaller address. */ +#define STACK_GROWS_DOWNWARD 1 + +/* Define this if the nominal address of the stack frame is at the + high-address end of the local variables; that is, each additional local + variable allocated goes at a more negative offset in the frame. */ +#define FRAME_GROWS_DOWNWARD 1 + +/* Offset within stack frame to start allocating local variables at. If + FRAME_GROWS_DOWNWARD, this is the offset to the END of the first local + allocated. Otherwise, it is the offset to the BEGINNING of the first local + allocated. */ +#define STARTING_FRAME_OFFSET 0 + +/* Offset of first parameter from the argument pointer register value. */ +#define FIRST_PARM_OFFSET(FNDECL) 0 + +/* Define this if stack space is still allocated for a parameter passed + in a register. The value is the number of bytes allocated to this + area. + + No such allocation for OR1K. */ +/* #define REG_PARM_STACK_SPACE(FNDECL) (UNITS_PER_WORD * GP_ARG_NUM_REG) */ + +/* Define this if the above stack space is to be considered part of the + space allocated by the caller. + + N/a for OR1K. */ +/* #define OUTGOING_REG_PARM_STACK_SPACE */ + +/* Define this macro if `REG_PARM_STACK_SPACE' is defined, but the + stack parameters don't skip the area specified by it. + + N/a for OR1K. */ +/* #define STACK_PARMS_IN_REG_PARM_AREA */ + +/* If nonzero, the maximum amount of space required for outgoing arguments + will be computed and placed into the variable + current_function_outgoing_args_size. No space will be pushed onto the stack + for each call; instead, the function prologue should increase the stack + frame size by this amount. + + Setting both PUSH_ARGS and ACCUMULATE_OUTGOING_ARGS is not proper. + + This is the approached used by OR1K. */ +#define ACCUMULATE_OUTGOING_ARGS 1 + +#define ELIMINABLE_REGS \ +{{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ + { ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \ + { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ + { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}} + +#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \ + (OFFSET) = or1k_initial_elimination_offset ((FROM), (TO)) + +/* Minimum and maximum general purpose registers used to hold arguments. */ +#define GP_ARG_MIN_REG 3 +#define GP_ARG_MAX_REG 8 +#define GP_ARG_NUM_REG (GP_ARG_MAX_REG - GP_ARG_MIN_REG + 1) + +/* Return register */ +#define GP_ARG_RETURN 11 +#define GP_ARG_RETURNH 12 + +/* TLS thread pointer register */ +#define THREAD_PTR_REGNUM 10 + +/* Position Independent Code. */ + +#define PIC_OFFSET_TABLE_REGNUM 16 + +/* A C expression that is nonzero if X is a legitimate immediate + operand on the target machine when generating position independent code. + You can assume that X satisfies CONSTANT_P, so you need not + check this. You can also assume `flag_pic' is true, so you need not + check it either. You need not define this macro if all constants + (including SYMBOL_REF) can be immediate operands when generating + position independent code. */ +#define LEGITIMATE_PIC_OPERAND_P(X) or1k_legitimate_pic_operand_p (X) + +/* A C expression to create an RTX representing the place where a library + function returns a value of mode mode. + + Note that “library function” in this context means a compiler support + routine, used to perform arithmetic, whose name is known specially by the + compiler and was not mentioned in the C code being compiled. + + For the OR1K, return value is in R11 (GP_ARG_RETURN). */ +#define LIBCALL_VALUE(mode) \ + gen_rtx_REG( \ + ((GET_MODE_CLASS (mode) != MODE_INT \ + || GET_MODE_SIZE (mode) >= 4) \ + ? (mode) \ + : SImode), \ + GP_ARG_RETURN) + +/* Define this if PCC uses the nonreentrant convention for returning + structure and union values. + + Not needed for OR1K. */ +/*#define PCC_STATIC_STRUCT_RETURN */ + +/* A C expression that is nonzero if regno is the number of a hard register in + which the values of called function may come back. + + A register whose use for returning values is limited to serving as the + second of a pair (for a value of type double, say) need not be recognized + by this macro. So for most machines, this definition suffices: + + #define FUNCTION_VALUE_REGNO_P(N) ((N) == 0) + + If the machine has register windows, so that the caller and the called + function use different registers for the return value, this macro should + recognize only the caller's register numbers. + + For OR1K, we must check if we have the return register. + + From GCC 4.6, this will be replaced by TARGET_FUNCION_VALUE_REGNO_P target + hook function. */ +#define FUNCTION_VALUE_REGNO_P(N) ((N) == GP_ARG_RETURN) + +/* 1 if N is a possible register number for function argument passing. */ +#define FUNCTION_ARG_REGNO_P(N) \ + ((N) >= GP_ARG_MIN_REG && (N) <= GP_ARG_MAX_REG) + +/* A code distinguishing the floating point format of the target + machine. There are three defined values: IEEE_FLOAT_FORMAT, + VAX_FLOAT_FORMAT, and UNKNOWN_FLOAT_FORMAT. */ +#define TARGET_FLOAT_FORMAT IEEE_FLOAT_FORMAT +#define FLOAT_WORDS_BIG_ENDIAN 1 + +/* A C type for declaring a variable that is used as the first argument of + FUNCTION_ARG and other related values. For some target machines, the type + int suffices and can hold the number of bytes of argument so far. + + There is no need to record in CUMULATIVE_ARGS anything about the arguments + that have been passed on the stack. The compiler has other variables to + keep track of that. For target machines on which all arguments are passed + on the stack, there is no need to store anything in CUMULATIVE_ARGS; + however, the data structure must exist and should not be empty, so use + int. */ +#define CUMULATIVE_ARGS int + +/* A C statement (sans semicolon) for initializing the variable "cum" for the + state at the beginning of the argument list. The variable has type + CUMULATIVE_ARGS. The value of "fntype" is the tree node for the data type + of the function which will receive the args, or 0 if the args are to a + compiler support library function. For direct calls that are not libcalls, + "fndecl" contain the declaration node of the function. "fndecl" is also set + when INIT_CUMULATIVE_ARGS is used to find arguments for the function being + compiled. "n_named_args" is set to the number of named arguments, + including a structure return address if it is passed as a parameter, when + making a call. When processing incoming arguments, "n_named_args" is set to + −1. + + When processing a call to a compiler support library function, "libname" + identifies which one. It is a symbol_ref rtx which contains the name of the + function, as a string. "libname" is 0 when an ordinary C function call is + being processed. Thus, each time this macro is called, either "libname" or + "fntype" is nonzero, but never both of them at once. + + For the OR1K, we set "cum" to zero each time. + JPB 29-Aug-10: Is this correct? */ +#define INIT_CUMULATIVE_ARGS(cum, fntype, libname, fndecl, n_named_args) \ + (cum = 0) + +/* -------------------------------------------------------------------------- */ +/* Define intermediate macro to compute the size (in registers) of an argument + for the or1k. + + The OR1K_ROUND_ADVANCE* macros are local to this file. */ + +/* Round "size" up to a word boundary. */ +#define OR1K_ROUND_ADVANCE(size) \ + (((size) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) + +/* Round arg "mode"/"type" up to the next word boundary. */ +#define OR1K_ROUND_ADVANCE_ARG(mode, type) \ + ((mode) == BLKmode \ + ? OR1K_ROUND_ADVANCE (int_size_in_bytes (type)) \ + : OR1K_ROUND_ADVANCE (GET_MODE_SIZE (mode))) + +/* The ABI says that no rounding to even or odd words takes place. */ +#define OR1K_ROUND_ADVANCE_CUM(cum, mode, type) (cum) + +/* Return boolean indicating if arg of type "type" and mode "mode" will be + passed in a reg. This includes arguments that have to be passed by + reference as the pointer to them is passed in a reg if one is available + (and that is what we're given). + + When passing arguments "named" is always 1. When receiving arguments + "named" is 1 for each argument except the last in a stdarg/varargs + function. In a stdarg function we want to treat the last named arg as + named. In a varargs function we want to treat the last named arg (which is + `__builtin_va_alist') as unnamed. + + This macro is only used in this file. */ +#define OR1K_PASS_IN_REG_P(cum, mode, type, named) \ + ((named) \ + && ((OR1K_ROUND_ADVANCE_CUM ((cum), (mode), (type)) \ + + OR1K_ROUND_ADVANCE_ARG ((mode), (type)) \ + <= GP_ARG_NUM_REG))) + +/* Output assembler code to FILE to increment profiler label # LABELNO + for profiling a function entry. */ +#define FUNCTION_PROFILER(FILE, LABELNO) + +/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function, the + stack pointer does not matter. The value is tested only in functions that + have frame pointers. No definition is equivalent to always zero. + + The default suffices for OR1K. */ +#define EXIT_IGNORE_STACK 0 + +/* A C expression whose value is RTL representing the location of the + incoming return address at the beginning of any function, before the + prologue. This RTL is either a REG, indicating that the return + value is saved in REG, or a MEM representing a location in + the stack. */ +#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (Pmode, LINK_REGNUM) + +#define RETURN_ADDR_RTX or1k_return_addr_rtx + +/* Addressing modes, and classification of registers for them. */ + +/* #define HAVE_POST_INCREMENT */ +/* #define HAVE_POST_DECREMENT */ + +/* #define HAVE_PRE_DECREMENT */ +/* #define HAVE_PRE_INCREMENT */ + +/* Macros to check register numbers against specific register classes. */ +#define MAX_REGS_PER_ADDRESS 1 + +/* True if X is an rtx for a constant that is a valid address. + + JPB 29-Aug-10: Why is the default implementation not OK? */ +#define CONSTANT_ADDRESS_P(X) \ + (GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \ + || GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST \ + || GET_CODE (X) == HIGH) + +/* A C expression which is nonzero if register number num is suitable for use + as a base register in operand addresses. Like TARGET_LEGITIMATE_ADDRESS_P, + this macro should also define a strict and a non-strict variant. Both + variants behave the same for hard register; for pseudos, the strict variant + will pass only those that have been allocated to a valid hard registers, + while the non-strict variant will pass all pseudos. + + Compiler source files that want to use the strict variant of this and other + macros define the macro REG_OK_STRICT. You should use an #ifdef + REG_OK_STRICT conditional to define the strict variant in that case and the + non-strict variant otherwise. + + JPB 29-Aug-10: This has been conflated with the old REG_OK_FOR_BASE_P + function, which is no longer part of GCC. + + I'm not sure this is right. r0 can be a base register, just + it can't get set by the user. */ +#ifdef REG_OK_STRICT +#define REGNO_OK_FOR_BASE_P(num) \ + ( ((0 < (num)) && ((num) <= OR1K_LAST_INT_REG)) \ + || ((0 < reg_renumber[num]) && (reg_renumber[num] <= OR1K_LAST_INT_REG))) + +#else +/* Accept an int register or a pseudo reg. + + JPB 1-Sep-10: Should this allow r0, if the strict version does not? */ +#define REGNO_OK_FOR_BASE_P(num) ((num) <= OR1K_LAST_INT_REG || \ + (num) >= FIRST_PSEUDO_REGISTER) +#endif + +/* OR1K doesn't have any indexed addressing. */ +#define REG_OK_FOR_INDEX_P(X) 0 +#define REGNO_OK_FOR_INDEX_P(X) 0 + + +/* Specify the machine mode that this machine uses for the index in the + tablejump instruction. */ +#define CASE_VECTOR_MODE SImode + +/* Define as C expression which evaluates to nonzero if the tablejump + instruction expects the table to contain offsets from the address of the + table. + + Do not define this if the table should contain absolute addresses. */ +/* #define CASE_VECTOR_PC_RELATIVE 1 */ + +/* Define this as 1 if `char' should by default be signed; else as 0. */ +#define DEFAULT_SIGNED_CHAR 1 + +/* The maximum number of bytes that a single instruction can move quickly + between memory and registers or between two memory locations. */ +#define MOVE_MAX 4 + +/* Define this if zero-extension is slow (more than one real instruction). */ +/* #define SLOW_ZERO_EXTEND */ + +/* Nonzero if access to memory by bytes is slow and undesirable. + For RISC chips, it means that access to memory by bytes is no + better than access by words when possible, so grab a whole word + and maybe make use of that. */ +#define SLOW_BYTE_ACCESS 1 + +/* Define if shifts truncate the shift count + which implies one can omit a sign-extension or zero-extension + of a shift count. */ +/* #define SHIFT_COUNT_TRUNCATED */ + +/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits + is done just by pretending it is already truncated. */ +#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1 + +/* Specify the machine mode that pointers have. + After generation of rtl, the compiler makes no further distinction + between pointers and any other objects of this machine mode. */ +#define Pmode SImode + +/* A function address in a call instruction + is a byte address (for indexing purposes) + so give the MEM rtx a byte's mode. */ +#define FUNCTION_MODE SImode + + +/* -------------------------------------------------------------------------- */ +/* Condition code stuff */ + +/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE, + return the mode to be used for the comparison. */ +#define SELECT_CC_MODE(op, x, y) or1k_select_cc_mode(op) + +/* Can the condition code MODE be safely reversed? This is safe in + all cases on this port, because at present it doesn't use the + trapping FP comparisons (fcmpo). */ +#define REVERSIBLE_CC_MODE(mode) 1 + +/* Given a condition code and a mode, return the inverse condition. + + JPB 31-Aug-10: This seems like the default. Do we even need this? */ +#define REVERSE_CONDITION(code, mode) reverse_condition (code) + + +/* -------------------------------------------------------------------------- */ +/* Control the assembler format that we output. */ + +/* A C string constant describing how to begin a comment in the target + assembler language. The compiler assumes that the comment will end at + the end of the line. */ +#define ASM_COMMENT_START "#" + +/* Output to assembler file text saying following lines may contain character + constants, extra white space, comments, etc. + + JPB 29-Aug-10: Default would seem to be OK here. */ +#define ASM_APP_ON "#APP\n" + +/* Output to assembler file text saying following lines no longer contain + unusual constructs. + + JPB 29-Aug-10: Default would seem to be OK here. */ +#define ASM_APP_OFF "#NO_APP\n" + +/* Switch to the text or data segment. */ + +/* Output before read-only data. */ +#define TEXT_SECTION_ASM_OP "\t.section .text" + +/* Output before writable data. */ +#define DATA_SECTION_ASM_OP "\t.section .data" + +/* Output before uninitialized data. */ +#define BSS_SECTION_ASM_OP "\t.section .bss" + +/* How to refer to registers in assembler output. This sequence is indexed by + compiler's hard-register-number (see above). */ +#define REGISTER_NAMES \ + {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \ + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", \ + "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", \ + "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", \ + "argp", "frame", "cc-flag"} + + +/* -------------------------------------------------------------------------- */ +/* Debug things for DBX (STABS) */ +/* */ +/* Note. Our config.gcc includes dbxelf.h, which sets up appropriate */ +/* defaults. Choice of which debug format to use is in our elf.h */ +/* -------------------------------------------------------------------------- */ + +/* Don't try to use the type-cross-reference character in DBX data. + Also has the consequence of putting each struct, union or enum + into a separate .stabs, containing only cross-refs to the others. */ +/* JPB 24-Aug-10: Is this really correct. Can't GDB use this info? */ +#define DBX_NO_XREFS + +/* -------------------------------------------------------------------------- */ +/* Debug things for DWARF2 */ +/* */ +/* Note. Choice of which debug format to use is in our elf.h */ +/* -------------------------------------------------------------------------- */ + +/* We support frame unwind info including for exceptions handling. This needs + INCOMING_RETURN_ADDR_RTX to be set and OBJECT_FORMAT_ELF to be defined (in + elfos.h). Override any default value. */ +#undef DWARF2_UNWIND_INFO +#define DWARF2_UNWIND_INFO 1 + +/* We want frame info produced. Note that this is superfluous if + DWARF2_UNWIND_INFO is non-zero, but we set so this so, we can produce frame + info even when it is zero. Override any default value. */ +#undef DWARF2_FRAME_INFO +#define DWARF2_FRAME_INFO 1 + +/* Macro specifying which register holds the return address */ +#define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGNUM (LINK_REGNUM) + +/* Where is the start of our stack frame in relation to the end of the + previous stack frame at the start of a function, before the prologue */ +#define INCOMING_FRAME_SP_OFFSET 0 + +/* Use compact debug tables. Generates .file/.loc directives. */ +#undef DWARF2_ASM_LINE_DEBUG_INFO +#define DWARF2_ASM_LINE_DEBUG_INFO 1 + +/* We don't need an alternative return address for now. */ +/* DWARF_ALT_FRAME_RETURN_COLUMN */ + +/* We always save registers in the prologue with word alignment, so don't + need this. */ +/* DWARF_CIE_DATA_ALIGNMENT */ + +/* This specifies the maximum number of registers we can save in a frame. We + could note that only SP, FP, LR, arg regs and callee saved regs come into + this category. However this is only an efficiency thing, so for now we + don't use it. */ +/* DWARF_FRAME_REGISTERS */ + +/* This specifies a mapping from register numbers in .dwarf_frame to + .eh_frame. However for us they are the same, so we don't need it. */ +/* DWARF_FRAME_REGNUM */ + +/* Defined if the DWARF column numbers do not match register numbers. For us + they do, so this is not needed. */ +/* DWARF_REG_TO_UNWIND_COLUMN */ + +/* Can be used to define a register guaranteed to be zero. Only useful if zero + is used to terminate backtraces, and not recommended for new ports, so we + don't use it. */ +/* DWARF_ZERO_REG */ + +/* This is the inverse function for DWARF_FRAME_REGNUM. Again not needed. */ +/* DWARF2_FRAME_REG_OUT */ + + +/* -------------------------------------------------------------------------- */ +/* Node: Label Output */ + +/* Globalizing directive for a label. */ +#define GLOBAL_ASM_OP "\t.global " + +#define SUPPORTS_WEAK 1 + +/* This is how to output the definition of a user-level label named NAME, + such as the label on a static function or variable NAME. */ +#define ASM_OUTPUT_LABEL(FILE,NAME) \ + { assemble_name (FILE, NAME); fputs (":\n", FILE); } + +/* We use -fleading-underscore to add it, when necessary. + JPB: No prefix for global symbols */ +#define USER_LABEL_PREFIX "" + +/* Remove any previous definition (elfos.h). */ +#define ASM_GENERATE_INTERNAL_LABEL(LABEL, PREFIX, NUM) \ + sprintf (LABEL, "*%s%d", PREFIX, NUM) + +/* This is how to output an assembler line defining an int constant. */ +#define ASM_OUTPUT_INT(stream, value) \ + { \ + fprintf (stream, "\t.word\t"); \ + output_addr_const (stream, (value)); \ + fprintf (stream, "\n")} + +/* This is how to output an assembler line defining a float constant. */ +#define ASM_OUTPUT_FLOAT(stream, value) \ + { long l; \ + REAL_VALUE_TO_TARGET_SINGLE (value,l); \ + fprintf(stream,"\t.word\t0x%08x\t\t# float %26.7e\n", l, value); } + +/* This is how to output an assembler line defining a double constant. */ +#define ASM_OUTPUT_DOUBLE(stream, value) \ + { long l[2]; \ + REAL_VALUE_TO_TARGET_DOUBLE (value,&l[0]); \ + fprintf(stream,"\t.word\t0x%08x,0x%08x\t# float %26.16le\n", \ + l[0],l[1],value); } + +/* This is how to output an assembler line defining a long double constant. + + JPB 29-Aug-10: Do we really mean this. I thought long double on OR1K was + the same as double. */ +#define ASM_OUTPUT_LONG_DOUBLE(stream, value) \ + { long l[4]; \ + REAL_VALUE_TO_TARGET_DOUBLE (value,&l[0]); \ + fprintf (stream, \ + "\t.word\t0x%08x,0x%08x,0x%08x,0x%08x\t# float %26.18lle\n", \ + l[0],l[1],l[2],l[3],value); } + +/* This is how to output an assembler line defining a short constant. */ +#define ASM_OUTPUT_SHORT(stream, value) \ + { fprintf (stream, "\t.half\t"); \ + output_addr_const (stream, (value)); \ + fprintf (stream, "\n"); } + +/* This is how to output an assembler line defining a char constant. */ +#define ASM_OUTPUT_CHAR(stream, value) \ + { fprintf (stream, "\t.byte\t"); \ + output_addr_const (stream, (value)); \ + fprintf (stream, "\n")} + +/* This is how to output an assembler line for a numeric constant byte. */ +#define ASM_OUTPUT_BYTE(stream, value) \ + fprintf (stream, "\t.byte\t0x%02x\n", (value)) + +/* This is how to output an insn to push a register on the stack. + It need not be very fast code. + + JPB 29-Aug-10: This was using l.sub (since we don't have l.subi), so it + was potty code. Replaced by adding immediate -1. */ +#define ASM_OUTPUT_REG_PUSH(stream, regno) \ + { fprintf (stream, "\tl.addi\tr1,r1,-4\n"); \ + fprintf (stream, "\tl.sw\t0(r1),%s\n", reg_names[regno]); } + +/* This is how to output an insn to pop a register from the stack. + It need not be very fast code. */ +#define ASM_OUTPUT_REG_POP(stream,REGNO) \ + { fprintf (stream, "\tl.lwz\t%s,0(r1)\n", reg_names[REGNO]); \ + fprintf (stream, "\tl.addi\tr1,r1,4\n"); } + +/* This is how to output an element of a case-vector that is absolute. + (The Vax does not use such vectors, + but we must define this macro anyway.) */ +#define ASM_OUTPUT_ADDR_VEC_ELT(stream, value) \ + fprintf (stream, "\t.word\t.L%d\n", value) + +/* This is how to output an element of a case-vector that is relative. */ +#define ASM_OUTPUT_ADDR_DIFF_ELT(stream, body, value, rel) \ + fprintf (stream, "\t.word\t.L%d-.L%d\n", value, rel) + +#define JUMP_TABLES_IN_TEXT_SECTION (flag_pic) +/* ??? If we were serious about PIC, we should also use l.jal to get + the table start address. */ + +/* This is how to output an assembler line that says to advance the location + counter to a multiple of 2**log bytes. */ +#define ASM_OUTPUT_ALIGN(stream, log) \ + if ((log) != 0) \ + { \ + fprintf (stream, "\t.align\t%d\n", 1 << (log)); \ + } + +/* This is how to output an assembler line that says to advance the location + counter by "size" bytes. */ +#define ASM_OUTPUT_SKIP(stream, size) \ + fprintf (stream, "\t.space %d\n", (size)) + +/* Need to split up .ascii directives to avoid breaking + the linker. */ + +/* This is how to output a string. */ +#define ASM_OUTPUT_ASCII(stream, ptr, len) \ + output_ascii_pseudo_op (stream, (const unsigned char *) (ptr), len) + +/* Invoked just before function output. */ +#define ASM_OUTPUT_FUNCTION_PREFIX(stream, fnname) \ + { fputs (".proc\t", stream); assemble_name (stream, fnname); \ + fputs ("\n", stream); } + +/* This says how to output an assembler line to define a global common + symbol. */ +#define ASM_OUTPUT_COMMON(stream,name,size,rounded) \ + { data_section (); \ + fputs ("\t.global\t", stream); \ + assemble_name(stream, name); \ + fputs ("\n", stream); \ + assemble_name (stream, name); \ + fputs (":\n", stream); \ + fprintf (stream, "\t.space\t%d\n", rounded); } + +/* This says how to output an assembler line to define a local common + symbol. + + JPB 29-Aug-10: I'm sure this doesn't work - we don't have a .bss directive + like this. */ +#define ASM_OUTPUT_LOCAL(stream, name, size, rounded) \ + { fputs ("\t.bss\t", (stream)); \ + assemble_name ((stream), (name)); \ + fprintf ((stream), ",%d,%d\n", (size), (rounded)); } + +/* This says how to output an assembler line to define a global common symbol + with size "size" (in bytes) and alignment "align" (in bits). */ +#define ASM_OUTPUT_ALIGNED_COMMON(stream, name, size, align) \ + { data_section(); \ + if ((ALIGN) > 8) \ + { \ + fprintf(stream, "\t.align %d\n", ((align) / BITS_PER_UNIT)); \ + } \ + fputs("\t.global\t", stream); assemble_name(stream, name); \ + fputs("\n", stream); \ + assemble_name(stream, name); \ + fputs (":\n", stream); \ + fprintf(stream, "\t.space\t%d\n", size); } + +/* This says how to output an assembler line to define a local common symbol + with size "size" (in bytes) and alignment "align" (in bits). */ +#define ASM_OUTPUT_ALIGNED_LOCAL(stream, name, size, align) \ + { data_section(); \ + if ((align) > 8) \ + { \ + fprintf(stream, "\t.align %d\n", ((align) / BITS_PER_UNIT)); \ + } \ + assemble_name(stream, name); \ + fputs (":\n", stream); \ + fprintf(stream, "\t.space %d\n", size); } + +/* Store in "output" a string (made with alloca) containing an assembler-name + for a local static variable named "name". "labelno" is an integer which is + different for each call. */ +#define ASM_FORMAT_PRIVATE_NAME(output, name, labelno) \ + { (output) = (char *) alloca (strlen ((name)) + 10); \ + sprintf ((output), "%s.%lu", (name), (unsigned long int) (labelno)); } + +/* Macro for %code validation. Returns nonzero if valid. + + The acceptance of '(' is an idea taken from SPARC; output nop for %( if not + optimizing or the slot is not filled. */ +#define PRINT_OPERAND_PUNCT_VALID_P(code) (('(' == code) || ('%' == code)) + +/* Print an instruction operand "x" on file "stream". "code" is the code from + the %-spec that requested printing this operand; if `%z3' was used to print + operand 3, then CODE is 'z'. */ +#define PRINT_OPERAND(stream, x, code) \ +{ \ + if (code == 'r' \ + && GET_CODE (x) == MEM \ + && GET_CODE (XEXP (x, 0)) == REG) \ + { \ + fprintf (stream, "%s", reg_names[REGNO (XEXP (x, 0))]); \ + } \ + else if (code == '(') \ + { \ + if (TARGET_DELAY_ON && dbr_sequence_length ()) \ + fprintf (stream, "\t# delay slot filled"); \ + else if (!TARGET_DELAY_OFF) \ + fprintf (stream, "\n\tl.nop\t\t\t# nop delay slot"); \ + } \ + else if (code == 'C') \ + { \ + switch (GET_CODE (x)) \ + { \ + case EQ: \ + fputs ("eq", stream); \ + break; \ + case NE: \ + fputs ("ne", stream); \ + break; \ + case GT: \ + fputs ("gts", stream); \ + break; \ + case GE: \ + fputs ("ges", stream); \ + break; \ + case LT: \ + fputs ("lts", stream); \ + break; \ + case LE: \ + fputs ("les", stream); \ + break; \ + case GTU: \ + fputs ("gtu", stream); \ + break; \ + case GEU: \ + fputs ("geu", stream); \ + break; \ + case LTU: \ + fputs ("ltu", stream); \ + break; \ + case LEU: \ + fputs ("leu", stream); \ + break; \ + default: \ + abort (); \ + } \ + } \ + else if (code == 'H') \ + { \ + if (GET_CODE (x) == REG) \ + fprintf (stream, "%s", reg_names[REGNO (x) + 1]); \ + else \ + abort (); \ + } \ + else if (GET_CODE (x) == REG) \ + fprintf (stream, "%s", reg_names[REGNO (x)]); \ + else if (GET_CODE (x) == MEM) \ + output_address (XEXP (x, 0)); \ + else \ + output_addr_const (stream, x); \ +} + +/* The size of the trampoline in bytes. This is a block of code followed by + two words specifying the function address and static chain pointer. */ +#define TRAMPOLINE_SIZE \ + (or1k_trampoline_code_size () + GET_MODE_SIZE (ptr_mode) * 2) + +/* Alignment required for trampolines, in bits. + + For the OR1K, there is no need for anything other than word alignment. */ +#define TRAMPOLINE_ALIGNMENT 32 + +/* Assume that if the assembler supports thread local storage + * the system supports it. */ +#if !defined(TARGET_HAVE_TLS) && defined(HAVE_AS_TLS) +#define TARGET_HAVE_TLS true +#endif + +/* Describe how we implement __builtin_eh_return. */ +#define EH_RETURN_REGNUM 23 +/* Use r25, r27, r29 and r31 (clobber regs) for exception data */ +#define EH_RETURN_DATA_REGNO(N) ((N) < 4 ? (25 + ((N)<<1)) : INVALID_REGNUM) +#define EH_RETURN_STACKADJ_RTX gen_rtx_REG (Pmode, EH_RETURN_REGNUM) +#define EH_RETURN_HANDLER_RTX or1k_eh_return_handler_rtx () + +#define INIT_EXPANDERS or1k_init_expanders () + +/* A C structure for machine-specific, per-function data. This is + * added to the cfun structure. */ +typedef struct GTY(()) machine_function +{ + /* Force stack save of LR. Used in RETURN_ADDR_RTX. */ + int force_lr_save; +} machine_function; + +#endif /* _OR1K_H_ */ diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/config/or1k/or1k.md gcc-4.8.2-or1k-rtems/gcc/config/or1k/or1k.md --- gcc-4.8.2/gcc/config/or1k/or1k.md 1970-01-01 02:00:00.000000000 +0200 +++ gcc-4.8.2-or1k-rtems/gcc/config/or1k/or1k.md 2014-03-14 07:27:49.000000000 +0200 @@ -0,0 +1,1426 @@ +;; Machine description for GNU compiler, OpenRISC 1000 family, OR32 ISA +;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +;; 2009, 2010 Free Software Foundation, Inc. +;; Copyright (C) 2010 Embecosm Limited + +;; Contributed by Damjan Lampret in 1999. +;; Major optimizations by Matjaz Breskvar in 2005. +;; Floating point additions by Jungsook Yang +;; Julius Baxter in 2010 +;; Updated for GCC 4.5 by Jeremy Bennett +;; and Joern Rennecke in 2010 + +;; This file is part of GNU CC. + +;; This program 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 3 of the License, or (at your option) +;; any later version. +;; +;; This program 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. If not, see . */ + +(define_constants [ + (SP_REG 1) + (FP_REG 2) ; hard frame pointer + (CC_REG 34) + + ;; unspec values + (UNSPEC_FRAME 0) + (UNSPEC_GOT 1) + (UNSPEC_GOTOFFHI 2) + (UNSPEC_GOTOFFLO 3) + (UNSPEC_TPOFFLO 4) + (UNSPEC_TPOFFHI 5) + (UNSPEC_GOTTPOFFLO 6) + (UNSPEC_GOTTPOFFHI 7) + (UNSPEC_GOTTPOFFLD 8) + (UNSPEC_TLSGDLO 9) + (UNSPEC_TLSGDHI 10) + (UNSPEC_SET_GOT 101) +]) + +(include "predicates.md") + +(include "constraints.md") + +(define_attr "type" + "unknown,load,store,move,extend,logic,add,mul,shift,compare,branch,jump,fp,jump_restore" + (const_string "unknown")) + +;; Number of machine instructions required to implement an insn. +(define_attr "length" "" (const_int 1)) + +;; Single delay slot after branch or jump instructions, wich may contain any +;; instruction but another branch or jump. +;; If TARGET_DELAY_OFF is not true, then never use delay slots. +;; If TARGET_DELAY_ON is not true, no instruction will be allowed to +;; fill the slot, and so it will be filled by a nop instead. +(define_delay (and (match_test "!TARGET_DELAY_OFF") (eq_attr "type" "branch,jump")) + [(and (match_test "TARGET_DELAY_ON") + (eq_attr "type" "!branch,jump") + (eq_attr "length" "1")) (nil) (nil)]) + +;; ALU is modelled as a single functional unit, which is reserved for varying +;; numbers of slots. +;; +;; I think this is all incorrect for the OR1K. The latency says when the +;; result will be ready, not how long the pipeline takes to execute. +(define_cpu_unit "or1k_alu") +(define_insn_reservation "bit_unit" 3 (eq_attr "type" "shift") "or1k_alu") +(define_insn_reservation "lsu_load" 3 (eq_attr "type" "load") "or1k_alu*3") +(define_insn_reservation "lsu_store" 2 (eq_attr "type" "store") "or1k_alu") +(define_insn_reservation "alu_unit" 2 + (eq_attr "type" "add,logic,extend,move,compare") + "or1k_alu") +(define_insn_reservation "mul_unit" 16 (eq_attr "type" "mul") "or1k_alu*16") + + +;; Called after register allocation to add any instructions needed for the +;; prologue. Using a prologue insn is favored compared to putting all of the +;; instructions in output_function_prologue(), since it allows the scheduler +;; to intermix instructions with the saves of the caller saved registers. In +;; some cases, it might be necessary to emit a barrier instruction as the last +;; insn to prevent such scheduling. + +(define_expand "prologue" + [(use (const_int 1))] + "" +{ + or1k_expand_prologue (); + DONE; +}) + +;; Called after register allocation to add any instructions needed for the +;; epilogue. Using an epilogue insn is favored compared to putting all of the +;; instructions in output_function_epilogue(), since it allows the scheduler +;; to intermix instructions with the restores of the caller saved registers. +;; In some cases, it might be necessary to emit a barrier instruction as the +;; first insn to prevent such scheduling. +(define_expand "epilogue" + [(use (const_int 2))] + "" +{ + or1k_expand_epilogue (); + DONE; +}) + +(define_insn "frame_alloc_fp" + [(set (reg:SI SP_REG) + (plus:SI (reg:SI SP_REG) + (match_operand:SI 0 "nonmemory_operand" "r,I"))) + (clobber (mem:QI (plus:SI (reg:SI FP_REG) + (unspec:SI [(const_int FP_REG)] UNSPEC_FRAME))))] + "" + "@ + l.add\tr1,r1,%0\t# allocate frame + l.addi\tr1,r1,%0\t# allocate frame" + [(set_attr "type" "add") + (set_attr "length" "1")]) + +(define_insn "frame_dealloc_fp" + [(set (reg:SI SP_REG) (reg:SI FP_REG)) + (clobber (mem:QI (plus:SI (reg:SI FP_REG) + (unspec:SI [(const_int FP_REG)] UNSPEC_FRAME))))] + "" + "l.ori\tr1,r2,0\t# deallocate frame" + [(set_attr "type" "logic") + (set_attr "length" "1")]) + +(define_insn "frame_dealloc_sp" + [(set (reg:SI SP_REG) + (plus:SI (reg:SI SP_REG) + (match_operand:SI 0 "nonmemory_operand" "r,I"))) + (clobber (mem:QI (plus:SI (reg:SI SP_REG) + (unspec:SI [(const_int SP_REG)] UNSPEC_FRAME))))] + "" + "@ + l.add\tr1,r1,%0 + l.addi\tr1,r1,%0" + [(set_attr "type" "add") + (set_attr "length" "1")]) + +(define_insn "return_internal" + [(return) + (use (match_operand 0 "pmode_register_operand" ""))] + "" + "l.jr \t%0\t# return_internal%(" + [(set_attr "type" "jump") + (set_attr "length" "1")]) + + + +;; +;; movQI +;; + +(define_expand "movqi" + [(set (match_operand:QI 0 "general_operand" "") + (match_operand:QI 1 "general_operand" ""))] + "" + " + if (can_create_pseudo_p()) + { + if (GET_CODE (operands[1]) == CONST_INT) + { + rtx reg = gen_reg_rtx (SImode); + + emit_insn (gen_movsi (reg, operands[1])); + operands[1] = gen_lowpart (QImode, reg); + } + if (GET_CODE (operands[1]) == MEM && optimize > 0) + { + rtx reg = gen_reg_rtx (SImode); + + emit_insn (gen_rtx_SET (SImode, reg, + gen_rtx_ZERO_EXTEND (SImode, + operands[1]))); + + operands[1] = gen_lowpart (QImode, reg); + } + if (GET_CODE (operands[0]) != REG) + operands[1] = force_reg (QImode, operands[1]); + } +") + +(define_insn "*movqi_internal" + [(set (match_operand:QI 0 "nonimmediate_operand" "=m,r,r,r,r") + (match_operand:QI 1 "general_operand" "r,r,I,K,m"))] + "" + "@ + l.sb \t%0,%1\t # movqi + l.ori \t%0,%1,0\t # movqi: move reg to reg + l.addi \t%0,r0,%1\t # movqi: move immediate + l.ori \t%0,r0,%1\t # movqi: move immediate + l.lbz \t%0,%1\t # movqi" + [(set_attr "type" "store,add,add,logic,load")]) + + +;; +;; movHI +;; + +(define_expand "movhi" + [(set (match_operand:HI 0 "general_operand" "") + (match_operand:HI 1 "general_operand" ""))] + "" + " + if (can_create_pseudo_p()) + { + if (GET_CODE (operands[1]) == CONST_INT) + { + rtx reg = gen_reg_rtx (SImode); + + emit_insn (gen_movsi (reg, operands[1])); + operands[1] = gen_lowpart (HImode, reg); + } + else if (GET_CODE (operands[1]) == MEM && optimize > 0) + { + rtx reg = gen_reg_rtx (SImode); + + emit_insn (gen_rtx_SET (SImode, reg, + gen_rtx_ZERO_EXTEND (SImode, + operands[1]))); + operands[1] = gen_lowpart (HImode, reg); + } + if (GET_CODE (operands[0]) != REG) + operands[1] = force_reg (HImode, operands[1]); + } +") + +(define_insn "*movhi_internal" + [(set (match_operand:HI 0 "nonimmediate_operand" "=m,r,r,r,r") + (match_operand:HI 1 "general_operand" "r,r,I,K,m"))] + "" + "@ + l.sh \t%0,%1\t # movhi + l.ori \t%0,%1,0\t # movhi: move reg to reg + l.addi \t%0,r0,%1\t # movhi: move immediate + l.ori \t%0,r0,%1\t # movhi: move immediate + l.lhz \t%0,%1\t # movhi" + [(set_attr "type" "store,add,add,logic,load")]) + +(define_expand "movsi" + [(set (match_operand:SI 0 "general_operand" "") + (match_operand:SI 1 "general_operand" ""))] + "" +{ + if (or1k_expand_move (SImode, operands)) DONE; +}) + +;; +;; movSI +;; + +(define_insn "*movsi_insn" + [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,r,m") + (match_operand:SI 1 "input_operand" "I,K,M,r,m,r"))] + "(register_operand (operands[0], SImode) + || (register_operand (operands[1], SImode)) + || (operands[1] == const0_rtx))" + "@ + l.addi \t%0,r0,%1\t # move immediate I + l.ori \t%0,r0,%1\t # move immediate K + l.movhi \t%0,hi(%1)\t # move immediate M + l.ori \t%0,%1,0\t # move reg to reg + l.lwz \t%0,%1\t # SI load + l.sw \t%0,%1\t # SI store" + [(set_attr "type" "add,load,store,add,logic,move") + (set_attr "length" "1,1,1,1,1,1")]) + +(define_insn "movsi_lo_sum" + [(set (match_operand:SI 0 "register_operand" "=r") + (lo_sum:SI (match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "immediate_operand" "i")))] + "" + "l.ori \t%0,%1,lo(%2) # movsi_lo_sum" + [(set_attr "type" "logic") + (set_attr "length" "1")]) + +(define_insn "movsi_high" + [(set (match_operand:SI 0 "register_operand" "=r") + (high:SI (match_operand:SI 1 "immediate_operand" "i")))] + "" + "l.movhi \t%0,hi(%1) # movsi_high" +[(set_attr "type" "move") + (set_attr "length" "1")]) + +(define_insn "movsi_gotofflo" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI [(lo_sum:SI (match_operand:SI 1 "register_operand" "r") + (match_operand 2 "" ""))] UNSPEC_GOTOFFLO))] + "flag_pic" + "l.ori \t%0,%1,gotofflo(%2) # movsi_gotofflo" + [(set_attr "type" "logic") + (set_attr "length" "1")]) + +(define_insn "movsi_gotoffhi" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI [(match_operand 1 "" "")] UNSPEC_GOTOFFHI))] + "flag_pic" + "l.movhi \t%0,gotoffhi(%1) # movsi_gotoffhi" + [(set_attr "type" "move") + (set_attr "length" "1")]) + +(define_insn "movsi_got" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI [(match_operand 1 "" "")] UNSPEC_GOT)) + (use (reg:SI 16))] + "flag_pic" + "l.lwz \t%0, got(%1)(r16)" + [(set_attr "type" "load")] +) + +(define_insn "movsi_tlsgdlo" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI [(lo_sum:SI (match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "immediate_operand" "i"))] UNSPEC_TLSGDLO))] + "" + "l.ori \t%0,%1,tlsgdlo(%2) # movsi_tlsgdlo" + [(set_attr "type" "logic") + (set_attr "length" "1")]) + +(define_insn "movsi_tlsgdhi" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI [(match_operand:SI 1 "immediate_operand" "i")] UNSPEC_TLSGDHI))] + "" + "l.movhi \t%0,tlsgdhi(%1) # movsi_tlsgdhi" +[(set_attr "type" "move") + (set_attr "length" "1")]) + +(define_insn "movsi_gottpofflo" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI [(lo_sum:SI (match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "immediate_operand" "i"))] UNSPEC_GOTTPOFFLO))] + "" + "l.ori \t%0,%1,gottpofflo(%2) # movsi_gottpofflo" + [(set_attr "type" "logic") + (set_attr "length" "1")]) + +(define_insn "movsi_gottpoffhi" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI [(match_operand:SI 1 "immediate_operand" "i")] UNSPEC_GOTTPOFFHI))] + "" + "l.movhi \t%0,gottpoffhi(%1) # movsi_gottpoffhi" +[(set_attr "type" "move") + (set_attr "length" "1")]) + +(define_insn "load_gottpoff" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI [(match_operand:SI 1 "register_operand" "r")] UNSPEC_GOTTPOFFLD))] + "" + "l.lwz \t%0,0(%1) # load_gottpoff" +[(set_attr "type" "load") + (set_attr "length" "1")]) + +(define_insn "movsi_tpofflo" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI [(lo_sum:SI (match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "immediate_operand" "i"))] UNSPEC_TPOFFLO))] + "" + "l.ori \t%0,%1,tpofflo(%2) # movsi_tpofflo" + [(set_attr "type" "logic") + (set_attr "length" "1")]) + +(define_insn "movsi_tpoffhi" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI [(match_operand:SI 1 "immediate_operand" "i")] UNSPEC_TPOFFHI))] + "" + "l.movhi \t%0,tpoffhi(%1) # movsi_tpoffhi" +[(set_attr "type" "move") + (set_attr "length" "1")]) + + +(define_insn_and_split "movsi_insn_big" + [(set (match_operand:SI 0 "register_operand" "=r") + (match_operand:SI 1 "immediate_operand" "i"))] + "GET_CODE (operands[1]) != CONST_INT" + ;; the switch of or1k bfd to Rela allows us to schedule insns separately. + "l.movhi \t%0,hi(%1)\;l.ori \t%0,%0,lo(%1)" + "(GET_CODE (operands[1]) != CONST_INT + || ! (CONST_OK_FOR_CONSTRAINT_P (INTVAL (operands[1]), 'I', \"I\") + || CONST_OK_FOR_CONSTRAINT_P (INTVAL (operands[1]), 'K', \"K\") + || CONST_OK_FOR_CONSTRAINT_P (INTVAL (operands[1]), 'M', \"M\"))) + && reload_completed + && GET_CODE (operands[1]) != HIGH && GET_CODE (operands[1]) != LO_SUM" + [(pc)] +{ + if (!or1k_expand_symbol_ref(SImode, operands)) + { + emit_insn (gen_movsi_high (operands[0], operands[1])); + emit_insn (gen_movsi_lo_sum (operands[0], operands[0], operands[1])); + } + DONE; +} + [(set_attr "type" "move") + (set_attr "length" "2")]) + + +;; +;; Conditional Branches & Moves +;; + +(define_expand "addsicc" + [(match_operand:SI 0 "register_operand" "") + (match_operand 1 "comparison_operator" "") + (match_operand:SI 2 "register_operand" "") + (match_operand:SI 3 "register_operand" "")] + "" + "FAIL;") + +(define_expand "addhicc" + [(match_operand:HI 0 "register_operand" "") + (match_operand 1 "comparison_operator" "") + (match_operand:HI 2 "register_operand" "") + (match_operand:HI 3 "register_operand" "")] + "" + "FAIL;") + +(define_expand "addqicc" + [(match_operand:QI 0 "register_operand" "") + (match_operand 1 "comparison_operator" "") + (match_operand:QI 2 "register_operand" "") + (match_operand:QI 3 "register_operand" "")] + "" + "FAIL;") + + +;; +;; conditional moves +;; + +(define_expand "movsicc" + [(set (match_operand:SI 0 "register_operand" "") + (if_then_else:SI (match_operand 1 "comparison_operator" "") + (match_operand:SI 2 "register_operand" "") + (match_operand:SI 3 "register_operand" "")))] + "TARGET_MASK_CMOV" + " +{ + if (or1k_emit_cmove (operands[0], operands[1], operands[2], operands[3])) + DONE; +}") + +(define_expand "movhicc" + [(set (match_operand:HI 0 "register_operand" "") + (if_then_else:SI (match_operand 1 "comparison_operator" "") + (match_operand:HI 2 "register_operand" "") + (match_operand:HI 3 "register_operand" "")))] + "" + " +{ + FAIL; +}") + +(define_expand "movqicc" + [(set (match_operand:QI 0 "register_operand" "") + (if_then_else:SI (match_operand 1 "comparison_operator" "") + (match_operand:QI 2 "register_operand" "") + (match_operand:QI 3 "register_operand" "")))] + "" + " +{ + FAIL; +}") + + +;; We use the BASE_REGS for the cmov input operands because, if rA is +;; 0, the value of 0 is placed in rD upon truth. Similarly for rB +;; because we may switch the operands and rB may end up being rA. + +(define_insn "cmov" + [(set (match_operand:SI 0 "register_operand" "=r") + (if_then_else:SI + (match_operator 1 "comparison_operator" + [(match_operand 4 "cc_reg_operand" "") + (const_int 0)]) + (match_operand:SI 2 "register_operand" "r") + (match_operand:SI 3 "register_operand" "r")))] + "TARGET_MASK_CMOV" + "* + return or1k_output_cmov(operands); + ") + +;; +;; .................... +;; +;; COMPARISONS +;; +;; .................... + +;; Flow here is rather complex: +;; +;; 1) The cmp{si,di,sf,df} routine is called. It deposits the +;; arguments into the branch_cmp array, and the type into +;; branch_type. No RTL is generated. +;; +;; 2) The appropriate branch define_expand is called, which then +;; creates the appropriate RTL for the comparison and branch. +;; Different CC modes are used, based on what type of branch is +;; done, so that we can constrain things appropriately. There +;; are assumptions in the rest of GCC that break if we fold the +;; operands into the branches for integer operations, and use cc0 +;; for floating point, so we use the fp status register instead. +;; If needed, an appropriate temporary is created to hold the +;; of the integer compare. + +;; Compare insns are next. Note that the RS/6000 has two types of compares, +;; signed & unsigned, and one type of branch. +;; +;; Start with the DEFINE_EXPANDs to generate the rtl for compares, scc +;; insns, and branches. We store the operands of compares until we see +;; how it is used. + +;; JPB 31-Aug-10: cmpxx appears to be obsolete in GCC 4.5. Needs more +;; investigation. + +;;(define_expand "cmpsi" +;; [(set (reg:CC CC_REG) +;; (compare:CC (match_operand:SI 0 "register_operand" "") +;; (match_operand:SI 1 "nonmemory_operand" "")))] +;; "" +;; { +;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) +;; operands[0] = force_reg (SImode, operands[0]); +;; or1k_compare_op0 = operands[0]; +;; or1k_compare_op1 = operands[1]; +;; DONE; +;; }) + +;; (define_expand "cmpsf" +;; [(set (reg:CC CC_REG) +;; (compare:CC (match_operand:SF 0 "register_operand" "") +;; (match_operand:SF 1 "register_operand" "")))] +;; "TARGET_HARD_FLOAT" +;; { +;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) +;; operands[0] = force_reg (SFmode, operands[0]); +;; or1k_compare_op0 = operands[0]; +;; or1k_compare_op1 = operands[1]; +;; DONE; +;; }) + +(define_expand "cbranchsi4" + [(match_operator 0 "comparison_operator" + [(match_operand:SI 1 "register_operand") + (match_operand:SI 2 "nonmemory_operand")]) + (match_operand 3 "")] + "" + { + or1k_expand_conditional_branch (operands, SImode); + DONE; + }) + +(define_expand "cbranchsf4" + [(match_operator 0 "comparison_operator" + [(match_operand:SF 1 "register_operand") + (match_operand:SF 2 "register_operand")]) + (match_operand 3 "")] + "TARGET_HARD_FLOAT" + { + or1k_expand_conditional_branch (operands, SFmode); + DONE; + }) + +;; +;; Setting a CCxx registers from comparision +;; + + + +;; Here are the actual compare insns. +(define_insn "*cmpsi_eq" + [(set (reg:CCEQ CC_REG) + (compare:CCEQ (match_operand:SI 0 "register_operand" "r,r") + (match_operand:SI 1 "nonmemory_operand" "I,r")))] + "" + "@ + l.sfeqi\t%0,%1 # cmpsi_eq + l.sfeq \t%0,%1 # cmpsi_eq" + [(set_attr "type" "compare") + (set_attr "length" "1")]) + +(define_insn "*cmpsi_ne" + [(set (reg:CCNE CC_REG) + (compare:CCNE (match_operand:SI 0 "register_operand" "r,r") + (match_operand:SI 1 "nonmemory_operand" "I,r")))] + "" + "@ + l.sfnei\t%0,%1 # cmpsi_ne + l.sfne \t%0,%1 # cmpsi_ne" + [(set_attr "type" "compare") + (set_attr "length" "1")]) + +(define_insn "*cmpsi_gt" + [(set (reg:CCGT CC_REG) + (compare:CCGT (match_operand:SI 0 "register_operand" "r,r") + (match_operand:SI 1 "nonmemory_operand" "I,r")))] + "" + "@ + l.sfgtsi\t%0,%1 # cmpsi_gt + l.sfgts \t%0,%1 # cmpsi_gt" + [(set_attr "type" "compare") + (set_attr "length" "1")]) + +(define_insn "*cmpsi_gtu" + [(set (reg:CCGTU CC_REG) + (compare:CCGTU (match_operand:SI 0 "register_operand" "r,r") + (match_operand:SI 1 "nonmemory_operand" "I,r")))] + "" + "@ + l.sfgtui\t%0,%1 # cmpsi_gtu + l.sfgtu \t%0,%1 # cmpsi_gtu" + [(set_attr "type" "compare") + (set_attr "length" "1")]) + +(define_insn "*cmpsi_lt" + [(set (reg:CCLT CC_REG) + (compare:CCLT (match_operand:SI 0 "register_operand" "r,r") + (match_operand:SI 1 "nonmemory_operand" "I,r")))] + "" + "@ + l.sfltsi\t%0,%1 # cmpsi_lt + l.sflts \t%0,%1 # cmpsi_lt" + [(set_attr "type" "compare") + (set_attr "length" "1")]) + +(define_insn "*cmpsi_ltu" + [(set (reg:CCLTU CC_REG) + (compare:CCLTU (match_operand:SI 0 "register_operand" "r,r") + (match_operand:SI 1 "nonmemory_operand" "I,r")))] + "" + "@ + l.sfltui\t%0,%1 # cmpsi_ltu + l.sfltu \t%0,%1 # cmpsi_ltu" + [(set_attr "type" "compare") + (set_attr "length" "1")]) + +(define_insn "*cmpsi_ge" + [(set (reg:CCGE CC_REG) + (compare:CCGE (match_operand:SI 0 "register_operand" "r,r") + (match_operand:SI 1 "nonmemory_operand" "I,r")))] + "" + "@ + l.sfgesi\t%0,%1 # cmpsi_ge + l.sfges \t%0,%1 # cmpsi_ge" + [(set_attr "type" "compare") + (set_attr "length" "1")]) + + +(define_insn "*cmpsi_geu" + [(set (reg:CCGEU CC_REG) + (compare:CCGEU (match_operand:SI 0 "register_operand" "r,r") + (match_operand:SI 1 "nonmemory_operand" "I,r")))] + "" + "@ + l.sfgeui\t%0,%1 # cmpsi_geu + l.sfgeu \t%0,%1 # cmpsi_geu" + [(set_attr "type" "compare") + (set_attr "length" "1")]) + + +(define_insn "*cmpsi_le" + [(set (reg:CCLE CC_REG) + (compare:CCLE (match_operand:SI 0 "register_operand" "r,r") + (match_operand:SI 1 "nonmemory_operand" "I,r")))] + "" + "@ + l.sflesi\t%0,%1 # cmpsi_le + l.sfles \t%0,%1 # cmpsi_le" + [(set_attr "type" "compare") + (set_attr "length" "1")]) + +(define_insn "*cmpsi_leu" + [(set (reg:CCLEU CC_REG) + (compare:CCLEU (match_operand:SI 0 "register_operand" "r,r") + (match_operand:SI 1 "nonmemory_operand" "I,r")))] + "" + "@ + l.sfleui\t%0,%1 # cmpsi_leu + l.sfleu \t%0,%1 # cmpsi_leu" + [(set_attr "type" "compare") + (set_attr "length" "1")]) + +;; Single precision floating point evaluation instructions +(define_insn "*cmpsf_eq" + [(set (reg:CCEQ CC_REG) + (compare:CCEQ (match_operand:SF 0 "register_operand" "r,r") + (match_operand:SF 1 "register_operand" "r,r")))] + "TARGET_HARD_FLOAT" + "lf.sfeq.s\t%0,%1 # cmpsf_eq" + [(set_attr "type" "compare") + (set_attr "length" "1")]) + +(define_insn "*cmpsf_ne" + [(set (reg:CCNE CC_REG) + (compare:CCNE (match_operand:SF 0 "register_operand" "r,r") + (match_operand:SF 1 "register_operand" "r,r")))] + "TARGET_HARD_FLOAT" + "lf.sfne.s\t%0,%1 # cmpsf_ne" + [(set_attr "type" "compare") + (set_attr "length" "1")]) + + +(define_insn "*cmpsf_gt" + [(set (reg:CCGT CC_REG) + (compare:CCGT (match_operand:SF 0 "register_operand" "r,r") + (match_operand:SF 1 "register_operand" "r,r")))] + "TARGET_HARD_FLOAT" + "lf.sfgt.s\t%0,%1 # cmpsf_gt" + [(set_attr "type" "compare") + (set_attr "length" "1")]) + +(define_insn "*cmpsf_ge" + [(set (reg:CCGE CC_REG) + (compare:CCGE (match_operand:SF 0 "register_operand" "r,r") + (match_operand:SF 1 "register_operand" "r,r")))] + "TARGET_HARD_FLOAT" + "lf.sfge.s\t%0,%1 # cmpsf_ge" + [(set_attr "type" "compare") + (set_attr "length" "1")]) + + +(define_insn "*cmpsf_lt" + [(set (reg:CCLT CC_REG) + (compare:CCLT (match_operand:SF 0 "register_operand" "r,r") + (match_operand:SF 1 "register_operand" "r,r")))] + "TARGET_HARD_FLOAT" + "lf.sflt.s\t%0,%1 # cmpsf_lt" + [(set_attr "type" "compare") + (set_attr "length" "1")]) + +(define_insn "*cmpsf_le" + [(set (reg:CCLE CC_REG) + (compare:CCLE (match_operand:SF 0 "register_operand" "r,r") + (match_operand:SF 1 "register_operand" "r,r")))] + "TARGET_HARD_FLOAT" + "lf.sfle.s\t%0,%1 # cmpsf_le" + [(set_attr "type" "compare") + (set_attr "length" "1")]) + +(define_insn "*bf" + [(set (pc) + (if_then_else (match_operator 1 "comparison_operator" + [(match_operand 2 + "cc_reg_operand" "") + (const_int 0)]) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "* + return or1k_output_bf(operands); + " + [(set_attr "type" "branch") + (set_attr "length" "1")]) + +;; +;; +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; +(define_insn_and_split "movdi" + [(set (match_operand:DI 0 "nonimmediate_operand" "=r, r, m, r") + (match_operand:DI 1 "general_operand" " r, m, r, n"))] + "" + "* + return or1k_output_move_double (operands); + " + "&& reload_completed && CONSTANT_P (operands[1])" + [(set (match_dup 2) (match_dup 3)) (set (match_dup 4) (match_dup 5))] + "operands[2] = operand_subword (operands[0], 0, 0, DImode); + operands[3] = operand_subword (operands[1], 0, 0, DImode); + operands[4] = operand_subword (operands[0], 1, 0, DImode); + operands[5] = operand_subword (operands[1], 1, 0, DImode);" + [(set_attr "length" "2,2,2,3")]) + +;; Moving double and single precision floating point values + + +(define_insn "movdf" + [(set (match_operand:DF 0 "nonimmediate_operand" "=r, r, m, r") + (match_operand:DF 1 "general_operand" " r, m, r, i"))] + "" + "* + return or1k_output_move_double (operands); + " + [(set_attr "length" "2,2,2,3")]) + + +(define_insn "movsf" + [(set (match_operand:SF 0 "general_operand" "=r,r,m") + (match_operand:SF 1 "general_operand" "r,m,r"))] + "" + "@ + l.ori \t%0,%1,0\t # movsf + l.lwz \t%0,%1\t # movsf + l.sw \t%0,%1\t # movsf" + [(set_attr "type" "move,load,store") + (set_attr "length" "1,1,1")]) + + +;; +;; extendqisi2 +;; + +(define_expand "extendqisi2" + [(use (match_operand:SI 0 "register_operand" "")) + (use (match_operand:QI 1 "nonimmediate_operand" ""))] + "" + " +{ + if (TARGET_MASK_SEXT) + emit_insn (gen_extendqisi2_sext(operands[0], operands[1])); + else { + if ( GET_CODE(operands[1]) == MEM ) { + emit_insn (gen_extendqisi2_no_sext_mem(operands[0], operands[1])); + } + else { + emit_insn (gen_extendqisi2_no_sext_reg(operands[0], operands[1])); + } + } + DONE; +}") + +(define_insn "extendqisi2_sext" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))] + "TARGET_MASK_SEXT" + "@ + l.extbs \t%0,%1\t # extendqisi2_has_signed_extend + l.lbs \t%0,%1\t # extendqisi2_has_signed_extend" + [(set_attr "length" "1,1") + (set_attr "type" "extend,load")]) + +(define_insn "extendqisi2_no_sext_mem" + [(set (match_operand:SI 0 "register_operand" "=r") + (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))] + "!TARGET_MASK_SEXT" + "l.lbs \t%0,%1\t # extendqisi2_no_sext_mem" + [(set_attr "length" "1") + (set_attr "type" "load")]) + +(define_expand "extendqisi2_no_sext_reg" + [(set (match_dup 2) + (ashift:SI (match_operand:QI 1 "register_operand" "") + (const_int 24))) + (set (match_operand:SI 0 "register_operand" "") + (ashiftrt:SI (match_dup 2) + (const_int 24)))] + "!TARGET_MASK_SEXT" + " +{ + operands[1] = gen_lowpart (SImode, operands[1]); + operands[2] = gen_reg_rtx (SImode); }") + +;; +;; extendhisi2 +;; + +(define_expand "extendhisi2" + [(use (match_operand:SI 0 "register_operand" "")) + (use (match_operand:HI 1 "nonimmediate_operand" ""))] + "" + " +{ + if (TARGET_MASK_SEXT) + emit_insn (gen_extendhisi2_sext(operands[0], operands[1])); + else { + if ( GET_CODE(operands[1]) == MEM ) { + emit_insn (gen_extendhisi2_no_sext_mem(operands[0], operands[1])); + } + else { + emit_insn (gen_extendhisi2_no_sext_reg(operands[0], operands[1])); + } + } + DONE; +}") + +(define_insn "extendhisi2_sext" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))] + "TARGET_MASK_SEXT" + "@ + l.exths \t%0,%1\t # extendhisi2_has_signed_extend + l.lhs \t%0,%1\t # extendhisi2_has_signed_extend" + [(set_attr "length" "1,1") + (set_attr "type" "extend,load")]) + +(define_insn "extendhisi2_no_sext_mem" + [(set (match_operand:SI 0 "register_operand" "=r") + (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))] + "!TARGET_MASK_SEXT" + "l.lhs \t%0,%1\t # extendhisi2_no_sext_mem" + [(set_attr "length" "1") + (set_attr "type" "load")]) + +(define_expand "extendhisi2_no_sext_reg" + [(set (match_dup 2) + (ashift:SI (match_operand:HI 1 "register_operand" "") + (const_int 16))) + (set (match_operand:SI 0 "register_operand" "") + (ashiftrt:SI (match_dup 2) + (const_int 16)))] + "!TARGET_MASK_SEXT" + " +{ + operands[1] = gen_lowpart (SImode, operands[1]); + operands[2] = gen_reg_rtx (SImode); }") + + +;; +;; zero_extend2 +;; + +(define_insn "zero_extendqisi2" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))] + "" + "@ + l.andi \t%0,%1,0xff\t # zero_extendqisi2 + l.lbz \t%0,%1\t # zero_extendqisi2" + [(set_attr "type" "logic,load") + (set_attr "length" "1,1")]) + + +(define_insn "zero_extendhisi2" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))] + "" + "@ + l.andi \t%0,%1,0xffff\t # zero_extendqisi2 + l.lhz \t%0,%1\t # zero_extendqisi2" + [(set_attr "type" "logic,load") + (set_attr "length" "1,1")]) + +;; +;; Shift/rotate operations +;; + +(define_insn "ashlsi3" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (ashift:SI (match_operand:SI 1 "register_operand" "r,r") + (match_operand:SI 2 "nonmemory_operand" "r,L")))] + "" + "@ + l.sll \t%0,%1,%2 # ashlsi3 + l.slli \t%0,%1,%2 # ashlsi3" + [(set_attr "type" "shift,shift") + (set_attr "length" "1,1")]) + +(define_insn "ashrsi3" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (ashiftrt:SI (match_operand:SI 1 "register_operand" "r,r") + (match_operand:SI 2 "nonmemory_operand" "r,L")))] + "" + "@ + l.sra \t%0,%1,%2 # ashrsi3 + l.srai \t%0,%1,%2 # ashrsi3" + [(set_attr "type" "shift,shift") + (set_attr "length" "1,1")]) + +(define_insn "lshrsi3" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,r") + (match_operand:SI 2 "nonmemory_operand" "r,L")))] + "" + "@ + l.srl \t%0,%1,%2 # lshrsi3 + l.srli \t%0,%1,%2 # lshrsi3" + [(set_attr "type" "shift,shift") + (set_attr "length" "1,1")]) + +(define_insn "rotrsi3" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (rotatert:SI (match_operand:SI 1 "register_operand" "r,r") + (match_operand:SI 2 "nonmemory_operand" "r,L")))] + "TARGET_MASK_ROR" + "@ + l.ror \t%0,%1,%2 # rotrsi3 + l.rori \t%0,%1,%2 # rotrsi3" + [(set_attr "type" "shift,shift") + (set_attr "length" "1,1")]) + +;; +;; Logical bitwise operations +;; + +(define_insn "andsi3" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (and:SI (match_operand:SI 1 "register_operand" "%r,r") + (match_operand:SI 2 "nonmemory_operand" "r,K")))] + "" + "@ + l.and \t%0,%1,%2 # andsi3 + l.andi \t%0,%1,%2 # andsi3" + [(set_attr "type" "logic,logic") + (set_attr "length" "1,1")]) + +(define_insn "iorsi3" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (ior:SI (match_operand:SI 1 "register_operand" "%r,r") + (match_operand:SI 2 "nonmemory_operand" "r,K")))] + "" + "@ + l.or \t%0,%1,%2 # iorsi3 + l.ori \t%0,%1,%2 # iorsi3" + [(set_attr "type" "logic,logic") + (set_attr "length" "1,1")]) + +(define_insn "xorsi3" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (xor:SI (match_operand:SI 1 "register_operand" "%r,r") + (match_operand:SI 2 "nonmemory_operand" "r,I")))] + "" + "@ + l.xor \t%0,%1,%2 # xorsi3 + l.xori \t%0,%1,%2 # xorsi3" + [(set_attr "type" "logic,logic") + (set_attr "length" "1,1")]) + +(define_insn "one_cmplqi2" + [(set (match_operand:QI 0 "register_operand" "=r") + (not:QI (match_operand:QI 1 "register_operand" "r")))] + "" + "l.xori \t%0,%1,0x00ff # one_cmplqi2" + [(set_attr "type" "logic") + (set_attr "length" "1")]) + +(define_insn "one_cmplsi2" + [(set (match_operand:SI 0 "register_operand" "=r") + (not:SI (match_operand:SI 1 "register_operand" "r")))] + "" + "l.xori \t%0,%1,0xffff # one_cmplsi2" + [(set_attr "type" "logic") + (set_attr "length" "1")]) + +;; +;; Arithmetic operations +;; + +(define_insn "negsi2" + [(set (match_operand:SI 0 "register_operand" "=r") + (neg:SI (match_operand:SI 1 "register_operand" "r")))] + "" + "l.sub \t%0,r0,%1 # negsi2" + [(set_attr "type" "add") + (set_attr "length" "1")]) + +(define_insn "addsi3" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (plus:SI (match_operand:SI 1 "register_operand" "%r,r") + (match_operand:SI 2 "nonmemory_operand" "r,I")))] + "" + "@ + l.add \t%0,%1,%2 # addsi3 + l.addi \t%0,%1,%2 # addsi3" + [(set_attr "type" "add,add") + (set_attr "length" "1,1")]) + +(define_insn "subsi3" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (minus:SI (match_operand:SI 1 "register_operand" "r,r") + (match_operand:SI 2 "nonmemory_operand" "r,I")))] + "" + "@ + l.sub \t%0,%1,%2 # subsi3 + l.addi \t%0,%1,%n2 # subsi3" + [(set_attr "type" "add,add")] +) + +;; +;; mul and div +;; + +(define_insn "mulsi3" + [(set (match_operand:SI 0 "register_operand" "=r") + (mult:SI (match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "register_operand" "r")))] + "TARGET_HARD_MUL" + "l.mul \t%0,%1,%2 # mulsi3" + [(set_attr "type" "mul") + (set_attr "length" "1")]) + +(define_insn "divsi3" + [(set (match_operand:SI 0 "register_operand" "=r") + (div:SI (match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "register_operand" "r")))] + "TARGET_HARD_DIV" + "l.div \t%0,%1,%2 # divsi3" + [(set_attr "type" "mul") + (set_attr "length" "1")]) + +(define_insn "udivsi3" + [(set (match_operand:SI 0 "register_operand" "=r") + (udiv:SI (match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "register_operand" "r")))] + "TARGET_HARD_DIV" + "l.divu \t%0,%1,%2 # udivsi3" + [(set_attr "type" "mul") + (set_attr "length" "1")]) + +;; +;; jumps +;; + +;; jump + +(define_expand "jump" + [(set (pc) + (label_ref (match_operand 0 "" "")))] + "" + " +{ + emit_jump_insn (gen_jump_internal (operands[0])); + DONE; +}") + +(define_insn "jump_internal" + [(set (pc) + (label_ref (match_operand 0 "" "")))] + "" + "l.j \t%l0 # jump_internal%(" + [(set_attr "type" "jump") + (set_attr "length" "1")]) + +;; indirect jump + +(define_expand "indirect_jump" + [(set (pc) (match_operand:SI 0 "register_operand" "r"))] + "" + " +{ + emit_jump_insn (gen_indirect_jump_internal (operands[0])); + DONE; + +}") + +(define_insn "indirect_jump_internal" + [(set (pc) (match_operand:SI 0 "register_operand" "r"))] + "" + "l.jr \t%0 # indirect_jump_internal%(" + [(set_attr "type" "jump") + (set_attr "length" "1")]) + +;; +;; calls +;; + +;; call + +(define_expand "call" + [(parallel [(call (match_operand:SI 0 "sym_ref_mem_operand" "") + (match_operand 1 "" "i")) + (clobber (reg:SI 9)) + (use (reg:SI 16))])] + "" + " +{ + emit_call_insn (gen_call_internal (operands[0], operands[1])); + DONE; +}") + +(define_insn "call_internal" +[(parallel [(call (match_operand:SI 0 "sym_ref_mem_operand" "") + (match_operand 1 "" "i")) + (clobber (reg:SI 9)) + (use (reg:SI 16))])] + "" + { + if (flag_pic) + { + crtl->uses_pic_offset_table = 1; + return "l.jal \tplt(%S0)# call_internal%("; + } + + return "l.jal \t%S0# call_internal%("; + } + [(set_attr "type" "jump") + (set_attr "length" "1")]) + +;; call value + +(define_expand "call_value" + [(parallel [(set (match_operand 0 "register_operand" "=r") + (call (match_operand:SI 1 "sym_ref_mem_operand" "") + (match_operand 2 "" "i"))) + (clobber (reg:SI 9)) + (use (reg:SI 16))])] + "" + " +{ + emit_call_insn (gen_call_value_internal (operands[0], operands[1], operands[2])); + DONE; +}") + +(define_insn "call_value_internal" +[(parallel [(set (match_operand 0 "register_operand" "=r") + (call (match_operand:SI 1 "sym_ref_mem_operand" "") + (match_operand 2 "" "i"))) + (clobber (reg:SI 9)) + (use (reg:SI 16))])] + "" + { + if (flag_pic) + { + crtl->uses_pic_offset_table = 1; + return "l.jal \tplt(%S1) # call_value_internal%("; + } + return "l.jal \t%S1 # call_value_internal%("; + } + [(set_attr "type" "jump") + (set_attr "length" "1")]) + +;; indirect call value + +(define_expand "call_value_indirect" + [(parallel [(set (match_operand 0 "register_operand" "=r") + (call (mem:SI (match_operand:SI 1 "register_operand" "r")) + (match_operand 2 "" "i"))) + (clobber (reg:SI 9)) + (use (reg:SI 16))])] + "" + " +{ + emit_call_insn (gen_call_value_indirect_internal (operands[0], operands[1], operands[2])); + DONE; +}") + +(define_insn "call_value_indirect_internal" + [(parallel [(set (match_operand 0 "register_operand" "=r") + (call (mem:SI (match_operand:SI 1 "register_operand" "r")) + (match_operand 2 "" "i"))) + (clobber (reg:SI 9)) + (use (reg:SI 16))])] + "" + "l.jalr \t%1 # call_value_indirect_internal%(" + [(set_attr "type" "jump") + (set_attr "length" "1")]) + +;; indirect call + +(define_expand "call_indirect" + [(parallel [(call (mem:SI (match_operand:SI 0 "register_operand" "r")) + (match_operand 1 "" "i")) + (clobber (reg:SI 9)) + (use (reg:SI 16))])] + "" + " +{ + emit_call_insn (gen_call_indirect_internal (operands[0], operands[1])); + DONE; +}") + +(define_insn "call_indirect_internal" +[(parallel [(call (mem:SI (match_operand:SI 0 "register_operand" "r")) + (match_operand 1 "" "i")) + (clobber (reg:SI 9)) + (use (reg:SI 16))])] + "" + "l.jalr \t%0 # call_indirect_internal%(" + [(set_attr "type" "jump") + (set_attr "length" "1")]) + +;; table jump + +(define_expand "tablejump" + [(set (pc) (match_operand:SI 0 "register_operand" "r")) + (use (label_ref (match_operand 1 "" "")))] + "" + " +{ + if (CASE_VECTOR_PC_RELATIVE || flag_pic) + operands[0] + = force_reg (Pmode, + gen_rtx_PLUS (Pmode, operands[0], + gen_rtx_LABEL_REF (Pmode, operands[1]))); + emit_jump_insn (gen_tablejump_internal (operands[0], operands[1])); + DONE; +}") + +(define_insn "tablejump_internal" + [(set (pc) (match_operand:SI 0 "register_operand" "r")) + (use (label_ref (match_operand 1 "" "")))] + "" + "l.jr \t%0 # tablejump_internal%(" + [(set_attr "type" "jump") + (set_attr "length" "1")]) + + +;; no-op + +(define_insn "nop" + [(const_int 0)] + "" + "l.nop" + [(set_attr "type" "logic") + (set_attr "length" "1")]) + +;; +;; floating point +;; + +;; floating point arithmetic + +(define_insn "addsf3" + [(set (match_operand:SF 0 "register_operand" "=r") + (plus:SF (match_operand:SF 1 "register_operand" "r") + (match_operand:SF 2 "register_operand" "r")))] + "TARGET_HARD_FLOAT" + "lf.add.s\t%0,%1,%2 # addsf3" + [(set_attr "type" "fp") + (set_attr "length" "1")]) + +(define_insn "adddf3" + [(set (match_operand:DF 0 "register_operand" "=r") + (plus:DF (match_operand:DF 1 "register_operand" "r") + (match_operand:DF 2 "register_operand" "r")))] + "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" + "lf.add.d\t%0,%1,%2 # adddf3" + [(set_attr "type" "fp") + (set_attr "length" "1")]) + +(define_insn "subsf3" + [(set (match_operand:SF 0 "register_operand" "=r") + (minus:SF (match_operand:SF 1 "register_operand" "r") + (match_operand:SF 2 "register_operand" "r")))] + "TARGET_HARD_FLOAT" + "lf.sub.s\t%0,%1,%2 # subsf3" + [(set_attr "type" "fp") + (set_attr "length" "1")]) + +(define_insn "subdf3" + [(set (match_operand:DF 0 "register_operand" "=r") + (minus:DF (match_operand:DF 1 "register_operand" "r") + (match_operand:DF 2 "register_operand" "r")))] + "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" + "lf.sub.d\t%0,%1,%2 # subdf3" + [(set_attr "type" "fp") + (set_attr "length" "1")]) + +(define_insn "mulsf3" + [(set (match_operand:SF 0 "register_operand" "=r") + (mult:SF (match_operand:SF 1 "register_operand" "r") + (match_operand:SF 2 "register_operand" "r")))] + "TARGET_HARD_FLOAT" + "lf.mul.s\t%0,%1,%2 # mulsf3" + [(set_attr "type" "fp") + (set_attr "length" "1")]) + +(define_insn "muldf3" + [(set (match_operand:DF 0 "register_operand" "=r") + (mult:DF (match_operand:DF 1 "register_operand" "r") + (match_operand:DF 2 "register_operand" "r")))] + "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" + "lf.mul.d\t%0,%1,%2 # muldf3" + [(set_attr "type" "fp") + (set_attr "length" "1")]) + +(define_insn "divsf3" + [(set (match_operand:SF 0 "register_operand" "=r") + (div:SF (match_operand:SF 1 "register_operand" "r") + (match_operand:SF 2 "register_operand" "r")))] + "TARGET_HARD_FLOAT" + "lf.div.s\t%0,%1,%2 # divsf3" + [(set_attr "type" "fp") + (set_attr "length" "1")]) + +(define_insn "divdf3" + [(set (match_operand:DF 0 "register_operand" "=r") + (div:DF (match_operand:DF 1 "register_operand" "r") + (match_operand:DF 2 "register_operand" "r")))] + "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" + "lf.div.d\t%0,%1,%2 # divdf3" + [(set_attr "type" "fp") + (set_attr "length" "1")]) + +;; Conversion between fixed point and floating point. + + +(define_insn "floatsisf2" + [(set (match_operand:SF 0 "register_operand" "=r") + (float:SF (match_operand:SI 1 "register_operand" "r")))] + "TARGET_HARD_FLOAT" + "lf.itof.s\t%0, %1 # floatsisf2" + [(set_attr "type" "fp") + (set_attr "length" "1")]) + +;; not working +(define_insn "fixunssfsi2" + [(set (match_operand:SI 0 "register_operand" "=r") + (fix:SI (match_operand:SF 1 "register_operand" "r")))] + "TARGET_HARD_FLOAT" + "lf.ftoi.s\t%0, %1 # fixunssfsi2" + [(set_attr "type" "fp") + (set_attr "length" "1")]) + +;; The insn to set GOT. +;; TODO: support for no-delay target +(define_insn "set_got" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI [(const_int 0)] UNSPEC_SET_GOT)) + (clobber (reg:SI 9)) + (clobber (reg:SI 16))] + "" + "l.jal \t8 + \tl.movhi \tr16,gotpchi(_GLOBAL_OFFSET_TABLE_-4) + \tl.ori \tr16,r16,gotpclo(_GLOBAL_OFFSET_TABLE_+0) + \tl.add \tr16,r16,r9" + [(set_attr "length" "16")]) + + +;; Local variables: +;; mode:emacs-lisp +;; comment-start: ";; " +;; eval: (set-syntax-table (copy-sequence (syntax-table))) +;; eval: (modify-syntax-entry ?[ "(]") +;; eval: (modify-syntax-entry ?] ")[") +;; eval: (modify-syntax-entry ?{ "(}") +;; eval: (modify-syntax-entry ?} "){") +;; eval: (setq indent-tabs-mode t) +;; End: diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/config/or1k/or1k-modes.def gcc-4.8.2-or1k-rtems/gcc/config/or1k/or1k-modes.def --- gcc-4.8.2/gcc/config/or1k/or1k-modes.def 1970-01-01 02:00:00.000000000 +0200 +++ gcc-4.8.2-or1k-rtems/gcc/config/or1k/or1k-modes.def 2014-03-14 07:27:49.000000000 +0200 @@ -0,0 +1,38 @@ +/* Definitions of target machine for GNU compiler, for OR32. + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC 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. + + GCC 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 GCC; see the file COPYING. If not, write to the + Free Software Foundation, 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. */ + +/* Add any extra modes needed to represent the condition code. + */ + +CC_MODE (CCEQ); +CC_MODE (CCNE); + +CC_MODE (CCLE); +CC_MODE (CCGE); +CC_MODE (CCLT); +CC_MODE (CCGT); + +CC_MODE (CCLEU); +CC_MODE (CCGEU); +CC_MODE (CCLTU); +CC_MODE (CCGTU); + +CC_MODE(CCFP); +CC_MODE(CCUNS); diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/config/or1k/or1k.opt gcc-4.8.2-or1k-rtems/gcc/config/or1k/or1k.opt --- gcc-4.8.2/gcc/config/or1k/or1k.opt 1970-01-01 02:00:00.000000000 +0200 +++ gcc-4.8.2-or1k-rtems/gcc/config/or1k/or1k.opt 2014-03-14 07:27:49.000000000 +0200 @@ -0,0 +1,96 @@ +; Options for the OR1K port of the compiler +; This file is part of GCC. +; +; Copyright (C) 2010 Embecosm Limited +; +; GCC 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 3, or (at your option) any later +; version. +; +; GCC 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 GCC; see the file COPYING3. If not see +; . + +HeaderInclude +config/or1k/or1k-opts.h + +Variable +enum or1k_delay or1k_delay_selected = OR1K_DELAY_DEFAULT + +mdelay +Target RejectNegative Negative(mno-delay) Var(or1k_delay_selected, OR1K_DELAY_ON) +Assume branches and jumps have a delay slot + +mno-delay +Target RejectNegative Negative(mcompat-delay) Var(or1k_delay_selected, OR1K_DELAY_OFF) +Assume branches and jumps do not have a delay slot + +mcompat-delay +Target RejectNegative Negative(mdelay) Var(or1k_delay_selected, OR1K_DELAY_COMPAT) +Assume branches and jumps have a delay slot, but fill them with nops + +mhard-float +Target RejectNegative Mask(HARD_FLOAT) +Use hardware floating point + +msoft-float +Target RejectNegative InverseMask(HARD_FLOAT) +Do not use hardware floating point + +mdouble-float +Target Report RejectNegative Mask(DOUBLE_FLOAT) +Allow hardware floating-point instructions to cover both 32-bit and 64-bit operations + +mhard-div +Target RejectNegative Mask(HARD_DIV) +Use hardware division + +msoft-div +Target RejectNegative InverseMask(HARD_DIV) +Do not use hardware division + +mhard-mul +Target RejectNegative Mask(HARD_MUL) +Use hardware multiplication + +msoft-mul +Target RejectNegative InverseMask(HARD_MUL) +Do not use hardware multiplication + +msext +Target Mask(MASK_SEXT) +Use sign-extending instructions + +mcmov +Target Mask(MASK_CMOV) +Use conditional move instructions + +mror +Target Mask(MASK_ROR) +Emit ROR instructions + +mboard= +Target RejectNegative Joined +Link with libgloss configuration suitable for this board + +mnewlib +Target Report RejectNegative +Compile for the Linux/Gnu/newlib based toolchain + +;; provide struct padding as in previous releases. +;; Note that this will only affect STRUCTURE_SIZE_BOUNDARY, in particular +;; make 2 byte structs 4-byte alignned and sized. +;; We still use ROUND_TYPE_ALIGN to increase alignment of larger structs. +mpadstruct +Target Report RejectNegative Mask(PADSTRUCT) +Make structs a multiple of 4 bytes (warning: ABI altered) + +mredzone= +Target RejectNegative Joined UInteger Var(or1k_redzone) Init(128) +Set the size of the stack below sp that is assumed to be safe from interrupts. diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/config/or1k/or1k-opts.h gcc-4.8.2-or1k-rtems/gcc/config/or1k/or1k-opts.h --- gcc-4.8.2/gcc/config/or1k/or1k-opts.h 1970-01-01 02:00:00.000000000 +0200 +++ gcc-4.8.2-or1k-rtems/gcc/config/or1k/or1k-opts.h 2014-03-14 07:27:49.000000000 +0200 @@ -0,0 +1,14 @@ +#ifndef OR1K_OPTS_H +#define OR1K_OPTS_H + +enum or1k_delay { + OR1K_DELAY_OFF = 0, + OR1K_DELAY_ON = 1, + OR1K_DELAY_COMPAT = 2 +}; + +#define TARGET_DELAY_ON (or1k_delay_selected == OR1K_DELAY_ON) +#define TARGET_DELAY_OFF (or1k_delay_selected == OR1K_DELAY_OFF) +#define TARGET_DELAY_COMPAT (or1k_delay_selected == OR1K_DELAY_COMPAT) + +#endif diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/config/or1k/or1k-protos.h gcc-4.8.2-or1k-rtems/gcc/config/or1k/or1k-protos.h --- gcc-4.8.2/gcc/config/or1k/or1k-protos.h 1970-01-01 02:00:00.000000000 +0200 +++ gcc-4.8.2-or1k-rtems/gcc/config/or1k/or1k-protos.h 2014-03-14 07:27:49.000000000 +0200 @@ -0,0 +1,62 @@ +/* Definitions of target machine for GNU compiler, OR1K cpu. + + Copyright (C) 2010 Embecosm Limited + +This file is part of GCC. + +GCC 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 3, or (at your option) +any later version. + +GCC 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 GCC; see the file COPYING3. If not see +. */ + +#ifndef GCC_OR1K_PROTOS_H +#define GCC_OR1K_PROTOS_H + +/* The following are for general support. */ +extern int or1k_trampoline_code_size (void); + +/* The following are only needed when handling the machine definition. */ +#ifdef RTX_CODE +extern void or1k_init_expanders (void); +extern void or1k_expand_prologue (void); +extern void or1k_expand_epilogue (void); +extern bool or1k_expand_move (enum machine_mode mode, rtx operands[]); +extern const char *or1k_output_move_double (rtx *operands); +extern void or1k_expand_conditional_branch (rtx *operands, + enum machine_mode mode); +extern int or1k_emit_cmove (rtx dest, + rtx op, + rtx true_cond, + rtx false_cond); +extern enum machine_mode or1k_select_cc_mode (enum rtx_code op); +extern const char *or1k_output_bf (rtx * operands); +extern const char *or1k_output_cmov (rtx * operands); +extern void or1k_emit_set_const32 (rtx op0, + rtx op1); +extern bool or1k_expand_symbol_ref (enum machine_mode mode, + rtx operands[]); +#endif + +#endif +extern int or1k_struct_alignment (tree); +extern int or1k_data_alignment (tree, int); + +extern int or1k_initial_elimination_offset (int, int); +extern bool or1k_save_reg_p_cached (int regno); +extern void or1k_print_jump_restore (rtx jump_address); +extern rtx or1k_eh_return_handler_rtx (void); +extern rtx or1k_return_addr_rtx (int, rtx); + +extern int or1k_legitimate_pic_operand_p (rtx x); + +/* For RETURN_ADDR_RTX */ +extern rtx get_hard_reg_initial_val (enum machine_mode, unsigned int); diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/config/or1k/predicates.md gcc-4.8.2-or1k-rtems/gcc/config/or1k/predicates.md --- gcc-4.8.2/gcc/config/or1k/predicates.md 1970-01-01 02:00:00.000000000 +0200 +++ gcc-4.8.2-or1k-rtems/gcc/config/or1k/predicates.md 2014-03-14 07:27:49.000000000 +0200 @@ -0,0 +1,74 @@ +;; Predicate definitions for OR32 +;; +;; Copyright (C) 2010 Embecosm Limited +;; +;; This file is part of GCC. +;; +;; GCC 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 3, or (at your option) +;; any later version. +;; +;; GCC 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 GCC; see the file COPYING3. If not see +;; . + +(define_predicate "cc_reg_operand" + (match_code "subreg,reg") +{ + register_operand (op, mode); + + if (GET_CODE (op) == REG && REGNO (op) == CC_REG) + return 1; + + return 0; +}) + +(define_predicate "input_operand" + (match_code "subreg,reg,const_int,mem,const") +{ + /* If both modes are non-void they must be the same. */ + if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op)) + return 0; + + /* Allow any one instruction integer constant, and all CONST_INT + variants when we are working in DImode and !arch64. */ + if (GET_MODE_CLASS (mode) == MODE_INT + && ((GET_CODE (op) == CONST_INT) + && (satisfies_constraint_K (op) + || satisfies_constraint_M (op) + || satisfies_constraint_I (op)))) + return 1; + + if (register_operand (op, mode)) + return 1; + + /* If this is a SUBREG, look inside so that we handle + paradoxical ones. */ + if (GET_CODE (op) == SUBREG) + op = SUBREG_REG (op); + + + /* Check for valid MEM forms. */ + if (GET_CODE (op) == MEM) + return memory_address_p (mode, XEXP (op, 0)); + + return 0; +}) + +(define_predicate "sym_ref_mem_operand" + (match_code "mem") +{ + if (GET_CODE (op) == MEM) + { + rtx t1 = XEXP (op, 0); + if (GET_CODE (t1) == SYMBOL_REF) + return 1; + } + return 0; +}) diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/config/or1k/rtems.h gcc-4.8.2-or1k-rtems/gcc/config/or1k/rtems.h --- gcc-4.8.2/gcc/config/or1k/rtems.h 1970-01-01 02:00:00.000000000 +0200 +++ gcc-4.8.2-or1k-rtems/gcc/config/or1k/rtems.h 2014-04-29 01:30:16.103239278 +0200 @@ -0,0 +1,43 @@ +/* Definitions for rtems targeting an OpenRisc OR1K using ELF + + Copyright (C) 1996, 1997, 2005 Free Software Foundation, Inc. + Contributed by Joel Sherrill (joel@OARcorp.com). + +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 GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* Use ELF */ +#undef OBJECT_FORMAT_ELF +#define OBJECT_FORMAT_ELF + +/* what does this comment go to? + or1k debug info support is controlled by tm.h header files we include: + dbxelf.h enables optional stabs debug info. + elfos.h sets PREFERRED_DEBUGGING_TYPE to DWARF2_DEBUG . */ + +/* RTEMS always uses newlib */ +#undef DRIVER_SELF_SPECS + +/* Target OS builtins. */ +#undef TARGET_OS_CPP_BUILTINS +#define TARGET_OS_CPP_BUILTINS() \ + do \ + { \ + builtin_define ("__rtems__"); \ + builtin_assert ("system=rtems"); \ + } \ + while (0) diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/config/or1k/t-linux gcc-4.8.2-or1k-rtems/gcc/config/or1k/t-linux --- gcc-4.8.2/gcc/config/or1k/t-linux 1970-01-01 02:00:00.000000000 +0200 +++ gcc-4.8.2-or1k-rtems/gcc/config/or1k/t-linux 2014-03-14 07:27:49.000000000 +0200 @@ -0,0 +1,12 @@ +MULTILIB_DIRNAMES = +EXTRA_MULTILIB_PARTS = crti.o crtbegin.o crtend.o crtn.o + +# hack: +# the non-shared uclibc-0.9.31/libc/misc/internals/__uClibc_main.c +# already defines __dso_handle. To avoid a duplicate definition, +# we rename the crtbegin one. +# JPB 18-Nov-10: Commented out, since uClibc no longer defines. +# amend gcc Makefile CLFAGS variable +# $(T)crtbegin.o: CRTSTUFF_CFLAGS += '-D__dso_handle=__dso_handle_dummy' +# amend libgcc Makefile CLFAGS variable +# crtbegin$(objext): CRTSTUFF_T_CFLAGS += '-D__dso_handle=__dso_handle_dummy' diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/config/or1k/t-or1k gcc-4.8.2-or1k-rtems/gcc/config/or1k/t-or1k --- gcc-4.8.2/gcc/config/or1k/t-or1k 1970-01-01 02:00:00.000000000 +0200 +++ gcc-4.8.2-or1k-rtems/gcc/config/or1k/t-or1k 2014-03-14 07:27:49.000000000 +0200 @@ -0,0 +1,28 @@ +# t-or1k is a Makefile fragment to be included when +# building gcc for the or1k target + +# Copyright (C) 2010 Embecosm Limited + +# This file is part of GCC. +# +# GCC 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 3, or (at your option) +# any later version. +# +# GCC 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 GCC; see the file COPYING3. If not see +# . + +# we don't support -g so don't use it +LIBGCC2_DEBUG_CFLAGS = + +# Build the libraries for both hard and soft floating point +MULTILIB_OPTIONS = mno-delay/mcompat-delay msoft-float +MULTILIB_DIRNAMES = no-delay compat-delay soft-float +MULTILIB_MATCHES = diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/config/or1k/t-or1knd gcc-4.8.2-or1k-rtems/gcc/config/or1k/t-or1knd --- gcc-4.8.2/gcc/config/or1k/t-or1knd 1970-01-01 02:00:00.000000000 +0200 +++ gcc-4.8.2-or1k-rtems/gcc/config/or1k/t-or1knd 2014-03-14 07:27:49.000000000 +0200 @@ -0,0 +1,28 @@ +# t-or1knd is a Makefile fragment to be included when +# building gcc for the or1k target + +# Copyright (C) 2010 Embecosm Limited + +# This file is part of GCC. +# +# GCC 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 3, or (at your option) +# any later version. +# +# GCC 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 GCC; see the file COPYING3. If not see +# . + +# we don't support -g so don't use it +LIBGCC2_DEBUG_CFLAGS = + +# Build the libraries for both hard and soft floating point +MULTILIB_OPTIONS = mdelay/mcompat-delay msoft-float +MULTILIB_DIRNAMES = delay compat-delay soft-float +MULTILIB_MATCHES = diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/config/or1k/t-rtems gcc-4.8.2-or1k-rtems/gcc/config/or1k/t-rtems --- gcc-4.8.2/gcc/config/or1k/t-rtems 1970-01-01 02:00:00.000000000 +0200 +++ gcc-4.8.2-or1k-rtems/gcc/config/or1k/t-rtems 2014-04-29 00:32:16.947998363 +0200 @@ -0,0 +1,2 @@ +# Custom multilibs for RTEMS + diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/config.gcc gcc-4.8.2-or1k-rtems/gcc/config.gcc --- gcc-4.8.2/gcc/config.gcc 2013-10-03 02:47:24.000000000 +0200 +++ gcc-4.8.2-or1k-rtems/gcc/config.gcc 2014-04-29 01:29:36.179658466 +0200 @@ -415,6 +415,12 @@ extra_headers="loongson.h" extra_options="${extra_options} g.opt mips/mips-tables.opt" ;; +or1k-*-*) + cpu_type=or1k + ;; +or1knd-*-*) + cpu_type=or1k + ;; picochip-*-*) cpu_type=picochip ;; @@ -1964,6 +1970,40 @@ use_collect2=no use_gcc_stdint=wrap ;; +or1k-*-elf*) + tm_file="${tm_file} dbxelf.h elfos.h newlib-stdint.h ${cpu_type}/elf.h" + extra_parts="crti.o crtbegin.o crtend.o crtn.o" + tmake_file=or1k/t-or1k + tm_defines="${tm_defines} OR1K_DELAY_DEFAULT=OR1K_DELAY_ON" + ;; +or1k-*-linux-*) + tm_file="${tm_file} dbxelf.h elfos.h or1k/elf.h gnu-user.h linux.h or1k/linux-gas.h or1k/linux-elf.h uclibc-stdint.h" + tmake_file="or1k/t-or1k or1k/t-linux ${tmake_file}" + tm_defines="${tm_defines} OR1K_DELAY_DEFAULT=OR1K_DELAY_ON" + ;; +or1k-*-rtems*) + tm_file="${tm_file} dbxelf.h elfos.h newlib-stdint.h rtems.h ${cpu_type}/elf.h or1k/rtems.h" + extra_parts="crti.o crtbegin.o crtend.o crtn.o" + tmake_file="or1k/t-or1k t-rtems or1k/t-rtems" + tm_defines="${tm_defines} OR1K_DELAY_DEFAULT=OR1K_DELAY_ON" + ;; +or1knd-*-elf*) + tm_file="${tm_file} dbxelf.h elfos.h newlib-stdint.h ${cpu_type}/elf.h" + extra_parts="crti.o crtbegin.o crtend.o crtn.o" + tmake_file=or1k/t-or1knd + tm_defines="${tm_defines} OR1K_DELAY_DEFAULT=OR1K_DELAY_OFF" + ;; +or1knd-*-linux-*) + tm_file="${tm_file} dbxelf.h elfos.h or1k/elf.h linux.h or1k/linux-gas.h or1k/linux-elf.h uclibc-stdint.h" + tmake_file="or1k/t-or1knd or1k/t-linux ${tmake_file}" + tm_defines="${tm_defines} OR1K_DELAY_DEFAULT=OR1K_DELAY_OFF" + ;; +or1knd-*-rtems*) + tm_file="${tm_file} dbxelf.h elfos.h newlib-stdint.h rtems.h ${cpu_type}/elf.h or1k/rtems.h" + extra_parts="crti.o crtbegin.o crtend.o crtn.o" + tmake_file="or1k/t-or1k t-rtems or1k/t-rtems" + tm_defines="${tm_defines} OR1K_DELAY_DEFAULT=OR1K_DELAY_OFF" + ;; pdp11-*-*) tm_file="${tm_file} newlib-stdint.h" use_gcc_stdint=wrap diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/configure.ac gcc-4.8.2-or1k-rtems/gcc/configure.ac --- gcc-4.8.2/gcc/configure.ac 2013-06-19 03:18:38.000000000 +0200 +++ gcc-4.8.2-or1k-rtems/gcc/configure.ac 2014-03-17 04:57:55.337050724 +0200 @@ -3026,6 +3026,20 @@ tls_first_minor=20 tls_as_opt='--fatal-warnings' ;; + or1k*-*-*) + conftest_s=' + .section ".tdata","awT",%progbits +foo: .long 25 + .text + l.movhi r3,tlsgdhi(foo) + l.ori r3,r3,tlsgdlo(foo) + + l.jal __tls_get_addr + l.nop' + tls_first_major=2 + tls_first_minor=23 + tls_as_opt='--fatal-warnings' + ;; powerpc-ibm-aix*) conftest_s=' .extern __get_tpointer diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/testsuite/gcc.c-torture/execute/20101011-1.c gcc-4.8.2-or1k-rtems/gcc/testsuite/gcc.c-torture/execute/20101011-1.c --- gcc-4.8.2/gcc/testsuite/gcc.c-torture/execute/20101011-1.c 2013-02-08 18:02:47.000000000 +0200 +++ gcc-4.8.2-or1k-rtems/gcc/testsuite/gcc.c-torture/execute/20101011-1.c 2014-03-17 05:04:56.421052207 +0200 @@ -36,6 +36,12 @@ /* Epiphany does not have hardware division, and the software implementation has truly undefined behaviour for division by 0. */ # define DO_TEST 0 +#elif defined (__or1k__) + /* There is no strict behavior requirement for integer divide by zero + on OpenRISC 1000. The bare metal implementation ignores it, so we + will disable this test for now. + */ +# define DO_TEST 0 #elif defined (__m68k__) && !defined(__linux__) /* Attempting to trap division-by-zero in this way isn't likely to work on bare-metal m68k systems. */ diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/testsuite/gcc.dg/20020312-2.c gcc-4.8.2-or1k-rtems/gcc/testsuite/gcc.dg/20020312-2.c --- gcc-4.8.2/gcc/testsuite/gcc.dg/20020312-2.c 2013-02-16 21:32:15.000000000 +0200 +++ gcc-4.8.2-or1k-rtems/gcc/testsuite/gcc.dg/20020312-2.c 2014-03-17 05:07:59.717052852 +0200 @@ -34,6 +34,8 @@ /* PIC register is r1, but is used even without -fpic. */ #elif defined(__lm32__) /* No pic register. */ +#elif defined(__or1k__) +/* No pic register. */ #elif defined(__M32R__) /* No pic register. */ #elif defined(__m68k__) diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/testsuite/gcc.dg/builtin-apply2.c gcc-4.8.2-or1k-rtems/gcc/testsuite/gcc.dg/builtin-apply2.c --- gcc-4.8.2/gcc/testsuite/gcc.dg/builtin-apply2.c 2012-10-23 19:20:56.000000000 +0200 +++ gcc-4.8.2-or1k-rtems/gcc/testsuite/gcc.dg/builtin-apply2.c 2014-03-17 05:08:43.741053007 +0200 @@ -1,5 +1,5 @@ /* { dg-do run } */ -/* { dg-skip-if "Variadic funcs have all args on stack. Normal funcs have args in registers." { "aarch64*-*-* avr-*-* " } { "*" } { "" } } */ +/* { dg-skip-if "Variadic funcs have all args on stack. Normal funcs have args in registers." { "aarch64*-*-* avr-*-* or1k-*-*" } { "*" } { "" } } */ /* { dg-skip-if "Variadic funcs use Base AAPCS. Normal funcs use VFP variant." { "arm*-*-*" } { "-mfloat-abi=hard" } { "" } } */ /* PR target/12503 */ diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/testsuite/gcc.dg/builtin-stringop-chk-1.c gcc-4.8.2-or1k-rtems/gcc/testsuite/gcc.dg/builtin-stringop-chk-1.c --- gcc-4.8.2/gcc/testsuite/gcc.dg/builtin-stringop-chk-1.c 2012-05-03 10:48:22.000000000 +0200 +++ gcc-4.8.2-or1k-rtems/gcc/testsuite/gcc.dg/builtin-stringop-chk-1.c 2014-03-17 05:09:20.449053137 +0200 @@ -104,8 +104,8 @@ S *s[3]; memset (s, 0, sizeof (S) * 3); /* { dg-warning "will always overflow" "memset" } */ - struct T { char a[8]; char b[4]; char c[10]; } t; - stpcpy (t.c,"Testing..."); /* { dg-warning "will always overflow" "stpcpy" } */ + struct T { char a[8]; char b[4]; char c[10]; } t; /* or1k pads this to 12 bytes, and __builtin_object_size (t.c, 0) gives the size of the full object. */ + stpcpy (t.c,"Testing..."); /* { dg-warning "will always overflow" "stpcpy" { target { ! or1k-*-* } } } */ char b1[7]; char b2[4]; diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/testsuite/gcc.dg/nop.h gcc-4.8.2-or1k-rtems/gcc/testsuite/gcc.dg/nop.h --- gcc-4.8.2/gcc/testsuite/gcc.dg/nop.h 2010-11-17 22:35:46.000000000 +0200 +++ gcc-4.8.2-or1k-rtems/gcc/testsuite/gcc.dg/nop.h 2014-03-17 05:09:42.941053216 +0200 @@ -2,6 +2,8 @@ #define NOP "nop 0" #elif defined (__MMIX__) #define NOP "swym 0" +#elif defined (__or1k__) +#define NOP "l.nop 0" #else #define NOP "nop" #endif diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/testsuite/gcc.dg/torture/pr37868.c gcc-4.8.2-or1k-rtems/gcc/testsuite/gcc.dg/torture/pr37868.c --- gcc-4.8.2/gcc/testsuite/gcc.dg/torture/pr37868.c 2011-07-15 11:43:05.000000000 +0200 +++ gcc-4.8.2-or1k-rtems/gcc/testsuite/gcc.dg/torture/pr37868.c 2014-03-17 05:10:08.189053305 +0200 @@ -1,6 +1,7 @@ /* { dg-do run } */ /* { dg-options "-fno-strict-aliasing" } */ /* { dg-skip-if "unaligned access" { sparc*-*-* sh*-*-* tic6x-*-* } "*" "" } */ +/* { dg-skip-if "alignment exception" { or1k*-*-* } "*" "" } */ extern void abort (void); #if (__SIZEOF_INT__ <= 2) diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/testsuite/gcc.dg/torture/stackalign/builtin-apply-2.c gcc-4.8.2-or1k-rtems/gcc/testsuite/gcc.dg/torture/stackalign/builtin-apply-2.c --- gcc-4.8.2/gcc/testsuite/gcc.dg/torture/stackalign/builtin-apply-2.c 2012-10-16 00:38:37.000000000 +0200 +++ gcc-4.8.2-or1k-rtems/gcc/testsuite/gcc.dg/torture/stackalign/builtin-apply-2.c 2014-03-17 05:10:30.225053382 +0200 @@ -6,6 +6,7 @@ /* { dg-do run } */ +/* { dg-skip-if "Variadic funcs have all args on stack. Normal funcs have args in registers." {"or1k-*-*"} { "*" } { "" } } */ /* { dg-skip-if "Variadic funcs use Base AAPCS. Normal funcs use VFP variant." { arm_hf_eabi } } */ diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/testsuite/gcc.dg/tree-ssa/pr44258.c gcc-4.8.2-or1k-rtems/gcc/testsuite/gcc.dg/tree-ssa/pr44258.c --- gcc-4.8.2/gcc/testsuite/gcc.dg/tree-ssa/pr44258.c 2010-06-10 19:49:09.000000000 +0300 +++ gcc-4.8.2-or1k-rtems/gcc/testsuite/gcc.dg/tree-ssa/pr44258.c 2014-03-17 05:11:18.057053551 +0200 @@ -15,7 +15,7 @@ struct val { char y; - struct blah b2; + struct blah b2 __attribute__((packed)); /* { dg-warning "attribute ignored" "" { target { ! or1k-*-* } } } */ }; union U diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/testsuite/g++.dg/ext/strncpy-chk1.C gcc-4.8.2-or1k-rtems/gcc/testsuite/g++.dg/ext/strncpy-chk1.C --- gcc-4.8.2/gcc/testsuite/g++.dg/ext/strncpy-chk1.C 2009-07-10 14:56:55.000000000 +0300 +++ gcc-4.8.2-or1k-rtems/gcc/testsuite/g++.dg/ext/strncpy-chk1.C 2014-03-17 05:04:02.377052016 +0200 @@ -2,7 +2,7 @@ // { dg-do compile } // { dg-options "-O2" } -struct A { char x[12], y[35]; }; +struct A { char x[12], y[35]; }; // change to y[32] to get warning on or1k struct B { char z[50]; }; inline void diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/gcc/testsuite/lib/target-supports.exp gcc-4.8.2-or1k-rtems/gcc/testsuite/lib/target-supports.exp --- gcc-4.8.2/gcc/testsuite/lib/target-supports.exp 2013-02-12 01:11:12.000000000 +0200 +++ gcc-4.8.2-or1k-rtems/gcc/testsuite/lib/target-supports.exp 2014-03-17 05:12:15.121053752 +0200 @@ -386,7 +386,8 @@ # Some targets don't support gc-sections despite whatever's # advertised by ld's options. if { [istarget alpha*-*-*] - || [istarget ia64-*-*] } { + || [istarget ia64-*-*] + || [istarget or1k-*-*] } { set gc_sections_available_saved 0 return 0 } @@ -529,6 +530,7 @@ || [istarget mmix-*-*] || [istarget mn10300-*-elf*] || [istarget moxie-*-elf*] + || [istarget or1k-*-elf*] || [istarget picochip-*-*] || [istarget powerpc-*-eabi*] || [istarget powerpc-*-elf] diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/libgcc/config/or1k/crti.S gcc-4.8.2-or1k-rtems/libgcc/config/or1k/crti.S --- gcc-4.8.2/libgcc/config/or1k/crti.S 1970-01-01 02:00:00.000000000 +0200 +++ gcc-4.8.2-or1k-rtems/libgcc/config/or1k/crti.S 2014-03-14 07:28:07.000000000 +0200 @@ -0,0 +1,36 @@ +# Start .init and .fini sections. +# Copyright (C) 2010 Embecosm Limited +# +# This file 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 3, or (at your option) +# any later version. +# +# GCC 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. +# +# Under Section 7 of GPL version 3, you are granted additional +# permissions described in the GCC Runtime Library Exception, version +# 3.1, as published by the Free Software Foundation. +# +# You should have received a copy of the GNU General Public License and +# a copy of the GCC Runtime Library Exception along with this program; +# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +# . + +#include "or1k-asm.h" + + .section .init + .global _init + l.nop # So _init doesn't start at 0 +_init: + l.addi r1,r1,-4 + l.sw 0(r1),r9 + + .section .fini + .global _fini +_fini: + l.addi r1,r1,-4 + l.sw 0(r1),r9 diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/libgcc/config/or1k/crtn.S gcc-4.8.2-or1k-rtems/libgcc/config/or1k/crtn.S --- gcc-4.8.2/libgcc/config/or1k/crtn.S 1970-01-01 02:00:00.000000000 +0200 +++ gcc-4.8.2-or1k-rtems/libgcc/config/or1k/crtn.S 2014-03-14 07:28:08.000000000 +0200 @@ -0,0 +1,37 @@ +# End .init and .fini sections. +# Copyright (C) 2010 Embecosm Limited +# +# This file 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 3, or (at your option) +# any later version. +# +# GCC 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. +# +# Under Section 7 of GPL version 3, you are granted additional +# permissions described in the GCC Runtime Library Exception, version +# 3.1, as published by the Free Software Foundation. +# +# You should have received a copy of the GNU General Public License and +# a copy of the GCC Runtime Library Exception along with this program; +# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +# . + +#include "or1k-asm.h" + + .section .init + l.lwz r9,0(r1) + OR1K_DELAYED( + OR1K_INST(l.addi r1,r1,4), + OR1K_INST(l.jr r9) + ) + + .section .fini + l.lwz r9,0(r1) + OR1K_DELAYED( + OR1K_INST(l.addi r1,r1,4), + OR1K_INST(l.jr r9) + ) diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/libgcc/config/or1k/lib2funcs.c gcc-4.8.2-or1k-rtems/libgcc/config/or1k/lib2funcs.c --- gcc-4.8.2/libgcc/config/or1k/lib2funcs.c 1970-01-01 02:00:00.000000000 +0200 +++ gcc-4.8.2-or1k-rtems/libgcc/config/or1k/lib2funcs.c 2014-03-14 07:28:08.000000000 +0200 @@ -0,0 +1,40 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC 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 3, or (at your option) any later +version. + +GCC 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. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +typedef unsigned int USItype __attribute__ ((mode (SI))); + +USItype +__mulsi3 (USItype a, USItype b) +{ + USItype c = 0; + + while (a != 0) + { + if (a & 1) + c += b; + a >>= 1; + b <<= 1; + } + + return c; +} diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/libgcc/config/or1k/linux-unwind.h gcc-4.8.2-or1k-rtems/libgcc/config/or1k/linux-unwind.h --- gcc-4.8.2/libgcc/config/or1k/linux-unwind.h 1970-01-01 02:00:00.000000000 +0200 +++ gcc-4.8.2-or1k-rtems/libgcc/config/or1k/linux-unwind.h 2014-03-14 07:28:08.000000000 +0200 @@ -0,0 +1,77 @@ +/* DWARF2 EH unwinding support for OpenRISC. + Copyright (C) 2011, 2012 + Free Software Foundation, Inc. + +This file is part of GCC. + +GCC 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 3, or (at your option) +any later version. + +GCC 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. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +#ifndef inhibit_libc + +#include +#include +#include + +#define MD_FALLBACK_FRAME_STATE_FOR or1k_fallback_frame_state + +static _Unwind_Reason_Code +or1k_fallback_frame_state (struct _Unwind_Context *context, + _Unwind_FrameState *fs) +{ + struct rt_sigframe { + siginfo_t info; + struct ucontext uc; + } *frame = context->cfa; + + struct sigcontext *sc; + unsigned char *pc = context->ra; + long new_cfa; + int i; + + /* + * Note: These have to be the same as in the kernel. + * Please see arch/openrisc/kernel/signal.c + */ + if (!(*(unsigned short *)(pc + 0) == 0xa960 + && *(unsigned short *)(pc + 2) == __NR_rt_sigreturn + && *(unsigned long *)(pc + 4) == 0x20000001 + && *(unsigned long *)(pc + 8) == 0x15000000)) + return _URC_END_OF_STACK; + + sc = (struct sigcontext *) &frame->uc.uc_mcontext; + + new_cfa = sc->regs.gpr[1]; + fs->regs.cfa_how = CFA_REG_OFFSET; + fs->regs.cfa_reg = STACK_POINTER_REGNUM; + fs->regs.cfa_offset = new_cfa - (long) context->cfa; + + for (i = 0; i < 32; ++i) + { + fs->regs.reg[i].how = REG_SAVED_OFFSET; + fs->regs.reg[i].loc.offset = (long)&sc->regs.gpr[i] - new_cfa; + } + + fs->retaddr_column = 9; + fs->signal_frame = 1; + + return _URC_NO_REASON; +} + +#endif /* ifdef inhibit_libc */ diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/libgcc/config/or1k/or1k-asm.h gcc-4.8.2-or1k-rtems/libgcc/config/or1k/or1k-asm.h --- gcc-4.8.2/libgcc/config/or1k/or1k-asm.h 1970-01-01 02:00:00.000000000 +0200 +++ gcc-4.8.2-or1k-rtems/libgcc/config/or1k/or1k-asm.h 2014-03-14 07:28:08.000000000 +0200 @@ -0,0 +1,20 @@ +#ifndef OR1K_ASM_H +#define OR1K_ASM_H + +#define OR1K_INST(...) __VA_ARGS__ + +#if defined(__OR1K_NODELAY__) +#define OR1K_DELAYED(a, b) a; b +#define OR1K_DELAYED_NOP(a) a +.nodelay +#elif defined(__OR1K_DELAY__) +#define OR1K_DELAYED(a, b) b; a +#define OR1K_DELAYED_NOP(a) a; l.nop +#elif defined(__OR1K_DELAY_COMPAT__) +#define OR1K_DELAYED(a, b) a; b; l.nop +#define OR1K_DELAYED_NOP(a) a; l.nop +#else +#error One of __OR1K_NODELAY__, __OR1K_DELAY__, or __OR1K_DELAY_COMPAT__ must be defined +#endif + +#endif diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/libgcc/config/or1k/or1k.S gcc-4.8.2-or1k-rtems/libgcc/config/or1k/or1k.S --- gcc-4.8.2/libgcc/config/or1k/or1k.S 1970-01-01 02:00:00.000000000 +0200 +++ gcc-4.8.2-or1k-rtems/libgcc/config/or1k/or1k.S 2014-03-14 07:28:08.000000000 +0200 @@ -0,0 +1,182 @@ +/* + * Assembly functions for software multiplication and devision. + */ + +#define ENTRY(symbol) \ + .align 4 ;\ + .global symbol ;\ +symbol: + +#ifdef L__mulsi3 +ENTRY(__mulsi3) + l.addi r11,r0,0x0 + l.sfne r3,r11 + l.bnf 3f + l.ori r5,r3,0x0 + l.addi r6,r0,0x0 +1: + l.andi r3,r5,0x1 + l.sfeq r3,r6 + l.bf 2f + l.srli r5,r5,0x1 + l.add r11,r11,r4 +2: + l.sfne r5,r6 + l.bf 1b + l.slli r4,r4,0x1 +3: + l.jr r9 + l.nop 0x0 +#endif + +#ifdef L__udivsi3 +ENTRY(__udivsi3) + l.addi r1,r1,-4 + l.sw 0(r1),r9 + l.addi r11,r0,0 + l.addi r8,r4,0 + l.addi r5,r3,0 + l.sfne r8,r11 + l.bnf 4f + l.addi r7,r0,0 + l.sfgtu r8,r5 + l.bf 5f + l.sfeq r8,r5 + l.bf 6f + l.sfltu r11,r8 + l.bnf 2f + l.addi r13,r0,32 + l.movhi r9,hi(0x80000000) + l.addi r6,r0,-1 +1: + l.and r3,r5,r9 + l.slli r4,r7,1 + l.addi r15,r5,0 + l.srli r3,r3,31 + l.add r13,r13,r6 + l.or r7,r4,r3 + l.sfltu r7,r8 + l.bf 1b + l.slli r5,r5,1 +2: + l.srli r7,r7,1 + l.addi r13,r13,1 + l.addi r9,r0,0 + l.sfltu r9,r13 + l.bnf 4f + l.addi r5,r15,0 + l.movhi r15,hi(0x80000000) + l.addi r17,r0,0 +3: + l.and r3,r5,r15 + l.slli r4,r7,1 + l.srli r3,r3,31 + l.or r7,r4,r3 + l.sub r6,r7,r8 + l.and r3,r6,r15 + l.srli r3,r3,31 + l.addi r4,r0,0 + l.sfne r3,r4 + l.bf 1f + l.slli r3,r11,1 + l.addi r4,r0,1 +1: + l.slli r5,r5,1 + l.sfne r4,r17 + l.bnf 2f + l.or r11,r3,r4 + l.addi r7,r6,0 +2: + l.addi r9,r9,1 + l.sfltu r9,r13 + l.bf 3b + l.nop 0 + l.j 4f + l.nop 0 +6: + l.j 4f + l.addi r11,r0,1 +5: + l.addi r7,r5,0 +4: + l.lwz r9,0(r1) + l.jr r9 + l.addi r1,r1,4 +#endif + + +#ifdef L__divsi3 +ENTRY(__divsi3) + l.addi r1,r1,-8 + l.sw 0(r1),r9 + l.sw 4(r1),r14 + l.addi r5,r3,0 + l.addi r14,r0,0 + l.sflts r5,r0 + l.bnf 1f + l.addi r3,r0,0 + l.addi r14,r0,1 + l.sub r5,r0,r5 +1: + l.sflts r4,r0 + l.bnf 1f + l.nop 0 + l.addi r14,r14,1 + l.sub r4,r0,r4 +1: + l.jal __udivsi3 + l.addi r3,r5,0 + l.sfeqi r14,1 + l.bnf 1f + l.nop 0 + l.sub r11,r0,r11 +1: + l.lwz r9,0(r1) + l.lwz r14,4(r1) + l.jr r9 + l.addi r1,r1,8 +#endif + + +#ifdef L__umodsi3 +ENTRY(__umodsi3) + l.addi r1,r1,-4 + l.sw 0(r1),r9 + l.jal __udivsi3 + l.nop 0 + l.addi r11,r7,0 + l.lwz r9,0(r1) + l.jr r9 + l.addi r1,r1,4 +#endif + + +#ifdef L__modsi3 +ENTRY(__modsi3) + l.addi r1,r1,-8 + l.sw 0(r1),r9 + l.sw 4(r1),r14 + l.addi r14,r0,0 + l.sflts r3,r0 + l.bnf 1f + l.nop 0 + l.addi r14,r0,1 + l.sub r3,r0,r3 +1: + l.sflts r4,r0 + l.bnf 1f + l.nop 0 + l.sub r4,r0,r4 +1: + l.jal __udivsi3 + l.nop 0 + l.sfeqi r14,1 + l.bnf 1f + l.addi r11,r7,0 + l.sub r11,r0,r11 +1: + l.lwz r9,0(r1) + l.lwz r14,4(r1) + l.jr r9 + l.addi r1,r1,8 +#endif diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/libgcc/config/or1k/sfp-machine.h gcc-4.8.2-or1k-rtems/libgcc/config/or1k/sfp-machine.h --- gcc-4.8.2/libgcc/config/or1k/sfp-machine.h 1970-01-01 02:00:00.000000000 +0200 +++ gcc-4.8.2-or1k-rtems/libgcc/config/or1k/sfp-machine.h 2014-03-14 07:28:08.000000000 +0200 @@ -0,0 +1,51 @@ +#define _FP_W_TYPE_SIZE 32 +#define _FP_W_TYPE unsigned long +#define _FP_WS_TYPE signed long +#define _FP_I_TYPE long + +#define _FP_MUL_MEAT_S(R,X,Y) \ + _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm) +#define _FP_MUL_MEAT_D(R,X,Y) \ + _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm) +#define _FP_MUL_MEAT_Q(R,X,Y) \ + _FP_MUL_MEAT_4_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm) + +#define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_loop(S,R,X,Y) +#define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_2_udiv(D,R,X,Y) +#define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_4_udiv(Q,R,X,Y) + +#define _FP_NANFRAC_S ((_FP_QNANBIT_S << 1) - 1) +#define _FP_NANFRAC_D ((_FP_QNANBIT_D << 1) - 1), -1 +#define _FP_NANFRAC_Q ((_FP_QNANBIT_Q << 1) - 1), -1, -1, -1 +#define _FP_NANSIGN_S 0 +#define _FP_NANSIGN_D 0 +#define _FP_NANSIGN_Q 0 + +#define _FP_KEEPNANFRACP 1 + +/* Someone please check this. */ +#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \ + do { \ + if ((_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs) \ + && !(_FP_FRAC_HIGH_RAW_##fs(Y) & _FP_QNANBIT_##fs)) \ + { \ + R##_s = Y##_s; \ + _FP_FRAC_COPY_##wc(R,Y); \ + } \ + else \ + { \ + R##_s = X##_s; \ + _FP_FRAC_COPY_##wc(R,X); \ + } \ + R##_c = FP_CLS_NAN; \ + } while (0) + +#define __LITTLE_ENDIAN 1234 +#define __BIG_ENDIAN 4321 + +#define __BYTE_ORDER __BIG_ENDIAN + +/* Define ALIASNAME as a strong alias for NAME. */ +# define strong_alias(name, aliasname) _strong_alias(name, aliasname) +# define _strong_alias(name, aliasname) \ + extern __typeof (name) aliasname __attribute__ ((alias (#name))); diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/libgcc/config/or1k/t-crtstuff gcc-4.8.2-or1k-rtems/libgcc/config/or1k/t-crtstuff --- gcc-4.8.2/libgcc/config/or1k/t-crtstuff 1970-01-01 02:00:00.000000000 +0200 +++ gcc-4.8.2-or1k-rtems/libgcc/config/or1k/t-crtstuff 2014-03-14 07:28:08.000000000 +0200 @@ -0,0 +1,4 @@ +# This will prevent gcc from appending data to .eh_frame. +# Other archs use fno-asynchronous-unwind-tables but we do not have that flag. +CRTSTUFF_T_CFLAGS += -fno-dwarf2-cfi-asm +CRTSTUFF_T_CFLAGS_S += -fno-dwarf2-cfi-asm diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/libgcc/config/or1k/t-linux gcc-4.8.2-or1k-rtems/libgcc/config/or1k/t-linux --- gcc-4.8.2/libgcc/config/or1k/t-linux 1970-01-01 02:00:00.000000000 +0200 +++ gcc-4.8.2-or1k-rtems/libgcc/config/or1k/t-linux 2014-03-14 07:28:08.000000000 +0200 @@ -0,0 +1,12 @@ +MULTILIB_DIRNAMES = be +EXTRA_MULTILIB_PARTS = crti.o crtbegin.o crtend.o crtn.o + +# hack: +# the non-shared uclibc-0.9.31/libc/misc/internals/__uClibc_main.c +# already defines __dso_handle. To avoid a duplicate definition, +# we rename the crtbegin one. +# JPB 18-Nov-10: Commented out, since uClibc no longer defines. +# amend gcc Makefile CLFAGS variable +# $(T)crtbegin.o: CRTSTUFF_CFLAGS += '-D__dso_handle=__dso_handle_dummy' +# amend libgcc Makefile CLFAGS variable +# crtbegin$(objext): CRTSTUFF_T_CFLAGS += '-D__dso_handle=__dso_handle_dummy' diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/libgcc/config/or1k/t-or1k gcc-4.8.2-or1k-rtems/libgcc/config/or1k/t-or1k --- gcc-4.8.2/libgcc/config/or1k/t-or1k 1970-01-01 02:00:00.000000000 +0200 +++ gcc-4.8.2-or1k-rtems/libgcc/config/or1k/t-or1k 2014-03-14 07:28:08.000000000 +0200 @@ -0,0 +1,30 @@ +# t-or1k is a Makefile fragment to be included when +# building gcc for the or1k target + +# Copyright (C) 2010 Embecosm Limited + +# This file is part of GCC. +# +# GCC 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 3, or (at your option) +# any later version. +# +# GCC 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 GCC; see the file COPYING3. If not see +# . + +# for now, don't use asm versions of these functions +LIB2ADD = \ + $(srcdir)/udivmod.c \ + $(srcdir)/divmod.c \ + $(srcdir)/udivmodsi4.c \ + $(srcdir)/config/or1k/lib2funcs.c + +#LIB1ASMSRC = or1k/or1k.S +#LIB1ASMFUNCS = __mulsi3 __udivsi3 __divsi3 __umodsi3 __modsi3 diff -Naur -x '*.swp' -x '*.out' -x '*.diff' -x '*java*' gcc-4.8.2/libgcc/config.host gcc-4.8.2-or1k-rtems/libgcc/config.host --- gcc-4.8.2/libgcc/config.host 2013-07-09 23:35:57.000000000 +0200 +++ gcc-4.8.2-or1k-rtems/libgcc/config.host 2014-04-28 20:14:29.949218502 +0200 @@ -137,6 +137,12 @@ cpu_type=mips tmake_file=mips/t-mips ;; +or1k-*-*) + cpu_type=or1k + ;; +or1knd-*-*) + cpu_type=or1k + ;; powerpc*-*-*) cpu_type=rs6000 ;; @@ -797,6 +803,18 @@ # Don't use default. extra_parts= ;; +or1k*-*-linux* | or1k*-*-uclinux*) + tmake_file="$tmake_file or1k/t-or1k or1k/t-linux or1k/t-crtstuff t-softfp-sfdf t-softfp" + md_unwind_header=or1k/linux-unwind.h + ;; +or1k*-*-rtems*) + tmake_file="$tmake_file or1k/t-or1k or1k/t-crtstuff t-softfp-sfdf t-softfp" + extra_parts="crtbegin.o crtbeginS.o crtbeginT.o crtend.o crtendS.o crti.o crtn.o" + ;; +or1k*-*-*) + tmake_file="$tmake_file or1k/t-or1k or1k/t-crtstuff t-softfp-sfdf t-softfp" + extra_parts="crtbegin.o crtbeginS.o crtbeginT.o crtend.o crtendS.o crti.o crtn.o" + ;; pdp11-*-*) tmake_file="pdp11/t-pdp11 t-fdpbit" ;;