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 8b106f9..dbf84e4 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/configure b/configure
index 32a3863..bf29580 100755
--- a/configure
+++ b/configure
@@ -3656,10 +3656,6 @@ case "${target}" in
     ;;
   *-*-rtems*)
     noconfigdirs="$noconfigdirs target-libgloss"
-    # this is not caught below because this stanza matches earlier
-    case $target in
-      or1k*-*-*) noconfigdirs="$noconfigdirs gdb" ;;
-    esac
     ;;
     # The tpf target doesn't support gdb yet.
   *-*-tpf*)
@@ -3865,9 +3861,6 @@ case "${target}" in
   nvptx*-*-*)
     noconfigdirs="$noconfigdirs target-libssp target-libstdc++-v3 target-libobjc"
     ;;
-  or1k*-*-*)
-    noconfigdirs="$noconfigdirs gdb"
-    ;;
   sh-*-*)
     case "${target}" in
       sh*-*-elf)
diff --git a/configure.ac b/configure.ac
index 1237749..65c346e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -984,10 +984,6 @@ case "${target}" in
     ;;
   *-*-rtems*)
     noconfigdirs="$noconfigdirs target-libgloss"
-    # this is not caught below because this stanza matches earlier
-    case $target in
-      or1k*-*-*) noconfigdirs="$noconfigdirs gdb" ;;
-    esac
     ;;
     # The tpf target doesn't support gdb yet.
   *-*-tpf*)
@@ -1193,9 +1189,6 @@ case "${target}" in
   nvptx*-*-*)
     noconfigdirs="$noconfigdirs target-libssp target-libstdc++-v3 target-libobjc"
     ;;
-  or1k*-*-*)
-    noconfigdirs="$noconfigdirs gdb"
-    ;;
   sh-*-*)
     case "${target}" in
       sh*-*-elf)
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 437db8e..3076fc1 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1643,6 +1643,10 @@ fipa-icf-variables
 Common Report Var(flag_ipa_icf_variables) Optimization
 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..4b4f5de
--- /dev/null
+++ b/gcc/common/config/or1k/or1k-common.c
@@ -0,0 +1,62 @@
+/* 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_1_PLUS, OPT_fsection_anchors, 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 ATTRIBUTE_UNUSED)
+{
+    /* 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 | MASK_CMOV | MASK_SEXT)
+
+struct gcc_targetm_common targetm_common = TARGETM_COMMON_INITIALIZER;
diff --git a/gcc/config.gcc b/gcc/config.gcc
index 6e75bd4..8375157 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -442,6 +442,9 @@ nios2-*-*)
 nvptx-*-*)
 	cpu_type=nvptx
 	;;
+or1k*-*-*)
+	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"
@@ -579,6 +582,14 @@ arm*-*-*)
 	tm_p_file="arm/arm-flags.h arm/arm-isa.h ${tm_p_file} arm/aarch-common-protos.h"
 	tm_file="vxworks-dummy.h ${tm_file}"
 	;;
+or1k-*-*)
+	tm_defines="${tm_defines} OR1K_DELAY_DEFAULT=OR1K_DELAY_ON"
+	tmake_file=or1k/t-or1k
+	;;
+or1knd-*-*)
+	tm_defines="${tm_defines} OR1K_DELAY_DEFAULT=OR1K_DELAY_OFF"
+	tmake_file=or1k/t-or1knd
+	;;
 mips*-*-* | sh*-*-* | sparc*-*-*)
 	tm_file="vxworks-dummy.h ${tm_file}"
 	;;
@@ -2334,6 +2345,21 @@ nvptx-*)
 		tm_file="${tm_file} nvptx/offload.h"
 	fi
 	;;
+or1k*-*-elf*)
+	tm_file="${tm_file} dbxelf.h elfos.h newlib-stdint.h"
+	tm_file="${tm_file} ${cpu_type}/newlib.h"
+	extra_parts="crti.o crtbegin.o crtend.o crtn.o"
+	;;
+or1k-*-linux-*)
+	tm_file="${tm_file} dbxelf.h elfos.h gnu-user.h linux.h"
+	tm_file="${tm_file} or1k/linux-elf.h uclibc-stdint.h"
+	tmake_file="${tmake_file} or1k/t-linux"
+	;;
+or1k*-*-rtems*)
+	tm_file="${tm_file} 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"
+	;;
 pdp11-*-*)
 	tm_file="${tm_file} newlib-stdint.h"
 	use_gcc_stdint=wrap
diff --git a/gcc/config/or1k/constraints.md b/gcc/config/or1k/constraints.md
new file mode 100644
index 0000000..cf8908c
--- /dev/null
+++ b/gcc/config/or1k/constraints.md
@@ -0,0 +1,62 @@
+;; 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_register_constraint "c" "SIBCALL_REGS"
+  "Registers which can hold a siling call address")
+
+(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 "G"
+  ""
+  (and (match_code "const_double")
+       (match_test "op == CONST0_RTX (mode)")))
diff --git a/gcc/config/or1k/linux-elf.h b/gcc/config/or1k/linux-elf.h
new file mode 100644
index 0000000..fb28f13
--- /dev/null
+++ b/gcc/config/or1k/linux-elf.h
@@ -0,0 +1,43 @@
+/* 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.  */
+
+#define NO_IMPLICIT_EXTERN_C
+
+#define TARGET_OS_CPP_BUILTINS() \
+  GNU_USER_TARGET_OS_CPP_BUILTINS ()
+
+#define GLIBC_DYNAMIC_LINKER "/lib/ld.so.1"
+
+#undef MUSL_DYNAMIC_LINKER
+#define MUSL_DYNAMIC_LINKER  "/lib/ld.so.1"
+
+#undef LINK_SPEC
+#define LINK_SPEC "%{h*}			\
+   %{static:-Bstatic}				\
+   %{shared:-shared}				\
+   %{symbolic:-Bsymbolic}			\
+   %{!static:					\
+     %{rdynamic:-export-dynamic}		\
+     %{!shared:-dynamic-linker " GNU_USER_DYNAMIC_LINKER "}}"
diff --git a/gcc/config/or1k/newlib.h b/gcc/config/or1k/newlib.h
new file mode 100644
index 0000000..bf16761
--- /dev/null
+++ b/gcc/config/or1k/newlib.h
@@ -0,0 +1,51 @@
+/* Definitions for using newlib userspace.
+   Copyright (C) 2016 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/>.  */
+
+
+#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}						\
+                            }"
+
+#define DRIVER_SELF_SPECS "%{!mno-newlib:-mnewlib}"
diff --git a/gcc/config/or1k/or1k-modes.def b/gcc/config/or1k/or1k-modes.def
new file mode 100644
index 0000000..3f5be61
--- /dev/null
+++ b/gcc/config/or1k/or1k-modes.def
@@ -0,0 +1,20 @@
+/* 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.  */
+
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..e831b06
--- /dev/null
+++ b/gcc/config/or1k/or1k-protos.h
@@ -0,0 +1,62 @@
+/* Definitions of target machine for GNU compiler, OR1K cpu.
+
+   Copyright (C) 2010 Embecosm Limited
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_OR1K_PROTOS_H
+#define GCC_OR1K_PROTOS_H
+
+/* The following are for general support. */
+extern bool        or1k_regnum_ok_for_base_p (unsigned, bool);
+extern int         or1k_trampoline_code_size (void);
+extern void        or1k_output_opcode (FILE *);
+
+/* The following are only needed when handling the machine definition. */
+#ifdef RTX_CODE
+extern void        or1k_init_expanders (void);
+extern void        or1k_expand_call (rtx, rtx, rtx);
+extern void        or1k_expand_prologue (void);
+extern void        or1k_expand_epilogue (void);
+extern bool        or1k_direct_return (void);
+extern void        or1k_expand_move (machine_mode mode, rtx, rtx);
+extern void        or1k_expand_compare(rtx *operands);
+extern machine_mode or1k_promote_mode(machine_mode, bool, const_tree);
+
+void or1k_expand_atomic_compare_and_swap (rtx operands[]);
+void or1k_expand_atomic_compare_and_swap_qihi (rtx operands[]);
+void or1k_expand_atomic_exchange (rtx operands[]);
+void or1k_expand_atomic_exchange_qihi (rtx operands[]);
+void or1k_expand_atomic_op (rtx_code, rtx, rtx, rtx, rtx);
+void or1k_expand_atomic_op_qihi (rtx_code, rtx, rtx, rtx, rtx);
+
+#endif
+
+extern int or1k_struct_alignment (tree);
+extern int or1k_data_alignment (tree, int);
+
+extern HOST_WIDE_INT or1k_initial_elimination_offset (unsigned, unsigned);
+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);
+
+#endif
diff --git a/gcc/config/or1k/or1k.c b/gcc/config/or1k/or1k.c
new file mode 100644
index 0000000..c6c057c
--- /dev/null
+++ b/gcc/config/or1k/or1k.c
@@ -0,0 +1,2343 @@
+/* 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 "backend.h"
+#include "target.h"
+#include "rtl.h"
+#include "tree.h"
+#include "stor-layout.h"
+#include "memmodel.h"
+#include "gimple.h"
+#include "tm_p.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 "calls.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"
+#include "sbitmap.h"
+#include "tm-constrs.h"
+#include "alias.h"
+#include "cfgrtl.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 the function, as documented in
+   the Architecture Manual's ABI section:
+
+   Incoming arguments
+                      <- AP, HFP
+   Saved LR           \           \
+   Saved HFP          | save_size |
+   Other saved regs   /           |
+                      <- FP       | total_size
+   Local Stack frame              |
+   Outgoing arguments             /
+                      <- SP
+
+   Note that there is also (by default) 128 bytes of "red zone"
+   which can be used by leaf functions.  In that case, save_size
+   may be non-zero while total_size is zero, and the registers
+   will be saved below SP.
+*/
+
+static struct
+{
+  HOST_WIDE_INT static_size;
+  HOST_WIDE_INT total_size;
+  int save_size;
+  unsigned int save_mask;
+} frame_info;
+
+/* Return true if REGNO must be saved for the current function.  */
+
+static bool
+or1k_save_reg_p (unsigned int regno)
+{
+  /* Check call-saved registers.  */
+  if (!call_used_regs[regno] && df_regs_ever_live_p (regno))
+    return true;
+
+  switch (regno)
+    {
+    case HARD_FRAME_POINTER_REGNUM:
+      return frame_pointer_needed;
+
+    case LINK_REGNUM:
+      return (!crtl->is_leaf
+	      || cfun->machine->force_lr_save
+	      || crtl->uses_pic_offset_table
+	      || df_regs_ever_live_p (regno));
+
+    case HW_TO_GCC_REGNO (25):
+    case HW_TO_GCC_REGNO (27):
+    case HW_TO_GCC_REGNO (29):
+    case HW_TO_GCC_REGNO (31):
+      /* See EH_RETURN_DATA_REGNO.  */
+      return crtl->calls_eh_return;
+
+    default:
+      return false;
+    }
+}
+
+/* Compute the stack layout for the current function, filling in
+   FRAME_INFO.  Return the total size of the stack frame.  */
+
+static HOST_WIDE_INT
+or1k_compute_frame_size ()
+{
+  HOST_WIDE_INT vars_size, args_size, total_size;
+  unsigned int save_mask = 0;
+  int save_size = 0;
+
+  for (unsigned int regno = 1; regno <= OR1K_LAST_HGR_REGNUM; regno++)
+    if (or1k_save_reg_p (regno))
+      {
+	save_size += UNITS_PER_WORD;
+	save_mask |= 1U << regno;
+      }
+
+  vars_size = get_frame_size ();
+  vars_size = OR1K_ALIGN (vars_size, UNITS_PER_WORD);
+  args_size = crtl->outgoing_args_size;
+  total_size = vars_size + save_size + args_size;
+
+  frame_info.static_size = total_size;
+  if (crtl->is_leaf && !cfun->calls_alloca)
+    {
+      if (total_size > or1k_redzone)
+	total_size -= or1k_redzone;
+      else
+	total_size = 0;
+    }
+  frame_info.total_size = total_size;
+  frame_info.save_size = save_size;
+  frame_info.save_mask = save_mask;
+
+  return total_size;
+}
+
+/* Eliminate AP and FP by returning the displacement to HFP or SP.  */
+
+HOST_WIDE_INT
+or1k_initial_elimination_offset (unsigned int from, unsigned int to)
+{
+  HOST_WIDE_INT offset = 0;
+  or1k_compute_frame_size ();
+
+  /* For FP, move up (negative) to the top of the frame.  */
+  if (from == FRAME_POINTER_REGNUM)
+    offset = -frame_info.save_size;
+  else
+    gcc_assert (from == ARG_POINTER_REGNUM);
+
+  /* For SP, move down (positive) to the bottom of the frame.  */
+  if (to == STACK_POINTER_REGNUM)
+    offset += frame_info.total_size;
+  else
+    gcc_assert (to == HARD_FRAME_POINTER_REGNUM);
+
+  return offset;
+}
+
+void
+or1k_expand_compare (rtx *operands)
+{
+  rtx sr_f = gen_rtx_REG (BImode, SR_F_REG);
+
+  /* Emit the given comparison into the Flag bit.  */
+  PUT_MODE (operands[0], BImode);
+  emit_insn (gen_rtx_SET (sr_f, operands[0]));
+
+  /* Adjust the operands for use in the caller.  */
+  operands[0] = gen_rtx_NE (VOIDmode, sr_f, const0_rtx);
+  operands[1] = sr_f;
+  operands[2] = const0_rtx;
+}
+
+/* A subroutine of the atomic operation splitters.  Jump to LABEL if
+   COND is true.  Mark the jump as unlikely to be taken.  */
+
+static void
+emit_unlikely_jump (rtx_code code, rtx label)
+{
+  int very_unlikely = REG_BR_PROB_BASE / 100 - 1;
+  rtx_insn *i;
+  rtx x;
+
+  x = gen_rtx_REG (BImode, SR_F_REG);
+  x = gen_rtx_fmt_ee (code, VOIDmode, x, const0_rtx);
+  x = gen_rtx_IF_THEN_ELSE (VOIDmode, x, label, pc_rtx);
+  i = emit_jump_insn (gen_rtx_SET (pc_rtx, x));
+  add_int_reg_note (i, REG_BR_PROB, very_unlikely);
+}
+
+static void
+emit_compare (rtx_code code, rtx a, rtx b)
+{
+  emit_insn (gen_rtx_SET (gen_rtx_REG (BImode, SR_F_REG),
+			  gen_rtx_fmt_ee (code, BImode, a, b)));
+}
+
+/* A subroutine of the atomic operation splitters.  Emit a load-locked
+   instruction in MODE.  */
+
+static void
+emit_load_locked (machine_mode mode, rtx reg, rtx mem)
+{
+  gcc_assert (mode == SImode);
+  emit_insn (gen_load_locked_si (reg, mem));
+}
+
+/* A subroutine of the atomic operation splitters.  Emit a store-conditional
+   instruction in MODE.  */
+
+static void
+emit_store_conditional (machine_mode mode, rtx mem, rtx val)
+{
+  gcc_assert (mode == SImode);
+  emit_insn (gen_store_conditional_si (mem, val));
+}
+
+/* A subroutine of the various atomic expanders.  For sub-word operations,
+   we must adjust things to operate on SImode.  Given the original MEM,
+   return a new aligned memory.  Also build and return the quantities by
+   which to shift and mask.  */
+
+static rtx
+or1k_adjust_atomic_subword (rtx orig_mem, rtx *pshift, rtx *pmask)
+{
+  rtx addr, align, shift, mask, mem;
+  machine_mode mode = GET_MODE (orig_mem);
+
+  addr = XEXP (orig_mem, 0);
+  addr = force_reg (Pmode, addr);
+
+  /* Aligned memory containing subword.  Generate a new memory.  We
+     do not want any of the existing MEM_ATTR data, as we're now
+     accessing memory outside the original object.  */
+  align = expand_binop (Pmode, and_optab, addr, GEN_INT (-4),
+			NULL_RTX, 1, OPTAB_LIB_WIDEN);
+  mem = gen_rtx_MEM (SImode, align);
+  MEM_VOLATILE_P (mem) = MEM_VOLATILE_P (orig_mem);
+  if (MEM_ALIAS_SET (orig_mem) == ALIAS_SET_MEMORY_BARRIER)
+    set_mem_alias_set (mem, ALIAS_SET_MEMORY_BARRIER);
+
+  /* Shift amount for subword relative to aligned word.  */
+  rtx mode_mask = GEN_INT (mode == QImode ? 3 : 2);
+  shift = expand_binop (SImode, and_optab, gen_lowpart (SImode, addr),
+			mode_mask, NULL_RTX, 1, OPTAB_LIB_WIDEN);
+  if (BYTES_BIG_ENDIAN)
+    shift = expand_binop (SImode, xor_optab, shift, mode_mask,
+			  shift, 1, OPTAB_LIB_WIDEN);
+  shift = expand_binop (SImode, ashl_optab, shift, GEN_INT (3),
+			shift, 1, OPTAB_LIB_WIDEN);
+  *pshift = shift;
+
+  /* Mask for insertion.  */
+  mask = expand_binop (SImode, ashl_optab, GEN_INT (GET_MODE_MASK (mode)),
+		       shift, NULL_RTX, 1, OPTAB_LIB_WIDEN);
+  *pmask = mask;
+
+  return mem;
+}
+
+static void
+or1k_finish_atomic_subword (machine_mode mode, rtx o, rtx n, rtx shift)
+{
+  n = expand_binop (SImode, lshr_optab, n, shift,
+		    NULL_RTX, 1, OPTAB_LIB_WIDEN);
+  emit_move_insn (o, gen_lowpart (mode, n));
+}
+
+/* Expand an atomic compare and swap operation.  */
+
+void
+or1k_expand_atomic_compare_and_swap (rtx operands[])
+{
+  rtx boolval, retval, mem, oldval, newval;
+  rtx label1, label2;
+  machine_mode mode;
+  bool is_weak;
+
+  boolval = operands[0];
+  retval = operands[1];
+  mem = operands[2];
+  oldval = operands[3];
+  newval = operands[4];
+  is_weak = (INTVAL (operands[5]) != 0);
+  mode = GET_MODE (mem);
+
+  if (reg_overlap_mentioned_p (retval, oldval))
+    oldval = copy_to_reg (oldval);
+
+  label1 = NULL_RTX;
+  if (!is_weak)
+    {
+      label1 = gen_rtx_LABEL_REF (VOIDmode, gen_label_rtx ());
+      emit_label (XEXP (label1, 0));
+    }
+  label2 = gen_rtx_LABEL_REF (VOIDmode, gen_label_rtx ());
+
+  emit_load_locked (mode, retval, mem);
+  emit_compare (EQ, retval, oldval);
+  emit_unlikely_jump (EQ, label2);
+  emit_store_conditional (mode, mem, newval);
+
+  if (!is_weak)
+    emit_unlikely_jump (EQ, label1);
+  emit_label (XEXP (label2, 0));
+
+  /* In all cases, SR_F contains 1 on success, and 0 on failure.  */
+  emit_insn (gen_sne_sr_f (boolval));
+}
+
+void
+or1k_expand_atomic_compare_and_swap_qihi (rtx operands[])
+{
+  rtx boolval, orig_retval, retval, scratch, mem, oldval, newval;
+  rtx label1, label2, mask, shift;
+  machine_mode mode;
+  bool is_weak;
+
+  boolval = operands[0];
+  orig_retval = operands[1];
+  mem = operands[2];
+  oldval = operands[3];
+  newval = operands[4];
+  is_weak = (INTVAL (operands[5]) != 0);
+  mode = GET_MODE (mem);
+
+  mem = or1k_adjust_atomic_subword (mem, &shift, &mask);
+
+  /* Shift and mask OLDVAL and NEWVAL into position with the word.  */
+  if (oldval != const0_rtx)
+    {
+      oldval = convert_modes (SImode, mode, oldval, 1);
+      oldval = expand_binop (SImode, ashl_optab, oldval, shift,
+			     NULL_RTX, 1, OPTAB_LIB_WIDEN);
+    }
+  if (newval != const0_rtx)
+    {
+      newval = convert_modes (SImode, mode, newval, 1);
+      newval = expand_binop (SImode, ashl_optab, newval, shift,
+			     NULL_RTX, 1, OPTAB_LIB_WIDEN);
+    }
+
+  label1 = NULL_RTX;
+  if (!is_weak)
+    {
+      label1 = gen_rtx_LABEL_REF (VOIDmode, gen_label_rtx ());
+      emit_label (XEXP (label1, 0));
+    }
+  label2 = gen_rtx_LABEL_REF (VOIDmode, gen_label_rtx ());
+
+  scratch = gen_reg_rtx (SImode);
+  emit_load_locked (SImode, scratch, mem);
+
+  retval = expand_binop (SImode, and_optab, scratch, mask,
+			 NULL_RTX, 1, OPTAB_LIB_WIDEN);
+  scratch = expand_binop (SImode, xor_optab, scratch, retval,
+			  scratch, 1, OPTAB_LIB_WIDEN);
+
+  emit_compare (EQ, retval, oldval);
+  emit_unlikely_jump (EQ, label2);
+
+  if (newval != const0_rtx)
+    scratch = expand_binop (SImode, ior_optab, scratch, newval,
+			    scratch, 1, OPTAB_LIB_WIDEN);
+
+  emit_store_conditional (SImode, mem, scratch);
+
+  if (!is_weak)
+    emit_unlikely_jump (EQ, label1);
+  emit_label (XEXP (label2, 0));
+
+  or1k_finish_atomic_subword (mode, orig_retval, retval, shift);
+
+  /* In all cases, CR0 contains EQ on success, and NE on failure.  */
+  emit_insn (gen_sne_sr_f (boolval));
+}
+
+/* Expand an atomic exchange operation.  */
+
+void
+or1k_expand_atomic_exchange (rtx operands[])
+{
+  rtx retval, mem, val, label;
+  machine_mode mode;
+
+  retval = operands[0];
+  mem = operands[1];
+  val = operands[2];
+  mode = GET_MODE (mem);
+
+  if (reg_overlap_mentioned_p (retval, val))
+    val = copy_to_reg (val);
+
+  label = gen_rtx_LABEL_REF (VOIDmode, gen_label_rtx ());
+  emit_label (XEXP (label, 0));
+
+  emit_load_locked (mode, retval, mem);
+  emit_store_conditional (mode, mem, val);
+  emit_unlikely_jump (EQ, label);
+}
+
+void
+or1k_expand_atomic_exchange_qihi (rtx operands[])
+{
+  rtx orig_retval, retval, mem, val, scratch;
+  rtx label, mask, shift;
+  machine_mode mode;
+
+  orig_retval = operands[0];
+  mem = operands[1];
+  val = operands[2];
+  mode = GET_MODE (mem);
+
+  mem = or1k_adjust_atomic_subword (mem, &shift, &mask);
+
+  /* Shift and mask VAL into position with the word.  */
+  if (val != const0_rtx)
+    {
+      val = convert_modes (SImode, mode, val, 1);
+      val = expand_binop (SImode, ashl_optab, val, shift,
+		          NULL_RTX, 1, OPTAB_LIB_WIDEN);
+    }
+
+  label = gen_rtx_LABEL_REF (VOIDmode, gen_label_rtx ());
+  emit_label (XEXP (label, 0));
+
+  scratch = gen_reg_rtx (SImode);
+  emit_load_locked (SImode, scratch, mem);
+
+  retval = expand_binop (SImode, and_optab, scratch, mask,
+			 NULL_RTX, 1, OPTAB_LIB_WIDEN);
+  scratch = expand_binop (SImode, xor_optab, scratch, retval,
+			  scratch, 1, OPTAB_LIB_WIDEN);
+  if (val != const0_rtx)
+    scratch = expand_binop (SImode, ior_optab, scratch, val,
+			    scratch, 1, OPTAB_LIB_WIDEN);
+
+  emit_store_conditional (SImode, mem, scratch);
+  emit_unlikely_jump (EQ, label);
+
+  or1k_finish_atomic_subword (mode, orig_retval, retval, shift);
+}
+
+/* Expand an atomic fetch-and-operate pattern.  CODE is the binary operation
+   to perform (with MULT as a stand-in for NAND).  MEM is the memory on which
+   to operate.  VAL is the second operand of the binary operator.  BEFORE and
+   AFTER are optional locations to return the value of MEM either before of
+   after the operation.  */
+
+void
+or1k_expand_atomic_op (rtx_code code, rtx mem, rtx val,
+		       rtx orig_before, rtx orig_after)
+{
+  machine_mode mode = GET_MODE (mem);
+  rtx before = orig_before, after = orig_after;
+  rtx label;
+
+  label = gen_rtx_LABEL_REF (VOIDmode, gen_label_rtx ());
+  emit_label (XEXP (label, 0));
+
+  if (before == NULL_RTX)
+    before = gen_reg_rtx (mode);
+
+  emit_load_locked (mode, before, mem);
+
+  if (code == MULT)
+    {
+      after = expand_binop (mode, and_optab, before, val,
+			    after, 1, OPTAB_LIB_WIDEN);
+      after = expand_unop (mode, one_cmpl_optab, after, after, 1);
+    }
+  else
+    after = expand_simple_binop (mode, code, before, val,
+				 after, 1, OPTAB_LIB_WIDEN);
+
+  emit_store_conditional (mode, mem, after);
+  emit_unlikely_jump (EQ, label);
+
+  if (orig_before)
+    emit_move_insn (orig_before, before);
+  if (orig_after)
+    emit_move_insn (orig_after, after);
+}
+
+void
+or1k_expand_atomic_op_qihi (rtx_code code, rtx mem, rtx val,
+			    rtx orig_before, rtx orig_after)
+{
+  machine_mode mode = GET_MODE (mem);
+  rtx label, mask, shift, x;
+  rtx before, after, scratch;
+
+  mem = or1k_adjust_atomic_subword (mem, &shift, &mask);
+
+  /* Shift and mask VAL into position with the word.  */
+  val = convert_modes (SImode, mode, val, 1);
+  val = expand_binop (SImode, ashl_optab, val, shift,
+		      NULL_RTX, 1, OPTAB_LIB_WIDEN);
+
+  switch (code)
+    {
+    case IOR:
+    case XOR:
+      /* We've already zero-extended VAL.  That is sufficient to
+	 make certain that it does not affect other bits.  */
+      break;
+
+    case AND:
+    case MULT: /* NAND */
+      /* If we make certain that all of the other bits in VAL are
+	 set, that will be sufficient to not affect other bits.  */
+      x = expand_unop (SImode, one_cmpl_optab, mask, NULL_RTX, 1);
+      val = expand_binop (SImode, ior_optab, val, x,
+			  val, 1, OPTAB_LIB_WIDEN);
+      break;
+
+    case PLUS:
+    case MINUS:
+      /* These will all affect bits outside the field and need
+	 adjustment via MASK within the loop.  */
+      break;
+
+    default:
+      gcc_unreachable ();
+    }
+
+  label = gen_rtx_LABEL_REF (VOIDmode, gen_label_rtx ());
+  emit_label (XEXP (label, 0));
+
+  before = scratch = gen_reg_rtx (SImode);
+  emit_load_locked (SImode, before, mem);
+
+  switch (code)
+    {
+    case IOR:
+    case XOR:
+    case AND:
+      after = expand_simple_binop (SImode, code, before, val,
+				   NULL_RTX, 1, OPTAB_LIB_WIDEN);
+      scratch = after;
+      break;
+
+    case PLUS:
+    case MINUS:
+      before = expand_binop (SImode, and_optab, scratch, mask,
+			     NULL_RTX, 1, OPTAB_LIB_WIDEN);
+      scratch = expand_binop (SImode, xor_optab, scratch, before,
+			      scratch, 1, OPTAB_LIB_WIDEN);
+      after = expand_simple_binop (SImode, code, before, val,
+				   NULL_RTX, 1, OPTAB_LIB_WIDEN);
+      after = expand_binop (SImode, and_optab, after, mask,
+			    after, 1, OPTAB_LIB_WIDEN);
+      scratch = expand_binop (SImode, ior_optab, scratch, after,
+			      scratch, 1, OPTAB_LIB_WIDEN);
+      break;
+
+    case MULT: /* NAND */
+      after = expand_binop (SImode, and_optab, before, val,
+			    NULL_RTX, 1, OPTAB_LIB_WIDEN);
+      after = expand_binop (SImode, xor_optab, after, mask,
+			    after, 1, OPTAB_LIB_WIDEN);
+      scratch = after;
+      break;
+
+    default:
+      gcc_unreachable ();
+    }
+
+  emit_store_conditional (SImode, mem, scratch);
+  emit_unlikely_jump (EQ, label);
+
+  if (orig_before)
+    or1k_finish_atomic_subword (mode, orig_before, before, shift);
+  if (orig_after)
+    or1k_finish_atomic_subword (mode, orig_after, after, shift);
+}
+
+/* Implement the TARGET_PRINT_OPERAND_PUNCT_VALID_P hook.  */
+
+static bool
+or1k_print_operand_punct_valid_p (unsigned char code)
+{
+  return code == '(';
+}
+
+static void
+output_addr_reloc (FILE *stream, rtx x, const char *reloc)
+{
+  fputs (reloc, stream);
+  fputc ('(', stream);
+  output_addr_const (stream, x);
+  fputc (')', stream);
+}
+
+static void
+print_lo_sum_reloc (FILE *stream, rtx x)
+{
+  const char *reloc = "lo";
+
+  if (GET_CODE (x) == CONST)
+    x = XEXP (x, 0);
+  if (GET_CODE (x) == UNSPEC)
+    {
+      switch (XINT (x, 1))
+	{
+	case UNSPEC_GOT:
+	  reloc = "got";
+	  break;
+	case UNSPEC_GOTOFF:
+	  reloc = "gotofflo";
+	  break;
+	case UNSPEC_TPOFF:
+	  reloc = "tpofflo";
+	  break;
+	case UNSPEC_GOTTPOFF:
+	  reloc = "gottpofflo";
+	  break;
+	case UNSPEC_TLSGD:
+	  reloc = "tlsgdlo";
+	  break;
+	default:
+	  output_operand_lossage("invalid lo_sum relocation");
+	}
+      x = XVECEXP (x, 0, 0);
+    }
+  else
+    gcc_assert(!flag_pic);
+  output_addr_reloc (stream, x, reloc);
+}
+
+static void
+print_high_reloc (FILE *stream, rtx x)
+{
+  const char *reloc = "hi";
+
+  if (GET_CODE (x) == CONST)
+    x = XEXP (x, 0);
+  if (GET_CODE (x) == UNSPEC)
+    {
+      switch (XINT (x, 1))
+	{
+	case UNSPEC_GOTOFF:
+	  reloc = "gotoffhi";
+	  break;
+	case UNSPEC_TPOFF:
+	  reloc = "tpoffhi";
+	  break;
+	case UNSPEC_GOTTPOFF:
+	  reloc = "gottpoffhi";
+	  break;
+	case UNSPEC_TLSGD:
+	  reloc = "tlsgdhi";
+	  break;
+	default:
+	  output_operand_lossage("invalid high relocation");
+	}
+      x = XVECEXP (x, 0, 0);
+    }
+  else
+    gcc_assert(!flag_pic);
+  output_addr_reloc (stream, x, reloc);
+}
+
+/* Prettify the assembly.  Indicate an instruction is filling a delay slot
+   by indenting it one space.  */
+
+static bool or1k_indent_opcode;
+
+void
+or1k_output_opcode (FILE *stream)
+{
+  if (or1k_indent_opcode)
+    {
+      putc (' ', stream);
+      or1k_indent_opcode = false;
+    }
+}
+
+/* Implement the TARGET_PRINT_OPERAND hook.  */
+static void
+or1k_print_operand (FILE *stream, rtx x, int code)
+{
+  switch (code)
+    {
+    case 'r':
+      if (REG_P (x))
+	fputs (reg_names[REGNO (x)], stream);
+      else if (x == CONST0_RTX (GET_MODE (x)))
+	fputs ("r0", stream);
+      else
+	output_operand_lossage ("invalid %%r value");
+      break;
+
+    case 'H':
+      if (REG_P (x))
+	fputs (reg_names[REGNO (x) + 1], stream);
+      else
+	output_operand_lossage ("invalid %%H value");
+      break;
+
+    case '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:
+	  output_operand_lossage ("invalid %%C value");
+	}
+      break;
+
+    case '(':
+      /* Output a 'nop' if there is nothing for the delay slot.  Or remember
+	 to add a space at the beginning of the next insn to indicate that
+	 it is filling the delay slot.  */
+      if (TARGET_DELAY_ON && dbr_sequence_length ())
+	or1k_indent_opcode = true;
+      else if (!TARGET_DELAY_OFF)
+	fprintf (stream, "\n\t l.nop");
+      break;
+
+    case 'h':
+      print_high_reloc (stream, x);
+      break;
+    case 'L':
+      print_lo_sum_reloc (stream, x);
+      break;
+
+    case 'P':
+      if (!flag_pic || SYMBOL_REF_LOCAL_P (x))
+	output_addr_const (stream, x);
+      else
+	output_addr_reloc (stream, x, "plt");
+      break;
+
+    case 0:
+      if (REG_P (x))
+	fputs (reg_names[REGNO (x)], stream);
+      else if (MEM_P (x))
+	output_address (GET_MODE(x), XEXP (x, 0));
+      else
+	output_addr_const (stream, x);
+      break;
+
+    default:
+      output_operand_lossage ("invalid %%xn code");
+    }
+}
+
+static void
+or1k_print_operand_address (FILE *stream, machine_mode, rtx addr)
+{
+  rtx offset;
+
+  switch (GET_CODE (addr))
+    {
+    case REG:
+      putc ('0', stream);
+      break;
+
+    case PLUS:
+      gcc_assert (REG_P (XEXP (addr, 0)));
+      offset = XEXP (addr, 1);
+      addr = XEXP (addr, 0);
+      output_addr_const (stream, offset);
+      break;
+
+    case LO_SUM:
+      offset = XEXP (addr, 1);
+      addr = XEXP (addr, 0);
+      print_lo_sum_reloc (stream, offset);
+      break;
+
+    default:
+      output_addr_const (stream, addr);
+      return;
+    }
+
+  fprintf (stream, "(%s)", reg_names[REGNO (addr)]);
+}
+
+/* -------------------------------------------------------------------------- */
+/*!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.                                           */
+/* -------------------------------------------------------------------------- */
+
+bool
+or1k_regnum_ok_for_base_p (unsigned num, bool strict)
+{
+  if (strict)
+    return (num < FIRST_PSEUDO_REGISTER
+	    ? IN_RANGE (num, 0, OR1K_LAST_HGR_REGNUM)
+	    : IN_RANGE (reg_renumber[num], 0, OR1K_LAST_HGR_REGNUM));
+  else
+    return num <= OR1K_LAST_SGR_REGNUM || num >= FIRST_PSEUDO_REGISTER;
+}
+
+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 satisfies_constraint_I (XEXP (XEXP (x, 0), 1));
+
+  return 1;
+}
+
+/* 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
+gen_sym_unspec (rtx x, int kind)
+{
+  return gen_rtx_CONST (Pmode, gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), kind));
+}
+
+static rtx
+or1k_legitimize_address_1 (rtx x, rtx scratch)
+{
+  rtx base, addend, t1, t2;
+  enum tls_model tls_kind = TLS_MODEL_NONE;
+  bool is_local = true;
+
+  split_const (x, &base, &addend);
+
+  switch (GET_CODE (base))
+    {
+    case REG:
+    case SUBREG:
+      break;
+
+    case SYMBOL_REF:
+      tls_kind = SYMBOL_REF_TLS_MODEL (base);
+      is_local = SYMBOL_REF_LOCAL_P (base);
+      /* FALLTHRU */
+
+    case LABEL_REF:
+      switch (tls_kind)
+	{
+	case TLS_MODEL_NONE:
+	  t1 = can_create_pseudo_p () ? gen_reg_rtx (Pmode) : scratch;
+	  if (!flag_pic)
+	    {
+	      emit_insn (gen_rtx_SET (t1, gen_rtx_HIGH (Pmode, x)));
+	      emit_insn (gen_rtx_SET (t1, gen_rtx_LO_SUM (Pmode, t1, x)));
+	      return t1;
+	    }
+	  else if (is_local)
+	    {
+	      crtl->uses_pic_offset_table = 1;
+	      t2 = gen_sym_unspec (x, UNSPEC_GOTOFF);
+	      emit_insn (gen_rtx_SET (t1, gen_rtx_HIGH (Pmode, t2)));
+	      t2 = gen_sym_unspec (x, UNSPEC_GOTOFF);
+	      emit_insn (gen_rtx_SET (t1, gen_rtx_LO_SUM (Pmode, t1, t2)));
+	      emit_insn (gen_add3_insn (t1, pic_offset_table_rtx, t1));
+	      return t1;
+	    }
+	  else
+	    {
+	      crtl->uses_pic_offset_table = 1;
+	      base = gen_sym_unspec (base, UNSPEC_GOT);
+	      t2 = gen_rtx_LO_SUM (Pmode, pic_offset_table_rtx, base);
+	      t2 = gen_const_mem (Pmode, t2);
+	      emit_insn (gen_rtx_SET (t1, t2));
+	      base = t1;
+	    }
+	  break;
+
+	case TLS_MODEL_GLOBAL_DYNAMIC:
+	case TLS_MODEL_LOCAL_DYNAMIC:
+	  /* TODO: For now, treat LD as GD */
+	  crtl->uses_pic_offset_table = 1;
+	  t1 = gen_reg_rtx (Pmode);
+	  t2 = gen_sym_unspec (base, UNSPEC_TLSGD);
+	  emit_insn (gen_rtx_SET (t1, gen_rtx_HIGH (Pmode, t2)));
+	  t2 = gen_sym_unspec (base, UNSPEC_TLSGD);
+	  emit_insn (gen_rtx_SET (t1, gen_rtx_LO_SUM (Pmode, t1, t2)));
+	  emit_insn (gen_add3_insn (t1, pic_offset_table_rtx, t1));
+	  base = gen_reg_rtx (Pmode);
+	  or1k_tls_call (base, t1);
+	  break;
+
+	case TLS_MODEL_INITIAL_EXEC:
+	  crtl->uses_pic_offset_table = 1;
+	  t1 = gen_reg_rtx (Pmode);
+	  t2 = gen_sym_unspec (base, UNSPEC_GOTTPOFF);
+	  emit_insn (gen_rtx_SET (t1, gen_rtx_HIGH (Pmode, t2)));
+	  t2 = gen_sym_unspec (base, UNSPEC_GOTTPOFF);
+	  emit_insn (gen_rtx_SET (t1, gen_rtx_LO_SUM (Pmode, t1, t2)));
+	  emit_insn (gen_add3_insn (t1, pic_offset_table_rtx, t1));
+	  t2 = force_reg (Pmode, gen_const_mem (Pmode, t1));
+	  t1 = gen_rtx_REG (Pmode, THREAD_PTR_REGNUM);
+	  base = gen_reg_rtx (Pmode);
+	  emit_insn (gen_add3_insn (base, t1, t2));
+	  break;
+
+	case TLS_MODEL_LOCAL_EXEC:
+	  t1 = gen_reg_rtx (Pmode);
+	  t2 = gen_sym_unspec (x, UNSPEC_TPOFF);
+	  emit_insn (gen_rtx_SET (t1, gen_rtx_HIGH (Pmode, t2)));
+	  t2 = gen_sym_unspec (x, UNSPEC_TPOFF);
+	  emit_insn (gen_rtx_SET (t1, gen_rtx_LO_SUM (Pmode, t1, t2)));
+	  t2 = gen_rtx_REG (Pmode, THREAD_PTR_REGNUM);
+	  emit_insn (gen_add3_insn (t1, t1, t2));
+	  return t1;
+
+	default:
+	  gcc_unreachable ();
+	}
+      break;
+
+    case UNSPEC:
+      /* Re-recognize what we've already emitted.  The CONST will
+	 have been stripped by split_const.  */
+      gcc_assert (GET_CODE (x) == CONST);
+      gcc_assert (base == XEXP (x, 0));
+      switch (XINT (base, 1))
+	{
+	case UNSPEC_GOTOFF:
+	case UNSPEC_TPOFF:
+	case UNSPEC_GOTTPOFF:
+	case UNSPEC_TLSGD:
+	  t1 = can_create_pseudo_p () ? gen_reg_rtx (Pmode) : scratch;
+	  emit_insn (gen_rtx_SET (t1, gen_rtx_HIGH (Pmode, copy_rtx (x))));
+	  emit_insn (gen_rtx_SET (t1, gen_rtx_LO_SUM (Pmode, t1, x)));
+	  return t1;
+
+	case UNSPEC_GOT:
+	default:
+	  gcc_unreachable ();
+	};
+      break;
+
+    default:
+      gcc_assert (can_create_pseudo_p ());
+      base = force_reg (Pmode, base);
+      break;
+    }
+
+  /* If we get here, we still have addend outstanding.  */
+  gcc_checking_assert (register_operand (base, Pmode));
+  if (addend == const0_rtx)
+    return base;
+  if (!satisfies_constraint_I (addend))
+    {
+      HOST_WIDE_INT i = INTVAL (addend);
+      HOST_WIDE_INT l = sext_hwi (i, 16);
+
+      t1 = can_create_pseudo_p () ? gen_reg_rtx (Pmode) : scratch;
+      t2 = can_create_pseudo_p () ? gen_reg_rtx (Pmode) : scratch;
+      emit_move_insn (t1, gen_int_mode (i - l, Pmode));
+      emit_insn (gen_add3_insn (t2, base, t1));
+      return plus_constant (Pmode, t2, l);
+    }
+  return gen_rtx_PLUS (Pmode, base, addend);
+}
+
+static rtx
+or1k_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
+                         enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+  return or1k_legitimize_address_1 (x, NULL_RTX);
+}
+
+/* In the name of slightly smaller debug output, and to cater to
+   general assembler lossage, recognize PIC+GOTOFF and turn it back
+   into a direct symbol reference.  */
+
+static rtx
+or1k_delegitimize_address (rtx x)
+{
+  if (GET_CODE (x) == CONST)
+    {
+      /* The LO_SUM to which X was attached has been stripped.
+	 Since the only legitimate address we could have been computing
+	 is that of the symbol, assume that's what we've done.  */
+      rtx inner = XEXP (x, 0);
+      if (GET_CODE (inner) == UNSPEC
+	  && XINT (inner, 1) == UNSPEC_GOTOFF)
+	return XVECEXP (inner, 0, 0);
+    }
+  else if (MEM_P (x))
+    {
+      rtx addr = XEXP (x, 0);
+      if (GET_CODE (addr) == LO_SUM
+	  && XEXP (addr, 0) == pic_offset_table_rtx)
+	{
+	  rtx inner = XEXP (addr, 1);
+	  if (GET_CODE (inner) == UNSPEC
+	      && XINT (inner, 1) == UNSPEC_GOT)
+	    return XVECEXP (inner, 0, 0);
+	}
+    }
+  return delegitimize_mem_from_attrs (x);
+}
+
+/* Primarily this is required for TLS symbols, but given that our move
+   patterns *ought* to be able to handle any symbol at any time, we
+   should never be spilling symbolic operands to the constant pool, ever.  */
+
+static bool
+or1k_cannot_force_const_mem (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
+{
+  enum rtx_code code = GET_CODE (x);
+  return (code == SYMBOL_REF
+	  || code == LABEL_REF
+	  || code == CONST
+	  || code == HIGH);
+}
+
+void
+or1k_expand_move (machine_mode mode, rtx op0, rtx op1)
+{
+  if (MEM_P (op0))
+    {
+      if (!reg_or_0_operand (op1, mode))
+	op1 = force_reg (mode, op1);
+    }
+  else if (mode == QImode || mode == HImode)
+    {
+      if (can_create_pseudo_p() && optimize > 0)
+	{
+	  if (CONST_INT_P (op1))
+	    {
+	      rtx reg = gen_reg_rtx (SImode);
+	      emit_insn (gen_rtx_SET (reg, op1));
+	      op1 = gen_lowpart (mode, reg);
+	    }
+	  else if (MEM_P (op1))
+	    {
+	      rtx reg = gen_reg_rtx (SImode);
+	      if (mode == QImode)
+		emit_insn (gen_zero_extendqisi2 (reg, op1));
+	      else
+		emit_insn (gen_zero_extendhisi2 (reg, op1));
+	      op1 = gen_lowpart (mode, reg);
+	    }
+	}
+    }
+  else if (mode == SImode)
+    {
+      switch (GET_CODE (op1))
+	{
+	case CONST:
+	case SYMBOL_REF:
+	case LABEL_REF:
+	  op1 = or1k_legitimize_address_1 (op1, op0);
+	  if (GET_CODE (op1) == PLUS)
+	    {
+	      emit_insn (gen_add3_insn (op0, XEXP (op1, 0), XEXP (op1, 1)));
+	      return;
+	    }
+	  break;
+
+	case CONST_INT:
+	  if (!input_operand (op1, mode))
+	    {
+	      rtx sub = can_create_pseudo_p () ? gen_reg_rtx (mode) : op0;
+	      HOST_WIDE_INT i = INTVAL (op1);
+	      HOST_WIDE_INT l = i & 0xffff;
+
+	      emit_insn (gen_rtx_SET (sub, gen_int_mode (i - l, mode)));
+	      emit_insn (gen_rtx_SET (op0, gen_rtx_IOR (mode, sub,
+							GEN_INT (l))));
+	      return;
+	    }
+	  break;
+
+	default:
+	  break;
+	}
+    }
+  emit_insn (gen_rtx_SET (op0, op1));
+}
+
+/* ========================================================================== */
+/* Functions to support the Machine Description                               */
+
+void
+or1k_expand_call (rtx retval, rtx fnaddr, rtx callarg1)
+{
+  rtx call, use = NULL;
+
+  /* Calls via the PLT require the PIC register.  */
+  if (flag_pic
+      && GET_CODE (XEXP (fnaddr, 0)) == SYMBOL_REF
+      && !SYMBOL_REF_LOCAL_P (XEXP (fnaddr, 0)))
+    {
+      crtl->uses_pic_offset_table = 1;
+      rtx hard_pic = gen_rtx_REG (Pmode, REAL_PIC_OFFSET_TABLE_REGNUM);
+      emit_move_insn (hard_pic, pic_offset_table_rtx);
+      use_reg (&use, hard_pic);
+    }
+
+  if (!call_insn_operand (XEXP (fnaddr, 0), Pmode))
+    {
+      fnaddr = copy_to_mode_reg (Pmode, XEXP (fnaddr, 0));
+      fnaddr = gen_rtx_MEM (SImode, fnaddr);
+    }
+
+  call = gen_rtx_CALL (VOIDmode, fnaddr, callarg1);
+  if (retval)
+    call = gen_rtx_SET (retval, call);
+  call = emit_call_insn (call);
+
+  CALL_INSN_FUNCTION_USAGE (call) = use;
+}
+
+/* Create a mem in the "frame" alias set at BASE+OFF.  */
+static rtx
+stack_disp_mem (rtx base, HOST_WIDE_INT off)
+{
+  rtx x = plus_constant (Pmode, base, off);
+  return gen_frame_mem (word_mode, x);
+}
+
+/* Save a register for the prologue, marking it for unwind info.  */
+static void
+prologue_save_reg (unsigned regno, rtx base, HOST_WIDE_INT off)
+{
+  rtx mem = stack_disp_mem (base, off);
+  rtx reg = gen_rtx_REG (word_mode, regno);
+  rtx insn = emit_insn (gen_rtx_SET (mem, reg));
+  RTX_FRAME_RELATED_P (insn) = 1;
+}
+
+/* Save all required registers for the prologue.
+   The stores happen in decending order below BASE+OFF.  */
+static void
+prologue_save_registers (unsigned int mask, rtx base, HOST_WIDE_INT off)
+{
+  /* The ABI specifies LR and FP saved immediately below the
+     hard frame pointer.  We might as well use the same layout
+     even when not using a frame pointer.  */
+  if ((mask >> LINK_REGNUM) & 1)
+    {
+      off -= UNITS_PER_WORD;
+      prologue_save_reg (LINK_REGNUM, base, off);
+    }
+  if ((mask >> HARD_FRAME_POINTER_REGNUM) & 1)
+    {
+      off -= UNITS_PER_WORD;
+      prologue_save_reg (HARD_FRAME_POINTER_REGNUM, base, off);
+    }
+
+  for (unsigned regno = 1; regno <= OR1K_LAST_HGR_REGNUM; regno++)
+    {
+      if (regno == LINK_REGNUM || regno == HARD_FRAME_POINTER_REGNUM)
+	continue;
+      if ((mask >> regno) & 1)
+	{
+	  off -= UNITS_PER_WORD;
+	  prologue_save_reg (regno, base, off);
+	}
+    }
+}
+
+/* True if the entire local stack frame is in the redzone.  */
+static inline bool
+or1k_frame_in_redzone (void)
+{
+  return frame_info.total_size <= or1k_redzone;
+}
+
+/* True if the entire register save area is in the redzone.  */
+static inline bool
+or1k_regs_in_redzone (void)
+{
+  return frame_info.save_size <= or1k_redzone;
+}
+
+/* Adjust the stack by +SIZE.  If MAYBE_FP_PROTECT, then we are allocating
+   the bulk of the stack frame and we might need to clobber the local frame.
+   If CFA_P, then emit unwind info for the adjustment.  Return the insn
+   that makes the adjustment.  */
+static rtx
+pro_epi_adjust_stack (HOST_WIDE_INT size, bool fp_protect, bool cfa_p)
+{
+  rtx size_rtx, x, insn;
+
+  if (size == 0)
+    return NULL_RTX;
+
+  x = size_rtx = GEN_INT (size);
+  if (!satisfies_constraint_I (x))
+    {
+      rtx r = gen_rtx_REG (Pmode, PROLOGUE_TMP);
+      emit_move_insn (r, x);
+      x = r;
+    }
+
+  if (fp_protect)
+    x = gen_frame_alloc (stack_pointer_rtx, stack_pointer_rtx, x);
+  else
+    x = gen_add2_insn (stack_pointer_rtx, x);
+  insn = emit_insn (x);
+  if (cfa_p)
+    {
+      rtx t = gen_rtx_PLUS (Pmode, stack_pointer_rtx, size_rtx);
+      t = gen_rtx_SET (stack_pointer_rtx, t);
+      REG_NOTES (insn) = alloc_reg_note (REG_CFA_ADJUST_CFA, t, NULL);
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+  return insn;
+}
+
+/* Return true if we can return directly from the function.  */
+bool
+or1k_direct_return (void)
+{
+  return frame_info.total_size == 0 && frame_info.save_mask == 0;
+}
+
+/* Expand code to construct the local stack frame.  */
+void
+or1k_expand_prologue (void)
+{
+  HOST_WIDE_INT total_size = frame_info.total_size;
+  unsigned int save_mask = frame_info.save_mask;
+  rtx insn;
+
+  if (flag_stack_usage_info)
+    current_function_static_stack_size = frame_info.static_size;
+
+  if (total_size == 0 && save_mask == 0)
+    goto fini;
+
+  if (or1k_regs_in_redzone ())
+    {
+      /* When the register save area is in the redzone, we can
+	 save the registers before allocating any stack space.
+	 This avoids a dependency on the stack register subtraction.  */
+      prologue_save_registers (save_mask, stack_pointer_rtx, 0);
+      save_mask = 0;
+
+      /* When a frame pointer is needed, we've not yet adjusted
+	 the stack pointer, so it's a straght copy.  */
+      if (frame_pointer_needed)
+	{
+	  insn = emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);
+	  RTX_FRAME_RELATED_P (insn) = 1;
+	}
+    }
+  else if (frame_pointer_needed || save_mask != 0)
+    {
+      /* When the register save area exceeds the redzone, we must
+	 allcate stack before saving.  In this first step, allocate
+	 no more than we can use as a memory offset.  */
+      HOST_WIDE_INT step = MIN (32760, total_size);
+      pro_epi_adjust_stack (-step, step == total_size, true);
+      prologue_save_registers (save_mask, stack_pointer_rtx, step);
+
+      /* When a frame pointer is needed, we must add back what we
+	 just subtracted from the stack pointer.  */
+      if (frame_pointer_needed)
+	{
+	  insn = emit_insn (gen_add3_insn (hard_frame_pointer_rtx,
+					   stack_pointer_rtx,
+					   GEN_INT (step)));
+	  RTX_FRAME_RELATED_P (insn) = 1;
+	}
+      total_size -= step;
+    }
+
+  /* Allocate the balance of the stack frame.  */
+  pro_epi_adjust_stack (-total_size, frame_pointer_needed,
+			!frame_pointer_needed);
+
+ fini:
+  /* Fix up, or remove, the insn that initialized the pic register.  */
+  rtx_insn *set_got_insn = cfun->machine->set_got_insn;
+  if (crtl->uses_pic_offset_table)
+    {
+      rtx reg = SET_DEST (PATTERN (set_got_insn));
+      rtx_insn *insn = emit_insn_before (gen_set_got (reg), set_got_insn);
+      RTX_FRAME_RELATED_P (insn) = 1;
+      add_reg_note (insn, REG_CFA_FLUSH_QUEUE, NULL_RTX);
+    }
+  delete_insn (set_got_insn);
+}
+
+/* Load a register for the epilogue.  Add the unwind info to *DWARF.  */
+static rtx
+epilogue_load_reg (unsigned regno, rtx base, HOST_WIDE_INT off, rtx *dwarf)
+{
+  rtx mem = stack_disp_mem (base, off);
+  rtx reg = gen_rtx_REG (word_mode, regno);
+  rtx insn = emit_insn (gen_rtx_SET (reg, mem));
+  if (dwarf)
+    *dwarf = alloc_reg_note (REG_CFA_RESTORE, reg, *dwarf);
+  return insn;
+}
+
+/* Load all required registers for the epilogue.  The loads happen in
+   decending order below BASE+OFF.  Add the unwind info to *DWARF.  */
+static rtx
+epilogue_load_registers (unsigned int mask, rtx base, HOST_WIDE_INT off,
+			 rtx *dwarf)
+{
+  /* Since OFF will always be aligned, -1 is safe for "unused".  */
+  HOST_WIDE_INT fp = -1;
+
+  if ((mask >> LINK_REGNUM) & 1)
+    {
+      off -= UNITS_PER_WORD;
+      /* Note that eh_return sets the LR -- do not overwrite it.  */
+      if (!crtl->calls_eh_return)
+	epilogue_load_reg (LINK_REGNUM, base, off, dwarf);
+    }
+  if ((mask >> HARD_FRAME_POINTER_REGNUM) & 1)
+    {
+      off -= UNITS_PER_WORD;
+      /* If we're using the frame pointer to do the restores,
+	 then restore it last.  */
+      if (base == hard_frame_pointer_rtx)
+	fp = off;
+      else
+	epilogue_load_reg (HARD_FRAME_POINTER_REGNUM, base, off, dwarf);
+    }
+
+  for (unsigned int regno = 1; regno <= OR1K_LAST_HGR_REGNUM; regno++)
+    {
+      if (regno == LINK_REGNUM || regno == HARD_FRAME_POINTER_REGNUM)
+	continue;
+      if ((mask >> regno) & 1)
+	{
+	  off -= UNITS_PER_WORD;
+	  epilogue_load_reg (regno, base, off, dwarf);
+	}
+    }
+
+  if (fp != -1)
+    return epilogue_load_reg (HARD_FRAME_POINTER_REGNUM, base, fp, dwarf);
+  else
+    return NULL_RTX;
+}
+
+/* Expand code to deconstruct the local stack frame.  */
+void
+or1k_expand_epilogue (void)
+{
+  HOST_WIDE_INT total_size = frame_info.total_size;
+  unsigned int save_mask = frame_info.save_mask;
+  rtx insn, dwarf = NULL_RTX, x;
+  bool regs_in_redzone = or1k_regs_in_redzone ();
+
+  if (frame_pointer_needed)
+    {
+      /* Deallocate (most of) the local stack frame.  */
+      if (total_size != 0)
+	{
+	  /* When the save registers are in the redzone, we can deallocate
+	     all of the stack now.  Otherwise, deallocate all but the saved
+	     registers.  In either case, this can be done via a simple
+	     addition from the HFP.  Be careful to block local frame accesses
+	     from crossing this boundary.  */
+	  if (regs_in_redzone)
+	    total_size = 0;
+	  else
+	    total_size = frame_info.save_size;
+	  emit_insn (gen_frame_alloc (stack_pointer_rtx,
+				      hard_frame_pointer_rtx,
+				      GEN_INT (-total_size)));
+	}
+
+      insn = epilogue_load_registers (save_mask, hard_frame_pointer_rtx,
+				      0, &dwarf);
+
+      /* Since we just restored the frame pointer, we must
+	 switch the CFA back to being based on the stack pointer.  */
+      x = plus_constant (Pmode, stack_pointer_rtx, total_size);
+      dwarf = alloc_reg_note (REG_CFA_DEF_CFA, x, dwarf);
+      REG_NOTES (insn) = dwarf;
+      RTX_FRAME_RELATED_P (insn) = 1;
+      dwarf = NULL_RTX;
+    }
+  else
+    {
+      if (regs_in_redzone)
+	{
+	  pro_epi_adjust_stack (total_size, false, true);
+	  total_size = 0;
+	}
+      else if (total_size >= 32768)
+	{
+	  HOST_WIDE_INT save_size = frame_info.save_size;
+	  pro_epi_adjust_stack (total_size - save_size, false, true);
+	  total_size = save_size;
+	}
+
+      epilogue_load_registers (save_mask, stack_pointer_rtx,
+			       total_size, &dwarf);
+    }
+
+  /* Finish stack frame deallocation.  This will only be needed if
+     the register save area is not in the redzone.  */
+  if (total_size != 0)
+    {
+      insn = pro_epi_adjust_stack (total_size, false, false);
+      dwarf = alloc_reg_note (REG_CFA_DEF_CFA, stack_pointer_rtx, dwarf);
+      REG_NOTES (insn) = dwarf;
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+  else if (dwarf)
+    {
+      insn = get_last_insn ();
+      REG_NOTES (insn) = dwarf;
+      RTX_FRAME_RELATED_P (insn) = 1;
+    }
+
+  /* Move up to the stack frame of an exception handler.  */
+  if (crtl->calls_eh_return)
+    emit_insn (gen_add2_insn (stack_pointer_rtx, EH_RETURN_STACKADJ_RTX));
+
+  /* Return instruction emitted in gen_epilogue.  */
+}
+
+/* ========================================================================== */
+/* 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.    */
+
+machine_mode
+or1k_promote_mode(machine_mode mode, bool, const_tree type)
+{
+  if ((type ? INTEGRAL_TYPE_P (type) : SCALAR_INT_MODE_P (mode))
+      && GET_MODE_SIZE (mode) < UNITS_PER_WORD)
+    mode = SImode;
+  return mode;
+}
+
+static rtx
+or1k_libcall_value (machine_mode mode, const_rtx /* func */)
+{
+  mode = or1k_promote_mode (mode, false, NULL);
+  return gen_rtx_REG (mode, GP_ARG_RETURN);
+}
+
+static rtx
+or1k_function_value (const_tree ret_type, const_tree /* fn_decl_or_type */,
+                     bool /* outgoing */)
+{
+  machine_mode mode = VOIDmode;
+  if (ret_type)
+    mode = TYPE_MODE (ret_type);
+  mode = or1k_promote_mode (mode, false, ret_type);
+  return gen_rtx_REG (mode, GP_ARG_RETURN);
+}
+
+
+/* Check if a function is suitable for tail call optimization,
+   implementing the TARGET_FUNCTION_OK_FOR_SIBCALL target hook.  */
+
+static bool
+or1k_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
+{
+  /* We can sibcall optimize any indirect function.  */
+  if (decl == NULL)
+    return true;
+
+  /* We can sibcall to any direct function if not PIC.  */
+  if (!flag_pic)
+    return true;
+
+  /* If the call may go through the PLT, we need r16 live.  */
+  if (!targetm.binds_local_p (decl))
+    return false;
+
+  return true;
+}
+
+/* -------------------------------------------------------------------------- */
+/*!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 () */
+
+
+/* -------------------------------------------------------------------------- */
+/*!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 () */
+
+
+/* -------------------------------------------------------------------------- */
+/*!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 (machine_mode, rtx x, bool strict)
+{
+  rtx base;
+
+  switch (GET_CODE (x))
+    {
+    case REG:
+      base = x;
+      break;
+
+    case LO_SUM:
+      base = XEXP (x, 0);
+      if (!REG_P (base))
+	return false;
+      x = XEXP (x, 1);
+      switch (GET_CODE (x))
+	{
+	case CONST:
+	  x = XEXP (x, 0);
+	  if (GET_CODE (x) != UNSPEC)
+	    return false;
+	  switch (XINT (x, 1))
+	    {
+	    case UNSPEC_GOT:
+	      /* Assume legitimize_address properly categorized the symbol.
+		 Continue to check the base.  */
+	      break;
+	    default:
+	      return false;
+	    }
+	  break;
+	default:
+	  return false;
+	}
+      break;
+
+    case PLUS:
+      base = XEXP (x, 0);
+      if (!REG_P (base))
+	return false;
+      x = XEXP (x, 1);
+
+      /* Register elimination is going to adjust all of these offsets.
+	 We might as well keep them as a unit until then.  */
+      if (!strict && (base == arg_pointer_rtx || base == frame_pointer_rtx))
+	return CONST_INT_P (x);
+
+      if (!satisfies_constraint_I (x))
+	return false;
+      break;
+
+    default:
+      return false;
+    }
+
+  return or1k_regnum_ok_for_base_p (REGNO (base), strict);
+}
+
+/* -------------------------------------------------------------------------- */
+/*!Initialize a trampoline for nested functions.
+
+   For the OR1K, we choose to re-use the return value (rv) register as
+   the static chain.
+
+	l.movhi r13,hi(nested_func)
+	l.movhi r11,hi(static_chain)
+	l.ori	r13,r13,lo(nested_func)
+	l.jr	r13
+	 l.ori	r11,r11,lo(static_chain)
+
+   @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.                                          */
+/* -------------------------------------------------------------------------- */
+
+int
+or1k_trampoline_code_size (void)
+{
+  // Need one more word in TARGET_DELAY_COMPAT mode for l.nop in delay slot.
+  int words = 5 + !!TARGET_DELAY_COMPAT;
+  return words * 4;
+}
+
+static void
+or1k_trampoline_init (rtx m_tramp, tree fndecl, rtx chain)
+{
+  rtx tramp[6], fnaddr, f_hi, f_lo, c_hi, c_lo;
+  int n;
+
+  fnaddr = force_reg (SImode, XEXP (DECL_RTL (fndecl), 0));
+  f_hi = expand_binop (SImode, lshr_optab, fnaddr, GEN_INT (16),
+		       NULL, true, OPTAB_DIRECT);
+  f_lo = expand_binop (SImode, and_optab, fnaddr, GEN_INT (0xffff),
+		       NULL, true, OPTAB_DIRECT);
+
+  chain = force_operand (chain, NULL);
+  c_hi = expand_binop (SImode, lshr_optab, chain, GEN_INT (16),
+		       NULL, true, OPTAB_DIRECT);
+  c_lo = expand_binop (SImode, and_optab, chain, GEN_INT (0xffff),
+		       NULL, true, OPTAB_DIRECT);
+
+  tramp[0] = expand_binop (SImode, ior_optab, f_hi,
+			   gen_int_mode (OR1K_MOVHI (13, 0), SImode),
+			   f_hi, true, OPTAB_DIRECT);
+  tramp[1] = expand_binop (SImode, ior_optab, c_hi,
+			   gen_int_mode (OR1K_MOVHI (11, 0), SImode),
+			   c_hi, true, OPTAB_DIRECT);
+  tramp[2] = expand_binop (SImode, ior_optab, f_lo,
+			   gen_int_mode (OR1K_ORI (13, 13, 0), SImode),
+			   f_lo, true, OPTAB_DIRECT);
+  tramp[3] = expand_binop (SImode, ior_optab, c_lo,
+			   gen_int_mode (OR1K_ORI (11, 11, 0), SImode),
+			   c_lo, true, OPTAB_DIRECT);
+  tramp[4] = gen_int_mode (OR1K_JR (13), SImode);
+
+  n = 5;
+  if (TARGET_DELAY_COMPAT)
+    tramp[n++] = gen_int_mode (OR1K_NOP, SImode);
+  else if (TARGET_DELAY_ON)
+    std::swap (tramp[3], tramp[4]);
+
+  /* Copy the trampoline code.  Leave any padding uninitialized.  */
+  for (int i = 0; i < n; ++i)
+    {
+      rtx mem = adjust_address (m_tramp, SImode, i * 4);
+      emit_move_insn (mem, tramp[i]);
+    }
+
+  /* Flushing the trampoline from the instruction cache needs
+     to be done here. */
+}
+
+/* -------------------------------------------------------------------------- */
+/*!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_LIBCALL_VALUE
+#define TARGET_LIBCALL_VALUE or1k_libcall_value
+#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
+
+#undef  TARGET_PROMOTE_PROTOTYPES
+#define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
+
+#undef  TARGET_PROMOTE_FUNCTION_MODE
+#define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote
+
+#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_DELEGITIMIZE_ADDRESS
+#define TARGET_DELEGITIMIZE_ADDRESS or1k_delegitimize_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.  */
+
+static bool
+or1k_legitimate_constant_p (machine_mode mode, rtx x)
+{
+  switch (GET_CODE (x))
+    {
+    case CONST_INT:
+    case CONST_WIDE_INT:
+    case HIGH:
+      /* We construct these, rather than spilling to memory.  */
+      return true;
+
+    case CONST_DOUBLE:
+      /* We construct these, rather than spilling to memory.  */
+      return mode == SFmode;
+
+    case CONST:
+    case SYMBOL_REF:
+    case LABEL_REF:
+      /* These may need to be split and not reconstructed.  */
+      if (or1k_tls_symbolic_operand (x) != TLS_MODEL_NONE)
+	return false;
+      return true;
+
+    default:
+      return false;
+    }
+}
+#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_PUNCT_VALID_P
+#define TARGET_PRINT_OPERAND_PUNCT_VALID_P or1k_print_operand_punct_valid_p
+
+#undef TARGET_PRINT_OPERAND
+#define TARGET_PRINT_OPERAND or1k_print_operand
+
+#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
+
+static bool
+or1k_rtx_costs (rtx x, machine_mode mode, int outer_code,
+		int opno ATTRIBUTE_UNUSED, int *total,
+		bool speed ATTRIBUTE_UNUSED)
+{
+  switch (GET_CODE (x))
+    {
+    case CONST_INT:
+    case CONST_DOUBLE:
+      if (x == CONST0_RTX (mode))
+	*total = 0;
+      else if ((outer_code == PLUS || outer_code == XOR || outer_code == MULT)
+	       && satisfies_constraint_I (x))
+	*total = 0;
+      else if ((outer_code == AND || outer_code == IOR)
+	       && satisfies_constraint_K (x))
+	*total = 0;
+      else if (satisfies_constraint_I (x)
+	       || satisfies_constraint_K (x)
+	       || satisfies_constraint_M (x))
+	*total = 2;
+      else
+	*total = COSTS_N_INSNS (2);
+      return true;
+
+    case HIGH:
+      /* This is effectively an 'M' constraint.  */
+      *total = 2;
+      return true;
+
+    case CONST:
+    case SYMBOL_REF:
+    case LABEL_REF:
+      if (outer_code == LO_SUM || outer_code == HIGH)
+	*total = 0;
+      else
+	{
+	  /* ??? Extra cost for GOT or TLS symbols.  */
+	  *total = COSTS_N_INSNS (1 + (outer_code != MEM));
+	}
+      return true;
+
+    case LO_SUM:
+    case PLUS:
+      if (outer_code == MEM)
+	{
+	  *total = 0;
+	  return true;
+	}
+      break;
+
+    default:
+      break;
+    }
+  return false;
+}
+
+#undef TARGET_RTX_COSTS
+#define TARGET_RTX_COSTS or1k_rtx_costs
+
+/* Create and initialize PIC register if required.  */
+static void
+or1k_init_pic_reg (void)
+{
+  start_sequence ();
+
+  cfun->machine->set_got_insn
+    = emit_insn (gen_set_got_tmp (pic_offset_table_rtx));
+
+  rtx_insn *seq = get_insns ();
+  end_sequence ();
+
+  edge entry_edge = single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun));
+  insert_insn_on_edge (seq, entry_edge);
+  commit_one_edge_insertion (entry_edge);
+}
+#undef TARGET_INIT_PIC_REG
+#define TARGET_INIT_PIC_REG or1k_init_pic_reg
+#undef TARGET_USE_PSEUDO_PIC_REG
+#define TARGET_USE_PSEUDO_PIC_REG hook_bool_void_true
+
+#undef TARGET_MIN_ANCHOR_OFFSET
+#define TARGET_MIN_ANCHOR_OFFSET  -32768
+#undef TARGET_MAX_ANCHOR_OFFSET
+#define TARGET_MAX_ANCHOR_OFFSET  32767
+
+/* 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..00d34d2
--- /dev/null
+++ b/gcc/config/or1k/or1k.h
@@ -0,0 +1,941 @@
+/* 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)
+
+/* 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
+#define WCHAR_TYPE_SIZE 32
+
+#define SIZE_TYPE "unsigned int"
+#define PTRDIFF_TYPE "int"
+#define WCHAR_TYPE "unsigned int"
+
+/* 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  1
+
+/* 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)  \
+    do { (MODE) = or1k_promote_mode (MODE, UNSIGNEDP, TYPE); } while (0)
+
+/*
+ * 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.  */
+
+/* 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
+
+/* TLS thread pointer register */
+#define THREAD_PTR_REGNUM		10
+
+/* Register in which static-chain is passed to a function.  */
+#define STATIC_CHAIN_REGNUM		11
+
+/* Register which may be clobbered while setting up the prologue.  */
+#define PROLOGUE_TMP			13
+
+/* Position Independent Code.  See or1k_init_pic_reg.  */
+#define REAL_PIC_OFFSET_TABLE_REGNUM	HW_TO_GCC_REGNO (16)
+
+/* ??? Follow i386 in working around gimple costing estimation, which
+   happens without properly initializing the pic_offset_table pseudo.  */
+#define PIC_OFFSET_TABLE_REGNUM \
+  (pic_offset_table_rtx ? INVALID_REGNUM : REAL_PIC_OFFSET_TABLE_REGNUM)
+
+/* Fake registers for the incoming argument pointer and soft frame pointer.  */
+#define ARG_POINTER_REGNUM		32
+#define FRAME_POINTER_REGNUM 		33
+
+/* 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_HGR_REGNUM	31
+#define OR1K_LAST_SGR_REGNUM	FRAME_POINTER_REGNUM
+#define FIRST_PSEUDO_REGISTER	(SR_CY_REG + 1)
+
+/* The standard ABI has no adjacent call-saved registers, which means
+   that DImode pseudos cannot be call-saved and will always be spilled
+   across calls.  To solve this without changing the ABI, remap the
+   compiler internal register numbers to place the even registers
+   R16-R30 in 24-31, and the odd registers R17-R31 in 16-23.  */
+
+#define HW_TO_GCC_REGNO(X)		\
+  ((X) < 16 || (X) > 31 ? (X)		\
+   : (X) & 1 ? ((X) - 16) / 2 + 16	\
+   : ((X) - 16) / 2 + 24)
+
+#define GCC_TO_HW_REGNO(X)		\
+  ((X) < 16 || (X) > 31 ? (X)		\
+   : (X) < 24 ? ((X) - 16) * 2 + 16	\
+   : ((X) - 24) * 2 + 16)
+
+#define DBX_REGISTER_NUMBER(X)  GCC_TO_HW_REGNO(X)
+
+#define REGISTER_NAMES						\
+  {"r0",   "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",	\
+   "r8",   "r9", "r10", "r11", "r12", "r13", "r14", "r15",	\
+   "r17", "r19", "r21", "r23", "r25", "r27", "r29", "r31",	\
+   "r16", "r18", "r20", "r22", "r24", "r26", "r28", "r30",	\
+   "argp", "frame", "F", "CY" }
+
+/* 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,	\
+  0, 0, 0, 0, 0, 0, 0, 0,	\
+  0, 0, 0, 0, 0, 0, 0, 0,	\
+  1, 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, 1, 1, 1, 1, 1, 1, \
+  0, 0, 0, 0, 0, 0, 0, 0, \
+  1, 1, 1, 1 }
+
+/* List the order in which to allocate registers.  Each register must
+   be listed once, even those in FIXED_REGISTERS.
+
+   ??? Note that placing REAL_PIC_OFFSET_TABLE_REGNUM (r16 = 24) first
+   happens to make it most likely selected *as* the pic register when
+   compiling without optimization, simply because the pic pseudo happens
+   to be allocated with the lowest pseudo regno.  */
+
+#define REG_ALLOC_ORDER { \
+  16, 17, 18, 19, 20, 21, 22, 23,	/* r17-r31 (odd), non-saved */	\
+  13, 15,				/* non-saved */			\
+  12, 11,				/* non-saved return values */	\
+  8, 7, 6, 5, 4, 3,			/* non-saved argument regs */	\
+  24,					/* r16, saved, pic reg */	\
+  25, 26, 27, 28, 29, 30, 31, 14,	/* r18-r31,r14 (even), saved */	\
+  2,					/* saved hard frame pointer */	\
+  9,					/* saved return address */	\
+  0,					/* fixed zero reg */		\
+  1,					/* fixed stack pointer */	\
+  10,					/* fixed thread pointer */	\
+  32, 33,				/* fixed ap, fp */		\
+  34, 35,				/* fixed sr[f], sr[cy] */	\
+}
+
+/* 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)
+
+/* The flag registers are 1 bit wide, and thus can only hold BImode...  */
+#define HARD_REGNO_MODE_OK(REGNO, MODE) \
+  (REGNO_REG_CLASS (REGNO) != FLAG_REGS || (MODE) == BImode)
+
+/* ... and thus the flag registers cannot change mode at all.  */
+#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
+  ((CLASS) >= FLAG_REGS ? (FROM) != (TO) : 0)
+
+/* 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)  4
+
+/* Register in which address to store a structure value
+   is passed to a function.  */
+/*#define STRUCT_VALUE_REGNUM 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.  */
+   
+enum reg_class 
+{ 
+  NO_REGS,
+  SIBCALL_REGS,
+  GENERAL_REGS,
+  FLAG_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",								\
+  "SIBCALL_REGS",							\
+  "GENERAL_REGS",   							\
+  "FLAG_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'.
+
+   SIBCALL_REGS must be call-clobbered, and not used as a temporary in the
+   epilogue.  This excludes R9 (LINK), R11 (STATIC_CHAIN),
+   and R13 (PROLOGUE_TMP).  */
+
+#define SIBCALL_REGS_MASK	0x00ff95f8u
+#define REG_CLASS_CONTENTS						\
+  {									\
+    { 0x00000000, 0x00000000 },		/* NO_REGS */			\
+    { SIBCALL_REGS_MASK, 0x00000000 },	/* SIBCALL_REGS */		\
+    { 0xffffffff, 0x00000003 },		/* GENERAL_REGS */		\
+    { 0x00000000, 0x0000000c },		/* FLAG_REGS */			\
+    { 0xffffffff, 0x0000000f }		/* 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.  */
+
+#define REGNO_REG_CLASS(R)					\
+  ((R) <= 31 && ((SIBCALL_REGS_MASK >> (R)) & 1) ? SIBCALL_REGS	\
+   : (R) <= OR1K_LAST_SGR_REGNUM ? GENERAL_REGS			\
+   : (R) < FIRST_PSEUDO_REGISTER ? FLAG_REGS			\
+   : ALL_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 
+
+/* 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)
+
+/* 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.  */
+#define EXIT_IGNORE_STACK 1
+
+/* 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.  */
+#ifdef REG_OK_STRICT
+#define REGNO_OK_FOR_BASE_P(num) or1k_regnum_ok_for_base_p ((num), true)
+#else
+#define REGNO_OK_FOR_BASE_P(num) or1k_regnum_ok_for_base_p ((num), false)
+#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 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
+
+
+/* -------------------------------------------------------------------------- */
+/* 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"
+
+/* -------------------------------------------------------------------------- */
+/* 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
+
+/* Prettify the assembly.  */
+#define ASM_OUTPUT_OPCODE(FILE, PTR)  or1k_output_opcode(FILE)
+
+/* This is how to output an element of a case-vector that is absolute.  */
+#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)
+
+/* 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)					\
+  fprintf (stream, "\t.align\t%d\n", 1 << (log))
+
+/* Invoked just before function output. */
+#define ASM_OUTPUT_FUNCTION_PREFIX(stream, fnname)			\
+  { fputs (".proc\t", stream); assemble_name (stream, fnname);		\
+    fputs ("\n", stream); }
+
+/* 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)
+
+/* 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 ()
+
+/* 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	HW_TO_GCC_REGNO (23)
+/* Use r25, r27, r29 and r31 (clobber regs) for exception data.
+   Recall that these are remapped consecutively.  */
+#define EH_RETURN_DATA_REGNO(N)	\
+    ((N) < 4 ? HW_TO_GCC_REGNO (25) + (N) : 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;
+  /* Remember where the set_got_placeholder is located.  */
+  rtx_insn *set_got_insn;
+} machine_function;
+
+#define TARGET_SUPPORTS_WIDE_INT 1
+
+#endif /* _OR1K_H_ */
diff --git a/gcc/config/or1k/or1k.md b/gcc/config/or1k/or1k.md
new file mode 100644
index 0000000..0f12060
--- /dev/null
+++ b/gcc/config/or1k/or1k.md
@@ -0,0 +1,1618 @@
+;; 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
+  (LINK_REGNUM 9)
+  (SR_F_REG 34)
+  (SR_CY_REG 35)
+])
+
+(define_c_enum "unspec" [
+  UNSPEC_GOT
+  UNSPEC_GOTOFF
+  UNSPEC_TPOFF
+  UNSPEC_GOTTPOFF
+  UNSPEC_TLSGD
+  UNSPEC_SET_GOT
+  UNSPEC_MSYNC
+])
+
+(define_c_enum "unspecv" [
+  UNSPECV_LL
+  UNSPECV_SC
+])
+
+(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")
+
+(define_mode_iterator I12 [QI HI])
+(define_mode_attr sz [(QI "b") (HI "h") (SI "w")])
+
+;; Save registers and allocate the stack frame.
+(define_expand "prologue"
+  [(use (const_int 1))]
+  ""
+{
+  or1k_expand_prologue ();
+  DONE;
+})
+
+;; Restore registers, deallocate the stack frame, and return.
+(define_expand "epilogue"
+  [(const_int 0)]
+  ""
+{
+  or1k_expand_epilogue ();
+  emit_jump_insn (gen_return ());
+  DONE;
+})
+
+;; Similar, but omit the return so that a subsequent "sibcall"
+;; pattern can be emitted.
+(define_expand "sibcall_epilogue"
+  [(const_int 0)]
+  ""
+{
+  or1k_expand_epilogue ();
+  emit_insn (gen_rtx_USE (VOIDmode, gen_rtx_REG (Pmode, LINK_REGNUM)));
+  DONE;
+})
+
+(define_insn "frame_alloc"
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+	(plus:SI (match_operand:SI 1 "register_operand" "r,r")
+		 (match_operand:SI 2 "reg_or_s16_operand" "r,I")))
+   (clobber (mem:BLK (match_scratch:SI 3 "=X,X")))
+   (clobber (reg:BI SR_CY_REG))]
+  ""
+  "@
+   l.add\t%0,%1,%2
+   l.addi\t%0,%1,%2"
+  [(set_attr "type" "add")])
+
+(define_expand "return"
+  [(parallel [(return)
+	      (use (reg:SI LINK_REGNUM))])]
+  "or1k_direct_return ()"
+  "")
+
+(define_insn "*return"
+  [(return)
+   (use (match_operand 0 "pmode_register_operand" ""))]
+  ""
+  "l.jr\t%0%("
+  [(set_attr "type" "jump")])
+
+(define_expand "simple_return"
+  [(parallel [(simple_return)
+	      (use (reg:SI LINK_REGNUM))])]
+  "")
+
+(define_insn "*simple_return"
+  [(simple_return)
+   (use (match_operand 0 "pmode_register_operand" ""))]
+  ""
+  "l.jr\t%0%("
+  [(set_attr "type" "jump")])
+
+;;
+;; movQI/movHI
+;;
+
+(define_expand "mov<mode>"
+  [(set (match_operand:I12 0 "general_operand" "")
+	(match_operand:I12 1 "general_operand" ""))]
+  ""
+{
+  or1k_expand_move (<MODE>mode, operands[0], operands[1]);
+  DONE;
+})
+
+(define_insn "*mov<mode>"
+  [(set (match_operand:I12 0 "nonimmediate_operand" "=m,r,r,r,r")
+	(match_operand:I12 1 "general_operand"      "rO,r,K,I,m"))]
+  "register_operand (operands[0], <MODE>mode)
+   || reg_or_0_operand (operands[1], <MODE>mode)"
+  "@
+   l.s<sz>\t%0,%r1
+   l.ori\t%0,%1,0
+   l.ori\t%0,r0,%1
+   l.xori\t%0,r0,%1
+   l.l<sz>z\t%0,%1"
+  [(set_attr "type" "store,logic,logic,logic,load")])
+
+;;
+;; movSI
+;;
+
+(define_expand "movsi"
+  [(set (match_operand:SI 0 "general_operand" "")
+	(match_operand:SI 1 "general_operand" ""))]
+  ""
+{
+  or1k_expand_move (SImode, operands[0], operands[1]);
+  DONE;
+})
+
+(define_insn "*movsi_insn"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=m,r,r,r,r,r,?r")
+        (match_operand:SI 1 "input_operand"        "rO,M,K,I,r,m,i"))]
+  "register_operand (operands[0], SImode)
+   || reg_or_0_operand (operands[1], SImode)"
+  "@
+   l.sw\t%0,%r1
+   l.movhi\t%0,hi(%1)
+   l.ori\t%0,r0,%1
+   l.xori\t%0,r0,%1
+   l.ori\t%0,%1,0
+   l.lwz\t%0,%1
+   #"
+  [(set_attr "type" "store,move,logic,logic,logic,load,unknown")])
+
+(define_split
+  [(set (match_operand:SI 0 "register_operand")
+	(match_operand:SI 1 "immediate_operand"))]
+  "!input_operand (operands[1], SImode)"
+  [(const_int 0)]
+{
+  or1k_expand_move (SImode, operands[0], operands[1]);
+  DONE;
+})
+
+(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,%L2"
+  [(set_attr "type" "logic")])
+
+(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,%h1"
+  [(set_attr "type" "move")])
+
+(define_expand "movdi"
+  [(set (match_operand:DI 0 "nonimmediate_operand")
+	(match_operand:DI 1 "general_operand"))]
+  ""
+{
+  or1k_expand_move (DImode, operands[0], operands[1]);
+  DONE;
+})
+
+(define_insn_and_split "*movdi"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,o,r")
+	(match_operand:DI 1 "general_operand"      " r,o,rO,n"))]
+  "register_operand (operands[0], DImode)
+   || reg_or_0_operand (operands[1], DImode)"
+  "#"
+  ""
+  [(const_int 0)]
+{
+  rtx l0 = operand_subword (operands[0], 0, 0, DImode);
+  rtx l1 = operand_subword (operands[1], 0, 0, DImode);
+  rtx h0 = operand_subword (operands[0], 1, 0, DImode);
+  rtx h1 = operand_subword (operands[1], 1, 0, DImode);
+
+  if (REG_P (l0) && reg_overlap_mentioned_p (l0, h1))
+    {
+      gcc_assert (!reg_overlap_mentioned_p (h0, l1));
+      emit_move_insn (h0, h1);
+      emit_move_insn (l0, l1);
+    }
+  else
+    {
+      emit_move_insn (l0, l1);
+      emit_move_insn (h0, h1);
+    }
+  DONE;
+})
+
+;;
+;; Conditional Branches & Moves
+;; 
+
+; ??? Perhaps delay this expansion until after reload.  We may be
+; committing too early as to the sense of the comparison we use to
+; make the most of our immediate operands.
+(define_expand "cbranchsi4"
+  [(set (pc)
+	(if_then_else
+	  (match_operator 0 "ordered_comparison_operator"
+	    [(match_operand:SI 1 "reg_or_0_operand")
+	     (match_operand:SI 2 "reg_or_s16_operand")])
+	  (label_ref (match_operand 3 ""))
+	  (pc)))]
+   ""
+{
+  or1k_expand_compare (operands);
+})
+
+; ??? Note that we only support eq ge gt le lt ne.
+; There are no opcodes for (un)ordered comparisons.
+; Reject these and hope they go to the library.
+(define_expand "cbranchsf4"
+  [(set (pc)
+	(if_then_else
+	  (match_operator 0 "ordered_comparison_operator"
+	    [(match_operand:SF 1 "register_operand")
+	     (match_operand:SF 2 "register_operand")])
+	  (label_ref (match_operand 3 ""))
+	  (pc)))]
+   "TARGET_HARD_FLOAT"
+{
+  if (!ordered_comparison_operator (operands[0], VOIDmode))
+    FAIL;
+  or1k_expand_compare (operands);
+})
+
+(define_insn "*bf"
+  [(set (pc)
+	(if_then_else (ne (reg:BI SR_F_REG) (const_int 0))
+	  (label_ref (match_operand 0 "" ""))
+	  (pc)))]
+  ""
+  "l.bf\t%l0%("
+  [(set_attr "type" "branch")])
+
+(define_insn "*bnf"
+  [(set (pc)
+	(if_then_else (eq (reg:BI SR_F_REG) (const_int 0))
+	  (label_ref (match_operand 0 "" ""))
+	  (pc)))]
+  ""
+  "l.bnf\t%l0%("
+  [(set_attr "type" "branch")])
+
+(define_expand "movsicc"
+  [(set (reg:BI SR_F_REG) (match_operand 1 "comparison_operator" ""))
+   (set (match_operand:SI 0 "register_operand" "")
+	(if_then_else:SI
+	  (ne (reg:BI SR_F_REG) (const_int 0))
+	  (match_operand:SI 2 "reg_or_0_operand" "")
+	  (match_operand:SI 3 "reg_or_0_operand" "")))]
+  "TARGET_CMOV"
+{
+  PUT_MODE (operands[1], BImode);
+})
+
+(define_insn "*cmovsi_f"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(if_then_else:SI
+	  (ne (reg:BI SR_F_REG) (const_int 0))
+	  (match_operand:SI 1 "reg_or_0_operand" "rO")
+	  (match_operand:SI 2 "reg_or_0_operand" "rO")))]
+  "TARGET_CMOV"
+  "l.cmov\t%0,%r1,%r2")
+
+(define_insn "*cmovsi_nf"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(if_then_else:SI
+	  (eq (reg:BI SR_F_REG) (const_int 0))
+	  (match_operand:SI 1 "reg_or_0_operand" "rO")
+	  (match_operand:SI 2 "reg_or_0_operand" "rO")))]
+  "TARGET_CMOV"
+  "l.cmov\t%0,%r2,%r1")
+
+(define_expand "cstoresi4"
+  [(set (match_operand:SI 0 "register_operand")
+	(match_operator:SI 1 "ordered_comparison_operator"
+	  [(match_operand:SI 2 "reg_or_0_operand")
+	   (match_operand:SI 3 "nonmemory_operand")]))]
+  ""
+{
+  rtx_code code = GET_CODE (operands[1]);
+  rtx out = operands[0];
+  rtx in0 = operands[2];
+  rtx in1 = operands[3];
+  bool need_inv = false;
+  bool need_swap = false;
+  bool need_zero = false;
+  bool need_reg = false;
+
+ restart:
+  switch (code)
+    {
+    case EQ:
+      need_inv = true;
+      /* fallthru */
+    case NE:
+      need_zero = in1 != const0_rtx;
+      need_reg = !reg_or_s16_operand(in1, SImode);
+      break;
+
+    case LEU:
+      if (CONST_INT_P (in1) && INTVAL (in1) != -1)
+	{
+	  in1 = gen_int_mode (INTVAL (in1) + 1, SImode);
+	  code = LTU;
+	  goto do_ltu_i;
+	}
+      need_swap = true;
+      goto do_geu;
+
+    case GTU:
+      if (CONST_INT_P (in1) && INTVAL (in1) != -1)
+	{
+	  in1 = gen_int_mode (INTVAL (in1) + 1, SImode);
+	  code = GEU;
+	  goto do_geu;
+	}
+      need_swap = true;
+      goto do_ltu_r;
+
+    case GEU:
+    do_geu:
+      if (sgeui_operand (in1, SImode))
+	break;
+      need_inv = true;
+      goto do_ltu_r;
+
+    case LTU:
+    do_ltu_i:
+      if (sgeui_operand (in1, SImode))
+	{
+	  need_inv = true;
+	  break;
+	}
+    do_ltu_r:
+      need_reg = !reg_or_0_operand (in1, SImode);
+      break;
+
+    case LT:
+      if (in1 == const0_rtx)
+	break;
+      goto do_default;
+
+    case GE:
+      if (in1 == const0_rtx)
+	{
+	  need_inv = true;
+	  break;
+	}
+      goto do_default;
+
+    default:
+    do_default:
+      if (TARGET_CMOV)
+	goto do_cmov;
+      if (optimize_size)
+	FAIL;
+      rtx min = force_reg (SImode, gen_int_mode (0x80000000, SImode));
+      in0 = expand_binop (SImode, add_optab, in0, min, NULL, 1, OPTAB_DIRECT);
+      if (CONST_INT_P (in1))
+	in1 = gen_int_mode (INTVAL (in1) + 0x80000000, SImode);
+      else
+	in1 = expand_binop (SImode, add_optab, in1, min, NULL, 1, OPTAB_DIRECT);
+      code = unsigned_condition (code);
+      goto restart;
+    }
+
+  /* Use l.cmov unless it's more expensive.  */
+  if (TARGET_CMOV
+      && (3 + !reg_or_s16_operand (in1, SImode)
+	  <= 2 + need_inv + need_zero + need_reg))
+    {
+    do_cmov:
+      if (!reg_or_s16_operand (in1, SImode))
+	in1 = force_reg (SImode, in1);
+      if (GET_CODE (operands[1]) != code || operands[3] != in1)
+	{
+	  operands[1] = gen_rtx_fmt_ee (code, SImode, in0, in1);
+	  operands[3] = in1;
+	}
+      or1k_expand_compare (operands + 1);
+      PUT_MODE (operands[1], SImode);
+      emit_insn (gen_rtx_SET (out, operands[1]));
+      DONE;
+    }
+
+  if (need_swap)
+    {
+      std::swap (in0, in1);
+      code = swap_condition (code);
+    }
+  if (need_inv)
+    code = reverse_condition (code);
+  if (need_reg)
+    in1 = force_reg (SImode, in1);
+  if (need_zero)
+    {
+      emit_insn (gen_xorsi3 (out, in0, in1));
+      in0 = out;
+      in1 = const0_rtx;
+    }
+
+  switch (code)
+    {
+    case NE:
+      emit_insn (gen_sne_sr_cy (out, in0));
+      break;
+    case LT:
+      emit_insn (gen_lshrsi3 (out, in0, GEN_INT (31)));
+      break;
+    case LTU:
+      emit_insn (gen_sltu_sr_cy (out, in0, in1));
+      break;
+    case GEU:
+      emit_insn (gen_sgeui_sr_cy (out, in0, in1));
+      break;
+    default:
+      gcc_unreachable ();
+    }
+
+  if (need_inv)
+    emit_insn (gen_xorsi3 (out, out, const1_rtx));
+  DONE;
+})
+
+;; ??? See cbranchsf4.
+(define_expand "cstoresf4"
+  [(set (match_operand:SI 0 "register_operand")
+	(match_operator:SI 1 "ordered_comparison_operator"
+	  [(match_operand:SF 2 "register_operand")
+	   (match_operand:SF 3 "register_operand")]))]
+   "TARGET_CMOV && TARGET_HARD_FLOAT"
+{
+  if (!ordered_comparison_operator (operands[1], VOIDmode))
+    FAIL;
+  or1k_expand_compare (operands + 1);
+  PUT_MODE (operands[1], SImode);
+  emit_insn (gen_rtx_SET (operands[0], operands[1]));
+  DONE;
+})
+
+;; Being able to copy SR_F to a general register even without CMOV
+;; is helpful for the atomic insns, wherein the usual usage is to
+;; test the success of the compare-and-swap.  Leaving the success
+;; flag in SR_F means that we can in those cases avoid an extra compare
+;; and avoid the additional setting of a general register.
+;; Therefore, we allow for scc to operate without CMOV, but fail to
+;; advertise cstoresi4 without CMOV.
+
+(define_expand "sne_sr_f"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(ne:SI (reg:BI SR_F_REG) (const_int 0)))]
+  "")
+
+(define_insn "*scc"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(match_operator:SI 1 "equality_comparison_operator"
+	  [(reg:BI SR_F_REG) (const_int 0)]))]
+  ""
+  "#")
+
+(define_split
+  [(set (match_operand:SI 0 "register_operand")
+	(match_operator:SI 1 "equality_comparison_operator"
+	  [(reg:BI SR_F_REG) (const_int 0)]))]
+  "TARGET_CMOV"
+  [(set (match_dup 0) (const_int 1))
+   (set (match_dup 0)
+	(if_then_else:SI (match_dup 1)
+	  (match_dup 0)
+	  (const_int 0)))]
+  "")
+
+(define_split
+  [(set (match_operand:SI 0 "register_operand")
+	(match_operator:SI 1 "equality_comparison_operator"
+	  [(reg:BI SR_F_REG) (const_int 0)]))]
+  "!TARGET_CMOV && reload_completed"
+  [(const_int 0)]
+{
+  emit_move_insn (operands[0], const1_rtx);
+
+  rtx label = gen_label_rtx ();
+  rtx x = gen_rtx_LABEL_REF (Pmode, label);
+  x = gen_rtx_IF_THEN_ELSE (VOIDmode, operands[1], x, pc_rtx);
+  emit_jump_insn (gen_rtx_SET (pc_rtx, x));
+
+  emit_move_insn (operands[0], const0_rtx);
+
+  emit_label (label);
+  DONE;
+})
+
+(define_insn_and_split "sne_sr_cy"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(ne:SI (match_operand:SI 1 "register_operand" "r")
+	       (const_int 0)))
+   (clobber (reg:BI SR_CY_REG))]
+  ""
+  "#"
+  "reload_completed"
+  [(const_int 0)]
+{
+  emit_insn (gen_addsi_co (operands[0], operands[1], constm1_rtx));
+  emit_insn (gen_addsi_ci (operands[0], const0_rtx, const0_rtx));
+  DONE;
+})
+
+(define_insn_and_split "*add1_sne_sr_cy"
+  [(set (match_operand:SI 0 "register_operand" "=&r")
+	(plus:SI
+	  (ne:SI (match_operand:SI 1 "register_operand" "r")
+	         (const_int 0))
+	  (match_operand:SI 2 "reg_or_s16_operand" "rI")))
+   (clobber (reg:BI SR_CY_REG))]
+  ""
+  "#"
+  "reload_completed"
+  [(const_int 0)]
+{
+  emit_insn (gen_addsi_co (operands[0], operands[1], constm1_rtx));
+  emit_insn (gen_addsi_ci (operands[0], const0_rtx, operands[2]));
+  DONE;
+})
+
+(define_insn_and_split "*add2_sne_sr_cy"
+  [(set (match_operand:SI 0 "register_operand" "=&r")
+	(plus:SI
+	  (plus:SI
+	    (ne:SI (match_operand:SI 1 "register_operand" "r")
+	           (const_int 0))
+	    (match_operand:SI 2 "register_operand" "%r"))
+	  (match_operand:SI 3 "reg_or_s16_operand" "rI")))
+   (clobber (reg:BI SR_CY_REG))]
+  ""
+  "#"
+  "reload_completed"
+  [(const_int 0)]
+{
+  emit_insn (gen_addsi_co (operands[0], operands[1], constm1_rtx));
+  emit_insn (gen_addsi_ci (operands[0], operands[2], operands[3]));
+  DONE;
+})
+
+(define_insn_and_split "sltu_sr_cy"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(ltu:SI (match_operand:SI 1 "reg_or_0_operand" "rO")
+		(match_operand:SI 2 "reg_or_0_operand" "rO")))
+   (clobber (reg:BI SR_CY_REG))]
+  ""
+  "#"
+  "reload_completed"
+  [(const_int 0)]
+{
+  emit_insn (gen_subsi_co (operands[0], operands[1], operands[2]));
+  emit_insn (gen_addsi_ci (operands[0], const0_rtx, const0_rtx));
+  DONE;
+})
+
+(define_insn_and_split "*add1_slt_sr_cy"
+  [(set (match_operand:SI 0 "register_operand" "=&r")
+	(plus:SI
+	  (ltu:SI
+	    (match_operand:SI 1 "register_operand" "r")
+	    (match_operand:SI 2 "register_operand" "r"))
+	  (match_operand:SI 3 "reg_or_s16_operand" "rI")))
+   (clobber (reg:BI SR_CY_REG))]
+  ""
+  "#"
+  "reload_completed"
+  [(const_int 0)]
+{
+  emit_insn (gen_subsi_co (operands[0], operands[1], operands[2]));
+  emit_insn (gen_addsi_ci (operands[0], const0_rtx, operands[3]));
+  DONE;
+})
+
+(define_insn_and_split "*add2_slt_sr_cy"
+  [(set (match_operand:SI 0 "register_operand" "=&r")
+	(plus:SI
+	  (plus:SI
+	    (ltu:SI
+	      (match_operand:SI 1 "register_operand" "r")
+	      (match_operand:SI 2 "register_operand" "r"))
+	    (match_operand:SI 3 "register_operand" "%r"))
+	  (match_operand:SI 4 "reg_or_s16_operand" "rI")))
+   (clobber (reg:BI SR_CY_REG))]
+  ""
+  "#"
+  "reload_completed"
+  [(const_int 0)]
+{
+  emit_insn (gen_subsi_co (operands[0], operands[1], operands[2]));
+  emit_insn (gen_addsi_ci (operands[0], operands[3], operands[4]));
+  DONE;
+})
+
+(define_insn_and_split "sgeui_sr_cy"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(geu:SI (match_operand:SI 1 "register_operand" "r")
+		(match_operand:SI 2 "sgeui_operand" "n")))
+   (clobber (reg:BI SR_CY_REG))]
+  ""
+  "#"
+  "&& reload_completed"
+  [(const_int 0)]
+{
+  HOST_WIDE_INT c = INTVAL (operands[2]);
+  emit_insn (gen_addsi_co (operands[0], operands[1], GEN_INT (-c)));
+  emit_insn (gen_addsi_ci (operands[0], const0_rtx, const0_rtx));
+  DONE;
+})
+
+(define_insn_and_split "*add1_sgeui_sr_cy"
+  [(set (match_operand:SI 0 "register_operand" "=&r")
+	(plus:SI
+	  (geu:SI (match_operand:SI 1 "register_operand" "r")
+		  (match_operand:SI 2 "sgeui_operand" "n"))
+	  (match_operand:SI 3 "reg_or_s16_operand" "rI")))
+   (clobber (reg:BI SR_CY_REG))]
+  ""
+  "#"
+  "&& reload_completed"
+  [(const_int 0)]
+{
+  HOST_WIDE_INT c = INTVAL (operands[2]);
+  /* See sgeui_operand comments.  */
+  c = (c < 0 ? -c : -1 - (c + 1));
+  emit_insn (gen_addsi_co (operands[0], operands[1], GEN_INT (c)));
+  emit_insn (gen_addsi_ci (operands[0], const0_rtx, operands[3]));
+  DONE;
+})
+
+(define_insn_and_split "*add2_sgeui_sr_cy"
+  [(set (match_operand:SI 0 "register_operand" "=&r")
+	(plus:SI
+	  (plus:SI
+	    (geu:SI (match_operand:SI 1 "register_operand" "r")
+		    (match_operand:SI 2 "sgeui_operand" "n"))
+	    (match_operand:SI 3 "register_operand" "%r"))
+	  (match_operand:SI 4 "reg_or_s16_operand" "rI")))
+   (clobber (reg:BI SR_CY_REG))]
+  ""
+  "#"
+  "&& reload_completed"
+  [(const_int 0)]
+{
+  HOST_WIDE_INT c = INTVAL (operands[2]);
+  /* See sgeui_operand comments.  */
+  c = (c < 0 ? -c : -1 - (c + 1));
+  emit_insn (gen_addsi_co (operands[0], operands[1], GEN_INT (c)));
+  emit_insn (gen_addsi_ci (operands[0], operands[3], operands[4]));
+  DONE;
+})
+
+;;
+;; Setting SR[F] from comparision
+;;
+
+(define_insn "*comparesi"
+  [(set (reg:BI SR_F_REG)
+	(match_operator:BI 2 "ordered_comparison_operator"
+	  [(match_operand:SI 0 "reg_or_0_operand"  "rO,rO")
+	   (match_operand:SI 1 "reg_or_s16_operand" "I,r")]))]
+  ""
+  "@
+   l.sf%C2i\t%r0,%1
+   l.sf%C2\t%r0,%1"
+  [(set_attr "type" "compare")])
+
+(define_insn "*comparesf"
+  [(set (reg:BI SR_F_REG)
+	(match_operator:BI 2 "ordered_comparison_operator"
+	  [(match_operand:SF 0 "register_operand" "r")
+	   (match_operand:SF 1 "register_operand" "r")]))]
+  "TARGET_HARD_FLOAT"
+  "lf.sf%C2.s\t%0,%1"
+  [(set_attr "type" "compare")])
+
+;; Moving double and single precision floating point values
+
+(define_expand "movsf"
+  [(set (match_operand:SI 0 "general_operand" "")
+	(match_operand:SI 1 "general_operand" ""))]
+  ""
+{
+  or1k_expand_move (SFmode, operands[0], operands[1]);
+  DONE;
+})
+
+(define_insn "*movsf"
+  [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m,r")
+        (match_operand:SF 1 "general_operand"      "rG,m,rG,F"))]
+  "register_operand (operands[0], SFmode)
+   || reg_or_0_operand (operands[1], SFmode)"
+  "@
+   l.ori\t%0,%r1,0
+   l.lwz\t%0,%1
+   l.sw\t%0,%r1
+   #"
+  [(set_attr "type" "logic,load,store,unknown")])
+
+(define_split
+  [(set (match_operand:SF 0 "register_operand")
+        (match_operand:SF 1 "const_double_operand"))]
+  "reload_completed"
+  [(const_int 0)]
+{
+  long img;
+  REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (operands[1]), img);
+  emit_move_insn (gen_lowpart (SImode, operands[0]),
+		  gen_int_mode (img, SImode));
+  DONE;
+})
+
+;;
+;; extendqisi2
+;;
+
+(define_expand "extendqisi2"
+  [(set (match_operand:SI 0 "register_operand")
+	(sign_extend:SI
+	  (match_operand:QI 1 "nonimmediate_operand")))]
+  ""
+{
+  if (!TARGET_SEXT && !MEM_P (operands[1]))
+    {
+      rtx shift = GEN_INT (24);
+      rtx sub = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
+      operands[1] = gen_lowpart (SImode, operands[1]);
+      emit_insn (gen_ashlsi3 (sub, operands[1], shift));
+      emit_insn (gen_ashrsi3 (operands[0], sub, shift));
+      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_SEXT"
+  "@
+   l.extbs\t%0,%1
+   l.lbs\t%0,%1"
+  [(set_attr "type" "extend,load")])
+
+(define_insn "*extendqisi2_no_sext"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+        (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
+  "!TARGET_SEXT"
+  "l.lbs\t%0,%1"
+  [(set_attr "type" "load")])
+
+;;
+;; extendhisi2
+;;
+
+(define_expand "extendhisi2"
+  [(set (match_operand:SI 0 "register_operand")
+	(sign_extend:SI
+	  (match_operand:HI 1 "nonimmediate_operand")))]
+  ""
+{
+  if (!TARGET_SEXT && !MEM_P (operands[1]))
+    {
+      rtx shift = GEN_INT (16);
+      rtx sub = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
+      operands[1] = gen_lowpart (SImode, operands[1]);
+      emit_insn (gen_ashlsi3 (sub, operands[1], shift));
+      emit_insn (gen_ashrsi3 (operands[0], sub, shift));
+      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_SEXT"
+  "@
+   l.exths\t%0,%1
+   l.lhs\t%0,%1"
+  [(set_attr "type" "extend,load")])
+
+(define_insn "*extendhisi2_no_sext"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+        (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
+  "!TARGET_SEXT"
+  "l.lhs\t%0,%1"
+  [(set_attr "type" "load")])
+
+;;
+;; 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
+   l.lbz\t%0,%1"
+  [(set_attr "type" "logic,load")])
+
+(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
+   l.lhz\t%0,%1"
+  [(set_attr "type" "logic,load")])
+
+;;
+;; 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 "shift_operand"    "r,L")))]
+  ""
+  "@
+   l.sll\t%0,%1,%2
+   l.slli\t%0,%1,%2"
+  [(set_attr "type" "shift")])
+
+(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 "shift_operand"    "r,L")))]
+  ""
+  "@
+   l.sra\t%0,%1,%2
+   l.srai\t%0,%1,%2"
+  [(set_attr "type" "shift")])
+
+(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 "shift_operand"    "r,L")))]
+  ""
+  "@
+   l.srl\t%0,%1,%2
+   l.srli\t%0,%1,%2"
+  [(set_attr "type" "shift")])
+
+(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 "shift_operand"    "r,L")))]
+  "TARGET_ROR"
+  "@
+   l.ror\t%0,%1,%2
+   l.rori\t%0,%1,%2"
+  [(set_attr "type" "shift")])
+
+;;
+;; 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 "reg_or_u16_operand" "r,K")))]
+  ""
+  "@
+   l.and\t%0,%1,%2
+   l.andi\t%0,%1,%2"
+  [(set_attr "type" "logic")])
+
+(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 "reg_or_u16_operand" "r,K")))]
+  ""
+  "@
+   l.or\t%0,%1,%2
+   l.ori\t%0,%1,%2"
+  [(set_attr "type" "logic")])
+
+(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 "reg_or_s16_operand" "r,I")))]
+  ""
+  "@
+   l.xor\t%0,%1,%2
+   l.xori\t%0,%1,%2"
+  [(set_attr "type" "logic")])
+
+(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"
+  [(set_attr "type" "logic")])
+
+;;
+;; Arithmetic operations 
+;;
+
+(define_insn "negsi2"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(neg:SI (match_operand:SI 1 "register_operand" "r")))
+   (clobber (reg:BI SR_CY_REG))]
+  ""
+  "l.sub\t%0,r0,%1"
+  [(set_attr "type" "add")])
+
+(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 "reg_or_s16_operand" "r,I")))
+   (clobber (reg:BI SR_CY_REG))]
+  ""
+  "@
+   l.add\t%0,%1,%2
+   l.addi\t%0,%1,%2"
+  [(set_attr "type" "add")])
+
+(define_insn "subsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(minus:SI (match_operand:SI 1 "reg_or_0_operand" "rO")
+		  (match_operand:SI 2 "reg_or_0_operand" "rO")))
+   (clobber (reg:BI SR_CY_REG))]
+  ""
+  "l.sub\t%0,%r1,%r2"
+  [(set_attr "type" "add")])
+
+;;
+;; mul and div
+;;
+
+(define_insn "mulsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+        (mult:SI (match_operand:SI 1 "register_operand"   "%r,r")
+                 (match_operand:SI 2 "reg_or_s16_operand" " r,I")))]
+  "TARGET_HARD_MUL"
+  "@
+   l.mul\t%0,%1,%2
+   l.muli\t%0,%1,%2"
+  [(set_attr "type" "mul")])
+
+(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"
+  [(set_attr "type" "mul")])
+
+(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")))
+   (clobber (reg:BI SR_CY_REG))]
+  "TARGET_HARD_DIV"
+  "l.divu\t%0,%1,%2"
+  [(set_attr "type" "mul")])
+
+;;
+;; Double-word arithmetic
+;;
+
+;; Because there is no non-carry-clobbering addition insn,
+;; reload can clobber CY for address arithmetic.  Thus these
+;; patterns must remain whole until after reload.
+
+(define_expand "adddi3"
+  [(set (match_operand:DI 0 "register_operand")
+	(plus:DI (match_operand:DI 1 "register_operand")
+		 (match_operand:DI 2 "reg_or_s16_operand")))]
+  ""
+{
+  rtx h0, h1, h2, l0, l1, l2;
+
+  h0 = gen_highpart (SImode, operands[0]);
+  l0 = gen_lowpart (SImode, operands[0]);
+  h1 = gen_highpart (SImode, operands[1]);
+  l1 = gen_lowpart (SImode, operands[1]);
+  if (CONST_INT_P (operands[2]))
+    {
+      l2 = operands[2];
+      h2 = (INTVAL (l2) < 0 ? constm1_rtx : const0_rtx);
+    }
+  else
+    {
+      h2 = gen_highpart (SImode, operands[2]);
+      l2 = gen_lowpart (SImode, operands[2]);
+    }
+
+  emit_insn (gen_adddi_int (l0, l1, l2, h0, h1, h2));
+  DONE;
+})
+
+(define_insn_and_split "adddi_int"
+  [(set (match_operand:SI 0 "register_operand"         "=r,&r")
+	(plus:SI
+	  (match_operand:SI 1 "register_operand"       "%0, r")
+	  (match_operand:SI 2 "reg_or_s16_operand"     "rI,rI")))
+   (set (match_operand:SI 3 "register_operand"         "=r, r")
+	(plus:SI
+	  (plus:SI
+	    (ltu:SI
+	      (plus:SI (match_dup 1) (match_dup 2))
+              (match_dup 1))
+	    (match_operand:SI 4 "register_operand"     " r, r"))
+	  (match_operand:SI 5 "reg_or_s16_operand"     "rI,rI")))
+   (clobber (reg:BI SR_CY_REG))]
+  ""
+  "#"
+  "reload_completed"
+  [(const_int 0)]
+{
+  if (CONST_INT_P (operands[4]) && INTVAL (operands[4]) != 0)
+    std::swap (operands[4], operands[5]);
+  emit_insn (gen_addsi_co (operands[0], operands[1], operands[2]));
+  emit_insn (gen_addsi_ci (operands[3], operands[4], operands[5]));
+  DONE;
+})
+
+(define_insn_and_split "*adddi_1"
+  [(set (match_operand:SI 0 "register_operand"     "=r, r,&r")
+	(plus:SI
+	  (match_operand:SI 1 "register_operand"   "%0, r, r")
+	  (match_operand:SI 2 "reg_or_s16_operand" "rI,rI,rI")))
+   (set (match_operand:SI 3 "register_operand"     "=r, r, r")
+	(plus:SI
+	  (ltu:SI
+	    (plus:SI (match_dup 1) (match_dup 2))
+	    (match_dup 1))
+	  (match_operand:SI 4 "reg_or_s16_operand" "rI, I, r")))
+   (clobber (reg:BI SR_CY_REG))]
+  ""
+  "#"
+  "reload_completed"
+  [(const_int 0)]
+{
+  emit_insn (gen_addsi_co (operands[0], operands[1], operands[2]));
+  emit_insn (gen_addsi_ci (operands[3], const0_rtx, operands[4]));
+  DONE;
+})
+
+(define_insn_and_split "*adddi_2"
+  [(set (match_operand:SI 0 "register_operand"         "=r,&r")
+	(plus:SI
+	  (match_operand:SI 1 "register_operand"       "%0, r")
+	  (match_operand:SI 2 "reg_or_s16_operand"     "rI,rI")))
+   (set (match_operand:SI 3 "register_operand"         "=r, r")
+	(plus:SI
+	  (plus:SI
+	    (ltu:SI
+	      (plus:SI (match_dup 1) (match_dup 2))
+	      (match_dup 1))
+	    (match_operand:SI 4 "register_operand"     " r, r"))
+	  (match_operand:SI 5 "reg_or_s16_operand"     "rI,rI")))
+   (clobber (reg:BI SR_CY_REG))]
+  ""
+  "#"
+  "reload_completed"
+  [(const_int 0)]
+{
+  emit_insn (gen_addsi_co (operands[0], operands[1], operands[2]));
+  emit_insn (gen_addsi_ci (operands[3], operands[4], operands[5]));
+  DONE;
+})
+
+(define_insn_and_split "*adddi_3"
+  [(set (match_operand:SI 0 "register_operand"         "=r, r,&r")
+	(plus:SI
+	  (match_operand:SI 1 "register_operand"       "%0, r, r")
+	  (const_int -1)))
+   (set (match_operand:SI 2 "register_operand"         "=r, r, r")
+	(plus:SI
+	  (ne:SI (match_dup 1) (const_int 0))
+	  (match_operand:SI 3 "reg_or_s16_operand"     "rI, I, r")))
+   (clobber (reg:BI SR_CY_REG))]
+  ""
+  "#"
+  "reload_completed"
+  [(const_int 0)]
+{
+  emit_insn (gen_addsi_co (operands[0], operands[1], constm1_rtx));
+  emit_insn (gen_addsi_ci (operands[2], const0_rtx, operands[3]));
+  DONE;
+})
+
+(define_insn_and_split "*adddi_4"
+  [(set (match_operand:SI 0 "register_operand"         "=r,&r")
+	(plus:SI
+	  (match_operand:SI 1 "register_operand"       "%0, r")
+	  (const_int -1)))
+   (set (match_operand:SI 2 "register_operand"         "=r, r")
+	(plus:SI
+	  (plus:SI
+	    (ltu:SI
+	      (plus:SI (match_dup 1) (match_dup 2))
+	      (match_dup 1))
+	    (match_operand:SI 3 "register_operand"     " r, r"))
+	  (match_operand:SI 4 "reg_or_s16_operand"     "rI,rI")))
+   (clobber (reg:BI SR_CY_REG))]
+  ""
+  "#"
+  "reload_completed"
+  [(const_int 0)]
+{
+  emit_insn (gen_addsi_co (operands[0], operands[1], constm1_rtx));
+  emit_insn (gen_addsi_ci (operands[2], operands[3], operands[4]));
+  DONE;
+})
+
+(define_expand "subdi3"
+  [(set (match_operand:DI 0 "register_operand")
+	(plus:DI (match_operand:DI 1 "reg_or_0_operand")
+		 (match_operand:DI 2 "register_operand")))]
+  ""
+{
+  rtx h0, h1, h2, l0, l1, l2;
+
+  h0 = gen_highpart (SImode, operands[0]);
+  l0 = gen_lowpart (SImode, operands[0]);
+  if (operands[1] == const0_rtx)
+    h1 = l1 = const0_rtx;
+  else
+    {
+      h1 = gen_highpart (SImode, operands[1]);
+      l1 = gen_lowpart (SImode, operands[1]);
+    }
+  h2 = gen_highpart (SImode, operands[2]);
+  l2 = gen_lowpart (SImode, operands[2]);
+
+  emit_insn (gen_subdi_int (l0, l1, l2, h0, h1, h2));
+  DONE;
+})
+
+(define_insn_and_split "subdi_int"
+  [(set (match_operand:SI 0 "register_operand"           "=r,&r")
+	(minus:SI (match_operand:SI 1 "reg_or_0_operand" " 0,rO")
+		  (match_operand:SI 2 "reg_or_0_operand" "rO,rO")))
+   (set (match_operand:SI 3 "register_operand"           "=r,r")
+	(minus:SI
+	  (minus:SI
+	    (match_operand:SI 4 "reg_or_0_operand"       "rO,rO")
+	    (match_operand:SI 5 "reg_or_0_operand"       "rO,rO"))
+	  (ltu:SI (match_dup 1) (match_dup 2))))
+   (clobber (match_scratch:SI 6 "=&r,&r"))
+   (clobber (reg:BI SR_CY_REG))]
+  ""
+  "#"
+  "reload_completed"
+  [(const_int 0)]
+{
+  emit_insn (gen_subsi_co (operands[0], operands[1], operands[2]));
+  emit_insn (gen_addsi_ci (operands[6], const0_rtx, const0_rtx));
+  if (operands[5] == const0_rtx)
+    emit_insn (gen_subsi3 (operands[3], operands[4], operands[6]));
+  else
+    {
+      emit_insn (gen_subsi3 (operands[3], operands[4], operands[5]));
+      emit_insn (gen_subsi3 (operands[3], operands[3], operands[6]));
+    }
+  DONE;
+})
+
+(define_insn_and_split "*subdi_1"
+  [(set (match_operand:SI 0 "register_operand"           "=r,&r")
+	(minus:SI (match_operand:SI 1 "reg_or_0_operand" " 0,rO")
+		  (match_operand:SI 2 "reg_or_0_operand" "rO,rO")))
+   (set (match_operand:SI 3 "register_operand"           "=r,r")
+	(minus:SI
+	  (match_operand:SI 4 "reg_or_0_operand"         "rO,rO")
+	  (ltu:SI (match_dup 1) (match_dup 2))))
+   (clobber (match_scratch:SI 5 "=&r,&r"))
+   (clobber (reg:BI SR_CY_REG))]
+  ""
+  "#"
+  "reload_completed"
+  [(const_int 0)]
+{
+  emit_insn (gen_subsi_co (operands[0], operands[1], operands[2]));
+  emit_insn (gen_addsi_ci (operands[5], const0_rtx, const0_rtx));
+  emit_insn (gen_subsi3 (operands[3], operands[4], operands[5]));
+  DONE;
+})
+
+(define_insn_and_split "*subdi_2"
+  [(set (match_operand:SI 0 "register_operand"           "=r,&r")
+	(minus:SI (match_operand:SI 1 "reg_or_0_operand" " 0,rO")
+		  (match_operand:SI 2 "reg_or_0_operand" "rO,rO")))
+   (set (match_operand:SI 3 "register_operand"           "=r,r")
+	(minus:SI
+	  (ltu:SI (match_dup 1) (match_dup 2))
+	  (match_operand:SI 4 "reg_or_0_operand"         "rO,rO")))
+   (clobber (match_scratch:SI 5 "=&r,&r"))
+   (clobber (reg:BI SR_CY_REG))]
+  ""
+  "#"
+  "reload_completed"
+  [(const_int 0)]
+{
+  emit_insn (gen_subsi_co (operands[0], operands[1], operands[2]));
+  emit_insn (gen_addsi_ci (operands[5], const0_rtx, const0_rtx));
+  emit_insn (gen_subsi3 (operands[3], operands[5], operands[4]));
+  DONE;
+})
+
+(define_insn_and_split "*subdi_3"
+  [(set (match_operand:SI 0 "register_operand"     "=r")
+	(minus:SI
+	  (match_operand:SI 1 "reg_or_0_operand"   "rO")
+	  (ltu:SI
+	    (match_operand:SI 2 "reg_or_0_operand" "rO")
+	    (match_operand:SI 3 "reg_or_0_operand" "rO"))))
+   (clobber (match_scratch:SI 4 "=&r"))
+   (clobber (reg:BI SR_CY_REG))]
+  ""
+  "#"
+  "reload_completed"
+  [(const_int 0)]
+{
+  emit_insn (gen_subsi_co (operands[4], operands[2], operands[3]));
+  emit_insn (gen_addsi_ci (operands[4], const0_rtx, const0_rtx));
+  emit_insn (gen_subsi3 (operands[0], operands[1], operands[4]));
+  DONE;
+})
+
+(define_insn_and_split "*subdi_4"
+  [(set (match_operand:SI 0 "register_operand"     "=r")
+	(minus:SI
+	  (ltu:SI
+	    (match_operand:SI 1 "reg_or_0_operand" "rO")
+	    (match_operand:SI 2 "reg_or_0_operand" "rO"))
+	  (match_operand:SI 3 "reg_or_0_operand"   "rO")))
+   (clobber (match_scratch:SI 4 "=&r"))
+   (clobber (reg:BI SR_CY_REG))]
+  ""
+  "#"
+  "reload_completed"
+  [(const_int 0)]
+{
+  emit_insn (gen_subsi_co (operands[4], operands[1], operands[2]));
+  emit_insn (gen_addsi_ci (operands[4], const0_rtx, const0_rtx));
+  emit_insn (gen_subsi3 (operands[0], operands[4], operands[3]));
+  DONE;
+})
+
+(define_insn "addsi_co"
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+	(plus:SI (match_operand:SI 1 "reg_or_0_operand" "%rO,rO")
+		 (match_operand:SI 2 "reg_or_s16_operand" "r,I")))
+   (set (reg:BI SR_CY_REG)
+	(ltu:BI
+	  (plus:SI (match_dup 1) (match_dup 2))
+	  (match_dup 2)))]
+  "reload_completed"
+  "@
+   l.add\t%0,%r1,%2
+   l.addi\t%0,%r1,%2"
+  [(set_attr "type" "add")])
+
+(define_insn "addsi_ci"
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+	(plus:SI
+	  (plus:SI
+	    (ne:SI (reg:BI SR_CY_REG) (const_int 0))
+	    (match_operand:SI 1 "reg_or_0_operand" "%rO,rO"))
+	  (match_operand:SI 2 "reg_or_s16_operand" "r,I")))
+   (clobber (reg:BI SR_CY_REG))]
+  "reload_completed"
+  "@
+   l.addc\t%0,%r1,%2
+   l.addic\t%0,%r1,%2"
+  [(set_attr "type" "add")])
+
+(define_insn "subsi_co"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(minus:SI (match_operand:SI 1 "reg_or_0_operand" "rO")
+		  (match_operand:SI 2 "reg_or_0_operand" "rO")))
+   (set (reg:BI SR_CY_REG)
+	(ltu:BI (match_dup 1) (match_dup 2)))]
+  "reload_completed"
+  "l.sub\t%0,%r1,%r2"
+  [(set_attr "type" "add")])
+
+;;
+;; jumps 
+;;
+
+;; jump
+
+(define_insn "jump"
+  [(set (pc)
+	(label_ref (match_operand 0 "" "")))]
+  ""
+  "l.j\t%l0%("
+  [(set_attr "type" "jump")])
+
+;; indirect jump
+
+(define_insn "indirect_jump"
+  [(set (pc) (match_operand:SI 0 "register_operand" "r"))]
+  ""
+  "l.jr\t%0%("
+  [(set_attr "type" "jump")])
+
+;; table jump
+
+(define_expand "tablejump"
+  [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
+	      (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])));
+})
+
+(define_insn "*tablejump_internal"
+  [(set (pc) (match_operand:SI 0 "register_operand" "r"))
+   (use (label_ref (match_operand 1 "" "")))]
+  ""
+  "l.jr\t%0%("
+  [(set_attr "type" "jump")])
+
+
+;; no-op
+
+(define_insn "nop"
+  [(const_int 0)]
+  ""
+  "l.nop"
+  [(set_attr "type" "logic")])
+
+;;
+;; 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"
+  [(set_attr "type" "fp")])
+
+(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"
+  [(set_attr "type" "fp")])
+
+(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"
+  [(set_attr "type" "fp")])
+
+(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"
+  [(set_attr "type" "fp")])
+
+;; 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"
+  [(set_attr "type" "fp")])
+
+;; 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"
+  [(set_attr "type" "fp")])
+
+;; This is a placeholder, during RA, in order to create the PIC register.
+;; We do this so that we don't unconditionally mark the LINK register as
+;; clobbered.  It is replaced during prologue generation with the proper
+;; set_got pattern below.  This works because the set_got_tmp insn is the
+;; first insn in the stream and that it isn't moved during RA.
+(define_insn "set_got_tmp"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(unspec_volatile:SI [(const_int 0)] UNSPEC_SET_GOT))]
+  ""
+  { abort (); })
+
+;; The insn to set GOT.
+(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:BI SR_CY_REG))]
+  ""
+{
+  if (TARGET_DELAY_ON)
+    return ("l.jal\t8\;"
+	    " l.movhi\t%0,gotpchi(_GLOBAL_OFFSET_TABLE_-4)\;"
+	    "l.ori\t%0,%0,gotpclo(_GLOBAL_OFFSET_TABLE_+0)\;"
+	    "l.add\t%0,%0,r9");
+  else if (TARGET_DELAY_OFF)
+    return ("l.jal\t4\;"
+	    "l.movhi\t%0,gotpchi(_GLOBAL_OFFSET_TABLE_)\;"
+	    "l.ori\t%0,%0,gotpclo(_GLOBAL_OFFSET_TABLE_+4)\;"
+	    "l.add\t%0,%0,r9");
+  else
+    return ("l.jal\t8\;"
+	    " l.nop\;"
+	    "l.movhi\t%0,gotpchi(_GLOBAL_OFFSET_TABLE_)\;"
+	    "l.ori\t%0,%0,gotpclo(_GLOBAL_OFFSET_TABLE_+4)\;"
+	    "l.add\t%0,%0,r9");
+}
+  [(set (attr "length")
+	(if_then_else (ne (symbol_ref "TARGET_DELAY_COMPAT") (const_int 0))
+	  (const_int 5)
+	  (const_int 4)))])
+
+;;
+;; Atomic operations
+;;
+
+(include "sync.md")
+
+;;
+;; CALLS
+;; Leave these to last, as the modeless operand for call_value
+;; interferes with normal patterns.
+;;
+
+(define_expand "call"
+  [(call (match_operand 0)
+	 (match_operand 1))
+   (use (match_operand 2))]
+  ""
+{
+  or1k_expand_call (NULL, operands[0], operands[1]);
+  DONE;
+})
+
+(define_expand "sibcall"
+  [(call (match_operand 0)
+	 (match_operand 1))
+   (use (match_operand 2))]
+  ""
+{
+  or1k_expand_call (NULL, operands[0], operands[1]);
+  DONE;
+})
+
+(define_expand "call_value"
+  [(set (match_operand 0)
+	(call (match_operand:SI 1)
+	      (match_operand 2)))
+   (use (match_operand 3))]
+  ""
+{
+  or1k_expand_call (operands[0], operands[1], operands[2]);
+  DONE;
+})
+
+(define_expand "sibcall_value"
+  [(set (match_operand 0)
+	(call (match_operand:SI 1)
+	      (match_operand 2)))
+   (use (match_operand 3))]
+  ""
+{
+  or1k_expand_call (operands[0], operands[1], operands[2]);
+  DONE;
+})
+
+(define_insn "*call"
+  [(call (mem:SI (match_operand:SI 0 "call_insn_operand" "r,s"))
+                 (match_operand 1))]
+  "!SIBLING_CALL_P (insn)"
+  "@
+   l.jalr\t%0%(
+   l.jal\t%P0%("
+  [(set_attr "type" "jump")])
+
+(define_insn "*sibcall"
+  [(call (mem:SI (match_operand:SI 0 "call_insn_operand" "c,s"))
+                 (match_operand 1))]
+  "SIBLING_CALL_P (insn)"
+  "@
+   l.jr\t%0%(
+   l.j\t%P0%("
+  [(set_attr "type" "jump")])
+
+(define_insn "*call_value"
+  [(set (match_operand 0)
+	(call (mem:SI (match_operand:SI 1 "call_insn_operand" "r,s"))
+	      (match_operand 2)))]
+  "!SIBLING_CALL_P (insn)"
+  "@
+   l.jalr\t%1%(
+   l.jal\t%P1%("
+  [(set_attr "type" "jump")])
+
+(define_insn "*sibcall_value"
+  [(set (match_operand 0)
+	(call (mem:SI (match_operand:SI 1 "call_insn_operand" "c,s"))
+	      (match_operand 2)))]
+  "SIBLING_CALL_P (insn)"
+  "@
+   l.jr\t%1%(
+   l.j\t%P1%("
+  [(set_attr "type" "jump")])
+
+;; 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..f939b04
--- /dev/null
+++ b/gcc/config/or1k/or1k.opt
@@ -0,0 +1,92 @@
+; 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.
+
+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(SEXT)
+Use sign-extending instructions.
+
+mcmov
+Target Mask(CMOV)
+Use conditional move instructions.
+
+mror
+Target 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..eaaa6d0
--- /dev/null
+++ b/gcc/config/or1k/predicates.md
@@ -0,0 +1,136 @@
+;; 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/>.
+
+;; Return 1 if OP is the zero constant for MODE.
+(define_predicate "const0_operand"
+  (and (match_code "const_int,const_double,const_vector")
+       (match_test "op == CONST0_RTX (mode)")))
+
+;; Returns true if OP is either the constant zero or a register.
+(define_predicate "reg_or_0_operand"
+  (ior (match_operand 0 "register_operand")
+       (match_operand 0 "const0_operand")))
+
+(define_predicate "reg_or_s16_operand"
+  (ior (match_operand 0 "register_operand")
+       (and (match_code "const_int")
+	    (match_test "satisfies_constraint_I (op)"))))
+
+(define_predicate "reg_or_u16_operand"
+  (ior (match_operand 0 "register_operand")
+       (and (match_code "const_int")
+	    (match_test "satisfies_constraint_K (op)"))))
+
+(define_predicate "shift_operand"
+  (ior (match_operand 0 "register_operand")
+       (and (match_code "const_int")
+	    (match_test "satisfies_constraint_L (op)"))))
+
+(define_predicate "sgeui_operand"
+  (match_code "const_int")
+{
+  HOST_WIDE_INT ival = INTVAL (op);
+  return ival != 0 && IN_RANGE (-ival, -32768, 32767);
+})
+
+(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 "call_insn_operand"
+  (match_code "reg,subreg,symbol_ref"))
+
+;; 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")))
+
+(define_predicate "equality_comparison_operator"
+  (match_code "eq,ne"))
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/sync.md b/gcc/config/or1k/sync.md
new file mode 100644
index 0000000..6984493
--- /dev/null
+++ b/gcc/config/or1k/sync.md
@@ -0,0 +1,202 @@
+;; Atomic operations for GNU compiler, OpenRISC 1000 family, OR32 ISA
+;; Copyright (C) 2016 Free Software Foundation, Inc.
+;;
+;; 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/>. */
+
+;; Note that MULT stands in for the non-existant NAND rtx_code.
+(define_code_iterator FETCHOP [plus minus ior xor and mult])
+
+(define_code_attr fetchop_name
+  [(plus "add")
+   (minus "sub")
+   (ior "or")
+   (xor "xor")
+   (and "and")
+   (mult "nand")])
+
+(define_code_attr fetchop_pred
+  [(plus "reg_or_s16_operand")
+   (minus "register_operand")
+   (ior "reg_or_u16_operand")
+   (xor "reg_or_s16_operand")
+   (and "reg_or_u16_operand")
+   (mult "reg_or_u16_operand")])
+
+(define_expand "mem_thread_fence"
+  [(match_operand:SI 0 "const_int_operand" "")]		;; model
+  ""
+{
+  memmodel model = memmodel_base (INTVAL (operands[0]));
+  if (model != MEMMODEL_RELAXED)
+    emit_insn (gen_msync ());
+  DONE;
+})
+
+(define_expand "msync"
+  [(set (match_dup 0) (unspec:BLK [(match_dup 0)] UNSPEC_MSYNC))]
+  ""
+{
+  operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
+  MEM_VOLATILE_P (operands[0]) = 1;
+})
+
+(define_insn "*msync"
+  [(set (match_operand:BLK 0 "" "")
+	(unspec:BLK [(match_dup 0)] UNSPEC_MSYNC))]
+  ""
+  "l.msync"
+  [(set_attr "type" "logic")])
+
+(define_insn "load_locked_si"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(unspec_volatile:SI
+	  [(match_operand:SI 1 "memory_operand" "m")] UNSPECV_LL))]
+  ""
+  "l.lwa\t%0,%1"
+  [(set_attr "type" "load")])
+
+(define_insn "store_conditional_si"
+  [(set (reg:BI SR_F_REG)
+	(unspec_volatile:BI [(const_int 0)] UNSPECV_SC))
+   (set (match_operand:SI 0 "memory_operand" "=m")
+	(match_operand:SI 1 "reg_or_0_operand" "rO"))]
+  ""
+  "l.swa\t%0,%r1"
+  [(set_attr "type" "store")])
+
+(define_expand "atomic_compare_and_swapsi"
+  [(match_operand:SI 0 "register_operand")   ;; bool output
+   (match_operand:SI 1 "register_operand")   ;; val output
+   (match_operand:SI 2 "memory_operand")     ;; memory
+   (match_operand:SI 3 "reg_or_s16_operand") ;; expected
+   (match_operand:SI 4 "reg_or_0_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
+  ""
+{
+  or1k_expand_atomic_compare_and_swap (operands);
+  DONE;
+})
+
+(define_expand "atomic_compare_and_swap<mode>"
+  [(match_operand:SI 0 "register_operand")   ;; bool output
+   (match_operand:I12 1 "register_operand")  ;; val output
+   (match_operand:I12 2 "memory_operand")    ;; memory
+   (match_operand:I12 3 "register_operand")  ;; expected
+   (match_operand:I12 4 "reg_or_0_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
+  ""
+{
+  or1k_expand_atomic_compare_and_swap_qihi (operands);
+  DONE;
+})
+
+(define_expand "atomic_exchangesi"
+  [(match_operand:SI 0 "register_operand")	;; output
+   (match_operand:SI 1 "memory_operand")	;; memory
+   (match_operand:SI 2 "reg_or_0_operand")	;; input
+   (match_operand:SI 3 "const_int_operand")]	;; model
+  ""
+{
+  or1k_expand_atomic_exchange (operands);
+  DONE;
+})
+
+(define_expand "atomic_exchange<mode>"
+  [(match_operand:I12 0 "register_operand")	;; output
+   (match_operand:I12 1 "memory_operand")	;; memory
+   (match_operand:I12 2 "reg_or_0_operand")	;; input
+   (match_operand:SI 3 "const_int_operand")]	;; model
+  ""
+{
+  or1k_expand_atomic_exchange_qihi (operands);
+  DONE;
+})
+
+(define_expand "atomic_<fetchop_name>si"
+  [(match_operand:SI 0 "memory_operand")	;; memory
+   (FETCHOP:SI (match_dup 0)
+     (match_operand:SI 1 "<fetchop_pred>"))	;; operand
+   (match_operand:SI 2 "const_int_operand")]	;; model
+  ""
+{
+  or1k_expand_atomic_op (<CODE>, operands[0], operands[1], NULL, NULL);
+  DONE;
+})
+
+(define_expand "atomic_<fetchop_name><mode>"
+  [(match_operand:I12 0 "memory_operand")	;; memory
+   (FETCHOP:I12 (match_dup 0)
+     (match_operand:I12 1 "register_operand"))	;; operand
+   (match_operand:SI 2 "const_int_operand")]	;; model
+  ""
+{
+  or1k_expand_atomic_op_qihi (<CODE>, operands[0], operands[1], NULL, NULL);
+  DONE;
+})
+
+(define_expand "atomic_fetch_<fetchop_name>si"
+  [(match_operand:SI 0 "register_operand" "")		;; output
+   (match_operand:SI 1 "memory_operand" "")		;; memory
+   (FETCHOP:SI (match_dup 1)
+     (match_operand:SI 2 "<fetchop_pred>" ""))		;; operand
+   (match_operand:SI 3 "const_int_operand" "")]		;; model
+  ""
+{
+  or1k_expand_atomic_op (<CODE>, operands[1], operands[2], operands[0], NULL);
+  DONE;
+})
+
+(define_expand "atomic_fetch_<fetchop_name><mode>"
+  [(match_operand:I12 0 "register_operand" "")		;; output
+   (match_operand:I12 1 "memory_operand" "")		;; memory
+   (FETCHOP:I12 (match_dup 1)
+     (match_operand:I12 2 "<fetchop_pred>" ""))		;; operand
+   (match_operand:SI 3 "const_int_operand" "")]		;; model
+  ""
+{
+  or1k_expand_atomic_op_qihi (<CODE>, operands[1], operands[2],
+			      operands[0], NULL);
+  DONE;
+})
+
+(define_expand "atomic_<fetchop_name>_fetchsi"
+  [(match_operand:SI 0 "register_operand" "")		;; output
+   (match_operand:SI 1 "memory_operand" "")		;; memory
+   (FETCHOP:SI (match_dup 1)
+     (match_operand:SI 2 "<fetchop_pred>" ""))		;; operand
+   (match_operand:SI 3 "const_int_operand" "")]		;; model
+  ""
+{
+  or1k_expand_atomic_op (<CODE>, operands[1], operands[2], NULL, operands[0]);
+  DONE;
+})
+
+(define_expand "atomic_<fetchop_name>_fetch<mode>"
+  [(match_operand:I12 0 "register_operand" "")		;; output
+   (match_operand:I12 1 "memory_operand" "")		;; memory
+   (FETCHOP:I12 (match_dup 1)
+     (match_operand:I12 2 "<fetchop_pred>" ""))	;; operand
+   (match_operand:SI 3 "const_int_operand" "")]		;; model
+  ""
+{
+  or1k_expand_atomic_op_qihi (<CODE>, operands[1], operands[2],
+			      NULL, operands[0]);
+  DONE;
+})
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/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 043a62b..a2c65d6 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -5065,6 +5065,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.
 	;;
@@ -24078,6 +24081,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
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 2b52da3..cb8c9e5 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -3315,6 +3315,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
diff --git a/gcc/testsuite/g++.dg/init/pr25811.C b/gcc/testsuite/g++.dg/init/pr25811.C
index 4cda484..81feddd 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 } .-1 }
 {
@@ -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 899a401..e115131 100644
--- a/gcc/testsuite/gcc.c-torture/execute/20101011-1.c
+++ b/gcc/testsuite/gcc.c-torture/execute/20101011-1.c
@@ -53,6 +53,12 @@
   /* Epiphany does not have hardware division, and the software implementation
      has truly undefined behavior 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 f5929e0..9694272 100644
--- a/gcc/testsuite/gcc.dg/20020312-2.c
+++ b/gcc/testsuite/gcc.dg/20020312-2.c
@@ -35,6 +35,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 ad61d3b..20bea3b 100644
--- a/gcc/testsuite/gcc.dg/builtin-apply2.c
+++ b/gcc/testsuite/gcc.dg/builtin-apply2.c
@@ -45,3 +45,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/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/stack-usage-1.c b/gcc/testsuite/gcc.dg/stack-usage-1.c
index f10ba20..dd6636e 100644
--- a/gcc/testsuite/gcc.dg/stack-usage-1.c
+++ b/gcc/testsuite/gcc.dg/stack-usage-1.c
@@ -97,6 +97,8 @@
 #define SIZE 252
 #elif defined (__M32R__)
 #define SIZE 252
+#elif defined (__OR1K__) || defined(__OR1KND__)
+#define SIZE 252
 #else
 #  define SIZE 256
 #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 41b5c05..d32375f 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-*-* riscv*-*-* } } "*" "" } */
-/* { 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 0d91fc7..c52d877 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 063f339..94821cf 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -632,6 +632,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/include/longlong.h b/include/longlong.h
index 9d3ab21..2f0eb485 100644
--- a/include/longlong.h
+++ b/include/longlong.h
@@ -894,6 +894,50 @@ extern UDItype __umulsidi3 (USItype, USItype);
   } while (0)
 #endif /* __ns32000__ */
 
+#if defined(__OR1K__) || defined(__OR1KND__)
+# define add_ssaaaa(sh, sl, ah, al, bh, bl)			\
+  do {								\
+    UDItype __a = ((UDItype)(ah) << 32) | (USItype)(al);	\
+    UDItype __b = ((UDItype)(bh) << 32) | (USItype)(bl);	\
+    UDItype __s = __a + __b;					\
+    (sl) = (USItype)__s; (sh) = __s >> 32;			\
+  } while (0)
+# define sub_ddmmss(sh, sl, ah, al, bh, bl)			\
+  do {								\
+    UDItype __a = ((UDItype)(ah) << 32) | (USItype)(al);	\
+    UDItype __b = ((UDItype)(bh) << 32) | (USItype)(bl);	\
+    UDItype __s = __a - __b;					\
+    (sl) = (USItype)__s; (sh) = __s >> 32;			\
+  } while (0)
+/* Unlike the generic version below, make use of carry arithmetic
+   to fold the intermediate multiples.  */
+#define umul_ppmm(w1, w0, u, v)						\
+  do {									\
+    UWtype __x0, __x1, __x2, __x3, __x1h, __x1l, __x2h, __x2l;		\
+    UHWtype __ul, __vl, __uh, __vh;					\
+									\
+    __ul = __ll_lowpart (u);						\
+    __uh = __ll_highpart (u);						\
+    __vl = __ll_lowpart (v);						\
+    __vh = __ll_highpart (v);						\
+									\
+    __x0 = (UWtype) __ul * __vl;					\
+    __x1 = (UWtype) __ul * __vh;					\
+    __x2 = (UWtype) __uh * __vl;					\
+    __x3 = (UWtype) __uh * __vh;					\
+									\
+    __x1l = __x1 << (W_TYPE_SIZE / 2);					\
+    __x2l = __x2 << (W_TYPE_SIZE / 2);					\
+    __x1h = __ll_highpart (__x1);					\
+    __x2h = __ll_highpart (__x2);					\
+									\
+    add_ssaaaa(__x3, __x0, __x3, __x0, __x1h, __x1l);			\
+    add_ssaaaa(__x3, __x0, __x3, __x0, __x2h, __x2l);			\
+    (w1) = __x3;							\
+    (w0) = __x0;							\
+  } while (0)
+#endif /* __OR1K__ */
+
 /* FIXME: We should test _IBMR2 here when we add assembly support for the
    system vendor compilers.
    FIXME: What's needed for gcc PowerPC VxWorks?  __vxworks__ is not good
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 8beb492..2107dc0 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
 	;;
@@ -979,6 +985,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 9a7eb84..0d339b8 100644
--- a/libgcc/configure
+++ b/libgcc/configure
@@ -2350,6 +2350,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/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/libiberty/configure b/libiberty/configure
index 8687935..0beb844 100755
--- a/libiberty/configure
+++ b/libiberty/configure
@@ -5132,6 +5132,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/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 c493065..14e72e8 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 bc292c7..0fa6a11 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 e8d2b88..33e374b 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 37c99dd..274ab06 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 8d8a636..c3a4c75 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 f78bbfe..432af01 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 bf6ec15..1f36731 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 334868e..8408917 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 18e3721..52b16ac 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 9e09a02..4003786 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 8ca1f97..47cb66a 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 939a323..aa11d1c 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 9fef592..c750087 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 12f9a41..fddbb02 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 69a5fdb..4c603fa 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>
