Skip to content

Instantly share code, notes, and snippets.

@ssvb
Created July 26, 2016 18:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ssvb/949fe453b349b4d1be9f30ca3d2161c7 to your computer and use it in GitHub Desktop.
Save ssvb/949fe453b349b4d1be9f30ca3d2161c7 to your computer and use it in GitHub Desktop.
From 44eac78981c07cf2f73a338d3e34eed685f6309d Mon Sep 17 00:00:00 2001
From: Siarhei Siamashka <siarhei.siamashka@gmail.com>
Date: Mon, 25 Jul 2016 17:42:19 +0300
Subject: [PATCH] OpenRISC support for GCC 5.3.0
This is the difference between dfad8a2635433704c74c70db28c3559867c2e362
from https://github.com/openrisc/or1k-gcc.git and vanilla GCC 5.3.0
---
ChangeLog.or1k | 8 +
config/picflag.m4 | 3 +
fixincludes/mkfixinc.sh | 3 +-
gcc/ChangeLog.or1k | 900 +++++++
gcc/ada/s-osinte-posix.adb | 2 +-
gcc/common.opt | 4 +
gcc/common/config/or1k/or1k-common.c | 61 +
gcc/config.gcc | 43 +-
gcc/config/aarch64/aarch64-linux.h | 2 +
gcc/config/arm/linux-eabi.h | 17 +
gcc/config/i386/linux.h | 1 +
gcc/config/i386/linux64.h | 4 +
gcc/config/linux.h | 100 +-
gcc/config/linux.opt | 4 +
gcc/config/microblaze/linux.h | 17 +-
gcc/config/microblaze/microblaze.h | 6 +
gcc/config/mips/linux.h | 9 +-
gcc/config/or1k/constraints.md | 59 +
gcc/config/or1k/elf.h | 31 +
gcc/config/or1k/linux-elf.h | 99 +
gcc/config/or1k/linux-gas.h | 37 +
gcc/config/or1k/or1k-modes.def | 38 +
gcc/config/or1k/or1k-opts.h | 14 +
gcc/config/or1k/or1k-protos.h | 67 +
gcc/config/or1k/or1k.c | 2445 ++++++++++++++++++++
gcc/config/or1k/or1k.h | 1197 ++++++++++
gcc/config/or1k/or1k.md | 1599 +++++++++++++
gcc/config/or1k/or1k.opt | 96 +
gcc/config/or1k/predicates.md | 121 +
gcc/config/or1k/rtems.h | 30 +
gcc/config/or1k/t-linux | 12 +
gcc/config/or1k/t-or1k | 28 +
gcc/config/or1k/t-or1knd | 28 +
gcc/config/or1k/t-rtems | 3 +
gcc/config/rs6000/linux64.h | 12 +-
gcc/config/rs6000/secureplt.h | 1 +
gcc/config/rs6000/sysv4.h | 16 +-
gcc/config/sh/linux.h | 7 +
gcc/config/uclibc-stdint.h | 70 +
gcc/configure | 24 +
gcc/configure.ac | 21 +
gcc/gcc.c | 2 +-
gcc/ginclude/stddef.h | 3 +
gcc/testsuite/g++.dg/ext/strncpy-chk1.C | 4 +-
gcc/testsuite/g++.dg/init/pr25811.C | 195 ++
gcc/testsuite/gcc.c-torture/execute/20101011-1.c | 6 +
gcc/testsuite/gcc.dg/20020312-2.c | 2 +
gcc/testsuite/gcc.dg/builtin-apply2.c | 32 +
gcc/testsuite/gcc.dg/builtin-stringop-chk-1.c | 4 +-
gcc/testsuite/gcc.dg/nop.h | 2 +
gcc/testsuite/gcc.dg/torture/pr37868.c | 1 +
.../gcc.dg/torture/stackalign/builtin-apply-2.c | 2 +-
gcc/testsuite/gcc.dg/tree-ssa/pr44258.c | 2 +-
gcc/testsuite/lib/target-supports.exp | 1 +
libgcc/ChangeLog.or1k | 61 +
libgcc/config.host | 14 +
libgcc/config/or1k/crti.S | 36 +
libgcc/config/or1k/crtn.S | 37 +
libgcc/config/or1k/linux-unwind.h | 77 +
libgcc/config/or1k/or1k-asm.h | 20 +
libgcc/config/or1k/or1k.S | 237 ++
libgcc/config/or1k/sfp-machine.h | 54 +
libgcc/config/or1k/t-crtstuff | 4 +
libgcc/config/or1k/t-linux | 2 +
libgcc/config/or1k/t-or1k | 23 +
libgcc/configure | 3 +
libgcc/gthr.h | 2 -
libgcc/unwind-dw2-fde-dip.c | 4 +
libgomp/config/posix/time.c | 2 +
libiberty/ChangeLog.or1k | 4 +
libitm/config/arm/hwcap.cc | 4 +
libitm/config/linux/x86/tls.h | 8 +-
libjava/classpath/config.guess | 4 +-
libjava/classpath/config.sub | 6 +-
libstdc++-v3/configure.host | 10 +
.../basic_string/inserters_extractors/wchar_t/5.cc | 2 +
.../copy/streambuf_iterators/wchar_t/4.cc | 2 +
.../find/istreambuf_iterators/wchar_t/2.cc | 2 +
.../27_io/basic_filebuf/seekpos/wchar_t/12790-1.cc | 2 +
.../basic_istream/extractors_other/wchar_t/2.cc | 2 +
.../testsuite/27_io/basic_istream/get/wchar_t/2.cc | 3 +
.../27_io/basic_istream/ignore/wchar_t/3.cc | 2 +
.../27_io/basic_istream/seekg/wchar_t/sstream.cc | 2 +
.../27_io/basic_istream/tellg/wchar_t/sstream.cc | 2 +
.../basic_ostream/inserters_other/wchar_t/1.cc | 2 +
.../testsuite/27_io/ios_base/sync_with_stdio/1.cc | 2 +
.../testsuite/27_io/objects/wchar_t/12048-1.cc | 2 +
.../testsuite/27_io/objects/wchar_t/12048-2.cc | 2 +
.../testsuite/27_io/objects/wchar_t/12048-3.cc | 2 +
.../testsuite/27_io/objects/wchar_t/12048-4.cc | 2 +
90 files changed, 8097 insertions(+), 41 deletions(-)
create mode 100644 ChangeLog.or1k
create mode 100644 gcc/ChangeLog.or1k
create mode 100644 gcc/common/config/or1k/or1k-common.c
create mode 100644 gcc/config/or1k/constraints.md
create mode 100644 gcc/config/or1k/elf.h
create mode 100644 gcc/config/or1k/linux-elf.h
create mode 100644 gcc/config/or1k/linux-gas.h
create mode 100644 gcc/config/or1k/or1k-modes.def
create mode 100644 gcc/config/or1k/or1k-opts.h
create mode 100644 gcc/config/or1k/or1k-protos.h
create mode 100644 gcc/config/or1k/or1k.c
create mode 100644 gcc/config/or1k/or1k.h
create mode 100644 gcc/config/or1k/or1k.md
create mode 100644 gcc/config/or1k/or1k.opt
create mode 100644 gcc/config/or1k/predicates.md
create mode 100644 gcc/config/or1k/rtems.h
create mode 100644 gcc/config/or1k/t-linux
create mode 100644 gcc/config/or1k/t-or1k
create mode 100644 gcc/config/or1k/t-or1knd
create mode 100644 gcc/config/or1k/t-rtems
create mode 100644 gcc/config/uclibc-stdint.h
create mode 100644 libgcc/ChangeLog.or1k
create mode 100644 libgcc/config/or1k/crti.S
create mode 100644 libgcc/config/or1k/crtn.S
create mode 100644 libgcc/config/or1k/linux-unwind.h
create mode 100644 libgcc/config/or1k/or1k-asm.h
create mode 100644 libgcc/config/or1k/or1k.S
create mode 100644 libgcc/config/or1k/sfp-machine.h
create mode 100644 libgcc/config/or1k/t-crtstuff
create mode 100644 libgcc/config/or1k/t-linux
create mode 100644 libgcc/config/or1k/t-or1k
create mode 100644 libiberty/ChangeLog.or1k
diff --git a/ChangeLog.or1k b/ChangeLog.or1k
new file mode 100644
index 0000000..ea19a46
--- /dev/null
+++ b/ChangeLog.or1k
@@ -0,0 +1,8 @@
+2012-05-13 Peter Gavin <pgavin@gmail.com>
+
+ * config.guess, config.sub: add or1knd target
+
+2012-03-03 Peter Gavin <pgavin@gmail.com>
+
+ * config.picflag: no pic flag for or1k
+
diff --git a/config/picflag.m4 b/config/picflag.m4
index 2f5b972..e96c85a 100644
--- a/config/picflag.m4
+++ b/config/picflag.m4
@@ -47,6 +47,9 @@ case "${$2}" in
mips-sgi-irix6*)
# PIC is the default.
;;
+ or1k-*-*)
+ $1=-fPIC
+ ;;
rs6000-ibm-aix* | powerpc-ibm-aix*)
# All AIX code is PIC.
;;
diff --git a/fixincludes/mkfixinc.sh b/fixincludes/mkfixinc.sh
index 6653fed..0d96c8c 100755
--- a/fixincludes/mkfixinc.sh
+++ b/fixincludes/mkfixinc.sh
@@ -19,7 +19,8 @@ case $machine in
powerpc-*-eabi* | \
powerpc-*-rtems* | \
powerpcle-*-eabisim* | \
- powerpcle-*-eabi* )
+ powerpcle-*-eabi* | \
+ *-musl* )
# IF there is no include fixing,
# THEN create a no-op fixer and exit
(echo "#! /bin/sh" ; echo "exit 0" ) > ${target}
diff --git a/gcc/ChangeLog.or1k b/gcc/ChangeLog.or1k
new file mode 100644
index 0000000..0c74185
--- /dev/null
+++ b/gcc/ChangeLog.or1k
@@ -0,0 +1,900 @@
+2015-01-17 Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
+
+ * config/or1k/or1k.md (cmpxchg_mask): Mask set register.
+
+2014-08-13 Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
+
+ * config/or1k/or1k.h (ASM_PREFERRED_EH_DATA_FORMAT): Define.
+
+2013-02-13 Franck Jullien <franck.jullien@gmail.com>
+
+ * config/or1k/or1k.h:
+ (LIB_SPEC): use -lboard-%* or -lboard-or1ksim even when
+ -static option is used.
+
+2013-02-13 Christian Svensson <blue@cmd.nu>
+
+ * config/or1k/or1k-protos.h
+ (or1k_expand_pic_symbol_ref): Removed declaration.
+ (or1k_expand_symbol_ref): Added declaration.
+ * config/or1k/or1k.c
+ (or1k_expand_pic_symbol_ref): Made static.
+ (or1k_tls_symbolic_operand): New, returns TLS model of operand.
+ (gen_tls_tga): New, static cache of __tls_get_addr reference.
+ (gen_tls_get_addr): New, returns reference to __tls_get_addr.
+ (or1k_tls_call): New, emits call to __tls_get_addr.
+ (or1k_expand_symbol_ref): New, handles TLS operands.
+ (or1k_expand_move): Call or1k_expand_symbol_ref instead which will
+ then call or1k_expand_pic_symbol_ref if needed.
+ (gt-or1k.h): Include. Needed for gen_tls_tga.
+ * config/or1k/or1k.h (TARGET_HAVE_TLS): Define if HAVE_AS_TLS is set.
+ * config/or1k/or1k.md
+ (UNSPECS): Added UNSPEC_TPOFFLO, UNSPEC_TPOFFHI, UNSPEC_GOTTPOFFLO,
+ UNSPEC_GOTTPOFFHI, UNSPEC_GOTTPOFFLD, UNSPEC_TLSGDLO, UNSPEC_TLSGDHI.
+ (movsi_tlsgdlo): Added.
+ (movsi_tlsgdhi): Added.
+ (movsi_gottpofflo): Added.
+ (movsi_gottpoffhi): Added.
+ (load_gottpoff): Added.
+ (movsi_tpofflo): Added.
+ (movsi_tpoffhi): Added.
+ (movsi_insn_big): Call or1k_expand_symbol_ref instead.
+ * configure.ac: (TLS test): Check for or1k TLS support in AS.
+ * configure: (TLS test): Manually added same as in .ac.
+
+2013-02-11 Franck Jullien <franck.jullien@gmail.com>
+
+ * config/or1k/or1k.h:
+ (LINK_SPEC): add a space between arguments.
+
+2013-01-22 Christian Svensson <blue@cmd.nu>
+
+ * common/config/or1k/or1k-common.c
+ (TARGET_EXCEPT_UNWIND_INFO): define.
+ (or1k_except_unwind_info): use DWARF2 unwind info as default
+ but support SJLJ if forced with --enable-sjlj-exceptions.
+ * config/or1k/or1k-protos.h:
+ (or1k_expand_pic_symbol_ref): removed unneeded ATTRIBUTE_UNUSED.
+ (or1k_eh_return_handler_rtx): defined prototype (body in or1k.c).
+ (or1k_return_addr_rtx): defined prototype (body in or1k.c).
+ * config/or1k/or1k.c
+ (or1k_save_reg_p): save stack pointer when frame pointer is not saved.
+ (or1k_save_reg_p): save registers used with eh_return.
+ (or1k_save_reg_p): save LR to stack if used by RETURN_ADDR_RTX.
+ (or1k_expand_epilogue): do not restore link register if we are
+ returning from eh_return.
+ (or1k_expand_epilogue): apply EH stack adjustment to stack pointer.
+ (or1k_eh_return_handler_rtx): eh_return should write to the link register.
+ (or1k_return_addr_rtx): in the case of GOT the link register cannot be read
+ after the prologue. store LR on stack and read it back when needed.
+ (or1k_frame_pointer_required): require FP in eh_return and
+ when alloca is used.
+ (or1k_init_machine_status): init cfun->machine.
+ (or1k_init_expanders): added LR forced save, default to false.
+ (TARGET_FRAME_POINTER_REQUIRED): define.
+ * config/or1k/or1k.h
+ (INITIAL_FRAME_POINTER_OFFSET): not used, removed.
+ (RETURN_ADDR_RTX): define.
+ (EH_RETURN_REGNUM): define. use reg 23.
+ (EH_RETURN_DATA_REGNO): define. use reg 25, 27, 29 and 31.
+ (EH_RETURN_STACKADJ_RTX): define.
+ (EH_RETURN_HANDLER_RTX): define.
+ (INIT_EXPANDERS): define.
+ (struct GTY()): define.
+
+2012-12-29 Christian Svensson <blue@cmd.nu>
+
+ * config.gcc: Use GNU userspace link options when compiling for Linux.
+ * config/or1k/linux-elf.h:
+ (DRIVER_SELF_SPECS): Do not assume uclibc when -m glibc is absent, use
+ target configuration instead.
+
+2012-12-21 Christian Svensson <blue@cmd.nu>
+
+ * config/or1k/linux-elf.h (GLIBC_DYNAMIC_LINKER): Define.
+ (LINK_SPEC): Use -muclibc / -mglibc to detect wanted interp to
+ -dynamic_linker.
+
+2012-11-29 Peter Gavin <pgavin@gmail.com>
+
+ * config/or1k/or1k.c:
+ (or1k_output_highadd) removed, unneeded
+
+2012-11-29 Peter Gavin <pgavin@gmail.com>
+
+ * config/or1k/or1k-protos.h:
+ (or1k_expand_sibcall) removed, unneeded
+
+2012-11-29 Peter Gavin <pgavin@gmail.com>
+
+ fix some things that broke in merge with upstream
+ * config/or1k/or1k.h:
+ (GO_IF_MODE_DEPENDENT_ADDRESS) poisoned in last GCC merge, seems
+ obsolete now
+ (FIXUNS_TRUNC_LIKE_FIX_TRUNC) ditto
+ * config/or1k/or1k-protos.h:
+ (or1k_expand_pic_symbol_ref) added prototype (function body is in or1k.c)
+ (or1k_legitimate_pic_operand_p) ditto
+ * config/or1k/or1k.c:
+ (or1k_compute_frame_size) use crtl->is_leaf instead of current_function_is_leaf
+
+2012-10-28 Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
+
+ * common/config/or1k/or1k-common.c (or1k_handle_option): Remove.
+ (TARGET_HANDLE_OPTION): Likewise.
+ * gcc/config.gcc (or1k-*-elf*): Remove OR1K_LIBC_DEFAULT from tm_defines
+ (or1k-*-linux-*): Likewise.
+ (or1knd-*-elf*): Likewise.
+ (or1knd-*-linux-*): Likewise.
+ * config/or1k/linux-elf.h (DRIVER_SELF_SPECS): Define -muclibc when
+ -mglibc is not given.
+ (TARGET_OS_CPP_BUILTINS): Define "__UCLIBC__" on OPTION_UCLIBC.
+ * config/or1k/or1k.h: Remove custom libc handling
+ * config/or1k/or1k.opt: Likewise.
+
+2012-09-30 Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
+
+ * config/or1k/or1k.h (DWARF2_ASM_LINE_DEBUG_INFO): Define.
+
+2012-09-23 Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
+
+ * config/or1k/or1k.c (or1k_expand_prologue): Add asserts checking that
+ link reg and fp stack slots offsets are not equal to other offsets.
+
+2012-09-23 Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
+
+ * config/or1k/or1k.c (or1k_save_reg_p): Save link register when
+ crtl->uses_pic_offset_table is set.
+ (or1k_compute_frame_size): Reserve space for PIC reg and link register
+ when -fPIC is defined.
+ (or1k_print_operand_address): Remove UNSPEC_GOTOFF handling.
+ (or1k_legitimate_address_p): Likewise.
+ (or1k_legitimate_pic_operand_p): New function.
+ (expand_pic_symbol_ref): Rename to:
+ (or1k_expand_pic_symbol_ref): Emit appropriate GOT references.
+ I.e. labels, local symbols and weak symbols use relative referencing
+ to GOT and global symbol references use referencing through GOT.
+ (or1k_expand_move): Utilize the functionality from
+ (or1k_expand_pic_symbol_ref).
+ (or1k_expand_prologue): Use crtl->uses_pic_offset_tale and
+ frame_info.save_lr_p to determine if the got pointer should be acquired
+ instead of df_regs_ever_live_p (PIC_OFFSET_TABLE_REGNUM).
+ (or1k_output_addr_const_extra): Remove.
+ (or1k_legitimize_address): Likewise.
+ (TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA): Likewise.
+ (TARGET_LEGITIMIZE_ADDRESS): Likewise.
+ * config/or1k/or1k.h (FIXED_REGISTERS): Add r16 (GOT pointer).
+ (CALL_USED_REGISTERS): Likewise.
+ (PIC_OFFSET_TABLE_REGNUM): Change from r10 to r16.
+ (LEGITIMATE_PIC_OPERAND_P): Define.
+ * config/or1k/or1k.md (UNSPEC_GOTOFF): Remove.
+ (UNSPEC_PCREL): Likewise.
+ (UNSPEC_PIC_LABEL): Likewise.
+ (UNSPEC_SYMBOL_OFFSET): Likewise.
+ (UNSPEC_GOTOFFHI): New constant.
+ (UNSPEC_GOTOFFLO): Likewise.
+ (movsi_gotofflo): New insn.
+ (movsi_gotoffhi): Likewise.
+ (movsi_got): Likewise.
+ (movsi_insn_big): Expand PIC symbol ref if necessary on -fpic
+ (call): Set r16 as used.
+ (call_indirect): Likewise.
+ (call_indirect_internal): Likewise.
+ (call_value): Likewise.
+ (call_value_indirect): Likewise.
+ (call_value_indirect_internal): Likewise.
+ (call_internal): Set r16 as used and emit call through plt on -fpic.
+ (call_value_internal): Likewise.
+ (set_got): Set r9 and r16 as clobbered, use gotpchi() and gotpclo()
+ assembler keywords.
+
+2012-09-18 Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
+
+ * config/picflag.m4 (or1k-*-*): Set picflag.
+
+2012-09-14 Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
+
+ * gcc/config/or1k/t-linux (MULTILIB_DIRNAMES): Remove 'be' multilib.
+
+2012-09-12 Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
+
+ * config/or1k/linux-elf.h (TARGET_VERSION): Remove.
+
+2012-09-11 Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
+
+ * config/or1k/or1k.c (or1k_output_cmov): Remove '\t' in front of l.cmov
+ in asm output.
+
+2012-06-23 Peter Gavin <pgavin@gmail.com>
+
+ * config/or1k/or1k.c:
+ (or1k_output_tailcall) remove
+
+2012-06-23 Peter Gavin <pgavin@gmail.com>
+
+ turn off delay-slot pass when not using delayed branches
+ * config/or1k/or1k.c:
+ (or1k_option_override) new function, for now just clear
+ flag_delayed_branch when !TARGET_DELAY_ON
+ (TARGET_OPTION_OVERRIDE) define
+
+2012-06-23 Peter Gavin <pgavin@gmail.com>
+
+ * config/or1k/or1k.h:
+ (or1k_asm_file_start) remove prototype
+ (TARGET_ASM_FILE_START) moved to or1k.c
+ * config/or1k/or1k.c:
+ (or1k_asm_file_start) make static
+ (TARGET_ASM_FILE_START) moved from or1k.h
+
+2012-06-23 Peter Gavin <pgavin@gmail.com>
+
+ more fixes (and fixes to fixes) needed for update against upstream
+ * config/or1k/or1k-common.c: delete
+ * config/common/or1k/or1k-common.c:
+ include opts.h & flags.h
+ (or1k_option_optimization_table) add entry for OPT_fomit_frame_pointer
+ (or1k_handle_option) move from config/or1k/or1k-common.c
+ (TARGET_HANDLE_OPTION) move from config/or1k/or1k.c
+ * config/or1k/or1k.c:
+ (TARGET_HANDLE_OPTION) move from config/or1k/or1k.c
+
+2012-06-22 Peter Gavin <pgavin@gmail.com>
+
+ * config/or1k/or1k.md: add comments to each instruction annotating
+ where it came from; add "length" and "type" attributes to l.sf*
+ instructions
+
+2012-06-22 Peter Gavin <pgavin@gmail.com>
+
+ * config/or1k/or1k.h:
+ (TARGET_CPU_CPP_BUILTINS) make sure things are properly defined
+ for or1knd
+
+2012-06-22 Peter Gavin <pgavin@gmail.com>
+
+ * config/or1k/or1k.c:
+ (or1k_output_mi_thunk) remove (not used?)
+
+2012-06-22 Peter Gavin <pgavin@gmail.com>
+
+ * config/or1k/or1k.c: properly terminate some comments
+
+2012-06-22 Peter Gavin <pgavin@gmail.com>
+
+ * config/or1k/or1k.c:
+ (or1k_trampoline_code_words) make static
+
+2012-06-22 Peter Gavin <pgavin@gmail.com>
+
+ some fixes needed for update against mainline
+ * config/or1k/or1k-common.c: new file
+ (or1k_handle_option) moved from or1k.c
+ * config/or1k/or1k.c
+ (stack_disp_mem) pass Pmode as first argument to plus_constant
+ (or1k_handle_option) removed
+
+2012-05-28 Peter Gavin <pgavin@gmail.com>
+
+ fix cmov
+ * config/or1k/or1k-protos.h:
+ (or1k_select_cc_mode) new prototype
+ * config/or1k/or1k.h:
+ (SELECT_CC_MODE) redefine to call or1k_select_cc_mode
+ (or1k_compare_op0) remove
+ (or1k_compare_op1) remove
+ * config/or1k/or1k.c:
+ (or1k_select_cc_mode) new function: does what SELECT_CC_MODE did,
+ but as a function; only takes one argument (the first), since the
+ second two in SELECT_CC_MODE are never used
+ (or1k_compare_op0) remove
+ (or1k_compare_op1) remove
+ (or1k_emit_int_cmov) use operands passed in instead of
+ or1k_compare_op[01]
+ (or1k_output_bf) call or1k_select_cc_mode instead of using SELECT_CC_MODE
+ (or1k_output_cmov) ditto
+
+2012-05-24 Peter Gavin <pgavin@gmail.com>
+
+ remove some unneeded code
+ * config/or1k/or1k.c: remove use of INITIALIZER (was commented
+ anyways)
+ (calculate_stack_size) remove, never used
+ (or1k_frame_pointer_required) ditto
+
+2012-05-24 Peter Gavin <pgavin@gmail.com>
+
+ remove sibcall support for or1k
+ * config/or1k/constraints.md:
+ (define_constraint "Rsc") removed
+ * config/or1k/predicates.md:
+ (define_predicate "sibcall_insn_operand") removed
+ * config/or1k/or1k-protos.h:
+ (or1k_expand_epilogue) removed sibcall parameter
+ * config/or1k/or1k.h:
+ (PRINT_OPERAND) removed 'J' and 'K' constraints
+ * config/or1k/or1k.c:
+ (or1k_expand_epilogue) removed sibcall parameter, don't check for
+ sibcalls
+ (or1k_print_jump_restore) removed
+ (or1k_expand_sibcall) removed
+ (or1k_function_ok_for_sibcall) return 0 so sibcalls are never used
+ * config/or1k/or1k.md:
+ (define_constants UNSPECV_SIBCALL_EPILOGUE) removed
+ (define_expand "epilogue") don't pass null to or1k_expand_epilogue
+ (define_insn_and_split "sibcall_epilogue") removed
+ (define_expand "sibcall") removed
+ (define_expand "sibcall_value") removed
+ (define_insn "sibcall_internal") removed
+
+2012-05-24 Peter Gavin <pgavin@gmail.com>
+
+ remove -mlogue flag, always use scheduled prologue/epilogue
+ * config/common/or1k-common.c:
+ (TARGET_DEFAULT_TARGET_FLAGS) remove MASK_SCHED_LOGUE
+ * config/or1k/or1k.c:
+ (or1k_output_function_prologue) removed
+ (or1k_output_function_epilogue) removed
+ (TARGET_ASM_FUNCTION_PROLOGUE) removed
+ (TARGET_ASM_FUNCTION_EPILOGUE) removed
+ * config/or1k/or1k.md:
+ (prologue) remove TARGET_SCHED_LOGUE from constraints
+ (epilogue) ditto
+ (sibcall_epilogue) ditto
+ (return_internal) ditto
+ * config/or1k/or1k.opt:
+ (mlogue) removed
+
+2012-05-13 Peter Gavin <pgavin@gmail.com>
+
+ * gcc/config.gcc: add or1knd target; add OR1K_DELAY_DEFAULT
+ definitions to tm_defines for or1k and or1knd
+ * gcc/config/or1k/or1k-opts.h: new file; defines enum and flags
+ for delay slot options
+ * gcc/config/or1k/or1k.h: make delay slot optional
+ (TARGET_CPU_CPP_BUILTINS) define __OR1K_DELAY__, __OR1K_NODELAY__,
+ or __OR1K_DELAY_COMPAT__ depending on delay slot option chosen
+ (TARGET_ASM_FILE_START) new define
+ (or1k_asm_file_start) new prototype
+ (PRINT_OPERAND) emit different code depending on delay slot option
+ - added %K operand which is like %J but only emits code when no
+ delay slot
+ * gcc/config/or1k/or1k.c: make delay slot optional
+ (OR1K_NOP) new define, needed when inserting NOP in trampoline for
+ -mcompat-delay mode
+ (or1k_asm_file_start) new function; add ".nodelay" directive to
+ assembly file when not using delay slot
+ (or1k_trampoline_words) new function; return number of words in
+ trampoline. The number of words depends on whether a delay slot is
+ used
+ (or1k_trampoline_code_size) use or1k_trampoline_words
+ (or1k_output_function_epilogue) emit different code depending on
+ delay slot option
+ (or1k_trampoline_init) ditto
+ (or1k_output_mi_thunk) ditto
+ * gcc/config/or1k/or1k.md: make delay slot optional
+ - change when delay on branches & jumps is used
+ - add %K0 operand in sibcall with Rsc constraint
+ * gcc/config/or1k/or1k.opt: add -mdelay, -mno-delay -mcompat-delay flags
+ * gcc/config/or1k/t-or1k: add multilibs for no-delay and compat-delay
+ * gcc/config/or1k/t-or1knd: new file
+
+2012-05-13 Peter Gavin <pgavin@gmail.com>
+
+ * config/or1k/or1k.h: change some specs
+ (CONC_DIR) remove
+ (TARGET_PREFIX) remove
+ (EXTRA_SPECS) remove
+ (STARTFILE_SPEC) use %s to search for files instead of using target_prefix
+ (LINK_SPEC) set entry to 0x100 when using newlib; remove -L%(target_prefix)/...
+ (LIB_SPEC) use %s to search for files; use -lboard-${board} to
+ link, instead of adding -L.../${board} and using -lboard
+ - this fixes a problem finding the libraries when using multilibs
+
+2012-05-13 Peter Gavin <pgavin@gmail.com>
+
+ * config/or1k/or1k-protos.h: add prototype for
+ or1k_expand_move (suppresses "no previous prototype" warning)
+ * config/or1k/or1k.c: (or1k_legitimize_address) add
+ ATTRIBUTE_UNUSED to mode (suppresses unused variable warning)
+
+2012-04-25 Peter Gavin <pgavin@gmail.com>
+
+ * gcc/config/or1k/default.h: remove (why is this here?)
+
+2012-03-03 Peter Gavin <pgavin@gmail.com>
+
+ * configure: regenerated
+
+2012-02-23 Peter Gavin <pgavin@gmail.com>
+
+ * config/or1k/or1k.md: change if to else if in condition for
+ "movhi" (shouldn't make a difference); fix conditions for
+ "movsi_insn_big"
+ * config/or1k/predicates.md: remove unneeded fprintf
+
+2012-02-18 Peter Gavin <pgavin@gmail.com>
+
+ * config/or1k/or1k.S: moved to libgcc/config/or1k/or1k.S
+ * config/or1k/crti.S, gcc/config/or1k/crtn.S: deleted
+ * config/or1k/or1k.c: remove dwarf2 code since this has been
+ moved into it's own compiler pass (more will probably have to be
+ done about this but it seems to work ok for now); fix some
+ warnings; include <ansidecl.h>; remove INITIALIZER (what was it
+ supposed to do?)
+ * config/or1k/or1k.h: make SELECT_CC_MODE return an something
+ of correct type on failure instead of just 0
+ * config/or1k/t-or1k: remove a bunch of obsolete stuff
+
+2011-12-01 Joern Rennecke <joern.rennecke@embecosm.com>
+
+ * config/or32/or32.md (cbranchsi4): Fix mode of operands 1 and 2.
+
+2011-07-07 Giuseppe Scrivano <giuseppe@southpole.se>
+
+ * config/or32/or32.c (or32_print_operand_address): New function.
+ (expand_pic_symbol_ref): Likewise.
+ (or32_expand_move): Likewise.
+ (or32_expand_prologue): Set the PIC register.
+ (or32_output_addr_const_extra): Likewise.
+ (or32_legitimate_address_p): Handle UNSPEC.
+ (or32_legitimate_constant_p): When PIC is used don't allow
+ constants in VOIDmode.
+ (TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA, TARGET_LEGITIMIZE_ADDRESS): Define
+ hooks.
+
+ * config/or32/or32.md (UNSPEC_GOTOFF, UNSPEC_PCREL): Define.
+ (UNSPEC_PIC_LABEL, UNSPEC_SYMBOL_OFFSET, UNSPEC_SET_GOT): Likewise.
+ (set_got): New function.
+ (movhi_internal): Delegate to or32_expand_move.
+
+2011-06-27 Giuseppe Scrivano <giuseppe@southpole.se>
+
+ * config/or32/or32.h: Define PIC_OFFSET_TABLE_REGNUM.
+ * config/or32/or32.c: Remove definition for GOT_SYMBOL_NAME and
+ GOT_REGISTER.
+
+2011-06-20 Giuseppe Scrivano <giuseppe@southpole.se>
+
+ * config/or32/or32.c: Define GOT_SYMBOL_NAME and GOT_REGISTER.
+ (or32_expand_prologue): Store the GOT location in the GOT_REGISTER if
+ PIC code is generated.
+
+2011-06-17 Giuseppe Scrivano <giuseppe@southpole.se>
+
+ * common/config/or32/or32-common.c: New file.
+ * config/or32/or32.h (LINK_SPEC): Support -shared.
+ * config/or32/or32.c (TARGET_EXCEPT_UNWIND_INFO): Remove definition.
+ * config/or32/or32.c (or32_pass_by_reference): Change type of CUM to
+ cumulative_args_t.
+ (or32_arg_partial_bytes): Likewise.
+ (or32_function_arg): Likewise.
+ (or32_function_arg_advance): Likewise.
+
+2011-05-28 Giuseppe Scrivano <gscrivano@southpole.se>
+
+ * or32.h (FUNCTION_ARG, FUNCTION_ARG_ADVANCE): Undefine.
+ (HANDLE_PRAGMA_PACK_PUSH_POP, LEGITIMATE_CONSTANT_P): Likewise.
+ (CAN_DEBUG_WITHOUT_FP, RETURN_POPS_ARGS): Likewise.
+ (target_flags): Remove extern declaration.
+ * or32.c (TARGET_FUNCTION_ARG, TARGET_FUNCTION_ARG_ADVANCE): Define.
+ (TARGET_LEGITIMATE_CONSTANT_P, TARGET_EXCEPT_UNWIND_INFO): Likewise.
+ (or32_legitimate_constant_p, or32_function_arg): New functions.
+ (or32_function_arg, or32_function_arg_advance): Likewise.
+
+2011-04-13 Joern Rennecke <joern.rennecke@embecosm.com>
+
+ * config/or32/elf.h (DRIVER_SELF_SPECS): Define.
+ * config/or32/linux-elf.h (DRIVER_SELF_SPECS): Undef.
+
+2011-04-09 Jeremy Bennett <jeremy.bennett@embecosm.com>
+
+ * BASE_VER: Updated for gcc-4.5.1-or32-1.0rc3.
+
+2011-03-22 Joern Rennecke <joern.rennecke@embecosm.com>
+
+ * config/or32/or32.h (LEGITIMATE_CONSTANT_P): Allow VOIDmode
+ CONST_DOUBLE.
+ * config/or32/or32.md (movsi_insn_big): Enable splitting of CONST_INT.
+ (movdi): Now a define_insn_and_split.
+ * config/or32/or32.c (or32_output_move_double): Abort for CONST_INT.
+
+2011-02-17 Joern Rennecke <joern.rennecke@embecosm.com>
+
+ * gcc.c (do_spec_1) <%*>: Don't append a space unless the next
+ character is '}'.
+ * config/or32/or32.h (STARTFILE_SPEC): For mor32-newlib-*,
+ add crtparam-%*.o.
+
+2011-02-15 Joern Rennecke <joern.rennecke@embecosm.com>
+
+ * config/or32/or32.md (frame_alloc_fp): New pattern.
+ * config/or32/or32.c (or32_expand_prologue): Use it if a frame pointer
+ is used.
+
+2011-02-03 Joern Rennecke <joern.rennecke@embecosm.com>
+
+ * config/uclibc-stdint.h: New file.
+ * config.gcc (or32-*linux*): Add uclibc-stdint.h to tm_file.
+
+2011-02-03 Jonas Bonn <jonas@southpole.se>
+
+ * config/or32/or32.h (CALL_USED_REGS): Include r12.
+
+2011-01-12 Joern Rennecke <joern.rennecke@embecosm.com>
+
+ * config.or32/or32.h (CPP_SPEC): Add -D_XOPEN_SOURCE=600 for pthread.
+ (LIB_SPEC): Add --whole-archive -lpthread --no-whole-archive for
+ pthread.
+
+2010-12-19 Jeremy Bennett <jeremy.bennett@embecosm.com>
+
+ * config.gcc <or32-*-linux*>: Remove extra_parts.
+ * config/or32/crti.S (__init): Add l.nop, so doesn't start at zero.
+
+2010-12-19 Jeremy Bennett <jeremy.bennett@embecosm.com>
+
+ * config/or32/crtn.S (__init, __fini): remove labels.
+ * config.gcc <or32-*-linux*>: Add crti.o and crt.n to extra_parts.
+
+2010-12-16 Joern Rennecke <joern.rennecke@embecosm.com>
+
+ * config.gcc (or32-*-elf*) <tm_defines>:
+ Add OR32_LIBC_DEFAULT=or32_libc_newlib.
+ (or32-*linux*) <tm_defines>: Set UCLIBC_DEFAULT=1.
+ Add OR32_LIBC_DEFAULT=or32_libc_uclibc.
+ * config/or32/or32.opt (mnewlib): New option.
+ (muclibc, mglibc): Stub options.
+ * config/or32/or32.h (TARGET_CPU_CPP_BUILTINS): When using uClibc,
+ define __UCLIBC__.
+ (or32_libc_kind): New enum.
+ * config/or32/or32.c (or32_handle_option): New function.
+ (TARGET_HANDLE_OPTION): Override.
+
+2010-12-10 Joern Rennecke <joern.rennecke@embecosm.com>
+
+ * config/or32/or32.c (TARGET_STRICT_ARGUMENT_NAMING): Overrride.
+
+2010-11-18 Jeremy Bennett <jeremy.bennett@embecosm.com>
+
+ * config/or32/t-linux ($(T)crtbegin.o): Reverse out __dso_handle
+ rename.
+ (crtbegin$(objext)): Likewise.
+
+2010-11-07 Joern Rennecke <joern.rennecke@embecosm.com>
+
+ * config/or32/or32.opt (mredzone=): New option.
+ * config/or32/or32.c (frame_info): New members gpr_frame, late_frame.
+ (or32_compute_frame_size, or32_expand_prologue): Implement -mredzone.
+ or32_expand_epilogue, or32_initial_elimination_offset): Likewise.
+ (or32_function_ok_for_sibcall): Suppress sibcall optimization if
+ the sibcall register might not be available.
+
+ * config/or32/or32.c (or32_expand_prologue): Fix threshold for
+ loading the frame size into a register.
+
+ * config/or32/or32.md (SP_REG, FP_REG, UNSPEC_FRAME): New constants.
+ (frame_dealloc_fp, frame_dealloc_sp): New insn patterns.
+ * config/or32/or32.c (or32_expand_epilogue): Use frame_dealloc_[fs]p.
+
+2010-11-01 Joern Rennecke <joern.rennecke@embecosm.com>
+
+ * config/or32/or32.h (HANDLE_PRAGMA_PACK_PUSH_POP): Define.
+
+ * config/or32/t-linux ($(T)crtbegin.o): Rename __dso_handle.
+
+ (crtbegin$(objext)): Likewise.
+
+2010-10-31 Joern Rennecke <joern.rennecke@embecosm.com>
+
+ * config/or32/or32.c (or32_struct_alignment): Refine rules to
+ avoid overriding user settings.
+
+ * Don't increase alignment of struct with sole packed field.
+
+2010-10-29 Joern Rennecke <joern.rennecke@embecosm.com>
+
+ * config/or32/or32.c (or32_output_mi_thunk): New function.
+ (or32_output_highadd, or32_output_tailcall): Likewise.
+ (TARGET_ASM_OUTPUT_MI_THUNK): Redefine.
+ (TARGET_ASM_CAN_OUTPUT_MI_THUNK): Likewise.
+
+ (or32_output_mi_thunk): Don't emit add of zero delta.
+
+ * config/or32/or32.opt: Remove -maj option.
+ * config/or32/or32.md, config/or32/or32.c: Likewise.
+
+ * config.gcc: Add Embecosm Copyright notice.
+ * config/or32/predicates.md: Likewise.
+ * config/or32/or32.md: Likewise.
+ * config/or32/t-or32: Likewise.
+ * config/or32/or32.opt: Likewise.
+ * config/or32/or32-protos.h: Likewise.
+ * config/or32/crti.S: Likewise.
+ * config/or32/or32.c: Likewise.
+ * config/or32/constraints.md: Likewise.
+ * config/or32/crtn.S: Likewise.
+ * config/or32/default.h: Likewise.
+ * config/or32/or32.h: Likewise.
+
+2010-10-28 Joern Rennecke <joern.rennecke@embecosm.com>
+
+ * config/or32/or32.md (movsi_lo_sum, movsi_high): Enable generator
+ function generation.
+ (movsi_insn_big): Now define_insn_and_split.
+
+ * config.gcc (or32-*-elf*): Change extra_parts to:
+ "crti.o crtbegin.o crtend.o crtn.o".
+ ( or32-*linux*): Change tmake_file to
+ "${cpu_type}/t-${cpu_type} or32/t-linux"
+ * config/or32/t-default, config/or32/initfini.c: Delete.
+ * t-or32 ((T)or32-crtbegin.o, $(T)or32-crtend.o): Replace with:
+ ((T)crti.o, $(T)crtn.o).
+ * config/or32/t-linux: New file.
+ * config/or32/crti.S, config/or32/crtn.S: Likewise.
+ * config/or32/or32.h (STARTFILE_SPEC): Replace or32-crtbegin.o%s with
+ crti.o%s crtbegin.o%s.
+ (ENDFILE_SPEC): Set to crtend.o%s crtn.o%s.
+
+ * config/or32/elf.h (DBX_DEBUGGING_INFO): Don't redefine.
+ (PREFERRED_DEBUGGING_TYPE, PUT_SDB_DEF): Likewise.
+
+ * config/or32/or32.md (tablejump): For -fpic, emit add of table base.
+
+2010-10-26 Joern Rennecke <joern.rennecke@embecosm.com>
+
+ * config.gcc (or32-*-elf*): Rename crtinit.o / crtfini.o
+ to or32-crtbegin.o / or32-crtend.o.
+ * config/or32/t-default, config/or32/t-or32 (Entire file): Likewise.
+ * config/or32/initfini.c, config/or32/or32.h: Likewise.
+
+2010-10-26 Joern Rennecke <joern.rennecke@embecosm.com>
+
+ * config/or32/or32.opt Mask(MASK_SCHED_LOGUE): Renamed to
+ Mask(SCHED_LOGUE). Changed all users.
+ (-msibcall): Delete option.
+ * config/or32/or32.md (sibcall, sibcall_value, sibcall_internal): Make
+ patterns unconditional.
+ (sibcall_internal): Change alternatives to handle callee-saved
+ registers correctly.
+ * config/or32/or32.c (or32_compute_frame_size): Place register save
+ area at bottom of frame.
+ (or32_expand_prologue): Initialize frame pointer from stack pointer.
+ For large offsets, add a REG_FRAME_RELATED_EXPR note.
+ (or32_expand_epilogue): Restore stack pointer from frame pointer.
+ sibcall is now the sibcall epilogue insn to be split.
+ (or32_compute_frame_size, or32_expand_prologue, or32_expand_epilogue):
+ Use PROLOGUE_TMP and EPILOGUE_TMP.
+ (or32_function_ok_for_sibcall): Retrun true.
+ (TARGET_DEFAULT_TARGET_FLAGS): Include MASK_SCHED_LOGUE.
+ (PROLOGUE_TMP, EPILOGUE_TMP): Define.
+ * config/or32/or32.md (CC_REG): New constant. Use it to denote
+ register number of flags register.
+ Include constraints.md.
+ * config/or32/predicates.md (cc_reg_operand): Use CC_REG.
+ (input_operand): Use satisfies_constraint_[KMI].
+ * config/or32/or32-protos.h (or32_initial_elimination_offset): Declare.
+ (or32_print_jump_restore): Declare.
+ * config/or32/or32.h (OR32_LAST_ACTUAL_REG): Define. Use in place of
+ OR32_LAST_INT_REG to iterate through registers where appropriate.
+ (ELIMINABLE_REGS, INITIAL_ELIMINATION_OFFSET): Define.
+ (ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM): Define as fake hard
+ registers.
+ (FIXED_REGISTERS, CALL_USED_REGISTERS, REG_CLASS_CONTENTS): Update.
+ (REGNO_REG_CLASS, REGISTER_NAMES): : Likewise.
+ * config/or32/or32.c: Use HARD_FRAME_POINTER_REGNUM /
+ hard_frame_pointer_rtx to refer to the hard frame pointer.
+ (or32_emit_move): Now static.
+ (or32_print_jump_restore): New function.
+ (or32_compute_frame_size): Distinguish between saving the hard frame
+ pointer and saving the GPR with the regno of the eliminated frame
+ pointer.
+ (indexed_memory): Delete.
+ (stack_disp_mem): New function.
+ (or32_compute_frame_size): Avoid over-wide shifts.
+ (or32_output_function_prologue): Likewise.
+ (or32_output_function_epilogue): Likewise.
+ (or32_frame_pointer_required): Comment out.
+ (or32_initial_elimination_offset): New function.
+ (TARGET_FRAME_POINTER_REQUIRED): Don't redefine.
+ (PRINT_OPERAND): Handle %J.
+ * config/or32/constraints.md: New file.
+
+2010-10-25 Joern Rennecke <joern.rennecke@embecosm.com>
+
+ * config/or32/or32-protos.h (get_hard_reg_initial_val): Declare.
+ * config/or32/or32.h (INCOMING_RETURN_ADDR_RTX): Fix register number.
+ * (RETURN_ADDR_RTX): Define.
+
+2010-10-12 Joern Rennecke <joern.rennecke@embecosm.com>
+
+ * config/or32/or32.c (or32_struct_alignment): Round up alignment to
+ power of two.
+
+ For unions, use maximum of field size for size estimate.
+
+2010-10-11 Joern Rennecke <joern.rennecke@embecosm.com>
+
+ * config/or32/or32.opt (mpadstruct): New option.
+ * config/or32/or32-protos.h (or32_struct_alignment): Declare.
+ (or32_data_alignment): Likewise.
+ * config/or32/or32.c (or32_struct_alignment): New function.
+ (or32_data_alignment): Likewise.
+ * config/or32/or32.h (STRUCTURE_SIZE_BOUNDARY): Default to 8.
+ (ROUND_TYPE_ALIGN, DATA_ALIGNMENT, LOCAL_ALIGNMENT): Define.
+
+ * config/or32/or32.c (or32_struct_alignment): Take
+ maximum_field_alignment into account.
+
+2010-09-14 Joern Rennecke <joern.rennecke@embecosm.com>
+
+ * config/or32/or32.h (ASM_OUTPUT_ADDR_DIFF_ELT): Fix typo.
+ (JUMP_TABLES_IN_TEXT_SECTION): Define.
+ * config/or32/default.h (JUMP_TABLES_IN_TEXT_SECTION): Use flag_pic.
+
+2010-09-13 Joern Rennecke <joern.rennecke@embecosm.com>
+
+ * config/or32/or32.h (TRAMPOLINE_SIZE): Use result of
+ or32_trampoline_code_size rather than its address.
+
+ * config/or32/initfini.c (init): Rename to:
+ (__init).
+ * config/or32/or32.c (or32_trampoline_init): Don't clobber r12.
+
+ * config.gcc (or32-*-elf*): Add newlib-stdint.h to tm_file.
+
+2010-09-05 Jeremy Bennett <jeremy.bennett@embecosm.com>
+
+ * BASE_VER: Updated for gcc-4.5.1-or32-1.0rc1.
+
+2010-09-05 Jeremy Bennett <jeremy.bennett@embecosm.com>
+
+ * config/or32/or32-protos.c <or32_trampoline_code_size>: Added.
+ * config/or32/or32.c <TARGET_DEFAULT_TARGET_FLAGS>: Added.
+ * config/or32/or32.h <TARGET_DEFAULT>: Deleted.
+ * doc/contrib.texi: Updated for OpenRISC.
+ * doc/invoke.texi: Updated for OpenRISC.
+
+2010-09-04 Jeremy Bennett <jeremy.bennett@embecosm.com>
+
+ * config/or32/or32-protos.c <or32_trampoline_code_size>: Added.
+ * config/or32/or32.c <OR32_MOVHI, OR32_ORI, OR32_LWZ, OR32_JR>:
+ New macros added.
+ (or32_emit_mode, or32_emit_binary, or32_force_binary)
+ (or32_trampoline_code_size, or32_trampoline_init): Created.
+ (or32_output_bf): Tabbing fixed.
+ <TARGET_TRAMPOLINE_INIT>: Definition added.
+ * config/or32/or32.h <STATIC_CHAIN_REGNUM>: Uses R11.
+ <TRAMPOLINE_SIZE>: redefined.
+ <TRAMPOLINE_ENVIRONMENT>: Added definition.
+
+2010-09-01 Jeremy Bennett <jeremy.bennett@embecosm.com>
+
+ * haifa-sched.c (initiate_bb_reg_pressure_info): Declaration of i
+ made conditional to avoid warning.
+ * or32.c: Updated for compatibility with GCC 4.5.1. Redundant
+ functions remobed. Now contains all target hooks.
+ * or32.h: Complete rewrite for compatibility with GCC
+ 4.5.1. Removed all target hooks.
+ * or32.md: Rewrite for compatibility with GCC 4.5.1.
+ * or32-protos.h: Updated to match or32.c.
+
+2010-09-01 Jeremy Bennett <jeremy.bennett@embecosm.com>
+
+ * .: All files updated to GCC 4.5.1 base.
+
+2010-08-26 mirekez <mirekez@gmail.com>
+
+ * config/or32/or32.h <enum reg_class>: CR_REGS removed from
+ enumeration.
+
+2010-08-26 Jeremy Bennett <jeremy.bennett@embecosm.com>
+
+ * vec.h: All references to VEC_TA_GTY with an empty fourth
+ argument replaced by VEC_TA_GTY_ANON with only three arguments
+ <VEC_TA_GTY_ANON>: Created.
+
+2010-08-25 Jeremy Bennett <jeremy.bennett@embecosm.com>
+
+ * config/or32/elf.h <DWARF2_DEBUGGING_INFO>: Defined.
+ <PREFERRED_DEBUGGING_TYPE>: Changed to DWARF2_DEBUG.
+ <PUT_SDB_DEF>: Deleted.
+ * config/or32/or32.h: Obsolete code surrounded by "#if 0" removed
+ for clarity.
+ <SDB_DELIM>: Definition deleted.
+ <DBX_CONTIN_LENGTH, DBX_CONTIN_CHAR, DBX_REGISTER_NUMBER>:
+ Definition deleted (default suffices).
+ <DWARF2_UNWIND_INFO, DWARF2_FRAME_INFO>: Defined.
+ <DWARF2_ASM_LINE_DEBUG_INFO, INCOMIN_RETURN_ADDR_RTX>: Defined.
+ * config/or32/or32.md: Commenting clarified. Obsolete code for
+ define_function_unit deleted.
+
+2010-08-19 Jeremy Bennett <jeremy.bennett@embecosm.com>
+
+ * config/or32/elf.h <PUT_SDB_DEF>: Definition removed.
+ <USER_LABEL_PREFIX>: Modified to match or32.h
+ * config/or32/linux-elf.h<USER_LABEL_PREFIX>: Modified to match
+ or32.h
+ * config/or32/or32.h <LIB_SPEC>: Changed to use free instead of
+ _free to match change in USER_LABEL_PREFIX.
+ <USER_LABEL_PREFIX>: Changed from "_" to "".
+ <ASM_OUTPUT_FUNCTION_PREFIX>: Surround .proc by tab chars.
+ * config/or32/or32.S (__mulsi3, __udivsi3, __divsi3, __umodsi3)
+ (__modsi3): Changed from ___mulsi3, ___udivsi3, ___divsi3,
+ ___umodsi3 and ___modsi3 respectively to match change in
+ USER_LABEL_PREFIX.
+
+2010-07-20 Jeremy Bennett <jeremy.bennett@embecosm.com>
+
+ * config/or32/or32.h: Updated LIB_SPEC for newlib 1.18.0 to force
+ linking of _malloc and _free against a weak reference also when
+ using -lg.
+
+2010-07-19 Jeremy Bennett <jeremy.bennett@embecosm.com>
+
+ * config/or32/or32.h: Updated LIB_SPEC for newlib 1.18.0 to force
+ linking of _malloc and _free against a weak reference.
+
+2010-07-17 Jeremy Bennett <jeremy.bennett@embecosm.com>
+
+ * config/or32/or32.h: Updated STARTFILE_SPEC and LIB_SPEC
+ definition for newlib.
+
+2010-07-16 Jeremy Bennett <jeremy.bennett@embecosm.com>
+
+ * config/or32/or32.h: Updated SPEC definitions to pick up newlib
+ in custom location.
+
+2010-07-13 Jeremy Bennett <jeremy.bennett@embecosm.com>
+
+ * config/or32/initfini.c: Corrected assembler sequences.
+
+2010-07-07 Jeremy Bennett <jeremy.bennett@embecosm.com>
+
+ * config.gcc: Specified cpu_type for or32. Corrected templates
+ specified for or32-*-elf*. Added extra_parts for
+ or32-*-elf*. Specified t-or32 as tmake_file for or32-*-elf*.
+ * config/or32/initfini.c: Created.
+ * config/or32/or32.h <LINK_SPEC>: Removed.
+ <STARTFILE_SPEC>: Add crtinit.o.
+ <ENDFILE_SPEC>: Just specify crtfini.o.
+ <LIB_SPEC>: Unified multiple definitions. Added newlib library
+ when specified.
+ * config/or32/or32.opt <mor32-newlib-uart>: New option added.
+ * config/or32/t-default: Added details for crtinit and crtfini.
+ * config/or32/t-or32: Added details for crtinit and crtfini.
+
+2010-06-30 Jeremy Bennett <jeremy.bennett@embecosm.com>
+
+ * config/or32/or32.h <FUNCTION_PROFILER>: Corrected definition.
+ <LINK_SPEC>: Pick up newlib specific linker script.
+ <ENDFILE_SPEC>: Specify newlib library.
+ * config/or32/or32.opt <mor32-newlib>: New option added.
+
+2010-06-21 Jeremy Bennett <jeremy.bennett@embecosm.com>
+
+ * config/or32/or32.md: Duplicate define_insn of "movdf" and "movsf"
+ removed.
+
+2010-06-17 Jungsook yang <jungsook.yang@uci.edu>
+
+ * config/or32/or32.c (or32_expand_branch): Added SFmode case.
+ * config/or32/or32.md <define_expand "*cmpsf">: Added.
+ <define_expand "*cmpsf_eq">: Added.
+ <define_expand "*cmpsf_ne">: Added.
+ <define_expand "*cmpsf_gt">: Added.
+ <define_expand "*cmpsf_ge">: Added.
+ <define_expand "*cmpsf_lt">: Added.
+ <define_expand "*cmpsf_le">: Added.
+ <define_insn "movdf">: Added.
+ <define_insn "movsf">: Added.
+ <define_insn "adddf3">: Added TARGET_DOUBLE_FLOAT.
+ <define_insn "subdf3">: Added TARGET_DOUBLE_FLOAT.
+ <define_insn "muldf3">: Added TARGET_DOUBLE_FLOAT.
+ <define_insn "divdf3">: Added TARGET_DOUBLE_FLOAT.
+ <define_insn "floatsisf2">: Added.
+ <define_insn "fixunssfsi2">: Added.
+ <define_insn "movdf">: Added.
+ <define_insn "movsf">: Added.
+ * config/or32/or32.opt: mdouble-float option added.
+
diff --git a/gcc/ada/s-osinte-posix.adb b/gcc/ada/s-osinte-posix.adb
index 6bcc722..2774f92 100644
--- a/gcc/ada/s-osinte-posix.adb
+++ b/gcc/ada/s-osinte-posix.adb
@@ -103,7 +103,7 @@ package body System.OS_Interface is
end if;
return timespec'(tv_sec => S,
- tv_nsec => long (Long_Long_Integer (F * 10#1#E9)));
+ tv_nsec => time_t (Long_Long_Integer (F * 10#1#E9)));
end To_Timespec;
end System.OS_Interface;
diff --git a/gcc/common.opt b/gcc/common.opt
index 1218a71..f219908 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1489,6 +1489,10 @@ fipa-icf-variables
Common Report Var(flag_ipa_icf_variables)
Perform Identical Code Folding for variables
+fipa-sem-equality
+Common Report Var(flag_ipa_sem_equality) Iinit(1) Optimization
+Perform Semantic function equality
+
fipa-reference
Common Report Var(flag_ipa_reference) Init(0) Optimization
Discover readonly and non addressable static variables
diff --git a/gcc/common/config/or1k/or1k-common.c b/gcc/common/config/or1k/or1k-common.c
new file mode 100644
index 0000000..d91cc1f
--- /dev/null
+++ b/gcc/common/config/or1k/or1k-common.c
@@ -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
+ <http://www.gnu.org/licenses/>. */
+
+#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 --git a/gcc/config.gcc b/gcc/config.gcc
index c835734..ed53d3e 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -429,6 +429,12 @@ nios2-*-*)
nvptx-*-*)
cpu_type=nvptx
;;
+or1k-*-*)
+ cpu_type=or1k
+ ;;
+or1knd-*-*)
+ cpu_type=or1k
+ ;;
powerpc*-*-*)
cpu_type=rs6000
extra_headers="ppc-asm.h altivec.h spe.h ppu_intrinsics.h paired.h spu2vmx.h vec_types.h si2vmx.h htmintrin.h htmxlintrin.h"
@@ -575,7 +581,7 @@ case ${target} in
esac
# Common C libraries.
-tm_defines="$tm_defines LIBC_GLIBC=1 LIBC_UCLIBC=2 LIBC_BIONIC=3"
+tm_defines="$tm_defines LIBC_GLIBC=1 LIBC_UCLIBC=2 LIBC_BIONIC=3 LIBC_MUSL=4"
# 32-bit x86 processors supported by --with-arch=. Each processor
# MUST be separated by exactly one space.
@@ -720,6 +726,9 @@ case ${target} in
*-*-*uclibc*)
tm_defines="$tm_defines DEFAULT_LIBC=LIBC_UCLIBC"
;;
+ *-*-*musl*)
+ tm_defines="$tm_defines DEFAULT_LIBC=LIBC_MUSL"
+ ;;
*)
tm_defines="$tm_defines DEFAULT_LIBC=LIBC_GLIBC"
;;
@@ -2244,6 +2253,34 @@ nvptx-*)
tm_file="${tm_file} nvptx/offload.h"
fi
;;
+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 ${cpu_type}/elf.h"
+ tm_file="${tm_file} newlib-stdint.h or1k/rtems.h rtems.h"
+ extra_parts="crti.o crtbegin.o crtend.o crtn.o"
+ 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"
+ ;;
pdp11-*-*)
tm_file="${tm_file} newlib-stdint.h"
use_gcc_stdint=wrap
@@ -2413,6 +2450,10 @@ powerpc*-*-linux*)
powerpc*-*-linux*paired*)
tm_file="${tm_file} rs6000/750cl.h" ;;
esac
+ case ${target} in
+ *-linux*-musl*)
+ enable_secureplt=yes ;;
+ esac
if test x${enable_secureplt} = xyes; then
tm_file="rs6000/secureplt.h ${tm_file}"
fi
diff --git a/gcc/config/aarch64/aarch64-linux.h b/gcc/config/aarch64/aarch64-linux.h
index 257acf0..4361edd 100644
--- a/gcc/config/aarch64/aarch64-linux.h
+++ b/gcc/config/aarch64/aarch64-linux.h
@@ -29,6 +29,8 @@
#undef CC1_SPEC
#define CC1_SPEC GNU_USER_TARGET_CC1_SPEC ASAN_CC1_SPEC
+#define MUSL_DYNAMIC_LINKER "/lib/ld-musl-aarch64.so.1"
+
#define CPP_SPEC "%{pthread:-D_REENTRANT}"
#define LINUX_TARGET_LINK_SPEC "%{h*} \
diff --git a/gcc/config/arm/linux-eabi.h b/gcc/config/arm/linux-eabi.h
index e9d65dc..f12e6bd 100644
--- a/gcc/config/arm/linux-eabi.h
+++ b/gcc/config/arm/linux-eabi.h
@@ -77,6 +77,23 @@
%{mfloat-abi=soft*:" GLIBC_DYNAMIC_LINKER_SOFT_FLOAT "} \
%{!mfloat-abi=*:" GLIBC_DYNAMIC_LINKER_DEFAULT "}"
+/* For ARM musl currently supports four dynamic linkers:
+ - ld-musl-arm.so.1 - for the EABI-derived soft-float ABI
+ - ld-musl-armhf.so.1 - for the EABI-derived hard-float ABI
+ - ld-musl-armeb.so.1 - for the EABI-derived soft-float ABI, EB
+ - ld-musl-armebhf.so.1 - for the EABI-derived hard-float ABI, EB
+ musl does not support the legacy OABI mode.
+ All the dynamic linkers live in /lib.
+ We default to soft-float, EL. */
+#undef MUSL_DYNAMIC_LINKER
+#if TARGET_BIG_ENDIAN_DEFAULT
+#define MUSL_DYNAMIC_LINKER_E "%{mlittle-endian:;:eb}"
+#else
+#define MUSL_DYNAMIC_LINKER_E "%{mbig-endian:eb}"
+#endif
+#define MUSL_DYNAMIC_LINKER \
+ "/lib/ld-musl-arm" MUSL_DYNAMIC_LINKER_E "%{mfloat-abi=hard:hf}.so.1"
+
/* At this point, bpabi.h will have clobbered LINK_SPEC. We want to
use the GNU/Linux version, not the generic BPABI version. */
#undef LINK_SPEC
diff --git a/gcc/config/i386/linux.h b/gcc/config/i386/linux.h
index a100963..836a97a 100644
--- a/gcc/config/i386/linux.h
+++ b/gcc/config/i386/linux.h
@@ -21,3 +21,4 @@ along with GCC; see the file COPYING3. If not see
#define GNU_USER_LINK_EMULATION "elf_i386"
#define GLIBC_DYNAMIC_LINKER "/lib/ld-linux.so.2"
+#define MUSL_DYNAMIC_LINKER "/lib/ld-musl-i386.so.1"
diff --git a/gcc/config/i386/linux64.h b/gcc/config/i386/linux64.h
index a27d3be..cba322b 100644
--- a/gcc/config/i386/linux64.h
+++ b/gcc/config/i386/linux64.h
@@ -30,3 +30,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define GLIBC_DYNAMIC_LINKER32 "/lib/ld-linux.so.2"
#define GLIBC_DYNAMIC_LINKER64 "/lib64/ld-linux-x86-64.so.2"
#define GLIBC_DYNAMIC_LINKERX32 "/libx32/ld-linux-x32.so.2"
+
+#define MUSL_DYNAMIC_LINKER32 "/lib/ld-musl-i386.so.1"
+#define MUSL_DYNAMIC_LINKER64 "/lib/ld-musl-x86_64.so.1"
+#define MUSL_DYNAMIC_LINKERX32 "/lib/ld-musl-x32.so.1"
diff --git a/gcc/config/linux.h b/gcc/config/linux.h
index 857389a..e2aba96 100644
--- a/gcc/config/linux.h
+++ b/gcc/config/linux.h
@@ -32,10 +32,12 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define OPTION_GLIBC (DEFAULT_LIBC == LIBC_GLIBC)
#define OPTION_UCLIBC (DEFAULT_LIBC == LIBC_UCLIBC)
#define OPTION_BIONIC (DEFAULT_LIBC == LIBC_BIONIC)
+#define OPTION_MUSL (DEFAULT_LIBC == LIBC_MUSL)
#else
#define OPTION_GLIBC (linux_libc == LIBC_GLIBC)
#define OPTION_UCLIBC (linux_libc == LIBC_UCLIBC)
#define OPTION_BIONIC (linux_libc == LIBC_BIONIC)
+#define OPTION_MUSL (linux_libc == LIBC_MUSL)
#endif
#define GNU_USER_TARGET_OS_CPP_BUILTINS() \
@@ -53,18 +55,21 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
uClibc or Bionic is the default C library and whether
-muclibc or -mglibc or -mbionic has been passed to change the default. */
-#define CHOOSE_DYNAMIC_LINKER1(LIBC1, LIBC2, LIBC3, LD1, LD2, LD3) \
- "%{" LIBC2 ":" LD2 ";:%{" LIBC3 ":" LD3 ";:" LD1 "}}"
+#define CHOOSE_DYNAMIC_LINKER1(LIBC1, LIBC2, LIBC3, LIBC4, LD1, LD2, LD3, LD4) \
+ "%{" LIBC2 ":" LD2 ";:%{" LIBC3 ":" LD3 ";:%{" LIBC4 ":" LD4 ";:" LD1 "}}}"
#if DEFAULT_LIBC == LIBC_GLIBC
-#define CHOOSE_DYNAMIC_LINKER(G, U, B) \
- CHOOSE_DYNAMIC_LINKER1 ("mglibc", "muclibc", "mbionic", G, U, B)
+#define CHOOSE_DYNAMIC_LINKER(G, U, B, M) \
+ CHOOSE_DYNAMIC_LINKER1 ("mglibc", "muclibc", "mbionic", "mmusl", G, U, B, M)
#elif DEFAULT_LIBC == LIBC_UCLIBC
-#define CHOOSE_DYNAMIC_LINKER(G, U, B) \
- CHOOSE_DYNAMIC_LINKER1 ("muclibc", "mglibc", "mbionic", U, G, B)
+#define CHOOSE_DYNAMIC_LINKER(G, U, B, M) \
+ CHOOSE_DYNAMIC_LINKER1 ("muclibc", "mglibc", "mbionic", "mmusl", U, G, B, M)
#elif DEFAULT_LIBC == LIBC_BIONIC
-#define CHOOSE_DYNAMIC_LINKER(G, U, B) \
- CHOOSE_DYNAMIC_LINKER1 ("mbionic", "mglibc", "muclibc", B, G, U)
+#define CHOOSE_DYNAMIC_LINKER(G, U, B, M) \
+ CHOOSE_DYNAMIC_LINKER1 ("mbionic", "mglibc", "muclibc", "mmusl", B, G, U, M)
+#elif DEFAULT_LIBC == LIBC_MUSL
+#define CHOOSE_DYNAMIC_LINKER(G, U, B, M) \
+ CHOOSE_DYNAMIC_LINKER1 ("mmusl", "mglibc", "muclibc", "mbionic", M, G, U, B)
#else
#error "Unsupported DEFAULT_LIBC"
#endif /* DEFAULT_LIBC */
@@ -84,21 +89,92 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define GNU_USER_DYNAMIC_LINKER \
CHOOSE_DYNAMIC_LINKER (GLIBC_DYNAMIC_LINKER, UCLIBC_DYNAMIC_LINKER, \
- BIONIC_DYNAMIC_LINKER)
+ BIONIC_DYNAMIC_LINKER, MUSL_DYNAMIC_LINKER)
#define GNU_USER_DYNAMIC_LINKER32 \
CHOOSE_DYNAMIC_LINKER (GLIBC_DYNAMIC_LINKER32, UCLIBC_DYNAMIC_LINKER32, \
- BIONIC_DYNAMIC_LINKER32)
+ BIONIC_DYNAMIC_LINKER32, MUSL_DYNAMIC_LINKER32)
#define GNU_USER_DYNAMIC_LINKER64 \
CHOOSE_DYNAMIC_LINKER (GLIBC_DYNAMIC_LINKER64, UCLIBC_DYNAMIC_LINKER64, \
- BIONIC_DYNAMIC_LINKER64)
+ BIONIC_DYNAMIC_LINKER64, MUSL_DYNAMIC_LINKER64)
#define GNU_USER_DYNAMIC_LINKERX32 \
CHOOSE_DYNAMIC_LINKER (GLIBC_DYNAMIC_LINKERX32, UCLIBC_DYNAMIC_LINKERX32, \
- BIONIC_DYNAMIC_LINKERX32)
+ BIONIC_DYNAMIC_LINKERX32, MUSL_DYNAMIC_LINKERX32)
/* Whether we have Bionic libc runtime */
#undef TARGET_HAS_BIONIC
#define TARGET_HAS_BIONIC (OPTION_BIONIC)
+/* musl avoids problematic includes by rearranging the include directories.
+ * Unfortunately, this is mostly duplicated from cppdefault.c */
+#if DEFAULT_LIBC == LIBC_MUSL
+#define INCLUDE_DEFAULTS_MUSL_GPP \
+ { GPLUSPLUS_INCLUDE_DIR, "G++", 1, 1, \
+ GPLUSPLUS_INCLUDE_DIR_ADD_SYSROOT, 0 }, \
+ { GPLUSPLUS_TOOL_INCLUDE_DIR, "G++", 1, 1, \
+ GPLUSPLUS_INCLUDE_DIR_ADD_SYSROOT, 1 }, \
+ { GPLUSPLUS_BACKWARD_INCLUDE_DIR, "G++", 1, 1, \
+ GPLUSPLUS_INCLUDE_DIR_ADD_SYSROOT, 0 },
+
+#ifdef LOCAL_INCLUDE_DIR
+#define INCLUDE_DEFAULTS_MUSL_LOCAL \
+ { LOCAL_INCLUDE_DIR, 0, 0, 1, 1, 2 }, \
+ { LOCAL_INCLUDE_DIR, 0, 0, 1, 1, 0 },
+#else
+#define INCLUDE_DEFAULTS_MUSL_LOCAL
+#endif
+
+#ifdef PREFIX_INCLUDE_DIR
+#define INCLUDE_DEFAULTS_MUSL_PREFIX \
+ { PREFIX_INCLUDE_DIR, 0, 0, 1, 0, 0},
+#else
+#define INCLUDE_DEFAULTS_MUSL_PREFIX
+#endif
+
+#ifdef CROSS_INCLUDE_DIR
+#define INCLUDE_DEFAULTS_MUSL_CROSS \
+ { CROSS_INCLUDE_DIR, "GCC", 0, 0, 0, 0},
+#else
+#define INCLUDE_DEFAULTS_MUSL_CROSS
+#endif
+
+#ifdef TOOL_INCLUDE_DIR
+#define INCLUDE_DEFAULTS_MUSL_TOOL \
+ { TOOL_INCLUDE_DIR, "BINUTILS", 0, 1, 0, 0},
+#else
+#define INCLUDE_DEFAULTS_MUSL_TOOL
+#endif
+
+#ifdef NATIVE_SYSTEM_HEADER_DIR
+#define INCLUDE_DEFAULTS_MUSL_NATIVE \
+ { NATIVE_SYSTEM_HEADER_DIR, 0, 0, 0, 1, 2 }, \
+ { NATIVE_SYSTEM_HEADER_DIR, 0, 0, 0, 1, 0 },
+#else
+#define INCLUDE_DEFAULTS_MUSL_NATIVE
+#endif
+
+#if defined (CROSS_DIRECTORY_STRUCTURE) && !defined (TARGET_SYSTEM_ROOT)
+# undef INCLUDE_DEFAULTS_MUSL_LOCAL
+# define INCLUDE_DEFAULTS_MUSL_LOCAL
+# undef INCLUDE_DEFAULTS_MUSL_NATIVE
+# define INCLUDE_DEFAULTS_MUSL_NATIVE
+#else
+# undef INCLUDE_DEFAULTS_MUSL_CROSS
+# define INCLUDE_DEFAULTS_MUSL_CROSS
+#endif
+
+#undef INCLUDE_DEFAULTS
+#define INCLUDE_DEFAULTS \
+ { \
+ INCLUDE_DEFAULTS_MUSL_GPP \
+ INCLUDE_DEFAULTS_MUSL_PREFIX \
+ INCLUDE_DEFAULTS_MUSL_CROSS \
+ INCLUDE_DEFAULTS_MUSL_TOOL \
+ INCLUDE_DEFAULTS_MUSL_NATIVE \
+ { GCC_INCLUDE_DIR, "GCC", 0, 1, 0, 0 }, \
+ { 0, 0, 0, 0, 0, 0 } \
+ }
+#endif
+
#if (DEFAULT_LIBC == LIBC_UCLIBC) && defined (SINGLE_LIBC) /* uClinux */
/* This is a *uclinux* target. We don't define below macros to normal linux
versions, because doing so would require *uclinux* targets to include
diff --git a/gcc/config/linux.opt b/gcc/config/linux.opt
index c054338..9334f74 100644
--- a/gcc/config/linux.opt
+++ b/gcc/config/linux.opt
@@ -30,3 +30,7 @@ Use GNU C library
muclibc
Target Report RejectNegative Var(linux_libc,LIBC_UCLIBC) Negative(mbionic)
Use uClibc C library
+
+mmusl
+Target Report RejectNegative Var(linux_libc,LIBC_MUSL) Negative(mglibc)
+Use musl C library
diff --git a/gcc/config/microblaze/linux.h b/gcc/config/microblaze/linux.h
index 655a70f..de1fcd2 100644
--- a/gcc/config/microblaze/linux.h
+++ b/gcc/config/microblaze/linux.h
@@ -28,7 +28,22 @@
#undef TLS_NEEDS_GOT
#define TLS_NEEDS_GOT 1
-#define DYNAMIC_LINKER "/lib/ld.so.1"
+#if TARGET_BIG_ENDIAN_DEFAULT == 0 /* LE */
+#define MUSL_DYNAMIC_LINKER_E "%{EB:;:el}"
+#else
+#define MUSL_DYNAMIC_LINKER_E "%{EL:el}"
+#endif
+
+#define MUSL_DYNAMIC_LINKER "/lib/ld-musl-microblaze" MUSL_DYNAMIC_LINKER_E ".so.1"
+#define GLIBC_DYNAMIC_LINKER "/lib/ld.so.1"
+
+#if DEFAULT_LIBC == LIBC_MUSL
+#define DYNAMIC_LINKER MUSL_DYNAMIC_LINKER
+#else
+#define DYNAMIC_LINKER GLIBC_DYNAMIC_LINKER
+#endif
+
+
#undef SUBTARGET_EXTRA_SPECS
#define SUBTARGET_EXTRA_SPECS \
{ "dynamic_linker", DYNAMIC_LINKER }
diff --git a/gcc/config/microblaze/microblaze.h b/gcc/config/microblaze/microblaze.h
index faeb780..30ea934 100644
--- a/gcc/config/microblaze/microblaze.h
+++ b/gcc/config/microblaze/microblaze.h
@@ -218,6 +218,12 @@ extern enum pipeline_type microblaze_pipe;
#undef PTRDIFF_TYPE
#define PTRDIFF_TYPE "int"
+#undef SIZE_TYPE
+#define SIZE_TYPE "unsigned int"
+
+#undef PTRDIFF_TYPE
+#define PTRDIFF_TYPE "int"
+
#define CONSTANT_ALIGNMENT(EXP, ALIGN) \
((TREE_CODE (EXP) == STRING_CST || TREE_CODE (EXP) == CONSTRUCTOR) \
&& (ALIGN) < BITS_PER_WORD \
diff --git a/gcc/config/mips/linux.h b/gcc/config/mips/linux.h
index 91df261..6cea86b 100644
--- a/gcc/config/mips/linux.h
+++ b/gcc/config/mips/linux.h
@@ -31,6 +31,13 @@ along with GCC; see the file COPYING3. If not see
#undef UCLIBC_DYNAMIC_LINKER32
#define UCLIBC_DYNAMIC_LINKER32 \
"%{mnan=2008:/lib/ld-uClibc-mipsn8.so.0;:/lib/ld-uClibc.so.0}"
+
+#undef MUSL_DYNAMIC_LINKER32
+#define MUSL_DYNAMIC_LINKER32 "/lib/ld-musl-mips%{EL:el}%{msoft-float:-sf}.so.1"
+#undef MUSL_DYNAMIC_LINKER64
+#define MUSL_DYNAMIC_LINKER64 "/lib/ld-musl-mips64%{EL:el}%{msoft-float:-sf}.so.1"
+#define MUSL_DYNAMIC_LINKERN32 "/lib/ld-musl-mipsn32%{EL:el}%{msoft-float:-sf}.so.1"
+
#undef UCLIBC_DYNAMIC_LINKER64
#define UCLIBC_DYNAMIC_LINKER64 \
"%{mnan=2008:/lib/ld64-uClibc-mipsn8.so.0;:/lib/ld64-uClibc.so.0}"
@@ -40,4 +47,4 @@ along with GCC; see the file COPYING3. If not see
#define BIONIC_DYNAMIC_LINKERN32 "/system/bin/linker32"
#define GNU_USER_DYNAMIC_LINKERN32 \
CHOOSE_DYNAMIC_LINKER (GLIBC_DYNAMIC_LINKERN32, UCLIBC_DYNAMIC_LINKERN32, \
- BIONIC_DYNAMIC_LINKERN32)
+ BIONIC_DYNAMIC_LINKERN32, MUSL_DYNAMIC_LINKERN32)
diff --git a/gcc/config/or1k/constraints.md b/gcc/config/or1k/constraints.md
new file mode 100644
index 0000000..3f8030c
--- /dev/null
+++ b/gcc/config/or1k/constraints.md
@@ -0,0 +1,59 @@
+;; Copyright (C) 2010 Embecosm Limited
+;;
+;; Contributed by Joern Rennecke <joern.rennecke@embecosm.com> 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
+;; <http://www.gnu.org/licenses/>.
+
+(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 --git a/gcc/config/or1k/elf.h b/gcc/config/or1k/elf.h
new file mode 100644
index 0000000..9751ccf
--- /dev/null
+++ b/gcc/config/or1k/elf.h
@@ -0,0 +1,31 @@
+/* Definitions for OpenRISC OR1K using ELF
+ ??? this is for OR1K, but the rest of the above seems bogus.
+ Copyright (C) 1996, 1997, 2005, 2014 Free Software Foundation, Inc.
+ Contributed by Joel Sherrill (joel.sherrill@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 --git a/gcc/config/or1k/linux-elf.h b/gcc/config/or1k/linux-elf.h
new file mode 100644
index 0000000..5437edb
--- /dev/null
+++ b/gcc/config/or1k/linux-elf.h
@@ -0,0 +1,99 @@
+/* Definitions for or1k running Linux-based GNU systems using ELF
+ Copyright (C) 2002, 2005
+ Free Software Foundation, Inc.
+ Contributed by Marko Mlinar <markom@opencores.org>
+
+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 MUSL_DYNAMIC_LINKER "/lib/ld-musl-or1k.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 " \
+ %{rdynamic:-export-dynamic} \
+ %{static:-static} \
+ %{shared:-shared}"
+
diff --git a/gcc/config/or1k/linux-gas.h b/gcc/config/or1k/linux-gas.h
new file mode 100644
index 0000000..4ab6fd6
--- /dev/null
+++ b/gcc/config/or1k/linux-gas.h
@@ -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 <markom@opencores.org>
+
+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 <machine/ansi.h> */
+
+#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 --git a/gcc/config/or1k/or1k-modes.def b/gcc/config/or1k/or1k-modes.def
new file mode 100644
index 0000000..39aedfa
--- /dev/null
+++ b/gcc/config/or1k/or1k-modes.def
@@ -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 --git a/gcc/config/or1k/or1k-opts.h b/gcc/config/or1k/or1k-opts.h
new file mode 100644
index 0000000..c830527
--- /dev/null
+++ b/gcc/config/or1k/or1k-opts.h
@@ -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 --git a/gcc/config/or1k/or1k-protos.h b/gcc/config/or1k/or1k-protos.h
new file mode 100644
index 0000000..7ff38ba
--- /dev/null
+++ b/gcc/config/or1k/or1k-protos.h
@@ -0,0 +1,67 @@
+/* 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
+<http://www.gnu.org/licenses/>. */
+
+#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[]);
+extern void or1k_expand_cmpxchg_qihi (rtx bval, rtx retval,
+ rtx mem, rtx oldval, rtx newval, int is_weak,
+ enum memmodel success_mode, enum memmodel failure_mode);
+extern void or1k_expand_fetch_op_qihi (rtx oldval, rtx mem, rtx operand,
+ rtx newval, rtx (*generator)(rtx, rtx, rtx, rtx, rtx));
+#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 --git a/gcc/config/or1k/or1k.c b/gcc/config/or1k/or1k.c
new file mode 100644
index 0000000..6ec3d57
--- /dev/null
+++ b/gcc/config/or1k/or1k.c
@@ -0,0 +1,2445 @@
+/* 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 <damjanl@bsemi.com> in 1999.
+ Major optimizations by Matjaz Breskvar <matjazb@bsemi.com> in 2005.
+ Updated for GCC 4.5 by Jeremy Bennett <jeremy.bennett@embecoms.com>
+ and Joern Rennecke <joern.rennecke@embecosm.com> 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 <http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "rtl.h"
+#include "hash-set.h"
+#include "inchash.h"
+#include "symtab.h"
+#include "tree.h"
+#include "stringpool.h"
+#include "stor-layout.h"
+#include "calls.h"
+#include "varasm.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 "explow.h"
+#include "emit-rtl.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 "predict.h"
+#include "basic-block.h"
+#include "df.h"
+#include "optabs.h"
+#include "dwarf2.h"
+#include "ansidecl.h"
+#include "builtins.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 () */
+
+
+/* TODO(bluecmd): Write documentation for this function */
+void
+or1k_expand_cmpxchg_qihi (rtx bval, rtx retval, rtx mem, rtx oldval, rtx newval,
+ int __attribute__ ((unused)) is_weak,
+ enum memmodel __attribute__ ((unused)) success_mode,
+ enum memmodel __attribute__ ((unused)) failure_mode)
+{
+ rtx addr1 = force_reg (Pmode, XEXP (mem, 0));
+ rtx addr = gen_reg_rtx (Pmode);
+ rtx off = gen_reg_rtx (SImode);
+ rtx shifter = gen_reg_rtx (SImode);
+ rtx retword = gen_reg_rtx (SImode);
+ rtx mask = gen_reg_rtx (SImode);
+ rtx shifted_oldval = gen_reg_rtx (SImode);
+ rtx shifted_newval = gen_reg_rtx (SImode);
+ rtx shifted_mask = gen_reg_rtx (SImode);
+ rtx mask_const;
+ rtx memsi;
+ enum machine_mode mode = GET_MODE (mem);
+
+ oldval = gen_lowpart_common (SImode, oldval);
+ newval = gen_lowpart_common (SImode, newval);
+
+ mask_const = gen_rtx_CONST_INT (VOIDmode,
+ mode == QImode ? 0xff : 0xffff);
+ emit_insn (gen_rtx_SET (VOIDmode, mask, mask_const));
+
+ /* align address and retrieve the offset. */
+ emit_insn (gen_rtx_SET (VOIDmode, addr,
+ gen_rtx_AND (Pmode, addr1, GEN_INT (-4))));
+ emit_insn (gen_rtx_SET (VOIDmode, off,
+ gen_rtx_AND (SImode, addr1, GEN_INT (3))));
+ emit_insn (gen_rtx_SET (VOIDmode, off,
+ gen_rtx_XOR (SImode, off,
+ GEN_INT (GET_MODE (mem) == QImode
+ ? 3 : 2))));
+
+ memsi = gen_rtx_MEM (SImode, addr);
+
+ /* shift all arguments to be aligned to where the data we want
+ * to operate on is located. */
+ emit_insn (gen_rtx_SET (VOIDmode, shifter,
+ gen_rtx_ASHIFT (SImode, off, GEN_INT (3))));
+
+ emit_insn (gen_ashlsi3 (shifted_oldval, oldval, shifter));
+ emit_insn (gen_ashlsi3 (shifted_newval, newval, shifter));
+ emit_insn (gen_ashlsi3 (shifted_mask, mask, shifter));
+
+ emit_insn (gen_cmpxchg_mask (bval, retword, memsi, shifted_oldval,
+ shifted_newval, shifted_mask));
+
+ /* shift the data we care about to the lower end. */
+ emit_insn (gen_lshrsi3 (retword, retword, shifter));
+
+ emit_move_insn (retval, gen_lowpart (GET_MODE (retval), retword));
+}
+
+/* TODO(bluecmd): Write documentation for this function */
+void
+or1k_expand_fetch_op_qihi (rtx oldval, rtx mem, rtx operand, rtx newval,
+ rtx (*generator)(rtx, rtx, rtx, rtx, rtx))
+{
+ rtx addr1 = force_reg (Pmode, XEXP (mem, 0));
+ rtx addr = gen_reg_rtx (Pmode);
+ rtx off = gen_reg_rtx (SImode);
+ rtx shifter = gen_reg_rtx (SImode);
+ rtx mask = gen_reg_rtx (SImode);
+ rtx shifted_oldval = gen_reg_rtx (SImode);
+ rtx shifted_newval = gen_reg_rtx (SImode);
+ rtx shifted_operand = gen_reg_rtx (SImode);
+ rtx shifted_mask = gen_reg_rtx (SImode);
+ rtx mask_const;
+ rtx memsi;
+ enum machine_mode mode = GET_MODE (mem);
+
+ /* TODO(bluecmd): A lot of code is shared between cmpxchg and this. We should
+ * move it to nice functions. */
+ operand = gen_lowpart_common (SImode, operand);
+
+ mask_const = gen_rtx_CONST_INT (VOIDmode,
+ mode == QImode ? 0xff : 0xffff);
+ emit_insn (gen_rtx_SET (VOIDmode, mask, mask_const));
+
+ /* align address and retrieve the offset. */
+ emit_insn (gen_rtx_SET (VOIDmode, addr,
+ gen_rtx_AND (Pmode, addr1, GEN_INT (-4))));
+ emit_insn (gen_rtx_SET (VOIDmode, off,
+ gen_rtx_AND (SImode, addr1, GEN_INT (3))));
+ emit_insn (gen_rtx_SET (VOIDmode, off,
+ gen_rtx_XOR (SImode, off,
+ GEN_INT (GET_MODE (mem) == QImode
+ ? 3 : 2))));
+
+ memsi = gen_rtx_MEM (SImode, addr);
+
+ /* shift all arguments to be aligned to where the data we want
+ * to operate on is located. */
+ emit_insn (gen_rtx_SET (VOIDmode, shifter,
+ gen_rtx_ASHIFT (SImode, off, GEN_INT (3))));
+
+ emit_insn (gen_ashlsi3 (shifted_operand, operand, shifter));
+ emit_insn (gen_ashlsi3 (shifted_mask, mask, shifter));
+
+ emit_insn (generator (shifted_oldval, memsi, shifted_operand,
+ shifted_newval, shifted_mask));
+
+ /* shift the data we care about to the lower end. */
+ emit_insn (gen_lshrsi3 (shifted_oldval, shifted_oldval, shifter));
+ emit_insn (gen_lshrsi3 (shifted_newval, shifted_newval, shifter));
+ emit_move_insn (oldval, gen_lowpart (GET_MODE (oldval), shifted_oldval));
+ emit_move_insn (newval, gen_lowpart (GET_MODE (newval), shifted_newval));
+}
+
+/* -------------------------------------------------------------------------- */
+/*!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 dest, rtx arg)
+{
+ emit_library_call_value (gen_tls_get_addr(), dest,
+ LCT_CONST, Pmode, 1, arg, Pmode);
+}
+
+static rtx
+or1k_legitimize_tls_address (rtx dest, rtx x)
+{
+ rtx sym;
+ rtx tp = gen_rtx_REG(Pmode, THREAD_PTR_REGNUM);
+ rtx addend = NULL_RTX;
+ rtx result = dest;
+
+ enum tls_model tls_kind = or1k_tls_symbolic_operand (x);
+
+ if (GET_CODE (x) == SYMBOL_REF)
+ sym = gen_rtx_SYMBOL_REF(Pmode, XSTR(x, 0));
+ else if (GET_CODE (x) == CONST)
+ {
+ result = gen_reg_rtx (Pmode);
+ split_const (x, &sym, &addend);
+ sym = gen_rtx_SYMBOL_REF(Pmode, XSTR(sym, 0));
+ }
+ else
+ gcc_unreachable ();
+
+ switch (tls_kind) {
+ case TLS_MODEL_GLOBAL_DYNAMIC:
+ case TLS_MODEL_LOCAL_DYNAMIC:
+ {
+ /* TODO: For now, treat LD as GD */
+ rtx hi = gen_reg_rtx (Pmode);
+ rtx offset = gen_reg_rtx (Pmode);
+ rtx addr = gen_reg_rtx (Pmode);
+ crtl->uses_pic_offset_table = 1;
+ /* Generate a new symbol ref that is not marked as TLS or we will recurse
+ * in or1k_legitimate_constant_p. */
+ emit_insn (gen_movsi_tlsgdhi (hi, sym));
+ emit_insn (gen_movsi_tlsgdlo (offset, hi, sym));
+ emit_insn (gen_add3_insn (addr, offset, pic_offset_table_rtx));
+ or1k_tls_call (result, addr);
+ break;
+ }
+ case TLS_MODEL_INITIAL_EXEC:
+ {
+ rtx hi = gen_reg_rtx (Pmode);
+ rtx offset = gen_reg_rtx (Pmode);
+ rtx addr = gen_reg_rtx (Pmode);
+ rtx tpoffset = gen_reg_rtx (Pmode);
+ crtl->uses_pic_offset_table = 1;
+ emit_insn (gen_movsi_gottpoffhi (hi, sym));
+ emit_insn (gen_movsi_gottpofflo (offset, hi, sym));
+ emit_insn (gen_add3_insn (addr, offset, pic_offset_table_rtx));
+ emit_insn (gen_load_gottpoff (tpoffset, addr));
+ emit_insn (gen_add3_insn (result, tpoffset, tp));
+ break;
+ }
+ case TLS_MODEL_LOCAL_EXEC:
+ {
+ rtx hi = gen_reg_rtx (Pmode);
+ rtx addr = gen_reg_rtx (Pmode);
+ emit_insn (gen_movsi_tpoffhi (hi, sym));
+ emit_insn (gen_movsi_tpofflo (addr, hi, sym));
+ emit_insn (gen_add3_insn (result, addr, tp));
+ break;
+ }
+ default:
+ gcc_unreachable ();
+ }
+
+ if (addend != NULL_RTX)
+ emit_insn (gen_add3_insn (dest, result, addend));
+
+ return dest;
+}
+
+static rtx
+or1k_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
+ enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+ if (or1k_tls_symbolic_operand (x) != TLS_MODEL_NONE)
+ return or1k_legitimize_tls_address (gen_reg_rtx (Pmode), x);
+
+ return x;
+}
+
+static bool
+or1k_cannot_force_const_mem (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
+{
+ return or1k_tls_symbolic_operand (x) != TLS_MODEL_NONE;
+}
+
+bool
+or1k_expand_symbol_ref(enum machine_mode mode, rtx operands[])
+{
+ 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_tls_symbolic_operand (operands[1]) != TLS_MODEL_NONE)
+ {
+ or1k_legitimize_tls_address (force_reg (Pmode, operands[0]),
+ operands[1]);
+ return true;
+ }
+
+ 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 <static chain>
+ .word <nested_function>
+
+ @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_LEGITIMIZE_ADDRESS
+#define TARGET_LEGITIMIZE_ADDRESS or1k_legitimize_address
+
+#undef TARGET_TRAMPOLINE_INIT
+#define TARGET_TRAMPOLINE_INIT or1k_trampoline_init
+
+#undef TARGET_CANNOT_FORCE_CONST_MEM
+#define TARGET_CANNOT_FORCE_CONST_MEM or1k_cannot_force_const_mem
+
+#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)
+{
+ if (or1k_tls_symbolic_operand (x) != TLS_MODEL_NONE)
+ return 0;
+
+ 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 (!tree_fits_uhwi_p (DECL_SIZE (field)))
+ field_size = max_align;
+ else
+ field_size = tree_to_uhwi (DECL_SIZE (field));
+ 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_cleared_alloc<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 --git a/gcc/config/or1k/or1k.h b/gcc/config/or1k/or1k.h
new file mode 100644
index 0000000..3444c57
--- /dev/null
+++ b/gcc/config/or1k/or1k.h
@@ -0,0 +1,1197 @@
+/* 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 <damjanl@bsemi.com> in 1999.
+ Major optimizations by Matjaz Breskvar <matjazb@bsemi.com> 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:%{posix:-D_POSIX_SOURCE} %{pthread:-D_REENTRANT}}"
+
+/* 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
+
+#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
+
+/* 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
+
+/* 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 ASM_PREFERRED_EH_DATA_FORMAT(CODE, GLOBAL) \
+ (flag_pic ? DW_EH_PE_pcrel : DW_EH_PE_absptr)
+
+#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 --git a/gcc/config/or1k/or1k.md b/gcc/config/or1k/or1k.md
new file mode 100644
index 0000000..4855a32
--- /dev/null
+++ b/gcc/config/or1k/or1k.md
@@ -0,0 +1,1599 @@
+;; 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 <damjanl@bsemi.com> in 1999.
+;; Major optimizations by Matjaz Breskvar <matjazb@bsemi.com> in 2005.
+;; Floating point additions by Jungsook Yang <jungsook.yang@uci.edu>
+;; Julius Baxter <julius@orsoc.se> in 2010
+;; Updated for GCC 4.5 by Jeremy Bennett <jeremy.bennett@embecosm.com>
+;; and Joern Rennecke <joern.rennecke@embecosm.com> 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 <http://www.gnu.org/licenses/>. */
+
+(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)
+ (UNSPEC_CMPXCHG 201)
+ (UNSPEC_FETCH_AND_OP 202)
+])
+
+(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")
+
+;; AI = Atomic Integers
+;; We do not support DI in our atomic operations.
+(define_mode_iterator AI [QI HI SI])
+
+;; Note: We use 'mult' here for nand since it does not have its own RTX class.
+(define_code_iterator atomic_op [plus minus and ior xor mult])
+(define_code_attr op_name
+ [(plus "add") (minus "sub") (and "and") (ior "or") (xor "xor") (mult "nand")])
+(define_code_attr op_insn
+ [(plus "add") (minus "sub") (and "and") (ior "or") (xor "xor") (mult "and")])
+(define_code_attr post_op_insn
+ [(plus "") (minus "") (and "") (ior "") (xor "")
+ (mult "l.xori \t%3,%3,0xffff # fetch_nand: invert")])
+
+;; 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 "symbolic_operand" "")] 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 "nonimmediate_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_extend<m><n>2
+;;
+
+(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")])
+
+(define_expand "atomic_compare_and_swap<mode>"
+ [(match_operand:SI 0 "register_operand") ;; bool output
+ (match_operand:AI 1 "register_operand") ;; val output
+ (match_operand:AI 2 "memory_operand") ;; memory
+ (match_operand:AI 3 "register_operand") ;; expected
+ (match_operand:AI 4 "register_operand") ;; desired
+ (match_operand:SI 5 "const_int_operand") ;; is_weak
+ (match_operand:SI 6 "const_int_operand") ;; mod_s
+ (match_operand:SI 7 "const_int_operand")] ;; mod_f
+ ""
+{
+ if (<MODE>mode == SImode)
+ emit_insn (gen_cmpxchg (operands[0], operands[1], operands[2], operands[3],
+ operands[4]));
+ else
+ or1k_expand_cmpxchg_qihi (operands[0], operands[1], operands[2],
+ operands[3], operands[4], INTVAL (operands[5]),
+ (enum memmodel) INTVAL (operands[6]),
+ (enum memmodel) INTVAL (operands[7]));
+ DONE;
+})
+
+(define_insn "cmpxchg"
+ [(set (match_operand:SI 0 "register_operand" "=&r")
+ (unspec_volatile:SI [(match_operand:SI 2 "memory_operand" "+m")]
+ UNSPEC_CMPXCHG))
+ (set (match_dup 2)
+ (unspec_volatile:SI [(match_operand:SI 3 "register_operand" "r")]
+ UNSPEC_CMPXCHG))
+ (set (match_operand:SI 1 "register_operand" "=&r")
+ (unspec_volatile:SI [(match_dup 2) (match_dup 3)
+ (match_operand:SI 4 "register_operand" "r")]
+ UNSPEC_CMPXCHG))]
+ ""
+ "
+ l.lwa \t%1,%2 # cmpxchg: load
+ l.sfeq \t%1,%3 # cmpxchg: cmp
+ l.bnf \t1f # cmpxchg: not expected
+ l.ori \t%0,r0,0 # cmpxchg: result = 0
+ l.swa \t%2,%4 # cmpxchg: store new
+ l.bnf \t1f # cmpxchg: done
+ l.nop
+ l.ori \t%0,r0,1 # cmpxchg: result = 1
+1:")
+
+(define_insn "cmpxchg_mask"
+ [(set (match_operand:SI 0 "register_operand" "=&r")
+ (unspec_volatile:SI [(match_operand:SI 2 "memory_operand" "+m")]
+ UNSPEC_CMPXCHG))
+ (set (match_dup 2)
+ (unspec_volatile:SI [(match_operand:SI 3 "register_operand" "r")]
+ UNSPEC_CMPXCHG))
+ (set (match_operand:SI 1 "register_operand" "=&r")
+ (unspec_volatile:SI [(match_dup 2) (match_dup 3)
+ (match_operand:SI 4 "register_operand" "r")
+ (match_operand:SI 5 "register_operand" "r")]
+ UNSPEC_CMPXCHG))
+ (clobber (match_scratch:SI 6 "=&r"))]
+ ""
+ "
+ l.lwa \t%6,%2 # cmpxchg: load
+ l.and \t%1,%6,%5 # cmpxchg: mask old
+ l.and \t%4,%4,%5 # cmpxchg: mask set
+ l.sfeq \t%1,%3 # cmpxchg: cmp
+ l.bnf \t1f # cmpxchg: not expected
+ l.ori \t%0,r0,0 # cmpxchg: result = 0
+ l.xor \t%6,%6,%1 # cmpxchg: clear
+ l.or \t%6,%6,%4 # cmpxchg: set
+ l.swa \t%2,%6 # cmpxchg: store new
+ l.bnf \t1f # cmpxchg: done
+ l.nop
+ l.ori \t%0,r0,1 # cmpxchg: result = 1
+1:
+ ")
+
+(define_expand "atomic_fetch_<op_name><mode>"
+ [(match_operand:AI 0 "register_operand")
+ (match_operand:AI 1 "memory_operand")
+ (match_operand:AI 2 "register_operand")
+ (match_operand:SI 3 "const_int_operand")
+ (atomic_op:AI (match_dup 0) (match_dup 1))]
+ ""
+{
+ rtx ret = gen_reg_rtx (<MODE>mode);
+ if (<MODE>mode != SImode)
+ or1k_expand_fetch_op_qihi (operands[0], operands[1], operands[2], ret,
+ gen_fetch_and_<op_name>_mask);
+ else
+ emit_insn (gen_fetch_and_<op_name> (operands[0], operands[1], operands[2],
+ ret));
+ DONE;
+})
+
+(define_expand "atomic_<op_name>_fetch<mode>"
+ [(match_operand:AI 0 "register_operand")
+ (match_operand:AI 1 "memory_operand")
+ (match_operand:AI 2 "register_operand")
+ (match_operand:SI 3 "const_int_operand")
+ (atomic_op:AI (match_dup 0) (match_dup 1))]
+ ""
+{
+ rtx ret = gen_reg_rtx (<MODE>mode);
+ if (<MODE>mode != SImode)
+ or1k_expand_fetch_op_qihi (ret, operands[1], operands[2], operands[0],
+ gen_fetch_and_<op_name>_mask);
+ else
+ emit_insn (gen_fetch_and_<op_name> (ret, operands[1], operands[2],
+ operands[0]));
+ DONE;
+})
+
+(define_insn "fetch_and_<op_name>"
+ [(set (match_operand:SI 0 "register_operand" "=&r")
+ (match_operand:SI 1 "memory_operand" "+m"))
+ (set (match_operand:SI 3 "register_operand" "=&r")
+ (unspec_volatile:SI [(match_dup 1)
+ (match_operand:SI 2 "register_operand" "r")]
+ UNSPEC_FETCH_AND_OP))
+ (set (match_dup 1)
+ (match_dup 3))
+ (atomic_op:SI (match_dup 0) (match_dup 1))]
+ ""
+ "
+1:
+ l.lwa \t%0,%1 # fetch_<op_name>: load
+ l.<op_insn>\t\t%3,%0,%2 # fetch_<op_name>: logic
+ <post_op_insn>
+ l.swa \t%1,%3 # fetch_<op_name>: store new
+ l.bnf \t1b # fetch_<op_name>: done
+ l.nop
+ ")
+
+(define_insn "fetch_and_<op_name>_mask"
+ [(set (match_operand:SI 0 "register_operand" "=&r")
+ (match_operand:SI 1 "memory_operand" "+m"))
+ (set (match_operand:SI 3 "register_operand" "=&r")
+ (unspec_volatile:SI [(match_dup 1)
+ (match_operand:SI 2 "register_operand" "r")
+ (match_operand:SI 4 "register_operand" "r")]
+ UNSPEC_FETCH_AND_OP))
+ (set (match_dup 1)
+ (unspec_volatile:SI [(match_dup 3) (match_dup 4)] UNSPEC_FETCH_AND_OP))
+ (clobber (match_scratch:SI 5 "=&r"))
+ (atomic_op:SI (match_dup 0) (match_dup 1))]
+ ""
+ "
+1:
+ l.lwa \t%0,%1 # fetch_<op_name>: load
+ l.and \t%5,%0,%4 # fetch_<op_name>: mask
+ l.xor \t%5,%0,%5 # fetch_<op_name>: clear
+ l.<op_insn>\t\t%3,%0,%2 # fetch_<op_name>: logic
+ <post_op_insn>
+ l.and \t%3,%3,%4 # fetch_<op_name>: mask result
+ l.or \t%3,%5,%3 # fetch_<op_name>: set
+ l.swa \t%1,%3 # fetch_<op_name>: store new
+ l.bnf \t1b # fetch_<op_name>: done
+ l.nop
+ ")
+
+;; 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 --git a/gcc/config/or1k/or1k.opt b/gcc/config/or1k/or1k.opt
new file mode 100644
index 0000000..019d923
--- /dev/null
+++ b/gcc/config/or1k/or1k.opt
@@ -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
+; <http://www.gnu.org/licenses/>.
+
+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 --git a/gcc/config/or1k/predicates.md b/gcc/config/or1k/predicates.md
new file mode 100644
index 0000000..48a9065
--- /dev/null
+++ b/gcc/config/or1k/predicates.md
@@ -0,0 +1,121 @@
+;; 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
+;; <http://www.gnu.org/licenses/>.
+
+(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;
+})
+
+;; True iff OP is a symbolic operand.
+
+(define_predicate "symbolic_operand"
+ (match_code "symbol_ref,label_ref,const")
+{
+ switch (GET_CODE (op))
+ {
+ case SYMBOL_REF:
+ return !SYMBOL_REF_TLS_MODEL (op);
+ case LABEL_REF:
+ return true;
+ case CONST:
+ op = XEXP (op, 0);
+ return (GET_CODE (op) == PLUS
+ && ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
+ && !SYMBOL_REF_TLS_MODEL (XEXP (op, 0)))
+ || GET_CODE (XEXP (op, 0)) == LABEL_REF)
+ && GET_CODE (XEXP (op, 1)) == CONST_INT);
+ default:
+ break;
+ }
+ return false;
+})
+
+;; Return true if OP is a symbolic operand for the TLS Global Dynamic model.
+(define_predicate "tgd_symbolic_operand"
+ (and (match_code "symbol_ref")
+ (match_test "SYMBOL_REF_TLS_MODEL (op) == TLS_MODEL_GLOBAL_DYNAMIC")))
+
+;; Return true if OP is a symbolic operand for the TLS Local Dynamic model.
+
+(define_predicate "tld_symbolic_operand"
+ (and (match_code "symbol_ref")
+ (match_test "SYMBOL_REF_TLS_MODEL (op) == TLS_MODEL_LOCAL_DYNAMIC")))
+
+;; Return true if OP is a symbolic operand for the TLS Initial Exec model.
+
+(define_predicate "tie_symbolic_operand"
+ (and (match_code "symbol_ref")
+ (match_test "SYMBOL_REF_TLS_MODEL (op) == TLS_MODEL_INITIAL_EXEC")))
+
+;; Return true if OP is a symbolic operand for the TLS Local Exec model.
+
+(define_predicate "tle_symbolic_operand"
+ (and (match_code "symbol_ref")
+ (match_test "SYMBOL_REF_TLS_MODEL (op) == TLS_MODEL_LOCAL_EXEC")))
diff --git a/gcc/config/or1k/rtems.h b/gcc/config/or1k/rtems.h
new file mode 100644
index 0000000..cfe83b4
--- /dev/null
+++ b/gcc/config/or1k/rtems.h
@@ -0,0 +1,30 @@
+/* Definitions for rtems targeting an OpenRISC OR1K using ELF.
+ Copyright (C) 2014 Free Software Foundation, Inc.
+ Contributed by Joel Sherrill (joel.sherrill@OARcorp.com).
+
+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
+<http://www.gnu.org/licenses/>. */
+
+/* Target OS builtins. */
+#undef TARGET_OS_CPP_BUILTINS
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("__rtems__"); \
+ builtin_define ("__USE_INIT_FINI__"); \
+ builtin_assert ("system=rtems"); \
+ } \
+ while (0)
diff --git a/gcc/config/or1k/t-linux b/gcc/config/or1k/t-linux
new file mode 100644
index 0000000..3f9a944
--- /dev/null
+++ b/gcc/config/or1k/t-linux
@@ -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 --git a/gcc/config/or1k/t-or1k b/gcc/config/or1k/t-or1k
new file mode 100644
index 0000000..81a4690
--- /dev/null
+++ b/gcc/config/or1k/t-or1k
@@ -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
+# <http://www.gnu.org/licenses/>.
+
+# 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 --git a/gcc/config/or1k/t-or1knd b/gcc/config/or1k/t-or1knd
new file mode 100644
index 0000000..6b84fa8
--- /dev/null
+++ b/gcc/config/or1k/t-or1knd
@@ -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
+# <http://www.gnu.org/licenses/>.
+
+# 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 --git a/gcc/config/or1k/t-rtems b/gcc/config/or1k/t-rtems
new file mode 100644
index 0000000..e4e5e1d
--- /dev/null
+++ b/gcc/config/or1k/t-rtems
@@ -0,0 +1,3 @@
+# RTEMS OR1K multilibs
+
+# No custom multilibs defined
diff --git a/gcc/config/rs6000/linux64.h b/gcc/config/rs6000/linux64.h
index 0879e7e..f00c775 100644
--- a/gcc/config/rs6000/linux64.h
+++ b/gcc/config/rs6000/linux64.h
@@ -365,17 +365,21 @@ extern int dot_symbols;
#endif
#define UCLIBC_DYNAMIC_LINKER32 "/lib/ld-uClibc.so.0"
#define UCLIBC_DYNAMIC_LINKER64 "/lib/ld64-uClibc.so.0"
+#define MUSL_DYNAMIC_LINKER32 "/lib/ld-musl-powerpc.so.1"
+#define MUSL_DYNAMIC_LINKER64 "/lib/ld-musl-powerpc64.so.1"
#if DEFAULT_LIBC == LIBC_UCLIBC
-#define CHOOSE_DYNAMIC_LINKER(G, U) "%{mglibc:" G ";:" U "}"
+#define CHOOSE_DYNAMIC_LINKER(G, U, M) "%{mglibc:" G ";:%{mmusl:" M ";:" U "}}"
#elif DEFAULT_LIBC == LIBC_GLIBC
-#define CHOOSE_DYNAMIC_LINKER(G, U) "%{muclibc:" U ";:" G "}"
+#define CHOOSE_DYNAMIC_LINKER(G, U, M) "%{muclibc:" U ";:%{mmusl:" M ";:" G "}}"
+#elif DEFAULT_LIBC == LIBC_MUSL
+#define CHOOSE_DYNAMIC_LINKER(G, U, M) "%{mglibc:" G ";:%{muclibc:" U ";:" M "}}"
#else
#error "Unsupported DEFAULT_LIBC"
#endif
#define GNU_USER_DYNAMIC_LINKER32 \
- CHOOSE_DYNAMIC_LINKER (GLIBC_DYNAMIC_LINKER32, UCLIBC_DYNAMIC_LINKER32)
+ CHOOSE_DYNAMIC_LINKER (GLIBC_DYNAMIC_LINKER32, UCLIBC_DYNAMIC_LINKER32, MUSL_DYNAMIC_LINKER32)
#define GNU_USER_DYNAMIC_LINKER64 \
- CHOOSE_DYNAMIC_LINKER (GLIBC_DYNAMIC_LINKER64, UCLIBC_DYNAMIC_LINKER64)
+ CHOOSE_DYNAMIC_LINKER (GLIBC_DYNAMIC_LINKER64, UCLIBC_DYNAMIC_LINKER64, MUSL_DYNAMIC_LINKER64)
#undef DEFAULT_ASM_ENDIAN
#if (TARGET_DEFAULT & MASK_LITTLE_ENDIAN)
diff --git a/gcc/config/rs6000/secureplt.h b/gcc/config/rs6000/secureplt.h
index b463463..77edf2a 100644
--- a/gcc/config/rs6000/secureplt.h
+++ b/gcc/config/rs6000/secureplt.h
@@ -18,3 +18,4 @@ along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#define CC1_SECURE_PLT_DEFAULT_SPEC "-msecure-plt"
+#define LINK_SECURE_PLT_DEFAULT_SPEC "--secure-plt"
diff --git a/gcc/config/rs6000/sysv4.h b/gcc/config/rs6000/sysv4.h
index c6c31dc..a6ddaef 100644
--- a/gcc/config/rs6000/sysv4.h
+++ b/gcc/config/rs6000/sysv4.h
@@ -537,6 +537,9 @@ ENDIAN_SELECT(" -mbig", " -mlittle", DEFAULT_ASM_ENDIAN)
#ifndef CC1_SECURE_PLT_DEFAULT_SPEC
#define CC1_SECURE_PLT_DEFAULT_SPEC ""
#endif
+#ifndef LINK_SECURE_PLT_DEFAULT_SPEC
+#define LINK_SECURE_PLT_DEFAULT_SPEC ""
+#endif
/* Pass -G xxx to the compiler. */
#undef CC1_SPEC
@@ -574,7 +577,8 @@ ENDIAN_SELECT(" -mbig", " -mlittle", DEFAULT_ASM_ENDIAN)
%{R*} \
%(link_shlib) \
%{!T*: %(link_start) } \
-%(link_os)"
+%(link_os)" \
+"%{!mbss-plt: %{!msecure-plt: %(link_secure_plt_default)}}"
/* Shared libraries are not default. */
#define LINK_SHLIB_SPEC "\
@@ -759,15 +763,18 @@ ENDIAN_SELECT(" -mbig", " -mlittle", DEFAULT_ASM_ENDIAN)
#define GLIBC_DYNAMIC_LINKER "/lib/ld.so.1"
#define UCLIBC_DYNAMIC_LINKER "/lib/ld-uClibc.so.0"
+#define MUSL_DYNAMIC_LINKER "/lib/ld-musl-powerpc.so.1"
#if DEFAULT_LIBC == LIBC_UCLIBC
-#define CHOOSE_DYNAMIC_LINKER(G, U) "%{mglibc:" G ";:" U "}"
+#define CHOOSE_DYNAMIC_LINKER(G, U, M) "%{mglibc:" G ";:%{mmusl:" M ";:" U "}}"
+#elif DEFAULT_LIBC == LIBC_MUSL
+#define CHOOSE_DYNAMIC_LINKER(G, U, M) "%{mglibc:" G ";:%{muclibc:" U ";:" M "}}"
#elif !defined (DEFAULT_LIBC) || DEFAULT_LIBC == LIBC_GLIBC
-#define CHOOSE_DYNAMIC_LINKER(G, U) "%{muclibc:" U ";:" G "}"
+#define CHOOSE_DYNAMIC_LINKER(G, U, M) "%{muclibc:" U ";:%{mmusl:" M ";:" G "}}"
#else
#error "Unsupported DEFAULT_LIBC"
#endif
#define GNU_USER_DYNAMIC_LINKER \
- CHOOSE_DYNAMIC_LINKER (GLIBC_DYNAMIC_LINKER, UCLIBC_DYNAMIC_LINKER)
+ CHOOSE_DYNAMIC_LINKER (GLIBC_DYNAMIC_LINKER, UCLIBC_DYNAMIC_LINKER, MUSL_DYNAMIC_LINKER)
#define LINK_OS_LINUX_SPEC "-m elf32ppclinux %{!shared: %{!static: \
%{rdynamic:-export-dynamic} \
@@ -889,6 +896,7 @@ ncrtn.o%s"
{ "link_os_openbsd", LINK_OS_OPENBSD_SPEC }, \
{ "link_os_default", LINK_OS_DEFAULT_SPEC }, \
{ "cc1_secure_plt_default", CC1_SECURE_PLT_DEFAULT_SPEC }, \
+ { "link_secure_plt_default", LINK_SECURE_PLT_DEFAULT_SPEC }, \
{ "cpp_os_ads", CPP_OS_ADS_SPEC }, \
{ "cpp_os_yellowknife", CPP_OS_YELLOWKNIFE_SPEC }, \
{ "cpp_os_mvme", CPP_OS_MVME_SPEC }, \
diff --git a/gcc/config/sh/linux.h b/gcc/config/sh/linux.h
index 0f5d614..16524da 100644
--- a/gcc/config/sh/linux.h
+++ b/gcc/config/sh/linux.h
@@ -43,7 +43,14 @@ along with GCC; see the file COPYING3. If not see
#define TARGET_ASM_FILE_END file_end_indicate_exec_stack
+#if TARGET_BIG_ENDIAN_DEFAULT /* BE */
+#define MUSL_DYNAMIC_LINKER_E "eb"
+#else
+#define MUSL_DYNAMIC_LINKER_E
+#endif
+
#define GLIBC_DYNAMIC_LINKER "/lib/ld-linux.so.2"
+#define MUSL_DYNAMIC_LINKER "/lib/ld-musl-sh" MUSL_DYNAMIC_LINKER_E ".so.1"
#undef SUBTARGET_LINK_EMUL_SUFFIX
#define SUBTARGET_LINK_EMUL_SUFFIX "_linux"
diff --git a/gcc/config/uclibc-stdint.h b/gcc/config/uclibc-stdint.h
new file mode 100644
index 0000000..cb345c1
--- /dev/null
+++ b/gcc/config/uclibc-stdint.h
@@ -0,0 +1,70 @@
+/* Definitions for <stdint.h> types on systems using uClibc.
+ Copyright (C) 2008, 2009, 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
+<http://www.gnu.org/licenses/>. */
+
+#define SIG_ATOMIC_TYPE "int"
+
+/* The newlib logic actually checks for sizes greater than 32 rather
+ than equal to 64 for various 64-bit types. */
+
+#define INT8_TYPE (CHAR_TYPE_SIZE == 8 ? "signed char" : 0)
+#define INT16_TYPE (SHORT_TYPE_SIZE == 16 ? "short int" : 0)
+#define INT32_TYPE (INT_TYPE_SIZE == 32 ? "int" : 0)
+#define INT64_TYPE (LONG_TYPE_SIZE == 64 ? "long int" : LONG_LONG_TYPE_SIZE == 64 ? "long long int" : 0)
+#define UINT8_TYPE (CHAR_TYPE_SIZE == 8 ? "unsigned char" : 0)
+/* uclibc-0.9.31/include/stdint.h has the 'unsigned' keyword first,
+ but GCC needs the length keyword first. */
+#define UINT16_TYPE (SHORT_TYPE_SIZE == 16 ? "short unsigned int" : 0)
+#define UINT32_TYPE (INT_TYPE_SIZE == 32 ? "unsigned int" : 0)
+#define UINT64_TYPE (LONG_TYPE_SIZE == 64 ? "long unsigned int" : LONG_LONG_TYPE_SIZE == 64 ? "long long unsigned int" : 0)
+
+#define INT_LEAST8_TYPE (INT8_TYPE ? INT8_TYPE : INT16_TYPE ? INT16_TYPE : INT32_TYPE ? INT32_TYPE : INT64_TYPE ? INT64_TYPE : 0)
+#define INT_LEAST16_TYPE (INT16_TYPE ? INT16_TYPE : INT32_TYPE ? INT32_TYPE : INT64_TYPE ? INT64_TYPE : 0)
+#define INT_LEAST32_TYPE (INT32_TYPE ? INT32_TYPE : INT64_TYPE ? INT64_TYPE : 0)
+#define INT_LEAST64_TYPE INT64_TYPE
+#define UINT_LEAST8_TYPE (UINT8_TYPE ? UINT8_TYPE : UINT16_TYPE ? UINT16_TYPE : UINT32_TYPE ? UINT32_TYPE : UINT64_TYPE ? UINT64_TYPE : 0)
+#define UINT_LEAST16_TYPE (UINT16_TYPE ? UINT16_TYPE : UINT32_TYPE ? UINT32_TYPE : UINT64_TYPE ? UINT64_TYPE : 0)
+#define UINT_LEAST32_TYPE (UINT32_TYPE ? UINT32_TYPE : UINT64_TYPE ? UINT64_TYPE : 0)
+#define UINT_LEAST64_TYPE UINT64_TYPE
+
+#define INT_FAST8_TYPE INT8_TYPE
+#define UINT_FAST8_TYPE UINT8_TYPE
+
+#if LONG_TYPE_SIZE == 64
+#define INT_FAST16_TYPE "long int"
+#define INT_FAST32_TYPE "long int"
+#define INT_FAST64_TYPE "long int"
+#define UINT_FAST16_TYPE "long unsigned int"
+#define UINT_FAST32_TYPE "long unsigned int"
+#define UINT_FAST64_TYPE "long unsigned int"
+#else
+#define INT_FAST16_TYPE "int"
+#define INT_FAST32_TYPE "int"
+#define INT_FAST64_TYPE "long long int"
+#define UINT_FAST16_TYPE "unsigned int"
+#define UINT_FAST32_TYPE "unsigned int"
+#define UINT_FAST64_TYPE "long long unsigned int"
+#endif
+
+#if LONG_TYPE_SIZE == 64
+#define INTPTR_TYPE "long int"
+#define UINTPTR_TYPE "long unsigned int"
+#else
+#define INTPTR_TYPE "int"
+#define UINTPTR_TYPE "unsigned int"
+#endif
diff --git a/gcc/configure b/gcc/configure
index 3c92795..b65699d 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -4835,6 +4835,9 @@ case "${target}" in
mips-sgi-irix6*)
# PIC is the default.
;;
+ or1k-*-*)
+ PICFLAG_FOR_TARGET=-fPIC
+ ;;
rs6000-ibm-aix* | powerpc-ibm-aix*)
# All AIX code is PIC.
;;
@@ -23639,6 +23642,20 @@ foo: .long 25
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
@@ -27802,6 +27819,9 @@ if test "${gcc_cv_libc_provides_ssp+set}" = set; then :
else
gcc_cv_libc_provides_ssp=no
case "$target" in
+ *-*-musl*)
+ # All versions of musl provide stack protector
+ gcc_cv_libc_provides_ssp=yes;;
*-*-linux* | *-*-kfreebsd*-gnu | *-*-knetbsd*-gnu)
# glibc 2.4 and later provides __stack_chk_fail and
# either __stack_chk_guard, or TLS access to stack guard canary.
@@ -27834,6 +27854,7 @@ fi
# <http://gcc.gnu.org/ml/gcc/2008-10/msg00130.html>) and for now
# simply assert that glibc does provide this, which is true for all
# realistically usable GNU/Hurd configurations.
+ # All supported versions of musl provide it as well
gcc_cv_libc_provides_ssp=yes;;
*-*-darwin* | *-*-freebsd*)
ac_fn_c_check_func "$LINENO" "__stack_chk_fail" "ac_cv_func___stack_chk_fail"
@@ -27930,6 +27951,9 @@ case "$target" in
gcc_cv_target_dl_iterate_phdr=no
fi
;;
+ *-linux-musl*)
+ gcc_cv_target_dl_iterate_phdr=yes
+ ;;
esac
if test x$gcc_cv_target_dl_iterate_phdr = xyes; then
diff --git a/gcc/configure.ac b/gcc/configure.ac
index d414081..1b74ab4 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -3185,6 +3185,20 @@ foo: .long 25
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
@@ -5282,6 +5296,9 @@ AC_CACHE_CHECK(__stack_chk_fail in target C library,
gcc_cv_libc_provides_ssp,
[gcc_cv_libc_provides_ssp=no
case "$target" in
+ *-*-musl*)
+ # All versions of musl provide stack protector
+ gcc_cv_libc_provides_ssp=yes;;
*-*-linux* | *-*-kfreebsd*-gnu | *-*-knetbsd*-gnu)
# glibc 2.4 and later provides __stack_chk_fail and
# either __stack_chk_guard, or TLS access to stack guard canary.
@@ -5308,6 +5325,7 @@ AC_CACHE_CHECK(__stack_chk_fail in target C library,
# <http://gcc.gnu.org/ml/gcc/2008-10/msg00130.html>) and for now
# simply assert that glibc does provide this, which is true for all
# realistically usable GNU/Hurd configurations.
+ # All supported versions of musl provide it as well
gcc_cv_libc_provides_ssp=yes;;
*-*-darwin* | *-*-freebsd*)
AC_CHECK_FUNC(__stack_chk_fail,[gcc_cv_libc_provides_ssp=yes],
@@ -5381,6 +5399,9 @@ case "$target" in
gcc_cv_target_dl_iterate_phdr=no
fi
;;
+ *-linux-musl*)
+ gcc_cv_target_dl_iterate_phdr=yes
+ ;;
esac
GCC_TARGET_TEMPLATE([TARGET_DL_ITERATE_PHDR])
if test x$gcc_cv_target_dl_iterate_phdr = xyes; then
diff --git a/gcc/gcc.c b/gcc/gcc.c
index d956c36..9b6b199 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -729,7 +729,7 @@ proper position among the other output files. */
#ifndef LINK_SSP_SPEC
#ifdef TARGET_LIBC_PROVIDES_SSP
#define LINK_SSP_SPEC "%{fstack-protector|fstack-protector-all" \
- "|fstack-protector-strong|fstack-protector-explicit:}"
+ "|fstack-protector-strong|fstack-protector-explicit:-lssp_nonshared}"
#else
#define LINK_SSP_SPEC "%{fstack-protector|fstack-protector-all" \
"|fstack-protector-strong|fstack-protector-explicit" \
diff --git a/gcc/ginclude/stddef.h b/gcc/ginclude/stddef.h
index f20a41b..eb879ef 100644
--- a/gcc/ginclude/stddef.h
+++ b/gcc/ginclude/stddef.h
@@ -184,6 +184,7 @@ typedef __PTRDIFF_TYPE__ ptrdiff_t;
#ifndef _GCC_SIZE_T
#ifndef _SIZET_
#ifndef __size_t
+#ifndef __DEFINED_size_t /* musl */
#define __size_t__ /* BeOS */
#define __SIZE_T__ /* Cray Unicos/Mk */
#define _SIZE_T
@@ -200,6 +201,7 @@ typedef __PTRDIFF_TYPE__ ptrdiff_t;
#define ___int_size_t_h
#define _GCC_SIZE_T
#define _SIZET_
+#define __DEFINED_size_t /* musl */
#if (defined (__FreeBSD__) && (__FreeBSD__ >= 5)) \
|| defined(__DragonFly__) \
|| defined(__FreeBSD_kernel__)
@@ -218,6 +220,7 @@ typedef __SIZE_TYPE__ size_t;
typedef long ssize_t;
#endif /* __BEOS__ */
#endif /* !(defined (__GNUG__) && defined (size_t)) */
+#endif /* __DEFINED_size_t */
#endif /* __size_t */
#endif /* _SIZET_ */
#endif /* _GCC_SIZE_T */
diff --git a/gcc/testsuite/g++.dg/ext/strncpy-chk1.C b/gcc/testsuite/g++.dg/ext/strncpy-chk1.C
index ebafc99..34a5df0 100644
--- a/gcc/testsuite/g++.dg/ext/strncpy-chk1.C
+++ b/gcc/testsuite/g++.dg/ext/strncpy-chk1.C
@@ -3,13 +3,13 @@
// { dg-options "-O2" }
// { dg-skip-if "packed attribute missing for struct A" { "epiphany-*-*" } { "*" } { "" } }
-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
foo (char *dest, const char *__restrict src, __SIZE_TYPE__ n)
{
- __builtin___strncpy_chk (dest, src, n, __builtin_object_size (dest, 0)); // { dg-warning "will always overflow" }
+ __builtin___strncpy_chk (dest, src, n, __builtin_object_size (dest, 0)); // { dg-warning "will always overflow" "" { target { ! or1k*-*-* } } }
}
void bar (const char *, int);
diff --git a/gcc/testsuite/g++.dg/init/pr25811.C b/gcc/testsuite/g++.dg/init/pr25811.C
index c29f406..8e01c4c 100644
--- a/gcc/testsuite/g++.dg/init/pr25811.C
+++ b/gcc/testsuite/g++.dg/init/pr25811.C
@@ -1,6 +1,59 @@
// PR c++/25811
// { dg-do compile }
+struct A1
+{
+ int const j; // { dg-message "should be initialized" "" { target { ! c++11 } } }
+};
+
+struct A2
+{
+ int const volatile i; // { dg-message "should be initialized" "" { target { ! c++11 } } }
+};
+
+struct A3
+{
+ int& ref; // { dg-message "should be initialized" "" { target { ! c++11 } } }
+};
+
+struct A4
+{
+ int const& ref; // { dg-message "should be initialized" "" { target { ! c++11 } } }
+};
+
+struct A5
+{
+ int& ref; // { dg-message "should be initialized" "" { target { ! c++11 } } }
+ int const i; // { dg-message "should be initialized" "" { target { ! c++11 } } }
+};
+
+template <class T> struct S1
+{
+ T const i; // { dg-message "should be initialized" "" { target { ! c++11 } } }
+};
+
+template <class T> struct S2
+{
+ T const volatile i; // { dg-message "should be initialized" "" { target { ! c++11 } } }
+};
+
+template <class T> struct S3
+{
+ T& ref; // { dg-message "should be initialized" "" { target { ! c++11 } } }
+};
+
+template <class T> struct S4
+{
+ T const i; // { dg-message "should be initialized" "" { target { ! c++11 } } }
+ T& ref; // { dg-message "should be initialized" "" { target { ! c++11 } } }
+};
+
+struct X
+{
+ X () : c (0), r (c) {}
+ int const c;// PR c++/25811
+// { dg-do compile }
+
struct A1 // { dg-message "implicitly deleted" "" { target c++11 } }
// { dg-error "uninitialized" "" { target c++11 } 4 }
{
@@ -209,3 +262,145 @@ void f16 ()
{
new U; // { dg-error "deleted|uninitialized const member" }
}
+
+ int const& r;
+};
+
+struct Y11
+{
+ int const i; // { dg-message "should be initialized" "" { target { ! c++11 } } }
+};
+
+struct Y1
+{
+ Y11 a[1];
+};
+
+struct Y22
+{
+ int& ref; // { dg-message "should be initialized" "" { target { ! c++11 } } }
+};
+
+struct Y2
+{
+ Y22 a[1];
+};
+
+struct Z1
+{
+ int const i; // { dg-message "should be initialized" "" { target { ! c++11 } } }
+};
+
+struct Z2
+{
+ int& ref; // { dg-message "should be initialized" "" { target { ! c++11 } } }
+};
+
+struct Z3
+{
+ int const i; // { dg-message "should be initialized" "" { target { ! c++11 } } }
+};
+
+struct Z4
+{
+ int& ref; // { dg-message "should be initialized" "" { target { ! c++11 } } }
+};
+
+struct Z5
+{
+ int i;
+};
+
+struct Z
+{
+ Z1 z1;
+ Z2 z2;
+ Z3 z3;
+ Z4 z4;
+ Z5 z5;
+};
+
+union U
+{
+ int const i; // { dg-message "should be initialized" "" { target { ! c++11 } } }
+};
+
+void f1 ()
+{
+ new A1; // { dg-error "deleted|uninitialized const member" }
+}
+
+void f2 ()
+{
+ new A2; // { dg-error "deleted|uninitialized const member" }
+}
+
+void f3 ()
+{
+ new A3; // { dg-error "deleted|uninitialized reference member" }
+}
+
+void f4 ()
+{
+ new A4; // { dg-error "deleted|uninitialized reference member" }
+}
+
+void f5 ()
+{
+ new A5; // { dg-error "deleted|uninitialized reference member|uninitialized const member" }
+}
+
+void f6 ()
+{
+ new S1<int>; // { dg-error "deleted|uninitialized const member" }
+}
+
+void f7 ()
+{
+ new S2<int>; // { dg-error "deleted|uninitialized const member" }
+}
+
+void f8 ()
+{
+ new S3<int>; // { dg-error "deleted|uninitialized reference member" }
+}
+
+void f9 ()
+{
+ new S4<int>; // { dg-error "deleted|uninitialized reference member|uninitialized const member" }
+}
+
+void f10 ()
+{
+ new X;
+}
+
+void f11 ()
+{
+ new A1[1]; // { dg-error "deleted|uninitialized const member" }
+}
+
+void f12 ()
+{
+ new A3[1]; // { dg-error "deleted|uninitialized reference member" }
+}
+
+void f13 ()
+{
+ new Y1; // { dg-error "deleted|uninitialized const member" }
+}
+
+void f14 ()
+{
+ new Y2; // { dg-error "deleted|uninitialized reference member" }
+}
+
+void f15 ()
+{
+ new Z; // { dg-error "deleted|uninitialized reference member|uninitialized const member" }
+}
+
+void f16 ()
+{
+ new U; // { dg-error "deleted|uninitialized const member" }
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/20101011-1.c b/gcc/testsuite/gcc.c-torture/execute/20101011-1.c
index 34d0313..08f45d8 100644
--- a/gcc/testsuite/gcc.c-torture/execute/20101011-1.c
+++ b/gcc/testsuite/gcc.c-torture/execute/20101011-1.c
@@ -35,6 +35,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 --git a/gcc/testsuite/gcc.dg/20020312-2.c b/gcc/testsuite/gcc.dg/20020312-2.c
index 71201fe..a588388 100644
--- a/gcc/testsuite/gcc.dg/20020312-2.c
+++ b/gcc/testsuite/gcc.dg/20020312-2.c
@@ -34,6 +34,8 @@ extern void abort (void);
/* 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 --git a/gcc/testsuite/gcc.dg/builtin-apply2.c b/gcc/testsuite/gcc.dg/builtin-apply2.c
index b6cbe39..e4d3e6f 100644
--- a/gcc/testsuite/gcc.dg/builtin-apply2.c
+++ b/gcc/testsuite/gcc.dg/builtin-apply2.c
@@ -44,3 +44,35 @@ int main(void)
return 0;
}
+
+#if defined(__ARM_PCS) || defined(__epiphany__)
+/* For Base AAPCS, NAME is passed in r0. D is passed in r2 and r3.
+ E, F and G are passed on stack. So the size of the stack argument
+ data is 20. */
+#define STACK_ARGUMENTS_SIZE 20
+#elif defined __MMIX__ || defined __arc__
+/* No parameters on stack for bar. */
+#define STACK_ARGUMENTS_SIZE 0
+#else
+#define STACK_ARGUMENTS_SIZE 64
+#endif
+
+extern void abort(void);
+
+void foo(char *name, double d, double e, double f, int g)
+{
+ if (g != INTEGER_ARG)
+ abort();
+}
+
+void bar(char *name, ...)
+{
+ __builtin_apply(foo, __builtin_apply_args(), STACK_ARGUMENTS_SIZE);
+}
+
+int main(void)
+{
+ bar("eeee", 5.444567, 8.90765, 4.567789, INTEGER_ARG);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/builtin-stringop-chk-1.c b/gcc/testsuite/gcc.dg/builtin-stringop-chk-1.c
index bb727da..7f14818 100644
--- a/gcc/testsuite/gcc.dg/builtin-stringop-chk-1.c
+++ b/gcc/testsuite/gcc.dg/builtin-stringop-chk-1.c
@@ -105,8 +105,8 @@ test2 (const H h)
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 --git a/gcc/testsuite/gcc.dg/nop.h b/gcc/testsuite/gcc.dg/nop.h
index a0c19a3..c5089b1 100644
--- a/gcc/testsuite/gcc.dg/nop.h
+++ b/gcc/testsuite/gcc.dg/nop.h
@@ -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 --git a/gcc/testsuite/gcc.dg/torture/pr37868.c b/gcc/testsuite/gcc.dg/torture/pr37868.c
index 5204c5a..585e159 100644
--- a/gcc/testsuite/gcc.dg/torture/pr37868.c
+++ b/gcc/testsuite/gcc.dg/torture/pr37868.c
@@ -1,6 +1,7 @@
/* { dg-do run } */
/* { dg-options "-fno-strict-aliasing" } */
/* { dg-skip-if "unaligned access" { arc*-*-* epiphany-*-* nds32*-*-* sparc*-*-* sh*-*-* tic6x-*-* } "*" "" } */
+/* { dg-skip-if "alignment exception" { or1k*-*-* } "*" "" } */
extern void abort (void);
#if (__SIZEOF_INT__ <= 2)
diff --git a/gcc/testsuite/gcc.dg/torture/stackalign/builtin-apply-2.c b/gcc/testsuite/gcc.dg/torture/stackalign/builtin-apply-2.c
index ffd865b..eddadb6 100644
--- a/gcc/testsuite/gcc.dg/torture/stackalign/builtin-apply-2.c
+++ b/gcc/testsuite/gcc.dg/torture/stackalign/builtin-apply-2.c
@@ -10,7 +10,7 @@
avr: Variadic funcs don't pass arguments in registers, while normal funcs
do. */
/* { dg-skip-if "Variadic funcs use different argument passing from normal funcs" { arm_hf_eabi || { avr-*-* } } "*" "" } */
-/* { dg-skip-if "Variadic funcs have all args on stack. Normal funcs have args in registers." { nds32*-*-* } "*" "" } */
+/* { dg-skip-if "Variadic funcs have all args on stack. Normal funcs have args in registers." { nds32*-*-* or1k*-*-* } "*" "" } */
/* { dg-require-effective-target untyped_assembly } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr44258.c b/gcc/testsuite/gcc.dg/tree-ssa/pr44258.c
index 6dc233b..4ac4236 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr44258.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr44258.c
@@ -15,7 +15,7 @@ struct str
struct val
{
char y;
- struct blah b2;
+ struct blah b2 __attribute__((packed)); /* { dg-warning "attribute ignored" "" { target { ! or1k*-*-* } } } */
};
union U
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index 950db11..8ce55e7 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -547,6 +547,7 @@ proc check_profiling_available { test_what } {
|| [istarget nds32*-*-elf]
|| [istarget nios2-*-elf]
|| [istarget nvptx-*-*]
+ || [istarget or1k-*-elf]
|| [istarget powerpc-*-eabi*]
|| [istarget powerpc-*-elf]
|| [istarget rx-*-*]
diff --git a/libgcc/ChangeLog.or1k b/libgcc/ChangeLog.or1k
new file mode 100644
index 0000000..9abb993
--- /dev/null
+++ b/libgcc/ChangeLog.or1k
@@ -0,0 +1,61 @@
+2014-08-13 Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
+
+ * config/or1k/or1k.S: make internal calls to __udivsi3 hidden.
+
+2014-05-07 Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
+
+ * config/or1k/or1k.S: Use delay/no-delay compatibility macros.
+ * config/or1k/lib2funcs.c: Remove.
+ * config/or1k/t-or1k: Set LIB1ASMSRC and LIB1ASMFUNCS.
+ Remove LIB2ADD define.
+
+2013-07-17 Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
+
+ * config/or1k/sfp-machine.h (_FP_QNANNEGATEDP): Define to 0.
+
+2013-07-10 Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
+
+ * config/or1k/crti.S: Rename __init/__fini to _init/_fini
+
+2013-02-13 Christian Svensson <blue@cmd.nu>
+
+ * config.host: If we are targeting or1k*-linux or or1k*-uclibc do not
+ build crtn.o or crti.o. Do not include linux unwinder for other
+ targets (e.g. or1k*-elf)
+
+2013-02-01 Christian Svensson <blue@cmd.nu>
+
+ * config/or1k/t-crtstuff: updated file.
+ - Set CRTSTUFF_T_CFLAGS_S as well. (*-*-elf needs this)
+
+2013-01-24 Christian Svensson <blue@cmd.nu>
+
+ * config/or1k/linux-unwind.h: new file
+ - support signal handling in DWARF2 unwinding
+ * config.host: include or1k/linux-unwind.h
+
+2012-12-29 Christian Svensson <blue@cmd.nu>
+
+ * config/or1k/t-crtstuff: New file.
+ - Use -fno-dwarf2-cfi-asm on crtstuff to leave eh_frame empty.
+ * config.host: Include or1k/t-crtstuff
+
+2012-05-13 Peter Gavin <pgavin@gmail.com>
+
+ * config.host: add or1knd target
+ * config/or1k/or1k-asm.h: new file
+ - contains macros for making delay slot optional
+ * config/or1k/t-or1k: use C versions of divmod and mulsi3 for now
+ until asm versions are updated to use optional delay slot
+ * config/or1k/lib2funcs.c: new file; defines __mulsi3
+ * config/or1k/crti.S: include or1k-asm.h
+ * config/or1k/crtn.S: include or1k-asm.h; make delay slot optional
+
+2012-03-03 Peter Gavin <pgavin@gmail.com>
+
+ * configure: regenerated
+
+2012-02-18 Peter Gavin <pgavin@gmail.com>
+
+ * config/or1k/or1k.S: moved from gcc/config/or1k/or1k.S
+ * config/or1k/t-or1k: compile or1k.S
diff --git a/libgcc/config.host b/libgcc/config.host
index 4329891..a74ec43 100644
--- a/libgcc/config.host
+++ b/libgcc/config.host
@@ -162,6 +162,12 @@ nds32*-*)
nios2*-*-*)
cpu_type=nios2
;;
+or1k-*-*)
+ cpu_type=or1k
+ ;;
+or1knd-*-*)
+ cpu_type=or1k
+ ;;
powerpc*-*-*)
cpu_type=rs6000
;;
@@ -956,6 +962,14 @@ nios2-*-*)
tmake_file="$tmake_file nios2/t-nios2 t-softfp-sfdf t-softfp-excl t-softfp"
extra_parts="$extra_parts crti.o crtn.o"
;;
+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*-*-*)
+ tmake_file="$tmake_file or1k/t-or1k or1k/t-linux 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"
;;
diff --git a/libgcc/config/or1k/crti.S b/libgcc/config/or1k/crti.S
new file mode 100644
index 0000000..bda20f4
--- /dev/null
+++ b/libgcc/config/or1k/crti.S
@@ -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
+# <http://www.gnu.org/licenses/>.
+
+#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 --git a/libgcc/config/or1k/crtn.S b/libgcc/config/or1k/crtn.S
new file mode 100644
index 0000000..5d40348
--- /dev/null
+++ b/libgcc/config/or1k/crtn.S
@@ -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
+# <http://www.gnu.org/licenses/>.
+
+#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 --git a/libgcc/config/or1k/linux-unwind.h b/libgcc/config/or1k/linux-unwind.h
new file mode 100644
index 0000000..d42b672
--- /dev/null
+++ b/libgcc/config/or1k/linux-unwind.h
@@ -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
+<http://www.gnu.org/licenses/>. */
+
+#ifndef inhibit_libc
+
+#include <signal.h>
+#include <sys/ucontext.h>
+#include <linux/unistd.h>
+
+#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 --git a/libgcc/config/or1k/or1k-asm.h b/libgcc/config/or1k/or1k-asm.h
new file mode 100644
index 0000000..c328b20
--- /dev/null
+++ b/libgcc/config/or1k/or1k-asm.h
@@ -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 --git a/libgcc/config/or1k/or1k.S b/libgcc/config/or1k/or1k.S
new file mode 100644
index 0000000..f9266f3
--- /dev/null
+++ b/libgcc/config/or1k/or1k.S
@@ -0,0 +1,237 @@
+#include "or1k-asm.h"
+/*
+ * Assembly functions for software multiplication and devision.
+ */
+
+#define ENTRY(symbol) \
+ .align 4 ;\
+ .global symbol ;\
+ .type symbol, @function ;\
+symbol:
+
+#ifdef L__mulsi3
+ENTRY(__mulsi3)
+ l.addi r11,r0,0x0
+ l.sfne r3,r11
+OR1K_DELAYED(
+ OR1K_INST(l.ori r5,r3,0x0),
+ OR1K_INST(l.bnf 3f)
+)
+ l.addi r6,r0,0x0
+1:
+ l.andi r3,r5,0x1
+ l.sfeq r3,r6
+OR1K_DELAYED(
+ OR1K_INST(l.srli r5,r5,0x1),
+ OR1K_INST(l.bf 2f)
+)
+ l.add r11,r11,r4
+2:
+ l.sfne r5,r6
+OR1K_DELAYED(
+ OR1K_INST(l.slli r4,r4,0x1),
+ OR1K_INST(l.bf 1b)
+)
+3:
+OR1K_DELAYED_NOP(
+ OR1K_INST(l.jr r9)
+)
+.size __mulsi3,.-__mulsi3
+#endif
+
+#ifdef L__udivsi3
+.global __udivsi3_internal
+.hidden __udivsi3_internal
+__udivsi3_internal:
+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
+OR1K_DELAYED(
+ OR1K_INST(l.addi r7,r0,0),
+ OR1K_INST(l.bnf 4f)
+)
+ /* The following work equally on delay and no-delay implementations */
+ l.sfgtu r8,r5
+ l.bf 5f
+ l.sfeq r8,r5
+ l.bf 6f
+ l.sfltu r11,r8
+
+OR1K_DELAYED(
+ OR1K_INST(l.addi r13,r0,32),
+ OR1K_INST(l.bnf 2f)
+)
+ 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
+OR1K_DELAYED(
+ OR1K_INST(l.slli r5,r5,1),
+ OR1K_INST(l.bf 1b)
+)
+2:
+ l.srli r7,r7,1
+ l.addi r13,r13,1
+ l.addi r9,r0,0
+ l.sfltu r9,r13
+OR1K_DELAYED(
+ OR1K_INST(l.addi r5,r15,0),
+ OR1K_INST(l.bnf 4f)
+)
+ 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
+OR1K_DELAYED(
+ OR1K_INST(l.slli r3,r11,1),
+ OR1K_INST(l.bf 1f)
+)
+ l.addi r4,r0,1
+1:
+ l.slli r5,r5,1
+ l.sfne r4,r17
+OR1K_DELAYED(
+ OR1K_INST(l.or r11,r3,r4),
+ OR1K_INST(l.bnf 2f)
+)
+ l.addi r7,r6,0
+2:
+ l.addi r9,r9,1
+ l.sfltu r9,r13
+OR1K_DELAYED_NOP(
+ OR1K_INST(l.bf 3b)
+)
+OR1K_DELAYED_NOP(
+ OR1K_INST(l.j 4f)
+)
+6:
+OR1K_DELAYED(
+ OR1K_INST(l.addi r11,r0,1),
+ OR1K_INST(l.j 4f)
+)
+5:
+ l.addi r7,r5,0
+4:
+ l.lwz r9,0(r1)
+OR1K_DELAYED(
+ OR1K_INST(l.addi r1,r1,4),
+ OR1K_INST(l.jr r9)
+)
+.size __udivsi3,.-__udivsi3
+#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
+OR1K_DELAYED(
+ OR1K_INST(l.addi r3,r0,0),
+ OR1K_INST(l.bnf 1f)
+)
+ l.addi r14,r0,1
+ l.sub r5,r0,r5
+1:
+ l.sflts r4,r0
+OR1K_DELAYED_NOP(
+ OR1K_INST(l.bnf 1f)
+)
+ l.addi r14,r14,1
+ l.sub r4,r0,r4
+1:
+OR1K_DELAYED(
+ OR1K_INST(l.addi r3,r5,0),
+ OR1K_INST(l.jal __udivsi3_internal)
+)
+ l.sfeqi r14,1
+OR1K_DELAYED_NOP(
+ OR1K_INST(l.bnf 1f)
+)
+ l.sub r11,r0,r11
+1:
+ l.lwz r9,0(r1)
+ l.lwz r14,4(r1)
+OR1K_DELAYED(
+ OR1K_INST(l.addi r1,r1,8),
+ OR1K_INST(l.jr r9)
+)
+.size __divsi3,.-__divsi3
+#endif
+
+
+#ifdef L__umodsi3
+ENTRY(__umodsi3)
+ l.addi r1,r1,-4
+ l.sw 0(r1),r9
+OR1K_DELAYED_NOP(
+ OR1K_INST(l.jal __udivsi3_internal)
+)
+ l.addi r11,r7,0
+ l.lwz r9,0(r1)
+OR1K_DELAYED(
+ OR1K_INST(l.addi r1,r1,4),
+ OR1K_INST(l.jr r9)
+)
+.size __umodsi3,.-__umodsi3
+#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
+OR1K_DELAYED_NOP(
+ OR1K_INST(l.bnf 1f)
+)
+ l.addi r14,r0,1
+ l.sub r3,r0,r3
+1:
+ l.sflts r4,r0
+OR1K_DELAYED_NOP(
+ OR1K_INST(l.bnf 1f)
+)
+ l.sub r4,r0,r4
+1:
+OR1K_DELAYED_NOP(
+ OR1K_INST(l.jal __udivsi3_internal)
+)
+ l.sfeqi r14,1
+OR1K_DELAYED(
+ OR1K_INST(l.addi r11,r7,0),
+ OR1K_INST(l.bnf 1f)
+)
+ l.sub r11,r0,r11
+1:
+ l.lwz r9,0(r1)
+ l.lwz r14,4(r1)
+OR1K_DELAYED(
+ OR1K_INST(l.addi r1,r1,8),
+ OR1K_INST(l.jr r9)
+)
+.size __modsi3,.-__modsi3
+#endif
diff --git a/libgcc/config/or1k/sfp-machine.h b/libgcc/config/or1k/sfp-machine.h
new file mode 100644
index 0000000..5da9e84
--- /dev/null
+++ b/libgcc/config/or1k/sfp-machine.h
@@ -0,0 +1,54 @@
+#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
+#define _FP_QNANNEGATEDP 0
+
+/* 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 _FP_TININESS_AFTER_ROUNDING 0
+
+/* 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 --git a/libgcc/config/or1k/t-crtstuff b/libgcc/config/or1k/t-crtstuff
new file mode 100644
index 0000000..4898fc6
--- /dev/null
+++ b/libgcc/config/or1k/t-crtstuff
@@ -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 --git a/libgcc/config/or1k/t-linux b/libgcc/config/or1k/t-linux
new file mode 100644
index 0000000..f4bf22d
--- /dev/null
+++ b/libgcc/config/or1k/t-linux
@@ -0,0 +1,2 @@
+MULTILIB_DIRNAMES = be
+EXTRA_MULTILIB_PARTS = crti.o crtbegin.o crtend.o crtn.o
diff --git a/libgcc/config/or1k/t-or1k b/libgcc/config/or1k/t-or1k
new file mode 100644
index 0000000..ff3a8ae
--- /dev/null
+++ b/libgcc/config/or1k/t-or1k
@@ -0,0 +1,23 @@
+# 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
+# <http://www.gnu.org/licenses/>.
+
+LIB1ASMSRC = or1k/or1k.S
+LIB1ASMFUNCS = __mulsi3 __udivsi3 __divsi3 __umodsi3 __modsi3
diff --git a/libgcc/configure b/libgcc/configure
index 203d384..a0a7f30 100644
--- a/libgcc/configure
+++ b/libgcc/configure
@@ -2343,6 +2343,9 @@ case "${host}" in
mips-sgi-irix6*)
# PIC is the default.
;;
+ or1k-*-*)
+ PICFLAG=-fPIC
+ ;;
rs6000-ibm-aix* | powerpc-ibm-aix*)
# All AIX code is PIC.
;;
diff --git a/libgcc/gthr.h b/libgcc/gthr.h
index ba2c757..930da69 100644
--- a/libgcc/gthr.h
+++ b/libgcc/gthr.h
@@ -136,10 +136,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
/* The pe-coff weak support isn't fully compatible to ELF's weak.
For static libraries it might would work, but as we need to deal
with shared versions too, we disable it for mingw-targets. */
-#ifdef __MINGW32__
#undef GTHREAD_USE_WEAK
#define GTHREAD_USE_WEAK 0
-#endif
#ifndef GTHREAD_USE_WEAK
#define GTHREAD_USE_WEAK 1
diff --git a/libgcc/unwind-dw2-fde-dip.c b/libgcc/unwind-dw2-fde-dip.c
index e1e566b..3129ac5 100644
--- a/libgcc/unwind-dw2-fde-dip.c
+++ b/libgcc/unwind-dw2-fde-dip.c
@@ -46,6 +46,10 @@
#include "unwind-compat.h"
#include "gthr.h"
+#if !defined(inhibit_libc) && defined(HAVE_LD_EH_FRAME_HDR) && defined(TARGET_DL_ITERATE_PHDR)
+# define USE_PT_GNU_EH_FRAME
+#endif
+
#if !defined(inhibit_libc) && defined(HAVE_LD_EH_FRAME_HDR) \
&& (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) \
|| (__GLIBC__ == 2 && __GLIBC_MINOR__ == 2 && defined(DT_CONFIG)))
diff --git a/libgomp/config/posix/time.c b/libgomp/config/posix/time.c
index cb8b4c3..f5c11c2 100644
--- a/libgomp/config/posix/time.c
+++ b/libgomp/config/posix/time.c
@@ -29,6 +29,8 @@
The following implementation uses the most simple POSIX routines.
If present, POSIX 4 clocks should be used instead. */
+#define _POSIX_C_SOURCE 199309L /* for clocks */
+
#include "libgomp.h"
#include <unistd.h>
#if TIME_WITH_SYS_TIME
diff --git a/libiberty/ChangeLog.or1k b/libiberty/ChangeLog.or1k
new file mode 100644
index 0000000..16f3b07
--- /dev/null
+++ b/libiberty/ChangeLog.or1k
@@ -0,0 +1,4 @@
+2012-03-03 Peter Gavin <pgavin@gmail.com>
+
+ * configure: regenerated
+
diff --git a/libitm/config/arm/hwcap.cc b/libitm/config/arm/hwcap.cc
index a1c2cfd..dd4fad2 100644
--- a/libitm/config/arm/hwcap.cc
+++ b/libitm/config/arm/hwcap.cc
@@ -40,7 +40,11 @@ int GTM_hwcap HIDDEN = 0
#ifdef __linux__
#include <unistd.h>
+#ifdef __GLIBC__
#include <sys/fcntl.h>
+#else
+#include <fcntl.h>
+#endif
#include <elf.h>
static void __attribute__((constructor))
diff --git a/libitm/config/linux/x86/tls.h b/libitm/config/linux/x86/tls.h
index e731ab7..54ad8b6 100644
--- a/libitm/config/linux/x86/tls.h
+++ b/libitm/config/linux/x86/tls.h
@@ -25,16 +25,19 @@
#ifndef LIBITM_X86_TLS_H
#define LIBITM_X86_TLS_H 1
-#if defined(__GLIBC_PREREQ) && __GLIBC_PREREQ(2, 10)
+#if defined(__GLIBC_PREREQ)
+#if __GLIBC_PREREQ(2, 10)
/* Use slots in the TCB head rather than __thread lookups.
GLIBC has reserved words 10 through 13 for TM. */
#define HAVE_ARCH_GTM_THREAD 1
#define HAVE_ARCH_GTM_THREAD_DISP 1
#endif
+#endif
#include "config/generic/tls.h"
-#if defined(__GLIBC_PREREQ) && __GLIBC_PREREQ(2, 10)
+#if defined(__GLIBC_PREREQ)
+#if __GLIBC_PREREQ(2, 10)
namespace GTM HIDDEN {
#ifdef __x86_64__
@@ -101,5 +104,6 @@ static inline void set_abi_disp(struct abi_dispatch *x)
} // namespace GTM
#endif /* >= GLIBC 2.10 */
+#endif
#endif // LIBITM_X86_TLS_H
diff --git a/libjava/classpath/config.guess b/libjava/classpath/config.guess
index b02565c..4cef3f9 100755
--- a/libjava/classpath/config.guess
+++ b/libjava/classpath/config.guess
@@ -942,8 +942,8 @@ EOF
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 or32-unknown-linux-gnu
+ or1k:Linux:*:*)
+ echo or1k-unknown-linux-gnu
exit ;;
padre:Linux:*:*)
echo sparc-unknown-linux-gnu
diff --git a/libjava/classpath/config.sub b/libjava/classpath/config.sub
index 59bb593..b2d9ef5 100755
--- a/libjava/classpath/config.sub
+++ b/libjava/classpath/config.sub
@@ -300,7 +300,7 @@ case $basic_machine in
| nios | nios2 \
| ns16k | ns32k \
| open8 \
- | or32 \
+ | or1k \
| pdp10 | pdp11 | pj | pjl \
| powerpc | powerpc64 | powerpc64le | powerpcle \
| pyramid \
@@ -917,7 +917,7 @@ case $basic_machine in
os=-proelf
;;
openrisc | openrisc-*)
- basic_machine=or32-unknown
+ basic_machine=or1k-unknown
;;
os400)
basic_machine=powerpc-ibm
@@ -1583,7 +1583,7 @@ case $basic_machine in
mips*-*)
os=-elf
;;
- or32-*)
+ or1k-*)
os=-coff
;;
*-tti) # must be before sparc entry or we get the wrong os.
diff --git a/libstdc++-v3/configure.host b/libstdc++-v3/configure.host
index 640199c..de3e62f 100644
--- a/libstdc++-v3/configure.host
+++ b/libstdc++-v3/configure.host
@@ -274,6 +274,13 @@ case "${host_os}" in
os_include_dir="os/bsd/freebsd"
;;
gnu* | linux* | kfreebsd*-gnu | knetbsd*-gnu)
+ # check for musl by target
+ case "${host_os}" in
+ *-musl*)
+ os_include_dir="os/generic"
+ ;;
+ *)
+
if [ "$uclibc" = "yes" ]; then
os_include_dir="os/uclibc"
elif [ "$bionic" = "yes" ]; then
@@ -282,6 +289,9 @@ case "${host_os}" in
os_include_dir="os/gnu-linux"
fi
;;
+
+ esac
+ ;;
hpux*)
os_include_dir="os/hpux"
;;
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/inserters_extractors/wchar_t/5.cc b/libstdc++-v3/testsuite/21_strings/basic_string/inserters_extractors/wchar_t/5.cc
index 3e8280d..cafbd05 100644
--- a/libstdc++-v3/testsuite/21_strings/basic_string/inserters_extractors/wchar_t/5.cc
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/inserters_extractors/wchar_t/5.cc
@@ -23,6 +23,8 @@
// working, not to mention other major details like char_traits, and
// all of the string class.
+// { dg-xfail-run-if "not supported on OR1K newlib" { or1k-*-elf } }
+
#include <string>
#include <fstream>
#include <iostream>
diff --git a/libstdc++-v3/testsuite/25_algorithms/copy/streambuf_iterators/wchar_t/4.cc b/libstdc++-v3/testsuite/25_algorithms/copy/streambuf_iterators/wchar_t/4.cc
index 0981e5e..ca28d8c 100644
--- a/libstdc++-v3/testsuite/25_algorithms/copy/streambuf_iterators/wchar_t/4.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/copy/streambuf_iterators/wchar_t/4.cc
@@ -17,6 +17,8 @@
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
+// { dg-xfail-run-if "not supported on OR1K newlib" { or1k-*-elf } }
+
#include <iterator>
#include <fstream>
#include <algorithm>
diff --git a/libstdc++-v3/testsuite/25_algorithms/find/istreambuf_iterators/wchar_t/2.cc b/libstdc++-v3/testsuite/25_algorithms/find/istreambuf_iterators/wchar_t/2.cc
index 2ab65f8..8e803ac 100644
--- a/libstdc++-v3/testsuite/25_algorithms/find/istreambuf_iterators/wchar_t/2.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/find/istreambuf_iterators/wchar_t/2.cc
@@ -17,6 +17,8 @@
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
+// { dg-xfail-run-if "not supported on OR1K newlib" { or1k-*-elf } }
+
#include <iterator>
#include <fstream>
#include <algorithm>
diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/wchar_t/12790-1.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/wchar_t/12790-1.cc
index 0cb18f6..4e0be89 100644
--- a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/wchar_t/12790-1.cc
+++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekpos/wchar_t/12790-1.cc
@@ -17,6 +17,8 @@
// 27.8.1.4 Overridden virtual functions
+// { dg-xfail-run-if "not supported on OR32 newlib" { or1k-*-elf } }
+
#include <locale>
#include <fstream>
#include <testsuite_hooks.h>
diff --git a/libstdc++-v3/testsuite/27_io/basic_istream/extractors_other/wchar_t/2.cc b/libstdc++-v3/testsuite/27_io/basic_istream/extractors_other/wchar_t/2.cc
index e789bb4..ccc5ecc 100644
--- a/libstdc++-v3/testsuite/27_io/basic_istream/extractors_other/wchar_t/2.cc
+++ b/libstdc++-v3/testsuite/27_io/basic_istream/extractors_other/wchar_t/2.cc
@@ -19,6 +19,8 @@
// @require@ %-*.tst %-*.txt
// @diff@ %-*.tst %-*.txt
+// { dg-xfail-run-if "not supported on OR1K newlib" { or1k-*-elf } }
+
#include <istream>
#include <fstream>
#include <testsuite_hooks.h>
diff --git a/libstdc++-v3/testsuite/27_io/basic_istream/get/wchar_t/2.cc b/libstdc++-v3/testsuite/27_io/basic_istream/get/wchar_t/2.cc
index 2180b96..d71e73f 100644
--- a/libstdc++-v3/testsuite/27_io/basic_istream/get/wchar_t/2.cc
+++ b/libstdc++-v3/testsuite/27_io/basic_istream/get/wchar_t/2.cc
@@ -19,6 +19,9 @@
// @require@ %-*.tst %-*.txt
// @diff@ %-*.tst %-*.txt
+// OpenRISC does not support file I/O in newlib
+// { dg-xfail-run-if "not supported on OR1K newlib" { or1k-*-elf } }
+
#include <istream>
#include <sstream>
#include <fstream>
diff --git a/libstdc++-v3/testsuite/27_io/basic_istream/ignore/wchar_t/3.cc b/libstdc++-v3/testsuite/27_io/basic_istream/ignore/wchar_t/3.cc
index 6c464c9..53c1f5a 100644
--- a/libstdc++-v3/testsuite/27_io/basic_istream/ignore/wchar_t/3.cc
+++ b/libstdc++-v3/testsuite/27_io/basic_istream/ignore/wchar_t/3.cc
@@ -19,6 +19,8 @@
// @require@ %-*.tst %-*.txt
// @diff@ %-*.tst %-*.txt
+// { dg-xfail-run-if "not supported on OR1K newlib" { or1k-*-elf } }
+
#include <istream>
#include <fstream>
#include <limits>
diff --git a/libstdc++-v3/testsuite/27_io/basic_istream/seekg/wchar_t/sstream.cc b/libstdc++-v3/testsuite/27_io/basic_istream/seekg/wchar_t/sstream.cc
index 43b3511..de063e3 100644
--- a/libstdc++-v3/testsuite/27_io/basic_istream/seekg/wchar_t/sstream.cc
+++ b/libstdc++-v3/testsuite/27_io/basic_istream/seekg/wchar_t/sstream.cc
@@ -22,6 +22,8 @@
// @require@ %-*.tst %-*.txt
// @diff@ %-*.tst %-*.txt
+// { dg-xfail-run-if "not supported on OR1K newlib" { or1k-*-elf } }
+
#include <istream>
#include <sstream>
#include <fstream>
diff --git a/libstdc++-v3/testsuite/27_io/basic_istream/tellg/wchar_t/sstream.cc b/libstdc++-v3/testsuite/27_io/basic_istream/tellg/wchar_t/sstream.cc
index 4cd901e..9d8f634 100644
--- a/libstdc++-v3/testsuite/27_io/basic_istream/tellg/wchar_t/sstream.cc
+++ b/libstdc++-v3/testsuite/27_io/basic_istream/tellg/wchar_t/sstream.cc
@@ -20,6 +20,8 @@
// @require@ %-*.tst %-*.txt
// @diff@ %-*.tst %-*.txt
+// { dg-xfail-run-if "not supported on OR1K newlib" { or1k-*-elf } }
+
#include <istream>
#include <sstream>
#include <fstream>
diff --git a/libstdc++-v3/testsuite/27_io/basic_ostream/inserters_other/wchar_t/1.cc b/libstdc++-v3/testsuite/27_io/basic_ostream/inserters_other/wchar_t/1.cc
index fe83ad3..6193103 100644
--- a/libstdc++-v3/testsuite/27_io/basic_ostream/inserters_other/wchar_t/1.cc
+++ b/libstdc++-v3/testsuite/27_io/basic_ostream/inserters_other/wchar_t/1.cc
@@ -19,6 +19,8 @@
// @require@ %-*.tst %-*.txt
// @diff@ %-*.tst %-*.txt
+// { dg-xfail-run-if "not supported on OR1K newlib" { or1k-*-elf } }
+
#include <ostream>
#include <sstream>
#include <fstream>
diff --git a/libstdc++-v3/testsuite/27_io/ios_base/sync_with_stdio/1.cc b/libstdc++-v3/testsuite/27_io/ios_base/sync_with_stdio/1.cc
index 1c9fa60..8ced491 100644
--- a/libstdc++-v3/testsuite/27_io/ios_base/sync_with_stdio/1.cc
+++ b/libstdc++-v3/testsuite/27_io/ios_base/sync_with_stdio/1.cc
@@ -23,6 +23,8 @@
// @require@ %-*.tst
// @diff@ %-*.tst %-*.txt
+// { dg-xfail-run-if "not supported on OR1K newlib" { or1k-*-elf } }
+
#include <cstdio>
#include <sstream>
#include <iostream>
diff --git a/libstdc++-v3/testsuite/27_io/objects/wchar_t/12048-1.cc b/libstdc++-v3/testsuite/27_io/objects/wchar_t/12048-1.cc
index 39458cd..f876d83 100644
--- a/libstdc++-v3/testsuite/27_io/objects/wchar_t/12048-1.cc
+++ b/libstdc++-v3/testsuite/27_io/objects/wchar_t/12048-1.cc
@@ -18,6 +18,8 @@
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
+// { dg-xfail-run-if "not supported on OR1K newlib" { or1k-*-elf } }
+
#include <iostream>
#include <cstdio>
#include <testsuite_hooks.h>
diff --git a/libstdc++-v3/testsuite/27_io/objects/wchar_t/12048-2.cc b/libstdc++-v3/testsuite/27_io/objects/wchar_t/12048-2.cc
index e048838..79955d8 100644
--- a/libstdc++-v3/testsuite/27_io/objects/wchar_t/12048-2.cc
+++ b/libstdc++-v3/testsuite/27_io/objects/wchar_t/12048-2.cc
@@ -15,6 +15,8 @@
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
+// { dg-xfail-run-if "not supported on OR1K newlib" { or1k-*-elf } }
+
#include <iostream>
#include <cstdio>
#include <cwchar>
diff --git a/libstdc++-v3/testsuite/27_io/objects/wchar_t/12048-3.cc b/libstdc++-v3/testsuite/27_io/objects/wchar_t/12048-3.cc
index 200f157..8eb30dd 100644
--- a/libstdc++-v3/testsuite/27_io/objects/wchar_t/12048-3.cc
+++ b/libstdc++-v3/testsuite/27_io/objects/wchar_t/12048-3.cc
@@ -18,6 +18,8 @@
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
+// { dg-xfail-run-if "not supported on OR1K newlib" { or1k-*-elf } }
+
#include <iostream>
#include <cwchar>
#include <cstdio>
diff --git a/libstdc++-v3/testsuite/27_io/objects/wchar_t/12048-4.cc b/libstdc++-v3/testsuite/27_io/objects/wchar_t/12048-4.cc
index ab4317b..6c6af65 100644
--- a/libstdc++-v3/testsuite/27_io/objects/wchar_t/12048-4.cc
+++ b/libstdc++-v3/testsuite/27_io/objects/wchar_t/12048-4.cc
@@ -15,6 +15,8 @@
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
+// { dg-xfail-run-if "not supported on OR1K newlib" { or1k-*-elf } }
+
#include <iostream>
#include <cstdio>
#include <cwchar>
--
2.7.3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment