OSDN Git Service

Contribute sh64-elf.
authoraoliva <aoliva@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 9 Feb 2002 03:08:08 +0000 (03:08 +0000)
committeraoliva <aoliva@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 9 Feb 2002 03:08:08 +0000 (03:08 +0000)
2002-02-09  Alexandre Oliva  <aoliva@redhat.com>
* config/sh/sh.c (TARGET_CANNOT_MODIFY_JUMPS_P): Define to...
(sh_cannot_modify_jumps_p): New function.
2002-02-05  Alexandre Oliva  <aoliva@redhat.com>
* config/sh/sh.c (TARGET_MS_BITFIELD_LAYOUT_P): Define to...
(sh_ms_bitfield_layout_p): New function.
2002-02-04  Alexandre Oliva  <aoliva@redhat.com>
    Zack Weinberg  <zack@codesourcery.com>
* config/sh/sh.h (TRAMPOLINE_ADJUST_ADDRESS): Use
expand_simple_binop instead of expand_binop.
2002-02-03  Alexandre Oliva  <aoliva@redhat.com>
* config/sh/sh.h (OVERRIDE_OPTIONS) [! TARGET_SH5]: Disable
use of .quad and .uaquad.
* config/sh/sh.c (TARGET_ASM_UNALIGNED_DI_OP,
TARGET_ASM_ALIGNED_DI_OP): Add comment pointing to the above.
2002-01-24  Alexandre Oliva  <aoliva@redhat.com>
* config/sh/sh.md (movdi_const, movdi_const_32bit,
movdi_const_16bit): Make sure all CONSTs have modes.
(sym2PIC): Ditto, but by adjusting all callers.
* config/sh/sh.c (calc_live_regs) [TARGET_SHCOMPACT]: Set pr_live
if the prologue calls the SHmedia argument decoder or register
saver.
2002-01-24  Alexandre Oliva  <aoliva@redhat.com>
* config/sh/sh.c (TARGET_ASM_UNALIGNED_DI_OP): Define.
(TARGET_ASM_ALIGNED_DI_OP): Likewise.
(sh_expand_epilogue): Don't emit USE of return target register.
(prepare_move_operands): Legitimize DImode PIC addresses.
(sh_media_register_for_return): Skip tr0, used to initialize the
PIC register.
(sh_expand_prologue): Remove explicit USE of return register.
(nonpic_symbol_mentioned_p): PC is non-PIC.  Don't recurse in
CONST_DOUBLEs.  UNSPEC_GOTPLT is PIC.
* config/sh/sh.h (ASM_OUTPUT_DOUBLE_INT): Removed, obsolete.
(OVERRIDE_OPTIONS): Don't disable PIC on SH5.
(EXTRA_CONSTRAINT_S): Use MOVI_SHORI_BASE_OPERAND_P instead of
EXTRA_CONSTRAINT_T.
(GOT_ENTRY_P, GOTPLT_ENTRY_P, GOTOFF_P, PIC_ADDR_P): New.
(MOVI_SHORI_BASE_OPERAND_P): New.
(NON_PIC_REFERENCE_P, PIC_REFERENCE_P): New.
(EXTRA_CONSTRAINT_T): Define in terms of them.
(OUTPUT_ADDR_CONST_EXTRA): Handle UNSPEC_GOTPLT.
* config/sh/sh.md (movsi_media, movsi_media_nofpu,
movdi_media, movdi_media_nofpu): Add SIBCALL_REGS class to
alternatives supporting TARGET_REGS.
(UNSPEC_GOTPLT): New constant.
(movdi split): Move incrementing of LABEL_NUSES...
(movdi_const, movdi_const_32bit): Here.  Use
MOVI_SHORI_BASE_OPERAND_P instead of EXTRA_CONSTRAINT_T.
(movdi_const_16bit): New.
(call, call_value) [flag_pic]: Use GOTPLT.
(call_pop, call_value_pop): New expands.
(call_pop_compact, call_pop_rettramp): New insns.
(call_value_pop_compact, call_value_pop_rettramp): New insns.
(sibcall) [flag_pic]: Use GOT.
(builtint_setjmp_receiver): Remove bogus, unused expand.
(GOTaddr2picreg): Implement for SHcompact and SHmedia.
(*pt, *ptb, ptrel): New insns.
(sym2GOT): Handle DImode GOT.
(sym2GOTPLT, symGOTPLT2reg): New expands.
(sym2PIC): New expand.
(shcompact_return_tramp): Use GOTPLT to return trampoline.
(shcompact_return_tramp_i): Use return register explicitly.
* config/sh/sh.h (OVERRIDE_OPTIONS) [TARGET_SHMEDIA]: Don't
disable flag_reorder_blocks.
2002-01-19  Alexandre Oliva  <aoliva@redhat.com>
* config/sh/sh.md (sibcall_compact): Reorder return, uses and
clobbers, for clarity.
(sibcall_epilogue) [TARGET_SHCOMPACT]: Mark saving and
restoring of r0 in macl as MAYBE_DEAD.
2002-01-18  Alexandre Oliva  <aoliva@redhat.com>
* config/sh/sh.h (LONG_DOUBLE_TYPE_SIZE): Define.
* config/sh/sh.md (movv4sf_i, movv16sf_i): Fix uses of
alter_subreg all over.
(jump) [TARGET_SHMEDIA]: FAIL to create new jumps after
reload, instead of emitting instructions that would require
reloading.
(casesi_load_media): Add missing modes.
2001-11-09  Alexandre Oliva  <aoliva@redhat.com>
* config/sh/sh.c (sh_expand_prologue): Mark the PIC register
as used if the argument decoder is called.
2001-08-28  Alexandre Oliva  <aoliva@redhat.com>
* config/sh/sh.md (udivsi3, divsi3): Load libcall symbol name in
Pmode, then extend it to DImode if necessary.
2001-08-28  Stephen Clarke  <Stephen.Clarke@st.com>
* config/sh/sh.h (LEGITIMATE_CONSTANT_P): Don't accept DFmode
constants in FPU-enabled SHmedia, let them be loaded from memory.
2001-08-28  Alexandre Oliva  <aoliva@redhat.com>
* config/sh/sh.md (cmpeqdi_media, cmpgtdi_media, cmpgtudi_media):
Adjust whitespace in assembly output templates.
2001-08-28  Stephen Clarke  <Stephen.Clarke@st.com>
* config/sh/sh.md (movdicc_false, movdicc_true, movdicc): Adjust
mode of if_then_else.
2001-08-04  Alexandre Oliva  <aoliva@redhat.com>
* config/sh/sh64.h (CPP_DEFAULT_CPU_SPEC): Override definition in
sh.h.
2001-07-26  Andrew Haley  <aph@cambridge.redhat.com>
    Joern Rennecke <amylaar@redhat.com>
* config/sh/sh64.h (CPP_DEFAULT_CPU_SPEC): New.
(SUBTARGET_CPP_PTR_SPEC): New.
(SUBTARGET_CPP_SPEC): Remove.
2001-07-06  Chandrakala Chavva  <cchavva@redhat.com>
* config/sh/sh.md (movsf_media_nofpu+1, movdf_media_nofpu+1):
Fix typo in previous checkin.
2001-07-11  Chandrakala Chavva  <cchavva@redhat.com>
* config/sh/sh.h (MODES_TIEABLE_P): Fix redact indentations.
2001-07-10  Chandrakala Chavva  <cchavva@cygnus.com>
    Alexandre Oliva  <aoliva@redhat.com>
* config/sh/sh.h (MODES_TIEABLE_P): Don't tie modes wider than
what single FP register can hold for SHmedia target.
2001-07-06  Chandrakala Chavva  <cchavva@redhat.com>
    Alexandre Oliva  <aoliva@redhat.com>
* config/sh/sh.md (movsf_media_nofpu+1, movdf_media_nofpu+1):
Do not split into SUBREG.
2001-06-14  Alexandre Oliva  <aoliva@redhat.com>
* config/sh/ushmedia.h, config/sh/sshmedia.h: Updated signatures
and added new functions as specified in SH5 ABI r9.
2001-06-04  Alexandre Oliva  <aoliva@redhat.com>
* config/sh/lib1funcs.asm (GCC_nested_trampoline): Align to an
8-byte boundary.
2001-06-03  Alexandre Oliva  <aoliva@redhat.com>
* config/sh/sh.c (dump_table): Add const0_rtx in calls of
gen_consttable_4 and gen_consttable_8.  Emit multiple labels
and consttable_window_ends.
2001-06-03  Graham Stott  <grahams@redhat,com>
* config/sh/sh.md (movdi split): Remove unused variable last_insn.
2001-05-16  Alexandre Oliva  <aoliva@redhat.com>
* config/sh/sh.c (print_operand): Handle floating-point pair,
vector and matrix registers.
* config/sh/sh.h (REGISTER_MOVE_COST): Take floating-pointer
vector modes into account.
* config/sh/sh.md (movv2sf): Split move between registers into
movdf.
(movv4sf, movv16sf): Introduce insns that get split only after
reload.
* config/sh/shmedia.h: Fix Copyright dates.
* config/sh/ushmedia.h: Likewise.  Move loop counter
declarations into conditionals that uses them.
(sh_media_FVADD_S, sh_media_FVSUB_S): Fix off-by-one error in
loop boundary.
* config/sh/sshmedia.h: Fix Copyright dates.
(sh_media_PUTCFG): Fix constraints.
2001-05-12  Alexandre Oliva  <aoliva@redhat.com>
* config/sh/sh.h (TARGET_PTRMEMFUNC_VBIT_LOCATION): Define to
ptrmemfunc_vbit_in_delta for SH5.
2001-05-08  Alexandre Oliva  <aoliva@redhat.com>
* config/sh/sh.h (TARGET_SWITCHES): Document -m5-*.
* invoke.texi: Likewise.
2001-04-14  Alexandre Oliva  <aoliva@redhat.com>
* config/sh/lib1funcs.asm (GCC_push_shmedia_regs,
GCC_push_shmedia_regs_nofpu, GCC_pop_shmedia_regs,
GCC_pop_shmedia_regs_nofpu): New global symbols.
* config/sh/t-sh64 (LIB1ASMFUNCS): Add them.
* config/sh/sh.h (SHMEDIA_REGS_STACK_ADJUST): New macro.
* config/sh/sh.c (calc_live_regs): Account for PR's saving in
compact function with nonlocal labels.
(sh_expand_prologue) [SHcompact]: Push SHmedia regs if needed.
(sh_expand_epilogue) [SHcompact]: Pop them when appropriate.
(initial_elimination_offset): Account for their stack space.
* config/sh/sh.md (shmedia_save_restore_regs_compact): New insn.
* config/sh/sh.md (movsi_media, movsi_media_nofpu, movqi_media,
movhi_media, movdi_media, movdi_media_nofpu, movdf_media,
movdf_media_nofpu, movsf_media, movsf_media_nofpu): Require at
least one of the operands to be a register.
(movv2sf): Likewise.  Renamed to movv2sf_i.
(movdi, movdf, movv2sf, movv4sf, movv16sf, movsf):
prepare_move_operands() before emitting SHmedia insns.
2001-04-03  Alexandre Oliva  <aoliva@redhat.com>
* config/sh/crti.asm (init, fini) [__SH5__ && ! __SHMEDIA__]:
Don't save nor initialize r12.  Don't mis-align the stack.
Pad the code with a nop.
* config/sh/crti.asm: Don't restore r12.  Don't mis-align the
stack.
2001-03-13  Alexandre Oliva  <aoliva@redhat.com>
* gcc/longlong.h (__umulsidi3, count_leading_zeros)
[__SHMEDIA__]: Implement.
2001-03-11  Alexandre Oliva  <aoliva@redhat.com>
* config/sh/sh.md: Set latency of `pt' closer to reality.
(movsi_media, movsi_media_nofpu, movdi_media, movdi_media_nofpu,
movdf_media, movdf_media_nofpu, movsf_media, movsf_media_nofpu):
Set move, load and store type attributes.
* config/sh/sh.c (sh_loop_align) [TARGET_SH5]: Set to 3.
* config/sh/sh.h (OVERRIDE_OPTIONS) [TARGET_SH5]: Disable
profiling.
* config/sh/sh.h (PROMOTE_MODE): Sign-extend SImode to DImode.
* config/sh/sh-protos.h (sh_media_register_for_return): Declare.
* config/sh/sh.c (sh_media_register_for_return): New function.
(sh_expand_prologue) [TARGET_SHMEDIA]: Copy r18 to an available
branch-target register.
(sh_expand_epilogue) [TARGET_SHMEDIA]: Explicitly USE it.
* config/sh/sh.md (return_media_i): Use any call-clobbered
branch-target register.
(return_media): If r18 wasn't copied in the prologue, copy it
here.
* config/sh/sh.h (CONDITIONAL_REGISTER_USAGE) [TARGET_SHMEDIA]:
Clear class FP0_REGS.
* config/sh/sh64.h (LINK_SPEC): Removed incorrect default copied
from elf.h.
2001-03-08  DJ Delorie  <dj@redhat.com>
* config/sh/sh.h (OVERRIDE_OPTIONS): Disable relaxing for SHMEDIA.
2001-02-09  Alexandre Oliva  <aoliva@redhat.com>
* config/sh/sh.md (sibcall_compact): Set fp_mode to single.
2001-02-07  Alexandre Oliva  <aoliva@redhat.com>
* config/sh/sh.h (INT_ASM_OP) [SHMEDIA64]: Use `.quad'.
2001-02-03  Alexandre Oliva  <aoliva@redhat.com>
* config/sh/sh.h (INIT_CUMULATIVE_ARGS): Compute size of BLKmode
return value correctly for call_cookie.
2001-02-01  Alexandre Oliva  <aoliva@redhat.com>
* config/sh/crt1.asm (start): Modified so as to call
___setup_argv_and_call_main.
2001-01-26  Alexandre Oliva  <aoliva@redhat.com>
* config/sh/sh.h (FUNCTION_ARG_ADVANCE): Don't count stack_regs in
SHmedia mode.
2001-01-20  Alexandre Oliva  <aoliva@redhat.com>
* config/sh/sh.h (STRIP_DATALABEL_ENCODING): New macro.
(STRIP_NAME_ENCODING): Use it.
(ASM_OUTPUT_LABELREF): Likewise.  Don't call assemble_name().
2001-01-19  Alexandre Oliva  <aoliva@redhat.com>
* config/sh/sh.md (sgeu) [! SHMEDIA]: Fix invocation of
prepare_scc_operands().
* config/sh/sh.h (SH_DATALABEL_ENCODING): Change to "#"...
(DATALABEL_SYMNAME_P): ... so that we don't need memcmp here.
2001-01-17  Alexandre Oliva  <aoliva@redhat.com>
* config/sh/sh.h (STRIP_NAME_ENCODING): Strip leading `*'.
2001-01-13  Alexandre Oliva  <aoliva@redhat.com>
* config/sh/sh.md (shcompact_incoming_args): Use R0_REG.
* config/sh/sh.md (R7_REG, R8_REG, R9_REG): Define as constants,
used in shcompact_incoming_args.
* config/sh/sh.c (sh_expand_epilogue): Fix thinko in previous
change.
* config/sh/crt1.asm (start) [SH5]: Switch to single-precision
mode.
* config/sh/lib1funcs.asm (sdivsi3_i4, udivsi3_i4, set_fpscr):
Adjust accordingly.
* config/sh/sh.c (sh_expand_prologue, sh_expand_epilogue):
Simplify.  Adjust.  Add sanity check.
* config/sh/sh.h (TARGET_SWITCHES) [5-compact]: Set
FPU_SINGLE_BIT.
* config/sh/sh.md (udivsi3_i4_single, divsi3_i4_single): Match
TARGET_SHCOMPACT.
(udivsi3, divsi3): Use them.
(force_mode_for_call): New insn.
(call, call_value, sibcall_value): Emit it before SHcompact
calls.
2001-01-11  Alexandre Oliva  <aoliva@redhat.com>
* config/sh/sh.md (call, call_value, sibcall): Make sure the
call cookie is non-NULL before taking its value.
2001-01-10  Alexandre Oliva  <aoliva@redhat.com>
* config.gcc (sh64): Set target_requires_64bit_host_wide_int.
2001-01-09  Alexandre Oliva  <aoliva@redhat.com>
* config/sh/sh.md (shcompact_incoming_args): Set argument memory
block.
* config/sh/sh.h (STATIC_CHAIN_REGNUM) [SH5]: Use r1.
* config/sh/sh.c (sh_expand_prologue) [SH5]: Use r0 as
temporary for stack adjusts.  Use MACL and MACH to pass
arguments to shcompact_incoming_args.
* config/sh/sh.md (shcompact_incoming_args): Adjust.  Don't
clobber r1.
* config/sh/lib1funcs.asm (shcompact_incoming_args): Likewise.
(nested_trampoline): Load static chain address into r1.
* config/sh/sh.md (movdi_media splits): Fix sign-extension.
2001-01-07  Alexandre Oliva  <aoliva@redhat.com
* config/sh/sh.c (fpul_operand) [SHMEDIA]: Just call
fp_arith_reg_operand().
2001-01-06  Alexandre Oliva  <aoliva@redhat.com>
* config/sh/sh.md (casesi): Sign-extend the first two operands,
and use signed compares for them.
* config/sh/sh.c (dump_table): Don't emit 8-byte constants after
4-byte ones.  Instead, inter-leave them, maintaining the 8-byte
ones properly aligned.
(find_barrier): Account for extra alignment needed for 8-byte wide
constants.
(machine_dependent_reorg): Require a label for the second 4-byte
constant after an 8-byte one.
* config/sh/lib1funcs.asm (sdivsi3): Fix typo in yesterday's
change.
2001-01-05  Alexandre Oliva  <aoliva@redhat.com>
* config/sh/sh.c (machine_dependent_reorg) [SHCOMPACT]: Reset
last_float when switching float modes.
* config/sh/sh.md (movdf) [SH5]: Don't use stack-pointer
auto-increment for general-purpose registers.
* config/sh/lib1funcs.asm (sdivsi3) [SHMEDIA]: Sign-extend the
result.
* config/sh/sh.c (sh_expand_prologue) [SH5]: Use r1 as temporary
for stack adjust.
* config/sh/sh.c (sh_builtin_saveregs): Support using all
registers for varargs.
2001-01-01  Alexandre Oliva  <aoliva@redhat.com>
* config/sh/sh.h (FUNCTION_ARG_ADVANCE): Simplify.
* config/sh/sh.h (CALL_COOKIE_STACKSEQ,
CALL_COOKIE_STACKSEQ_SHIFT, CALL_COOKIE_STACKSEQ_GET): New macros.
(CALL_COOKIE_INT_REG_SHIFT): Adjust.
(FUNCTION_ARG_ADVANCE): Use SHCOMPACT_FORCE_ON_STACK.  Adjust
call_cookie accordingly.
(FUNCTION_ARG): Test SHCOMPACT_FORCE_ON_STACK.
(SHCOMPACT_BYREF): Likewise.
(SHCOMPACT_FORCE_ON_STACK): New macro.
* config/sh/sh.c (sh_expand_prologue): Use new call_cookie format.
(sh_builtin_saveregs): Likewise.
* config/sh/lib1funcs.asm (shcompact_call_trampoline,
shcompact_incoming_args): Use new shift values.  Support
sequences of consecutive and non-consecutive pushes/pops.
* config/sh/sh.md (return): Don't explicitly use PR_REG.
2001-01-05  Hans-Peter Nilsson  <hpn@cygnus.com>
* config/sh/sh.h (TEXT_SECTION): Define.
* config/sh/elf.h (ASM_FILE_START): Output TEXT_SECTION_ASM_OP.
2001-01-05  Alexandre Oliva  <aoliva@redhat.com>
* config/sh/sh.h (INIT_CUMULATIVE_LIBCALL_ARGS): New macro.
* config/sh/sh.h (BASE_RETURN_VALUE_REG): Use FP regs for
return values on FPU-enabled SHmedia.
(FUNCTION_VALUE_REGNO_P): Mark FIRST_FP_RET_REG as used on
FPU-enabled SHmedia.
(INIT_CUMULATIVE_ARGS): Set up return trampoline only if
value is returned in a non-FP reg and is not returned by
reference.
* config/sh/sh.md (shcompact_return_tramp_i): Change type to
jump_ind.
2000-01-04  Alexandre Oliva  <aoliva@redhat.com>
* config/sh/sh.h (SH_MIN_ALIGN_FOR_CALLEE_COPY): New.
(FUNCTION_ARG_CALLEE_COPIES): Require argument to be
quad-aligned to be passed by callee-copy reference.
2001-01-03  Alexandre Oliva  <aoliva@redhat.com>
* config/sh/elf.h (MAX_WCHAR_TYPE_SIZE): Define.
* config/sh/sh64.h (MAX_WCHAR_TYPE_SIZE): Undefine.
2001-01-02  Alexandre Oliva  <aoliva@redhat.com>
* config/sh/lib1funcs.asm (shcompact_call_trampoline): Fix error in
copying low-numbered FP regs to r7 and r8.
* config/sh/sh.h (FUNCTION_ARG_ADVANCE): Don't request copying of
FP regs to general-purpose regs only if the copy was passed on the
stack.
* config/sh/lib1funcs.asm (shcompact_call_trampoline): Fix typo in
copying FP reg to r9.
* config/sh/sh.h (FUNCTION_ARG_ADVANCE): Use trampoline to
copy FP regs to general-purpose regs only in outgoing calls.
* config/sh/sh.md (movdf_media, movsf_media): Revert incorrect
change from  2000-10-30.  Adjust for 64-bit (or 32-bit)
HOST_WIDE_INT.
* config/sh/sh.h (struct sh_args): Document all fields.
(FUNCTION_OK_FOR_SIBCALL): Functions that receive arguments
passed partially on the stack should not consider making
sibcalls.
* config/sh/sh.h (FUNCTION_ARG_ADVANCE): Add byref regs to
stack_regs only for incoming calls.  When passing FP args,
make sure there are FP regs available before modifying
call_cookie.
(SHCOMPACT_BYREF): Pass double args in general-purpose
registers by reference.
2000-12-30  Alexandre Oliva  <aoliva@redhat.com>
* config/sh/sh.h (FUNCTION_OK_FOR_SIBCALL) [SHCOMPACT]: Don't
attempt to generate sibcalls if the caller got any arguments
by reference.
* config/sh/lib1funcs.asm (set_fpscr) [SH5]: Default to double.
* config/sh/sh.c (dump_table) [SHCOMPACT]: Align DImode and DFmode
to 8-byte boundaries.
* config/sh/sh.md (shcompact_preserve_incoming_args): New insn.
* config/sh/sh.h (CALL_COOKIE_INT_REG_GET): New macro.
* config/sh/sh.c (sh_expand_prologue): Preserve args that will be
stored in the stack.
* config/sh/lib1funcs.asm (ct_main_table, ia_main_table): Arrange
for the offsets to have the ISA bit set.
(shcompact_call_trampoline): Document.  Swap r0 and r1, to match
invocation.  Use beq instead of bgt to mark end of sequence of
loads.
(shcompact_incoming_args): Fix store of r2.  Use beq instead of
bgt to mark end of sequence of stores.
* config/sh/sh.c (arith_operand): Don't check whether
CONST_OK_FOR_J for now.
* config/sh/sh.md (movdf_media, movsf_media): Use HOST_WIDE_INT
instead of long for conversion.
2000-12-29  Alexandre Oliva  <aoliva@redhat.com>
* config/sh/sh.c (print_operand_address): Convert INTVAL to int
before passing it to fprintf.
2000-12-28  Alexandre Oliva  <aoliva@redhat.com>
* config/sh/crt1.asm (start): Reset SR.FD, to enable the FP unit.
Call set_fpscr before reading/writing SR.
* config/sh/crt1.asm (start): Set SR.SZ and SR.PR, but not SR.FR.
Call set_fpscr.
* config/sh/lib1funcs.asm: Add `.align 2' directives before
SHmedia code.
(FMOVD_WORKS): Define on SH5 with FPU.
(set_fpscr): Define on SH5.  Remove separate _fpscr_values
setting.
* config/sh/t-sh64 (LIB1ASMFUNCS): Add _set_fpscr instead of
_fpscr_values.
2000-12-28  Hans-Peter Nilsson  <hpn@cygnus.com>
* config/sh/lib1funcs.asm (ct_main_table): Align contents to even
address.
(ia_main_table): Ditto.
2000-12-27  Alexandre Oliva  <aoliva@redhat.com>
* config/sh/sh.h (MAX_WCHAR_TYPE_SIZE): Don't define.
* config/sh/sh64.h (WCHAR_TYPE, WCHAR_TYPE_SIZE): Reinstate
the definitions from sh.h.
* config/sh/sh.h (PTRDIFF_TYPE): Define as conditional on
TARGET_SH5.
(SUBTARGET_CPP_SPEC): Arrange for __PTRDIFF_TYPE__ to be defined.
* config/sh/elf.h (PTRDIFF_TYPE): Likewise.
* config/sh/sh64.h (SUBTARGET_CPP_SPEC): Likewise.
2000-12-26  Alexandre Oliva  <aoliva@redhat.com>
* config/sh/sh.md (movdi_media split): Don't add REG_LABEL notes.
Increment LABEL_NUSES.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@49630 138bc75d-0d04-0410-961f-82ee72b054a4

24 files changed:
gcc/ChangeLog
gcc/c-common.c
gcc/calls.c
gcc/config.gcc
gcc/config/sh/crt1.asm
gcc/config/sh/crti.asm
gcc/config/sh/crtn.asm
gcc/config/sh/elf.h
gcc/config/sh/lib1funcs.asm
gcc/config/sh/sh-protos.h
gcc/config/sh/sh.c
gcc/config/sh/sh.h
gcc/config/sh/sh.md
gcc/config/sh/sh64.h [new file with mode: 0644]
gcc/config/sh/shmedia.h [new file with mode: 0644]
gcc/config/sh/sshmedia.h [new file with mode: 0644]
gcc/config/sh/t-sh64 [new file with mode: 0644]
gcc/config/sh/ushmedia.h [new file with mode: 0644]
gcc/doc/invoke.texi
gcc/doc/tm.texi
gcc/longlong.h
gcc/machmode.def
gcc/tree.c
gcc/tree.h

index 7c2267c..6d0d267 100644 (file)
@@ -1,5 +1,888 @@
 2002-02-09  Alexandre Oliva  <aoliva@redhat.com>
 
+       Contribute sh64-elf.
+       2002-02-09  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.c (TARGET_CANNOT_MODIFY_JUMPS_P): Define to...
+       (sh_cannot_modify_jumps_p): New function.
+       2002-02-05  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.c (TARGET_MS_BITFIELD_LAYOUT_P): Define to...
+       (sh_ms_bitfield_layout_p): New function.
+       2002-02-04  Alexandre Oliva  <aoliva@redhat.com>
+                   Zack Weinberg  <zack@codesourcery.com>
+       * config/sh/sh.h (TRAMPOLINE_ADJUST_ADDRESS): Use
+       expand_simple_binop instead of expand_binop.
+       2002-02-03  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.h (OVERRIDE_OPTIONS) [! TARGET_SH5]: Disable
+       use of .quad and .uaquad.
+       * config/sh/sh.c (TARGET_ASM_UNALIGNED_DI_OP,
+       TARGET_ASM_ALIGNED_DI_OP): Add comment pointing to the above.
+       2002-01-24  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.md (movdi_const, movdi_const_32bit,
+       movdi_const_16bit): Make sure all CONSTs have modes.
+       (sym2PIC): Ditto, but by adjusting all callers.
+       * config/sh/sh.c (calc_live_regs) [TARGET_SHCOMPACT]: Set pr_live
+       if the prologue calls the SHmedia argument decoder or register
+       saver.
+       2002-01-24  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.c (TARGET_ASM_UNALIGNED_DI_OP): Define.
+       (TARGET_ASM_ALIGNED_DI_OP): Likewise.
+       (sh_expand_epilogue): Don't emit USE of return target register.
+       (prepare_move_operands): Legitimize DImode PIC addresses.
+       (sh_media_register_for_return): Skip tr0, used to initialize the
+       PIC register.
+       (sh_expand_prologue): Remove explicit USE of return register.
+       (nonpic_symbol_mentioned_p): PC is non-PIC.  Don't recurse in
+       CONST_DOUBLEs.  UNSPEC_GOTPLT is PIC.
+       * config/sh/sh.h (ASM_OUTPUT_DOUBLE_INT): Removed, obsolete.
+       (OVERRIDE_OPTIONS): Don't disable PIC on SH5.
+       (EXTRA_CONSTRAINT_S): Use MOVI_SHORI_BASE_OPERAND_P instead of
+       EXTRA_CONSTRAINT_T.
+       (GOT_ENTRY_P, GOTPLT_ENTRY_P, GOTOFF_P, PIC_ADDR_P): New.
+       (MOVI_SHORI_BASE_OPERAND_P): New.
+       (NON_PIC_REFERENCE_P, PIC_REFERENCE_P): New.
+       (EXTRA_CONSTRAINT_T): Define in terms of them.
+       (OUTPUT_ADDR_CONST_EXTRA): Handle UNSPEC_GOTPLT.
+       * config/sh/sh.md (movsi_media, movsi_media_nofpu,
+       movdi_media, movdi_media_nofpu): Add SIBCALL_REGS class to
+       alternatives supporting TARGET_REGS.
+       (UNSPEC_GOTPLT): New constant.
+       (movdi split): Move incrementing of LABEL_NUSES...
+       (movdi_const, movdi_const_32bit): Here.  Use
+       MOVI_SHORI_BASE_OPERAND_P instead of EXTRA_CONSTRAINT_T.
+       (movdi_const_16bit): New.
+       (call, call_value) [flag_pic]: Use GOTPLT.
+       (call_pop, call_value_pop): New expands.
+       (call_pop_compact, call_pop_rettramp): New insns.
+       (call_value_pop_compact, call_value_pop_rettramp): New insns.
+       (sibcall) [flag_pic]: Use GOT.
+       (builtint_setjmp_receiver): Remove bogus, unused expand.
+       (GOTaddr2picreg): Implement for SHcompact and SHmedia.
+       (*pt, *ptb, ptrel): New insns.
+       (sym2GOT): Handle DImode GOT.
+       (sym2GOTPLT, symGOTPLT2reg): New expands.
+       (sym2PIC): New expand.
+       (shcompact_return_tramp): Use GOTPLT to return trampoline.
+       (shcompact_return_tramp_i): Use return register explicitly.
+       * config/sh/sh.h (OVERRIDE_OPTIONS) [TARGET_SHMEDIA]: Don't
+       disable flag_reorder_blocks.
+       2002-01-19  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.md (sibcall_compact): Reorder return, uses and
+       clobbers, for clarity.
+       (sibcall_epilogue) [TARGET_SHCOMPACT]: Mark saving and
+       restoring of r0 in macl as MAYBE_DEAD.
+       2002-01-18  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.h (LONG_DOUBLE_TYPE_SIZE): Define.
+       * config/sh/sh.md (movv4sf_i, movv16sf_i): Fix uses of
+       alter_subreg all over.
+       (jump) [TARGET_SHMEDIA]: FAIL to create new jumps after
+       reload, instead of emitting instructions that would require
+       reloading.
+       (casesi_load_media): Add missing modes.
+       2001-11-09  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.c (sh_expand_prologue): Mark the PIC register
+       as used if the argument decoder is called.
+       2001-08-28  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.md (udivsi3, divsi3): Load libcall symbol name in
+       Pmode, then extend it to DImode if necessary.
+       2001-08-28  Stephen Clarke  <Stephen.Clarke@st.com>
+       * config/sh/sh.h (LEGITIMATE_CONSTANT_P): Don't accept DFmode
+       constants in FPU-enabled SHmedia, let them be loaded from memory.
+       2001-08-28  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.md (cmpeqdi_media, cmpgtdi_media, cmpgtudi_media):
+       Adjust whitespace in assembly output templates.
+       2001-08-28  Stephen Clarke  <Stephen.Clarke@st.com>
+       * config/sh/sh.md (movdicc_false, movdicc_true, movdicc): Adjust
+       mode of if_then_else.
+       2001-08-04  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh64.h (CPP_DEFAULT_CPU_SPEC): Override definition in
+       sh.h.
+       2001-07-26  Andrew Haley  <aph@cambridge.redhat.com>
+                   Joern Rennecke <amylaar@redhat.com>
+       * config/sh/sh64.h (CPP_DEFAULT_CPU_SPEC): New.
+       (SUBTARGET_CPP_PTR_SPEC): New.
+       (SUBTARGET_CPP_SPEC): Remove.
+       2001-07-06  Chandrakala Chavva  <cchavva@redhat.com>
+       * config/sh/sh.md (movsf_media_nofpu+1, movdf_media_nofpu+1):
+       Fix typo in previous checkin.
+       2001-07-11  Chandrakala Chavva  <cchavva@redhat.com>
+       * config/sh/sh.h (MODES_TIEABLE_P): Fix redact indentations.
+       2001-07-10  Chandrakala Chavva  <cchavva@cygnus.com>
+                   Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.h (MODES_TIEABLE_P): Don't tie modes wider than
+       what single FP register can hold for SHmedia target.
+       2001-07-06  Chandrakala Chavva  <cchavva@redhat.com>
+                   Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.md (movsf_media_nofpu+1, movdf_media_nofpu+1):
+       Do not split into SUBREG.
+       2001-06-14  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/ushmedia.h, config/sh/sshmedia.h: Updated signatures
+       and added new functions as specified in SH5 ABI r9.
+       2001-06-04  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/lib1funcs.asm (GCC_nested_trampoline): Align to an
+       8-byte boundary.
+       2001-06-03  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.c (dump_table): Add const0_rtx in calls of
+       gen_consttable_4 and gen_consttable_8.  Emit multiple labels
+       and consttable_window_ends.
+       2001-06-03  Graham Stott  <grahams@redhat,com>
+       * config/sh/sh.md (movdi split): Remove unused variable last_insn.
+       2001-05-16  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.c (print_operand): Handle floating-point pair,
+       vector and matrix registers.
+       * config/sh/sh.h (REGISTER_MOVE_COST): Take floating-pointer
+       vector modes into account.
+       * config/sh/sh.md (movv2sf): Split move between registers into
+       movdf.
+       (movv4sf, movv16sf): Introduce insns that get split only after
+       reload.
+       * config/sh/shmedia.h: Fix Copyright dates.
+       * config/sh/ushmedia.h: Likewise.  Move loop counter
+       declarations into conditionals that uses them.
+       (sh_media_FVADD_S, sh_media_FVSUB_S): Fix off-by-one error in
+       loop boundary.
+       * config/sh/sshmedia.h: Fix Copyright dates.
+       (sh_media_PUTCFG): Fix constraints.
+       2001-05-12  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.h (TARGET_PTRMEMFUNC_VBIT_LOCATION): Define to
+       ptrmemfunc_vbit_in_delta for SH5.
+       2001-05-08  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.h (TARGET_SWITCHES): Document -m5-*.
+       * invoke.texi: Likewise.
+       2001-04-14  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/lib1funcs.asm (GCC_push_shmedia_regs,
+       GCC_push_shmedia_regs_nofpu, GCC_pop_shmedia_regs,
+       GCC_pop_shmedia_regs_nofpu): New global symbols.
+       * config/sh/t-sh64 (LIB1ASMFUNCS): Add them.
+       * config/sh/sh.h (SHMEDIA_REGS_STACK_ADJUST): New macro.
+       * config/sh/sh.c (calc_live_regs): Account for PR's saving in
+       compact function with nonlocal labels.
+       (sh_expand_prologue) [SHcompact]: Push SHmedia regs if needed.
+       (sh_expand_epilogue) [SHcompact]: Pop them when appropriate.
+       (initial_elimination_offset): Account for their stack space.
+       * config/sh/sh.md (shmedia_save_restore_regs_compact): New insn.
+       * config/sh/sh.md (movsi_media, movsi_media_nofpu, movqi_media,
+       movhi_media, movdi_media, movdi_media_nofpu, movdf_media,
+       movdf_media_nofpu, movsf_media, movsf_media_nofpu): Require at
+       least one of the operands to be a register.
+       (movv2sf): Likewise.  Renamed to movv2sf_i.
+       (movdi, movdf, movv2sf, movv4sf, movv16sf, movsf):
+       prepare_move_operands() before emitting SHmedia insns.
+       2001-04-03  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/crti.asm (init, fini) [__SH5__ && ! __SHMEDIA__]:
+       Don't save nor initialize r12.  Don't mis-align the stack.
+       Pad the code with a nop.
+       * config/sh/crti.asm: Don't restore r12.  Don't mis-align the
+       stack.
+       2001-03-13  Alexandre Oliva  <aoliva@redhat.com>
+       * gcc/longlong.h (__umulsidi3, count_leading_zeros)
+       [__SHMEDIA__]: Implement.
+       2001-03-11  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.md: Set latency of `pt' closer to reality.
+       (movsi_media, movsi_media_nofpu, movdi_media, movdi_media_nofpu,
+       movdf_media, movdf_media_nofpu, movsf_media, movsf_media_nofpu):
+       Set move, load and store type attributes.
+       * config/sh/sh.c (sh_loop_align) [TARGET_SH5]: Set to 3.
+       * config/sh/sh.h (OVERRIDE_OPTIONS) [TARGET_SH5]: Disable
+       profiling.
+       * config/sh/sh.h (PROMOTE_MODE): Sign-extend SImode to DImode.
+       * config/sh/sh-protos.h (sh_media_register_for_return): Declare.
+       * config/sh/sh.c (sh_media_register_for_return): New function.
+       (sh_expand_prologue) [TARGET_SHMEDIA]: Copy r18 to an available
+       branch-target register.
+       (sh_expand_epilogue) [TARGET_SHMEDIA]: Explicitly USE it.
+       * config/sh/sh.md (return_media_i): Use any call-clobbered
+       branch-target register.
+       (return_media): If r18 wasn't copied in the prologue, copy it
+       here.
+       * config/sh/sh.h (CONDITIONAL_REGISTER_USAGE) [TARGET_SHMEDIA]:
+       Clear class FP0_REGS.
+       * config/sh/sh64.h (LINK_SPEC): Removed incorrect default copied
+       from elf.h.
+       2001-03-08  DJ Delorie  <dj@redhat.com>
+       * config/sh/sh.h (OVERRIDE_OPTIONS): Disable relaxing for SHMEDIA.
+       2001-02-09  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.md (sibcall_compact): Set fp_mode to single.
+       2001-02-07  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.h (INT_ASM_OP) [SHMEDIA64]: Use `.quad'.
+       2001-02-03  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.h (INIT_CUMULATIVE_ARGS): Compute size of BLKmode
+       return value correctly for call_cookie.
+       2001-02-01  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/crt1.asm (start): Modified so as to call
+       ___setup_argv_and_call_main.
+       2001-01-26  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.h (FUNCTION_ARG_ADVANCE): Don't count stack_regs in
+       SHmedia mode.
+       2001-01-20  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.h (STRIP_DATALABEL_ENCODING): New macro.
+       (STRIP_NAME_ENCODING): Use it.
+       (ASM_OUTPUT_LABELREF): Likewise.  Don't call assemble_name().
+       2001-01-19  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.md (sgeu) [! SHMEDIA]: Fix invocation of
+       prepare_scc_operands().
+       * config/sh/sh.h (SH_DATALABEL_ENCODING): Change to "#"...
+       (DATALABEL_SYMNAME_P): ... so that we don't need memcmp here.
+       2001-01-17  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.h (STRIP_NAME_ENCODING): Strip leading `*'.
+       2001-01-13  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.md (shcompact_incoming_args): Use R0_REG.
+       * config/sh/sh.md (R7_REG, R8_REG, R9_REG): Define as constants,
+       used in shcompact_incoming_args.
+       * config/sh/sh.c (sh_expand_epilogue): Fix thinko in previous
+       change.
+       * config/sh/crt1.asm (start) [SH5]: Switch to single-precision
+       mode.
+       * config/sh/lib1funcs.asm (sdivsi3_i4, udivsi3_i4, set_fpscr):
+       Adjust accordingly.
+       * config/sh/sh.c (sh_expand_prologue, sh_expand_epilogue):
+       Simplify.  Adjust.  Add sanity check.
+       * config/sh/sh.h (TARGET_SWITCHES) [5-compact]: Set
+       FPU_SINGLE_BIT.
+       * config/sh/sh.md (udivsi3_i4_single, divsi3_i4_single): Match
+       TARGET_SHCOMPACT.
+       (udivsi3, divsi3): Use them.
+       (force_mode_for_call): New insn.
+       (call, call_value, sibcall_value): Emit it before SHcompact
+       calls.
+       2001-01-11  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.md (call, call_value, sibcall): Make sure the
+       call cookie is non-NULL before taking its value.
+       2001-01-10  Alexandre Oliva  <aoliva@redhat.com>
+       * config.gcc (sh64): Set target_requires_64bit_host_wide_int.
+       2001-01-09  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.md (shcompact_incoming_args): Set argument memory
+       block.
+       * config/sh/sh.h (STATIC_CHAIN_REGNUM) [SH5]: Use r1.
+       * config/sh/sh.c (sh_expand_prologue) [SH5]: Use r0 as
+       temporary for stack adjusts.  Use MACL and MACH to pass
+       arguments to shcompact_incoming_args.
+       * config/sh/sh.md (shcompact_incoming_args): Adjust.  Don't
+       clobber r1.
+       * config/sh/lib1funcs.asm (shcompact_incoming_args): Likewise.
+       (nested_trampoline): Load static chain address into r1.
+       * config/sh/sh.md (movdi_media splits): Fix sign-extension.
+       2001-01-07  Alexandre Oliva  <aoliva@redhat.com
+       * config/sh/sh.c (fpul_operand) [SHMEDIA]: Just call
+       fp_arith_reg_operand().
+       2001-01-06  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.md (casesi): Sign-extend the first two operands,
+       and use signed compares for them.
+       * config/sh/sh.c (dump_table): Don't emit 8-byte constants after
+       4-byte ones.  Instead, inter-leave them, maintaining the 8-byte
+       ones properly aligned.
+       (find_barrier): Account for extra alignment needed for 8-byte wide
+       constants.
+       (machine_dependent_reorg): Require a label for the second 4-byte
+       constant after an 8-byte one.
+       * config/sh/lib1funcs.asm (sdivsi3): Fix typo in yesterday's
+       change.
+       2001-01-05  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.c (machine_dependent_reorg) [SHCOMPACT]: Reset
+       last_float when switching float modes.
+       * config/sh/sh.md (movdf) [SH5]: Don't use stack-pointer
+       auto-increment for general-purpose registers.
+       * config/sh/lib1funcs.asm (sdivsi3) [SHMEDIA]: Sign-extend the
+       result.
+       * config/sh/sh.c (sh_expand_prologue) [SH5]: Use r1 as temporary
+       for stack adjust.
+       * config/sh/sh.c (sh_builtin_saveregs): Support using all
+       registers for varargs.
+       2001-01-01  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.h (FUNCTION_ARG_ADVANCE): Simplify.
+       * config/sh/sh.h (CALL_COOKIE_STACKSEQ,
+       CALL_COOKIE_STACKSEQ_SHIFT, CALL_COOKIE_STACKSEQ_GET): New macros.
+       (CALL_COOKIE_INT_REG_SHIFT): Adjust.
+       (FUNCTION_ARG_ADVANCE): Use SHCOMPACT_FORCE_ON_STACK.  Adjust
+       call_cookie accordingly.
+       (FUNCTION_ARG): Test SHCOMPACT_FORCE_ON_STACK.
+       (SHCOMPACT_BYREF): Likewise.
+       (SHCOMPACT_FORCE_ON_STACK): New macro.
+       * config/sh/sh.c (sh_expand_prologue): Use new call_cookie format.
+       (sh_builtin_saveregs): Likewise.
+       * config/sh/lib1funcs.asm (shcompact_call_trampoline,
+       shcompact_incoming_args): Use new shift values.  Support
+       sequences of consecutive and non-consecutive pushes/pops.
+       * config/sh/sh.md (return): Don't explicitly use PR_REG.
+       2001-01-05  Hans-Peter Nilsson  <hpn@cygnus.com>
+       * config/sh/sh.h (TEXT_SECTION): Define.
+       * config/sh/elf.h (ASM_FILE_START): Output TEXT_SECTION_ASM_OP.
+       2001-01-05  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.h (INIT_CUMULATIVE_LIBCALL_ARGS): New macro.
+       * config/sh/sh.h (BASE_RETURN_VALUE_REG): Use FP regs for
+       return values on FPU-enabled SHmedia.
+       (FUNCTION_VALUE_REGNO_P): Mark FIRST_FP_RET_REG as used on
+       FPU-enabled SHmedia.
+       (INIT_CUMULATIVE_ARGS): Set up return trampoline only if
+       value is returned in a non-FP reg and is not returned by
+       reference.
+       * config/sh/sh.md (shcompact_return_tramp_i): Change type to
+       jump_ind.
+       2000-01-04  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.h (SH_MIN_ALIGN_FOR_CALLEE_COPY): New.
+       (FUNCTION_ARG_CALLEE_COPIES): Require argument to be
+       quad-aligned to be passed by callee-copy reference.
+       2001-01-03  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/elf.h (MAX_WCHAR_TYPE_SIZE): Define.
+       * config/sh/sh64.h (MAX_WCHAR_TYPE_SIZE): Undefine.
+       2001-01-02  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/lib1funcs.asm (shcompact_call_trampoline): Fix error in
+       copying low-numbered FP regs to r7 and r8.
+       * config/sh/sh.h (FUNCTION_ARG_ADVANCE): Don't request copying of
+       FP regs to general-purpose regs only if the copy was passed on the
+       stack.
+       * config/sh/lib1funcs.asm (shcompact_call_trampoline): Fix typo in
+       copying FP reg to r9.
+       * config/sh/sh.h (FUNCTION_ARG_ADVANCE): Use trampoline to
+       copy FP regs to general-purpose regs only in outgoing calls.
+       * config/sh/sh.md (movdf_media, movsf_media): Revert incorrect
+       change from     2000-10-30.  Adjust for 64-bit (or 32-bit)
+       HOST_WIDE_INT.
+       * config/sh/sh.h (struct sh_args): Document all fields.
+       (FUNCTION_OK_FOR_SIBCALL): Functions that receive arguments
+       passed partially on the stack should not consider making
+       sibcalls.
+       * config/sh/sh.h (FUNCTION_ARG_ADVANCE): Add byref regs to
+       stack_regs only for incoming calls.  When passing FP args,
+       make sure there are FP regs available before modifying
+       call_cookie.
+       (SHCOMPACT_BYREF): Pass double args in general-purpose
+       registers by reference.
+       2000-12-30  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.h (FUNCTION_OK_FOR_SIBCALL) [SHCOMPACT]: Don't
+       attempt to generate sibcalls if the caller got any arguments
+       by reference.
+       * config/sh/lib1funcs.asm (set_fpscr) [SH5]: Default to double.
+       * config/sh/sh.c (dump_table) [SHCOMPACT]: Align DImode and DFmode
+       to 8-byte boundaries.
+       * config/sh/sh.md (shcompact_preserve_incoming_args): New insn.
+       * config/sh/sh.h (CALL_COOKIE_INT_REG_GET): New macro.
+       * config/sh/sh.c (sh_expand_prologue): Preserve args that will be
+       stored in the stack.
+       * config/sh/lib1funcs.asm (ct_main_table, ia_main_table): Arrange
+       for the offsets to have the ISA bit set.
+       (shcompact_call_trampoline): Document.  Swap r0 and r1, to match
+       invocation.  Use beq instead of bgt to mark end of sequence of
+       loads.
+       (shcompact_incoming_args): Fix store of r2.  Use beq instead of
+       bgt to mark end of sequence of stores.
+       * config/sh/sh.c (arith_operand): Don't check whether
+       CONST_OK_FOR_J for now.
+       * config/sh/sh.md (movdf_media, movsf_media): Use HOST_WIDE_INT
+       instead of long for conversion.
+       2000-12-29  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.c (print_operand_address): Convert INTVAL to int
+       before passing it to fprintf.
+       2000-12-28  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/crt1.asm (start): Reset SR.FD, to enable the FP unit.
+       Call set_fpscr before reading/writing SR.
+       * config/sh/crt1.asm (start): Set SR.SZ and SR.PR, but not SR.FR.
+       Call set_fpscr.
+       * config/sh/lib1funcs.asm: Add `.align 2' directives before
+       SHmedia code.
+       (FMOVD_WORKS): Define on SH5 with FPU.
+       (set_fpscr): Define on SH5.  Remove separate _fpscr_values
+       setting.
+       * config/sh/t-sh64 (LIB1ASMFUNCS): Add _set_fpscr instead of
+       _fpscr_values.
+       2000-12-28  Hans-Peter Nilsson  <hpn@cygnus.com>
+       * config/sh/lib1funcs.asm (ct_main_table): Align contents to even
+       address.
+       (ia_main_table): Ditto.
+       2000-12-27  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.h (MAX_WCHAR_TYPE_SIZE): Don't define.
+       * config/sh/sh64.h (WCHAR_TYPE, WCHAR_TYPE_SIZE): Reinstate
+       the definitions from sh.h.
+       * config/sh/sh.h (PTRDIFF_TYPE): Define as conditional on
+       TARGET_SH5.
+       (SUBTARGET_CPP_SPEC): Arrange for __PTRDIFF_TYPE__ to be defined.
+       * config/sh/elf.h (PTRDIFF_TYPE): Likewise.
+       * config/sh/sh64.h (SUBTARGET_CPP_SPEC): Likewise.
+       2000-12-26  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.md (movdi_media split): Don't add REG_LABEL notes.
+       Increment LABEL_NUSES.
+       
+       * config/sh/sh.h (SIZE_TYPE): Define as conditional on
+       TARGET_SH5.
+       (SUBTARGET_CPP_SPEC): Arrange for __SIZE_TYPE__ to be always
+       defined.
+       * config/sh/elf.h (SIZE_TYPE): Likewise.
+       * config/sh/sh64.h (SUBTARGET_CPP_SPEC): Likewise.
+       * config/sh/lib1funcs.asm (shcompact_call_trampoline,
+       shcompact_incoming_args): Load switch table addresses using
+       datalabel.
+       * config/sh/sh.h (SUBTARGET_CPP_SPEC): Define __SIZE_TYPE__.
+       (NO_BUILTIN_SIZE_TYPE): Define.
+       (SIZE_TYPE): Don't define.
+       * config/sh/sh64.h (SUBTARGET_CPP_SPEC): Define __SIZE_TYPE__.
+       * config/sh/sh.h (CPP_SPEC): Fixed typo that prevented the
+       definition of __SH5__=32 for -m5-compact-nofpu.
+       * config/sh/sh.c (barrier_align): Ensure 32-bit alignment after
+       ADDR_DIFF_VEC.
+       2000-12-24  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.h (FUNCTION_ARG_PADDING): Removed.
+       2000-12-23  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.h (TARGET_CACHE32): Enable on SH5.
+       (FUNCTION_BOUNDARY): Ensure 32-bit alignment for SHmedia.
+       (INSN_LENGTH_ALIGNMENT): Likewise.
+       2000-12-22  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.md (call, call_value, sibcall): Simplify
+       copying of non-branch-target register.
+       2000-12-22  Alexandre Oliva  <aoliva@redhat.com>
+       * glimits.h (__LONG_MAX__): Revert      2000-12-13's patch.
+       * config/sh/sh.h (CPP_SPEC): Define it here for 64-bit SHmedia.
+       2000-12-22  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.h (GET_SH_ARG_CLASS): Handle complex
+       floating-point values as structs.
+       (FUNCTION_ARG): Use SH5_PROTOTYPED_FLOAT_ARG.
+       (SH5_PROTOTYPELESS_FLOAT_ARG): List FP registers before
+       general-purpose register.
+       (SH5_PROTOTYPED_FLOAT_ARG): New macro.
+       2000-12-20  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.md (addsi3): Force operand1 to reg for SHmedia.
+       * config/sh/sh.md (movsi_media): Split CONST_DOUBLE loads too.
+       * config/sh/sh.h (DATALABEL_REF_P): Don't require the CONST.
+       (ENCODE_SECTION_INFO): Enclose variables and constants in
+       DATALABEL unspecs.
+       (SH_DATALABEL_ENCODING, DATALABEL_SYMNAME_P): Define.
+       (STRIP_NAME_ENCODING): Strip SH_DATALABEL_ENCODING off.
+       (ASM_OUTPUT_LABELREF, AMS_OUTPUT_SYMBOL_REF): Define.
+       * config/sh/sh.c (gen_datalabel_ref): Use UNSPEC_DATALABEL
+       only for LABEL_REFs.  For SYMBOL_REFs, prepend
+       SH_DATALABEL_ENCODING to the symbol name.
+       * config/sh/sh.md (indirect_jump): Use SUBREG instead of
+       convert_mode().
+       2000-12-20  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.md (casesi): Enclose ADDR_DIFF_VEC address in
+       UNSPEC_DATALABEL.
+       * config/sh/sh.c (gen_datalabel_ref): Accept LABEL_REFs.
+       * config/sh/sh.h (DATALABEL_REF_NO_CONST_P): Likewise.
+       (DATALABEL_REF_P): Don't require CONST.
+       (ASM_OUTPUT_ADDR_DIFF_ELT): On SH5, output datalabel before
+       REL label.
+       2000-12-19  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.md (extendhidi2, extendqidi2): Use arithmetic shift
+       right.
+       2000-12-18  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.md (movsi_media, call, call_value, sibcall):
+       Use shallow_copy_rtx and PUT_MODE to change the mode of
+       SYMBOL_REFs, LABEL_REFs, CONSTs, etc.
+       * config/sh/sh.h (PREFERRED_RELOAD_CLASS): Reload SYMBOL_REFs
+       on SHmedia using GENERAL_REGs.
+       * config/sh/sh.md (ble_media_i, blt_media_i, bleu_media_i,
+       bltu_media_i): Fix reversion of conditions.
+       2000-12-18  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.md (zero_extendhidi2): Use logical shift right.
+       * config/sh/sh.c (output_far_jump): Save r13 in macl.
+       2000-12-17  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.c (gen_datalabel_ref): Fix mode of the UNSPEC.
+       2000-12-16  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/lib1funcs.asm (ic_invalidate): Define for SH5.
+       (GCC_nested_trampoline): Likewise.
+       * config/sh/sh-protos.h (gen_datalabel_ref): Declare.
+       * config/sh/sh.c (gen_datalabel_ref): Define.
+       * config/sh/sh.h (TRAMPOLINE_SIZE): Adjust for SH5.
+       (INITIALIZE_TRAMPOLINE): Likewise.
+       (TRAMPOLINE_ADJUST_ADDRESS): Define.
+       (DATALABEL_REF_NO_CONST_P, DATALABEL_REF_P): Define.
+       (EXTRA_CONSTRAINT_T): Match DATALABEL unspecs.
+       (OUTPUT_ADDR_CONST_EXTRA): Handle DATALABEL unspecs.
+       * config/sh/sh.md (UNSPEC_DATALABEL): New constant.
+       (ic_invalidate): Adjust for SH5.
+       (ic_invalidate_line_media, ic_invalidate_line_compact): New insns.
+       * config/sh/t-sh64 (LIB1ASMFUNCS): Added _ic_invalidate and
+       _nested_trampoline.
+       2000-12-15  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.h (MOVE_MAX): Set to 8 for SHmedia, 4 elsewhere.
+       (MOVE_MAX_PIECES): Set to 8 on SHmedia too.
+       2000-12-14  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.h (DBX_REGISTER_NUMBER): Adjust for sh64-elf-gdb.
+       * config/sh/elf.h (DBX_REGISTER_NUMBER): Likewise.
+       2000-12-14  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.c (target_reg_operand): Match only target-branch
+       registers and pseudos that aren't virtual registers.
+       * config/sh/sh.md (call, call_value, sibcall) [TARGET_SHMEDIA]:
+       Copy operands that don't match target_reg_operand to pseudos.
+       (call_media, call_value_media, sibcall_media): Use
+       target_reg_operand instead of target_operand.
+       2000-12-13  Alexandre Oliva  <aoliva@redhat.com>
+       * glimits.h (__LONG_MAX__) [SH5 == 64]: Adjust for 64 bits. 
+       * config/sh/sh.c (target_reg_operand): Match hardware registers
+       other than branch-target registers.
+       * config/sh/sh.md (zero_extendqidi2): Input operand is %1.
+       * config/sh/lib1funcs.asm (sdivsi3) [SH5]: Make it global.
+       (fpscr_values) [SH5 == 32]: Define.
+       * config/sh/t-sh64 (LIB1ASMFUNCS): Add fpscr_values.
+       * config/sh/sh.md (call, call_value, sibcall) [TARGET_SHMEDIA]:
+       Handle function addresses coming in SUBREGs.
+       2000-12-12  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/lib1funcs.asm (shcompact_call_trampoline,
+       shcompact_return_trampoline): Use datalabel where appropriate.
+       2000-12-09  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.h (SECONDARY_OUTPUT_RELOAD_CLASS): Use a
+       general-purpose register to copy one branch-target register to
+       another.
+       2000-12-06  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.c (target_operand): Accept LABEL_REFs and
+       SYMBOL_REFs with VOIDmode.
+       * config/sh/sh.md (ble_media_i, blt_media_i, bleu_media_i,
+       bltu_media_i): New insns.
+       2000-12-06  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.h (RETURN_IN_MEMORY): Adjust for SH5 ABI.
+       (INIT_CUMULATIVE_ARGS): Likewise.
+       2000-12-01  Alexandre Oliva  <aoliva@redhat.com>
+       * machmode.def (V16SFmode): New mode.
+       * c-common.c (type_for_mode): Support V2SF and V16SF.
+       * tree.c (build_common_tree_nodes_2): Likewise.
+       * tree.h (tree_index): Likewise.
+       * calls.c (emit_call_1): Take args_so_far.  Adjust all
+       callers.  Introduce CALL_POPS_ARGS.
+       * tm.texi (CALL_POPS_ARGS): Document.
+       * config/sh/crt1.asm: Implement in SHmedia mode.
+       * config/sh/crti.asm, config/sh/crtn.asm: Likewise
+       * config/sh/elf.h (ASM_SPEC, LINK_SPEC): Support SH5 flags.
+       (DBX_REGISTER_NUMBER): Renumber registers for SH5.
+       * config/sh/lib1funcs.asm: Disable functions unused in SH5.
+       Implement divsi and udivsi in SHmedia mode.  Introduce
+       SHcompact trampolines.
+       * config/sh/sh.c (GEN_MOV, GEN_ADD3, GEN_SUB3): Use DImode
+       only in SHmedia64.
+       (regno_reg_class): Rewrite.
+       (fp_reg_names): Remove.
+       (sh_register_names, sh_additional_register_names): New.
+       (print_operand): Added `u'.  Support SUBREGs in addresses.
+       Add parentheses around shifted CONSTs.
+       (output_file_start): Output .mode and .abi directives.
+       (shiftcosts, addsubcosts, multcosts): Adjust.
+       (output_stack_adjust): Compute alignment.  Sanity-check SIZE.
+       (push_regs): Take array of HOST_WIDE_INTs.  Adjust callers.
+       (calc_live_regs): Output to array of HOST_WIDE_INTs.  Count
+       bytes, not registers.  Take into account the need for the
+       SHcompact incoming args trampoline.  Adjust all callers.
+       (sh_expand_prologue): Take stack_regs into account.  Call
+       incoming args trampoline.  Keep stack aligned as per SH5 ABI.
+       (sh_expand_epilogue): Take stack_regs into accoutn.  Keep
+       stack aligned as per SH5 ABI.
+       (sh_builtin_saveregs): Support SH5 ABI.
+       (sh_build_va_list, sh_va_start): Likewise.
+       (initial_elimination_offset): Take alignment into account.
+       Compute location of PR according to the SH5 stack frame.
+       (arith_reg_operand): Reject branch-target registers.
+       (shmedia_6bit_operand): New.
+       (logical_operand): Use CONST_OK_FOR_P on SHmedia.
+       (target_reg_operand): Match DImode only.  Accept SUBREGs.
+       (target_operand): New.
+       * config/sh/sh.h (CPP_SPEC, SUBTARGET_CPP_SPEC): Support SH5 flags.
+       (CONDITIONAL_REGISTER_USAGE): Implement SH5 ABI.  Initialize
+       SIBCALL_REGS for SHmedia.
+       (TARGET_SH3E, TARGET_SH4): Only if SH1_BIT is set too.
+       (TARGET_FPU_DOUBLE, TARGET_FPU_ANY): New.
+       (TARGET_SHMEDIA32, TARGET_SHMEDIA64): New.
+       (TARGET_SWITCHES): New SH5 flags.
+       (OVERRIDE_OPTIONS): Set SH5-specific options.  Use
+       VALID_REGISTER_P to disable unsupported registers.
+       (LONG_TYPE_SIZE, LONG_LONG_TYPE_SIZE): Set.
+       (POINTER_SIZE, PARM_BOUNDARY): Adjust.
+       (FUNCTION_ARG_PADDING): Define.
+       (FASTEST_ALIGNMENT): Adjust.
+       (SH_REGISTER_NAMES_INITIALIZER): New.
+       (sh_register_names): Declare.
+       (DEBUG_REGISTER_NAMES): Define.
+       (REGISTER_NAMES): Define based on sh_register_names.
+       (SH_ADDITIONAL_REGISTER_NAMES_INITIALIZER): New.
+       (sh_additional_register_names): Declare.
+       (LAST_GENERAL_REG, LAST_FP_REG, LAST_XD_REG): Adjust for SHmedia.
+       (FIRST_TARGET_REG, LAST_TARGET_REG): Define.
+       (TARGET_REGISTER_P, SHMEDIA_REGISTER_P, VALID_REGISTER_P): Define.
+       (REGISTER_NATURAL_MODE): Define.
+       (FIRST_PSEUDO_REGISTER): Adjust.
+       (FIXED_REGISTERS, CALL_USED_REGISTERS): Adjust.
+       (HARD_REGNO_CALL_PART_CLOBBERED): Define.
+       (HARD_REGNO_NREGS, HARD_REGNO_MODE_OK): Adjust.
+       (VECTOR_MODE_SUPPORTED_P): Define.
+       (REG_CLASS_CONTENTS): Adjust.
+       (SMALL_REGISTER_CLASSES): Adjust.
+       (REG_ALLOC_ORDER): Adjust.
+       (INDEX_REG_CLASS): Adjust.
+       (CONST_OK_FOR_O, CONST_OK_FOR_P): New.
+       (CONST_OK_FOR_LETTER_P): Adjust.
+       (PREFERRED_RELOAD_CLASS): Adjust.
+       (SECONDARY_OUTPUT_RELOAD_CLASS): Adjust.
+       (SECONDARY_INPUT_RELOAD_CLASS): Adjust.
+       (NPARM_REGS, FIRST_PARM_REG, FIRST_RET_REG): Adjust.
+       (FIRST_FP_PARM_REG): Adjust.
+       (CALL_POPS_ARGS): Define.
+       (FUNCTION_ARG_REGNO_P): Adjust.
+       (struct sh_args): New fields.
+       (GET_SH_ARG_CLASS): Adjust.
+       (INIT_CUMULATIVE_ARGS): Adjust.
+       (INIT_CUMULATIVE_INCOMING_ARGS): Define.
+       (FUNCTION_ARG_ADVANCE): Adjust.
+       (FUNCTION_ARG): Adjust.
+       (FUNCTION_ARG_PASS_BY_REFERENCE, SHCOMPACT_BYREF): Define.
+       (FUNCTION_ARG_CALLEE_COPIES): Define.
+       (SH5_PROTOTYPELESS_FLOAT_ARG): Define.
+       (STRICT_ARGUMENT_NAMING): Define.
+       (PRETEND_OUTGOING_VARARGS_NAMED): Adjust.
+       (FUNCTION_ARG_PARTIAL_NREGS): Adjust.
+       (SH5_WOULD_BE_PARTIAL_NREGS): Define.
+       (SETUP_INCOMING_VARARGS): Adjust.
+       (HAVE_POST_INCREMENT, HAVE_PRE_DECREMENT): Adjust.
+       (USE_LOAD_POST_INCREMENT, USE_STORE_PRE_DECREMENT): Adjust.
+       (REGNO_OK_FOR_INDEX_P, REG_OK_FOR_INDEX_P): Adjust.
+       (SUBREG_OK_FOR_INDEX_P): Adjust.
+       (EXTRA_CONSTRAINT_S): Update.
+       (EXTRA_CONSTRAINT_T): New.
+       (EXTRA_CONSTRAINT): Adjust.
+       (GO_IF_LEGITIMATE_INDEX): Adjust.
+       (GO_IF_LEGITIMATE_ADDRESS): Adjust.
+       (LEGITIMIZE_ADDRESS, LEGITIMIZE_RELOAD_ADDRESS): Adjust.
+       (MOVE_MAX): Adjust.
+       (MAX_MOVE_MAX): Define.
+       (Pmode): Adjust.
+       (CONST_COSTS): Adjust.
+       (REGISTER_MOVE_COST): Adjust.
+       (BRANCH_COST): Adjust.
+       (TEXT_SECTION_ASM_OP): Adjust.
+       (DBX_REGISTER_NUMBER): Adjust.
+       (ASM_OUTPUT_DOUBLE_INT): New.
+       (UNALIGNED_DOUBLE_INT_ASM_OP): New.
+       (PREDICATE_CODES): Adjust.
+       (PROMOTE_MODE): Adjust.
+       (CRT_CALL_STATIC_FUNCTION): Do not define for SHmedia.
+       * config/sh/sh.md (AP_REG, PR_REG, T_REG, GBR_REG): Renumber.
+       (MACH_REG, MACL_REG, FPUL_REG, RAP_REG, FPSCR_REG): Renumber.
+       (PR_MEDIA_REG, T_MEDIA_REG, R10_REG): New.
+       (DR0_REG, DR2_REG, DR4_REG): Renumber.
+       (TR0_REG, TR1_REG, TR2_REG): New.
+       (XD0_REG): Renumber.
+       (UNSPEC_COMPACT_ARGS): New.
+       (type): Added pt and ptabs.
+       (length): Default to 4 on SHmedia.  Default pt length to 12
+       and     20 on SHmedia32 and SHmedia64, respectively.
+       (pt): New function unit.
+       (movdi, movsi): Add types pt and ptabs.  Don't increment LABEL_NUSES.
+       Add whitespace between operands of SHmedia instructions.
+       (movdicc): Fix.
+       (adddi3_media, addsi3_media): Adjust constraints.
+       (subsi3) [SHmedia]: Force operand 1 into a register.
+       (udivsi3_i1_media, udivsi3_i4_media): New.
+       (udivsi3): Support SHmedia.
+       (divsi3_i1_media, divsi3_i4_media): New.
+       (divsi3): Support SHmedia.
+       (anddi3, iordi3, xordi3): Adjust constraints.
+       (zero_extendhidi2, zero_extendqidi2): New.
+       (extendsidi2, extendhidi2, extendqidi2): New.
+       (push, pop, push_e, push_fpul, push_4): Disable on SH5.
+       (pop_e, pop_fpul, pop_4): Likewise.
+       (movsi_media): Support FP and BT registers.
+       (movsi_media_nofpu): New.  Adjust splits to DImode.
+       (lduw, ldub): Renamed to zero_extend* above.
+       (movqi_media): Fix typo.
+       (movdi_media): Support FP and BT registers.
+       (movdi_media_nofpu): New.  Adjust splits for SHmedia32.
+       (movdi_const_32bit): New.
+       (shori_media): Require immediate operand.  Use `u' for output.
+       (movdf_media, movsf_media): Simplified.
+       (movdf_media_nofpu, movsf_media_nofpu): New.
+       (movdf, movsf): Adjust
+       (movv2sf, movv2sf, movv16sf): New.
+       (beq_media, beq_media_i): Adjust constraints.  Don't use
+       scratch BT register.
+       (bne_media, bne_media_i): Likewise.
+       (bgt_media, bgt_media_i): Likewise.
+       (bge_media, bge_media_i): Likewise.
+       (bgtu_media, bgtu_media_i): Likewise.
+       (bgeu_media, bgeu_media_i): Likewise.
+       (beq, bne, bgt, blt, ble, bge, bgtu, bltu, bgeu, bleu,
+       bunordered): Emit jump insn.  Force operands to registers when
+       needed.
+       (jump_media, jump): Simplify.
+       (call_compact, call_compact_rettramp): New.
+       (call_value_compact, call_value_compact_rettramp): New.
+       (call_media, call_value_media): Simplify.
+       (sibcall_compact, sibcall_media): New.
+       (call, call_value): Adjust for SHmedia and SHcompact.
+       (sibcall, sibcall_value, untyped_call): Likewise.
+       (sibcall_epilogue): Preserve r0 across epilogue for SHcompact.
+       (indirect_jump): Adjust for SHmedia.
+       (casesi_jump_media): New.
+       (nop): Re-enable for SHmedia.
+       (call_site): Restrict to SH1.
+       (casesi): Adjust for SHmedia.
+       (casesi_shift_media, casesi_load_media): New.
+       (return): Explicitly use PR register.  Call return trampoline
+       on SHcompact.
+       (return_i): Explicitly use PR register.
+       (shcompact_return_tramp, shcompact_return_tramp_i): New.
+       (return_media): Adjust.
+       (shcompact_incoming_args): New.
+       (epilogue): Adjust.
+       (seq, slt, sle, sgt, sge, sgtu, sltu, sleu, sgeu, sne): Adjust.
+       (movstrsi): Disable on SH5.
+       (fpu_switch0, fpu_switch1, movpsi): Enable on SH4.
+       (addsf3, addsf3_media): Test TARGET_SHMEDIA_FPU.
+       (subsf3, subsf3_media): Likewise.
+       (mulsf3, mulsf3_media, mac_media): Likewise.
+       (divsf3, divsf3_media): Likewise.
+       (floatdisf2, floatsisf2_media): Likewise.  Adjust constraints.
+       (floatsisf2, fux_truncsfsi2): Likewise.
+       (fix_truncsfdi2, fix_truncsfsi2_media): Likewise.  Adjust
+       constraints.
+       (cmpeqsf_media, cmpgtsf_media, cmpgesf_media): Likewise.
+       (cmpunsf_media, cmpsf): Likewise.
+       (negsf2, negsf2_media, sqrtsf2, sqrtsf2_media): Likewise.
+       (abssf2, abssf2_media): Likewise.
+       (adddf3, adddf3_media, subdf3, subdf3_media): Likewise.
+       (muldf3, muldf3_media, divdf3, divdf3_media): Likewise.
+       (floatdidf2, floatsidf2_media): Likewise.  Adjust constraints.
+       (floatsidf2, fix_truncdfsi2): Likewise.
+       (fix_truncdfdi2, fix_truncdfsi2_media): Likewise.  Adjust
+       constraints.
+       (cmpeqdf_media, cmpgtdf_media): Likewise.
+       (cmpgedf_media, cmpundf_media, cmpdf): Likewise.
+       (negdf2, negdf2_media, sqrtdf2, sqrtdf2_media): Likewise.
+       (absdf2, absdf2_media): Likewise.
+       (extendsfdf2, extendsfdf2_media): Likewise.
+       (truncsfdf2, truncsfdf2_media): Likewise.
+       * config/sh/sh64.h: New file.
+       * config/sh/t-sh64: New file.
+       * config/sh/shmedia.h: New file.
+       * config/sh/ushmedia.h: New file.
+       * config/sh/sshmedia.h: New file.
+       * configure.in: Added sh64-*-elf.
+       * configure: Rebuilt.
+       2000-10-10  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.c (GEN_MOV, GEN_ADD3, GEN_SUB3): New macros.
+       (reg_class_from_letter): Use `b' for TARGET_REGS.
+       (print_operand): Support `%M', `%m', `AND' and
+       `ASHIFTRT'.  Do not precede constants with `#' on SHmedia.
+       (andcosts): Adjust for SHmedia.
+       (output_stack_adjust, sh_expand_prologue, sh_expand_epilogue):
+       Likewise.
+       (target_reg_operand): New function.
+       * config/sh/sh-protos.h (target_reg_operand): Declare.
+       * config/sh/sh.h (CONDITIONAL_REGISTER_USAGE): Don't disable
+       FP registers on SH5.
+       (HARD_REGNO_MODE_OK): Accept them whenever they're acceptable
+       on SH4.
+       (TARGET_REGISTER_P): New macro.
+       (reg_class, REG_CLASS_NAMES, REG_CLASS_CONTENTS): Added TARGET_REGS.
+       (FUNCTION_VALUE): Use DImode for promoted types on SHmedia.
+       (EXTRA_CONSTRAINT_S): New macro.
+       (EXTRA_CONSTRAINT): Adjust.
+       (FLOAT_TYPE_SIZE): Define to 32.
+       (Pmode): DImode on SHmedia.
+       (CONST_COSTS): Adjust for SHmedia literals.
+       (PREDICATE_CODES): Added target_reg_operand.
+       (PROMOTE_MODE): Promote signed types to DImode on SHmedia.
+       * config/sh/sh.md: Remove all attrs from SHmedia insns.
+       (cmpeqdi_media, cmpgtdi_media, cmpgtudi_media): New insns.
+       (cmpdi): Accept SHmedia.
+       (movdicc_false, movdicc_true): New insns.
+       (movdicc): New expand.
+       (adddi3): Accept arith_operand for op2, but FAIL on SH1 if
+       no_new_pseudos.
+       (addsi3_media): Match `S' constraint.
+       (anddi3, andcdi3, iordi3, xordi3, negdi_media): New insns.
+       (negdi2): Expand for SHmedia.
+       (one_cmpldi2): New expand.
+       (zero_extendsidi2): Change from expand to insn.
+       (extendsidi2): Add constraints.
+       (movdi_media, movsi_media): Change `%x' to `%M'.  Use `%m' for
+       LD/ST address.  Fix SI immediate loading split.
+       (movhi_media, movqi_media, lduw, ldub): New insns.
+       (movhi, movqi): Accept SHmedia.
+       (shori_media, movdi_media): Relax input constraints.  Split
+       symbolic constants.
+       (movdf_media, movsf_media): New insn.  New split to movdi.
+       (movdf, movsf): Match on SHmedia.
+       (beq_media, bne_media, bgt_media, bge_media, bgtu_media,
+       bgeu_media): New insns and splits.  New insns with `_i' suffix.
+       (beq, bne, bgt, blt, ble, bge, bgtu, bltu, bgeu, bleu): Adjust.
+       (bunordered): New expand.
+       (jump_compact): Renamed from `jump'.
+       (jump_media): New insn.
+       (jump): New expand.
+       (call_media, call_value_media): New insns.
+       (call, call_value): Adjust.
+       (indirect_jump_compact): Renamed from `indirect_jump'.
+       (indirect_jump_media): New insn.
+       (indirect_jump): New expand.
+       (untyped_call, return): Accept SHmedia.
+       (return_media): New insn.
+       (prologue, epilogue, blockage): Accept SHmedia.
+       (seq, slt, sle, sgt, sge, sgtu, sltu, sleu, sgeu, sne): Adjust.
+       (sunordered): New expand.
+       (addsf3, subsf3, mulsf3, divsf3, floatsisf2, fix_truncsfsi2,
+       cmpsf, negsf2, sqrtsf2, abssf2): Adjust for SHmedia.
+       (addsf3_media, subsf3_media, mulsf3_media, mac_media,
+       divsf3_media, floatdisf2, floatsisf2_media, fix_truncsfdi2,
+       fix_truncsfsi2_media, cmpeqsf_media, cmpgtsf_media,
+       cmpgesf_media, cmpunsf_media, negsf2_media, sqrtsf2_media,
+       abssf2_media): New insns.
+       (adddf3, subdf3, muldf3, divdf3, floatsidf2, fix_truncdfsi2,
+       cmpdf, negdf2, sqrtdf2, absdf2): Adjust for SHmedia.
+       (adddf3_media, subdf3_media, muldf3_media, divdf3_media,
+       floatdidf2, floatsidf2_media, fix_truncdfdi2,
+       fix_truncdfsi2_media, cmpeqdf_media, cmpgtdf_media,
+       cmpgedf_media, cmpundf_media, negdf2_media, sqrtdf2_media,
+       absdf2_media): New insns.
+       (extendsfdf2, truncdfsf2): Adjust for SHmedia.
+       (extendsfdf2_media, truncdfsf2_media): New insns.
+       2000-09-14  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.c (machine_dependent_reorg): On shmedia, skip for now.
+       * config/sh/sh.h (CONST_OK_FOR_J): Document.
+       (LEGITIMATE_CONSTANT_P): Accept CONST_DOUBLEs on shmedia.
+       * config/sh/sh.md (adddi3): New expand.
+       (adddi3_media, adddi3z_media): New insns.
+       (adddi3_compact): Renamed from adddi3.
+       (addsi3_media): Use add.l r63 to add constant zero.
+       (subdi3): New expand.
+       (subdi3_media): New insn.
+       (subdi3_compact): Renamed from subdi3.
+       (mulsidi3): New expand.
+       (mulsidi3_media): New insn.
+       (mulsidi3_compact): Renamed from mulsidi3.
+       (umulsidi3): New expand.
+       (umulsidi3_media): New insn.
+       (umulsidi3_compact): Renamed from umulsidi3.
+       (ashlsi3_media, ashrsi3_media, lshrsi3_media): New insns.
+       (ashlsi3, ashrsi3, lshrsi3): Use them.
+       (ashldi3_media, ashrdi3_media, lshrdi3_media): New insns.
+       (ashldi3, ashrdi3, lshrdi3): Use them.
+       (zero_extendsidi2): New expand.
+       (extendsidi2): New insn.
+       (movsi_media): New insn.  Split to movdi to load constants.
+       (movsi): Enable for shmedia.
+       (movdi_media): New insn.  Use shori_media to load wide constants.
+       (short_media): New insn.
+       (movdi): Enable for shmedia.
+       2000-09-08  Alexandre Oliva  <aoliva@redhat.com>
+       * config/sh/sh.h (CPP_SPEC): Added `m5'.
+       (SUBTARGET_CPP_SPEC): Added `!m5'.
+       (SH5_BIT, TARGET_SH5, TARGET_SHMEDIA, TARGET_SHCOMPACT): New macros.
+       (TARGET_SWITCHES): Added `5' and `5-compact'.  Added SH1_BIT
+       to all other SH variants.
+       (TARGET_DEFAULT): Set to SH1_BIT.
+       (OVERRIDE_OPTIONS): Recognize sh5 CPU.
+       (BITS_PER_WORD): Raise to 64 on shmedia.
+       (MAX_BITS_PER_WORD): Change to 64.
+       (MAX_LONG_TYPE_SIZE, MAX_WCHAR_TYPE_SIZE): Set to MAX_BITS_PER_WORD.
+       (INT_TYPE_SIZE): Keep as 32.
+       (UNITS_PER_WORD): Raise to 8 on shmedia.
+       (MIN_UNITS_PER_WORD): Keep as 4.
+       (POINTER_SIZE): Raise to 64 on shmedia.
+       (CONST_OK_FOR_J): New macro.
+       (CONST_OK_FOR_LETTER_P): Use it.
+       (processor_type): Add PROCESSOR_SH5.
+       * config/sh/sh.md: Conditionalize all expands, insns and
+       splits to TARGET_SH1.
+       (cpu): Added sh5.
+       (addsi3_compact): Renamed from...
+       (addsi3): Now an expand.
+       (addsi3_media, subsi3_media): New insns.
+       (subsi3): Don't negate constants with SHmedia.
+
        * hooks.c: New file.
        * hooks.h: New file.
        * Makefile.in (HOOKS_H): New.
index 6b986d8..3768db5 100644 (file)
@@ -1408,6 +1408,8 @@ type_for_mode (mode, unsignedp)
          return unsignedp ? unsigned_V4HI_type_node : V4HI_type_node;
        case V8QImode:
          return unsignedp ? unsigned_V8QI_type_node : V8QI_type_node;
+       case V16SFmode:
+         return V16SF_type_node;
        case V4SFmode:
          return V4SF_type_node;
        case V2SFmode:
index 3d4540d..9d014f9 100644 (file)
@@ -181,7 +181,8 @@ static int calls_function_1 PARAMS ((tree, int));
 
 static void emit_call_1                PARAMS ((rtx, tree, tree, HOST_WIDE_INT,
                                         HOST_WIDE_INT, HOST_WIDE_INT, rtx,
-                                        rtx, int, rtx, int));
+                                        rtx, int, rtx, int,
+                                        CUMULATIVE_ARGS *));
 static void precompute_register_parameters     PARAMS ((int,
                                                         struct arg_data *,
                                                         int *));
@@ -444,7 +445,7 @@ prepare_call_address (funexp, fndecl, call_fusage, reg_parm_seen, sibcallp)
 static void
 emit_call_1 (funexp, fndecl, funtype, stack_size, rounded_stack_size,
             struct_value_size, next_arg_reg, valreg, old_inhibit_defer_pop,
-            call_fusage, ecf_flags)
+            call_fusage, ecf_flags, args_so_far)
      rtx funexp;
      tree fndecl ATTRIBUTE_UNUSED;
      tree funtype ATTRIBUTE_UNUSED;
@@ -456,6 +457,7 @@ emit_call_1 (funexp, fndecl, funtype, stack_size, rounded_stack_size,
      int old_inhibit_defer_pop;
      rtx call_fusage;
      int ecf_flags;
+     CUMULATIVE_ARGS *args_so_far ATTRIBUTE_UNUSED;
 {
   rtx rounded_stack_size_rtx = GEN_INT (rounded_stack_size);
   rtx call_insn;
@@ -466,6 +468,10 @@ emit_call_1 (funexp, fndecl, funtype, stack_size, rounded_stack_size,
   struct_value_size_rtx = GEN_INT (struct_value_size);
 #endif
 
+#ifdef CALL_POPS_ARGS
+  n_popped += CALL_POPS_ARGS (* args_so_far);
+#endif
+  
   /* Ensure address is valid.  SYMBOL_REF is already valid, so no need,
      and we don't want to load it into a register as an optimization,
      because prepare_call_address already did it if it should be done.  */
@@ -3055,7 +3061,7 @@ expand_call (exp, target, ignore)
       emit_call_1 (funexp, fndecl, funtype, unadjusted_args_size,
                   adjusted_args_size.constant, struct_value_size,
                   next_arg_reg, valreg, old_inhibit_defer_pop, call_fusage,
-                  flags);
+                  flags, & args_so_far);
 
       /* Verify that we've deallocated all the stack we used.  */
       if (pass
@@ -4053,7 +4059,7 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
               struct_value_size,
               FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1),
               valreg,
-              old_inhibit_defer_pop + 1, call_fusage, flags);
+              old_inhibit_defer_pop + 1, call_fusage, flags, & args_so_far);
 
   /* For calls to `setjmp', etc., inform flow.c it should complain
      if nonvolatile values are live.  For functions that cannot return,
index e78fe09..80fb31a 100644 (file)
@@ -263,6 +263,9 @@ powerpc*-*-*)
 sparc*-*-*)
        cpu_type=sparc
        ;;
+sh64-*-*)
+       cpu_type=sh
+       ;;
 esac
 
 tm_file=${cpu_type}/${cpu_type}.h
@@ -2885,6 +2888,16 @@ sh-*-elf*)
        tm_file="${tm_file} sh/elf.h"
        float_format=sh
        ;;
+sh64-*-elf*)
+       tmake_file="sh/t-sh sh/t-elf sh/t-sh64"
+       tm_file="${tm_file} sh/sh.h sh/elf.h sh/sh64.h"
+       float_format=sh
+       extra_headers="../../config/sh/shmedia.h ../../config/sh/ushmedia.h ../../config/sh/sshmedia.h"
+       # Not strictly necessary to check this, but a good idea anyway.
+       if test $machine = $target; then
+               target_requires_64bit_host_wide_int=yes
+       fi
+       ;;
 sh-*-rtemself*)
        tmake_file="sh/t-sh sh/t-elf t-rtems"
        tm_file="${tm_file} sh/elf.h sh/rtemself.h"
index 902fb9a..e46c5ae 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 Free Software Foundation, Inc.
+/* Copyright (C) 2000, 2001 Free Software Foundation, Inc.
    This file was pretty much copied from newlib.
 
 This file is part of GNU CC.
@@ -27,6 +27,80 @@ 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.  */
 
+
+#ifdef __SH5__
+       .section .data,"aw"
+       .global ___data
+___data:
+
+       .section .rodata,"a"
+       .global ___rodata
+___rodata:
+
+#if __SH5__ == 64
+       .section .text,"ax"
+#define LOAD_ADDR(sym, reg) \
+       movi    (sym >> 48) & 65535, reg; \
+       shori   (sym >> 32) & 65535, reg; \
+       shori   (sym >> 16) & 65535, reg; \
+       shori   sym & 65535, reg
+#else
+       .mode   SHmedia
+       .section .text..SHmedia32,"ax"
+#define LOAD_ADDR(sym, reg) \
+       movi    (sym >> 16) & 65535, reg; \
+       shori   sym & 65535, reg
+#endif
+       .global start
+start:
+       LOAD_ADDR (_stack, r15)
+
+       pt/l    .Lzero_bss_loop, tr0
+       pt/l    _atexit, tr1
+       pt/l    _init, tr5
+       pt/l    ___setup_argv_and_call_main, tr6
+       pt/l    _exit, tr7
+
+       ! zero out bss
+       LOAD_ADDR (_edata, r0)
+       LOAD_ADDR (_end, r1)
+.Lzero_bss_loop:
+       stx.q   r0, r63, r63
+       addi    r0, 8, r0
+       bgt/l   r1, r0, tr0
+
+       LOAD_ADDR (___data, r26)
+       LOAD_ADDR (___rodata, r27)
+
+#if ! __SH4_NOFPU__
+#if __SH5__ == 32
+       pt/l ___set_fpscr, tr0
+       movi    0, r4
+       blink   tr0, r18
+#endif
+       getcon  sr, r0
+       ! enable the FP unit, by resetting SR.FD
+       ! also zero out SR.FR, SR.SZ and SR.PR, as mandated by the ABI
+       movi    0, r1
+       shori   0xf000, r1
+       andc    r0, r1, r0
+       putcon  r0, sr
+#endif
+
+       ! arrange for exit to call fini
+       LOAD_ADDR (_fini, r2)
+       blink   tr1, r18
+
+       ! call init
+       blink   tr5, r18
+
+       ! call the mainline
+       blink   tr6, r18
+
+       ! call exit
+       blink   tr7, r18
+       
+#else
        .section .text
        .global start
 start:
@@ -99,6 +173,7 @@ fini_k:
 ___main:
        rts
        nop
+#endif
 
 #ifdef __ELF__
        .section .stack,"aw"
index cfed71d..41bc910 100644 (file)
@@ -50,6 +50,19 @@ Boston, MA 02111-1307, USA.  */
 #endif
        .global  _init
 _init:
+#if __SHMEDIA__
+       addi    r15, -16, r15
+       st.q    r15, 8, r14
+       st.q    r15, 0, r18
+       add     r15, r63, r14
+#elif __SH5__ && ! __SHMEDIA__
+       mov     r15,r0
+       add     #-8,r15
+       mov.l   r14,@-r0
+       sts.l   pr,@-r0
+       mov     r15,r14
+       nop
+#else
 #ifdef __ELF__
        mov.l   r12,@-r15
        mova    0f,r0
@@ -68,6 +81,7 @@ _init:
 0:     .long   _GLOBAL_OFFSET_TABLE_
 1:
 #endif
+#endif /* __SHMEDIA__ */
 
        .section .fini
 /* The alignment below can't be smaller, otherwise the mova below
@@ -81,6 +95,19 @@ _init:
 #endif
        .global  _fini
 _fini: 
+#if __SHMEDIA__
+       addi    r15, -16, r15
+       st.q    r15, 8, r14
+       st.q    r15, 0, r18
+       add     r15, r63, r14
+#elif __SH5__ && ! __SHMEDIA__
+       mov     r15,r0
+       add     #-8,r15
+       mov.l   r14,@-r0
+       sts.l   pr,@-r0
+       mov     r15,r14
+       nop
+#else
 #ifdef __ELF__
        mov.l   r12,@-r15
        mova    0f,r0
@@ -99,3 +126,4 @@ _fini:
 0:     .long   _GLOBAL_OFFSET_TABLE_
 1:
 #endif
+#endif /* __SHMEDIA__ */
index 6aa9a52..e064a7b 100644 (file)
@@ -30,6 +30,20 @@ Boston, MA 02111-1307, USA.  */
 /* See an explanation about .init and .fini in crti.asm.  */
 
        .section .init
+#if __SHMEDIA__
+       add     r14, r63, r15
+       ld.q    r15, 0, r18
+       ptabs   r18, tr0
+       ld.q    r15, 8, r14
+       addi    r15, 16, r15
+       blink   tr0, r63
+#elif __SH5__ && ! __SHMEDIA__
+       mov     r14,r15
+       lds.l   @r14+,pr
+       mov.l   @r14,r14
+       rts
+       add     #8,r15
+#else
        mov     r14,r15
        lds.l   @r15+,pr
        mov.l   @r15+,r14
@@ -39,8 +53,23 @@ Boston, MA 02111-1307, USA.  */
 #else
        nop
 #endif
+#endif /* __SHMEDIA__ */
 
        .section .fini
+#if __SHMEDIA__
+       add     r14, r63, r15
+       ld.q    r15, 0, r18
+       ptabs   r18, tr0
+       ld.q    r15, 8, r14
+       addi    r15, 16, r15
+       blink   tr0, r63
+#elif __SH5__ && ! __SHMEDIA__
+       mov     r14,r15
+       lds.l   @r14+,pr
+       mov.l   @r14,r14
+       rts
+       add     #8,r15
+#else
        mov     r14,r15
        lds.l   @r15+,pr
        mov.l   @r15+,r14
@@ -50,3 +79,4 @@ Boston, MA 02111-1307, USA.  */
 #else
        nop
 #endif
+#endif /* __SHMEDIA__ */
index 8ad7490..9bd5a36 100644 (file)
@@ -27,6 +27,8 @@ Boston, MA 02111-1307, USA.  */
 #undef TARGET_ASM_NAMED_SECTION
 #undef ASM_DECLARE_FUNCTION_NAME
 #undef MAX_OFILE_ALIGNMENT
+#undef SIZE_TYPE
+#undef PTRDIFF_TYPE
 
 /* Be ELF-like.  */
 /* TODO: convert includes to ${tm_file} list in config.gcc.  */
@@ -47,6 +49,11 @@ Boston, MA 02111-1307, USA.  */
 /* use a more compact format for line information */
 #define DWARF2_ASM_LINE_DEBUG_INFO 1
 
+/* WCHAR_TYPE_SIZE is defined to BITS_PER_WORD in svr4.h, but
+   BITS_PER_WORD isn't constant any more.  Fortunately, on no SH
+   platform is it wider than 32-bits.  */
+#define MAX_WCHAR_TYPE_SIZE 32
+
 /* The prefix to add to user-visible assembler symbols.
    Note that svr4.h redefined it from the original value (that we want)
    in sh.h */
@@ -60,6 +67,14 @@ Boston, MA 02111-1307, USA.  */
 #undef ASM_FILE_START
 #define ASM_FILE_START(FILE) do {                              \
   output_file_directive ((FILE), main_input_filename);         \
+/* We also need to show the text section with the proper       \
+   attributes as in TEXT_SECTION_ASM_OP, before dwarf2out      \
+   emits it without attributes in TEXT_SECTION, else GAS       \
+   will complain.  We can teach GAS specifically about the     \
+   default attributes for our choice of text section, but      \
+   then we would have to change GAS again if/when we change    \
+   the text section name.  */                                  \
+   fprintf ((FILE), "%s\n", TEXT_SECTION_ASM_OP);              \
   if (TARGET_LITTLE_ENDIAN)                                    \
     fprintf ((FILE), "\t.little\n");                           \
 } while (0)
@@ -69,17 +84,54 @@ Boston, MA 02111-1307, USA.  */
 /* Let code know that this is ELF.  */
 #define CPP_PREDEFINES "-D__sh__ -D__ELF__ -Acpu=sh -Amachine=sh"
 
+#undef SIZE_TYPE
+#define SIZE_TYPE (TARGET_SH5 ? "long unsigned int" : "unsigned int")
+
+#undef PTRDIFF_TYPE
+#define PTRDIFF_TYPE (TARGET_SH5 ? "long int" : "int")
 /* Pass -ml and -mrelax to the assembler and linker.  */
 #undef ASM_SPEC
-#define ASM_SPEC  "%{ml:-little} %{mrelax:-relax}"
+#define ASM_SPEC  "%{ml:-little} %{mrelax:-relax} \
+%{m5-compact:--isa=SHcompact} %{m5-compact-nofpu:--isa=SHcompact} \
+%{m5-32media:--isa=SHmedia --abi=32} %{m5-32media-nofpu:--isa=SHmedia --abi=32} \
+%{m5-64media:--isa=SHmedia --abi=64} %{m5-64media-nofpu:--isa=SHmedia --abi=64}"
 
 #undef LINK_SPEC
-#define LINK_SPEC "%{ml:-m shlelf} %{mrelax:-relax}"
+#define LINK_SPEC " \
+%{m5-compact:%{!ml:-m shelf32} %{ml:-m shlelf32}} \
+%{m5-compact-nofpu:%{!ml:-m shelf32} %{ml:-m shlelf32}} \
+%{m5-32media:%{!ml:-m shelf32} %{ml:-m shlelf32}} \
+%{m5-32media-nofpu:%{!ml:-m shelf32} %{ml:-m shlelf32}} \
+%{m5-64media:%{!ml:-m shelf64} %{ml:-m shlelf64}} \
+%{m5-64media-nofpu:%{!ml:-m shelf64} %{ml:-m shlelf64}} \
+%{!m5-64media:%{!m5-64media-nofpu:%{!m5-32media:%{!m5-32media-nofpu:%{!m5-compact:%{!m5-compact-nofpu:%{ml:-m shlelf}}}}}}} \
+%{mrelax:-relax}"
 
 /* svr4.h undefined DBX_REGISTER_NUMBER, so we need to define it
    again.  */
-#define DBX_REGISTER_NUMBER(REGNO)     \
-  (((REGNO) >= 22 && (REGNO) <= 39) ? ((REGNO) + 1) : (REGNO))
+#define DBX_REGISTER_NUMBER(REGNO)                                     \
+  (GENERAL_REGISTER_P (REGNO)                                          \
+   ? ((REGNO) - FIRST_GENERAL_REG)                                     \
+   : FP_REGISTER_P (REGNO)                                             \
+   ? ((REGNO) - FIRST_FP_REG + (TARGET_SH5 ? (TARGET_SHCOMPACT ? 245   \
+                                             : 77) : 25))              \
+   : XD_REGISTER_P (REGNO)                                             \
+   ? ((REGNO) - FIRST_XD_REG + (TARGET_SH5 ? 289 : 87))                        \
+   : TARGET_REGISTER_P (REGNO)                                         \
+   ? ((REGNO) - FIRST_TARGET_REG + 68)                                 \
+   : (REGNO) == PR_REG                                                 \
+   ? (TARGET_SH5 ? 241 : 17)                                           \
+   : (REGNO) == T_REG                                                  \
+   ? (TARGET_SH5 ? 242 : 18)                                           \
+   : (REGNO) == GBR_REG                                                        \
+   ? (TARGET_SH5 ? 238 : 19)                                           \
+   : (REGNO) == MACH_REG                                               \
+   ? (TARGET_SH5 ? 239 : 20)                                           \
+   : (REGNO) == MACL_REG                                               \
+   ? (TARGET_SH5 ? 240 : 21)                                           \
+   : (REGNO) == FPUL_REG                                               \
+   ? (TARGET_SH5 ? 244 : 23)                                           \
+   : (abort(), -1))
 
 #undef ASM_GENERATE_INTERNAL_LABEL
 #define ASM_GENERATE_INTERNAL_LABEL(STRING, PREFIX, NUM) \
index 2170758..53ca874 100644 (file)
@@ -51,6 +51,11 @@ Boston, MA 02111-1307, USA.  */
 #define GLOBAL(X) ___##X
 #endif
 
+#if defined __SH5__ && ! defined __SH4_NOFPU__
+#define FMOVD_WORKS
+#endif
+
+#if ! __SH5__
 #ifdef L_ashiftrt
        .global GLOBAL(ashiftrt_r4_0)
        .global GLOBAL(ashiftrt_r4_1)
@@ -866,6 +871,7 @@ hiset:      sts     macl,r0         ! r0 = bb*dd
 
 
 #endif
+#endif /* ! __SH5__ */
 #ifdef L_sdivsi3_i4
        .title "SH DIVIDE"
 !! 4 byte integer Divide code for the Hitachi SH
@@ -882,9 +888,13 @@ GLOBAL(sdivsi3_i4):
        rts
        ftrc dr0,fpul
 
-#elif defined(__SH4_SINGLE__) || defined(__SH4_SINGLE_ONLY__)
+#elif defined(__SH4_SINGLE__) || defined(__SH4_SINGLE_ONLY__) || (defined (__SH5__) && ! defined __SH4_NOFPU__)
 !! args in r4 and r5, result in fpul, clobber r2, dr0, dr2
 
+#if ! __SH5__ || __SH5__ == 32
+#if __SH5__
+       .mode   SHcompact
+#endif
        .global GLOBAL(sdivsi3_i4)
 GLOBAL(sdivsi3_i4):
        sts.l fpscr,@-r15
@@ -900,6 +910,7 @@ GLOBAL(sdivsi3_i4):
        rts
        lds.l @r15+,fpscr
 
+#endif /* ! __SH5__ || __SH5__ == 32 */
 #endif /* ! __SH4__ */
 #endif
 
@@ -916,6 +927,71 @@ GLOBAL(sdivsi3_i4):
 !! args in r4 and r5, result in r0 clobber r1,r2,r3
 
        .global GLOBAL(sdivsi3)
+#if __SHMEDIA__
+#if __SH5__ == 32
+       .section        .text..SHmedia32,"ax"
+#else
+       .text
+#endif
+       .align  2
+/* The assembly code that follows is a hand-optimized version of the C
+   code that follows.  Note that the registers that are modified are
+   exactly those listed as clobbered in the patterns divsi3_i1 and
+   divsi3_i1_media.
+       
+int __sdivsi3 (i, j)
+     int i, j;
+{
+  register unsigned long long r18 asm ("r18");
+  register unsigned long long r19 asm ("r19");
+  register unsigned long long r0 asm ("r0") = 0;
+  register unsigned long long r1 asm ("r1") = 1;
+  register int r2 asm ("r2") = i >> 31;
+  register int r3 asm ("r3") = j >> 31;
+
+  r2 = r2 ? r2 : r1;
+  r3 = r3 ? r3 : r1;
+  r18 = i * r2;
+  r19 = j * r3;
+  r2 *= r3;
+  
+  r19 <<= 31;
+  r1 <<= 31;
+  do
+    if (r18 >= r19)
+      r0 |= r1, r18 -= r19;
+  while (r19 >>= 1, r1 >>= 1);
+
+  return r2 * (int)r0;
+}
+*/
+GLOBAL(sdivsi3):
+       pt/l    LOCAL(sdivsi3_dontadd), tr2
+       pt/l    LOCAL(sdivsi3_loop), tr1
+       ptabs/l r18, tr0
+       movi    0, r0
+       movi    1, r1
+       shari.l r4, 31, r2
+       shari.l r5, 31, r3
+       cmveq   r2, r1, r2
+       cmveq   r3, r1, r3
+       muls.l  r4, r2, r18
+       muls.l  r5, r3, r19
+       muls.l  r2, r3, r2
+       shlli   r19, 31, r19
+       shlli   r1, 31, r1
+LOCAL(sdivsi3_loop):
+       bgtu    r19, r18, tr2
+       or      r0, r1, r0
+       sub     r18, r19, r18
+LOCAL(sdivsi3_dontadd):
+       shlri   r1, 1, r1
+       shlri   r19, 1, r19
+       bnei    r1, 0, tr1
+       muls.l  r0, r2, r0
+       add.l   r0, r63, r0
+       blink   tr0, r63
+#else
 GLOBAL(sdivsi3):
        mov     r4,r1
        mov     r5,r0
@@ -1000,6 +1076,7 @@ GLOBAL(sdivsi3):
 div0:  rts
        mov     #0,r0
 
+#endif /* ! __SHMEDIA__ */
 #endif /* ! __SH4__ */
 #endif
 #ifdef L_udivsi3_i4
@@ -1050,9 +1127,13 @@ trivial:
 L1:
        .double 2147483648
 
-#elif defined(__SH4_SINGLE__) || defined(__SH4_SINGLE_ONLY__)
+#elif defined(__SH4_SINGLE__) || defined(__SH4_SINGLE_ONLY__) || (defined (__SH5__) && ! defined __SH4_NOFPU__)
 !! args in r4 and r5, result in fpul, clobber r0, r1, r4, r5, dr0, dr2, dr4
 
+#if ! __SH5__ || __SH5__ == 32
+#if __SH5__
+       .mode   SHcompact
+#endif
        .global GLOBAL(udivsi3_i4)
 GLOBAL(udivsi3_i4):
        mov #1,r1
@@ -1102,6 +1183,7 @@ L1:
 #endif
        .double 2147483648
 
+#endif /* ! __SH5__ || __SH5__ == 32 */
 #endif /* ! __SH4__ */
 #endif
 
@@ -1118,6 +1200,57 @@ L1:
 !! args in r4 and r5, result in r0, clobbers r4, pr, and t bit
        .global GLOBAL(udivsi3)
 
+#if __SHMEDIA__
+#if __SH5__ == 32
+       .section        .text..SHmedia32,"ax"
+#else
+       .text
+#endif
+       .align  2
+/* The assembly code that follows is a hand-optimized version of the C
+   code that follows.  Note that the registers that are modified are
+   exactly those listed as clobbered in the patterns udivsi3_i1 and
+   udivsi3_i1_media.
+       
+unsigned 
+__udivsi3 (i, j)
+    unsigned i, j; 
+{
+  register unsigned long long r0 asm ("r0") = 0;
+  register unsigned long long r18 asm ("r18") = 1;
+  register unsigned long long r4 asm ("r4") = i;
+  register unsigned long long r19 asm ("r19") = j;
+
+  r19 <<= 31;
+  r18 <<= 31;
+  do
+    if (r4 >= r19)
+      r0 |= r18, r4 -= r19;
+  while (r19 >>= 1, r18 >>= 1);
+
+  return r0;
+}
+*/
+GLOBAL(udivsi3):
+       pt/l    LOCAL(udivsi3_dontadd), tr2
+       pt/l    LOCAL(udivsi3_loop), tr1
+       ptabs/l r18, tr0
+       movi    0, r0
+       movi    1, r18
+       addz.l  r5, r63, r19
+       addz.l  r4, r63, r4
+       shlli   r19, 31, r19
+       shlli   r18, 31, r18
+LOCAL(udivsi3_loop):
+       bgtu    r19, r4, tr2
+       or      r0, r18, r0
+       sub     r4, r19, r4
+LOCAL(udivsi3_dontadd):
+       shlri   r18, 1, r18
+       shlri   r19, 1, r19
+       bnei    r18, 0, tr1
+       blink   tr0, r63
+#else
 GLOBAL(udivsi3):
 longway:
        mov     #0,r0
@@ -1166,10 +1299,14 @@ vshortway:
 ret:   rts
        mov     r4,r0
 
+#endif /* ! __SHMEDIA__ */
 #endif /* __SH4__ */
 #endif
 #ifdef L_set_fpscr
-#if defined (__SH3E__) || defined(__SH4_SINGLE__) || defined(__SH4__) || defined(__SH4_SINGLE_ONLY__)
+#if defined (__SH3E__) || defined(__SH4_SINGLE__) || defined(__SH4__) || defined(__SH4_SINGLE_ONLY__) || __SH5__ == 32
+#ifdef __SH5__
+       .mode   SHcompact
+#endif
        .global GLOBAL(set_fpscr)
 GLOBAL(set_fpscr):
        lds r4,fpscr
@@ -1211,7 +1348,17 @@ LOCAL(set_fpscr_L1):
 #endif /* SH3E / SH4 */
 #endif /* L_set_fpscr */
 #ifdef L_ic_invalidate
-#if defined(__SH4_SINGLE__) || defined(__SH4__) || defined(__SH4_SINGLE_ONLY__)
+#if __SH5__ == 32
+       .mode   SHmedia
+       .section        .text..SHmedia32,"ax"
+       .align  2
+       .global GLOBAL(ic_invalidate)
+GLOBAL(ic_invalidate):
+       icbi    r0, 0
+       ptabs   r18, tr0
+       synci
+       blink   tr0, r63
+#elif defined(__SH4_SINGLE__) || defined(__SH4__) || defined(__SH4_SINGLE_ONLY__)
        .global GLOBAL(ic_invalidate)
 GLOBAL(ic_invalidate):
        ocbwb   @r4
@@ -1237,3 +1384,786 @@ GLOBAL(ic_invalidate):
        .endr
 #endif /* SH4 */
 #endif /* L_ic_invalidate */
+
+#if defined (__SH5__) && __SH5__ == 32
+#ifdef L_shcompact_call_trampoline
+       .section        .rodata
+       .align  1
+LOCAL(ct_main_table):
+.word  LOCAL(ct_r2_fp) - datalabel LOCAL(ct_main_label)
+.word  LOCAL(ct_r2_ld) - datalabel LOCAL(ct_main_label)
+.word  LOCAL(ct_r2_pop) - datalabel LOCAL(ct_main_label)
+.word  LOCAL(ct_r3_fp) - datalabel LOCAL(ct_main_label)
+.word  LOCAL(ct_r3_ld) - datalabel LOCAL(ct_main_label)
+.word  LOCAL(ct_r3_pop) - datalabel LOCAL(ct_main_label)
+.word  LOCAL(ct_r4_fp) - datalabel LOCAL(ct_main_label)
+.word  LOCAL(ct_r4_ld) - datalabel LOCAL(ct_main_label)
+.word  LOCAL(ct_r4_pop) - datalabel LOCAL(ct_main_label)
+.word  LOCAL(ct_r5_fp) - datalabel LOCAL(ct_main_label)
+.word  LOCAL(ct_r5_ld) - datalabel LOCAL(ct_main_label)
+.word  LOCAL(ct_r5_pop) - datalabel LOCAL(ct_main_label)
+.word  LOCAL(ct_r6_fph) - datalabel LOCAL(ct_main_label)
+.word  LOCAL(ct_r6_fpl) - datalabel LOCAL(ct_main_label)
+.word  LOCAL(ct_r6_ld) - datalabel LOCAL(ct_main_label)
+.word  LOCAL(ct_r6_pop) - datalabel LOCAL(ct_main_label)
+.word  LOCAL(ct_r7_fph) - datalabel LOCAL(ct_main_label)
+.word  LOCAL(ct_r7_fpl) - datalabel LOCAL(ct_main_label)
+.word  LOCAL(ct_r7_ld) - datalabel LOCAL(ct_main_label)
+.word  LOCAL(ct_r7_pop) - datalabel LOCAL(ct_main_label)
+.word  LOCAL(ct_r8_fph) - datalabel LOCAL(ct_main_label)
+.word  LOCAL(ct_r8_fpl) - datalabel LOCAL(ct_main_label)
+.word  LOCAL(ct_r8_ld) - datalabel LOCAL(ct_main_label)
+.word  LOCAL(ct_r8_pop) - datalabel LOCAL(ct_main_label)
+.word  LOCAL(ct_r9_fph) - datalabel LOCAL(ct_main_label)
+.word  LOCAL(ct_r9_fpl) - datalabel LOCAL(ct_main_label)
+.word  LOCAL(ct_r9_ld) - datalabel LOCAL(ct_main_label)
+.word  LOCAL(ct_r9_pop) - datalabel LOCAL(ct_main_label)
+.word  LOCAL(ct_pop_seq) - datalabel LOCAL(ct_main_label)
+.word  LOCAL(ct_pop_seq) - datalabel LOCAL(ct_main_label)
+.word  LOCAL(ct_r9_pop) - datalabel LOCAL(ct_main_label)
+.word  LOCAL(ct_ret_wide) - datalabel LOCAL(ct_main_label)
+.word  LOCAL(ct_call_func) - datalabel LOCAL(ct_main_label)
+       .mode   SHmedia
+       .section        .text..SHmedia32, "ax"
+       .align  2
+       
+     /* This function loads 64-bit general-purpose registers from the
+       stack, from a memory address contained in them or from an FP
+       register, according to a cookie passed in r1.  Its execution
+       time is linear on the number of registers that actually have
+       to be copied.  See sh.h for details on the actual bit pattern.
+
+       The function to be called is passed in r0.  If a 32-bit return
+       value is expected, the actual function will be tail-called,
+       otherwise the return address will be stored in r10 (that the
+       caller should expect to be clobbered) and the return value
+       will be expanded into r2/r3 upon return.  */
+       
+       .global GLOBAL(GCC_shcompact_call_trampoline)
+GLOBAL(GCC_shcompact_call_trampoline):
+       ptabs/l r0, tr0 /* Prepare to call the actual function.  */
+       movi    ((datalabel LOCAL(ct_main_table) - 31 * 2) >> 16) & 65535, r0
+       pt/l    LOCAL(ct_loop), tr1
+       addz.l  r1, r63, r1
+       shori   ((datalabel LOCAL(ct_main_table) - 31 * 2)) & 65535, r0
+LOCAL(ct_loop):
+       nsb     r1, r28
+       shlli   r28, 1, r29
+       ldx.w   r0, r29, r30
+LOCAL(ct_main_label):
+       ptrel/l r30, tr2
+       blink   tr2, r63
+LOCAL(ct_r2_fp):       /* Copy r2 from an FP register.  */
+       /* It must be dr0, so just do it.  */
+       fmov.dq dr0, r2
+       movi    7, r30
+       shlli   r30, 29, r31
+       andc    r1, r31, r1
+       blink   tr1, r63
+LOCAL(ct_r3_fp):       /* Copy r3 from an FP register.  */
+       /* It is either dr0 or dr2.  */
+       movi    7, r30
+       shlri   r1, 26, r32
+       shlli   r30, 26, r31
+       andc    r1, r31, r1
+       fmov.dq dr0, r3
+       beqi/l  r32, 4, tr1
+       fmov.dq dr2, r3
+       blink   tr1, r63
+LOCAL(ct_r4_fp):       /* Copy r4 from an FP register.  */
+       shlri   r1, 23 - 3, r34
+       andi    r34, 3 << 3, r33
+       addi    r33, LOCAL(ct_r4_fp_copy) - datalabel LOCAL(ct_r4_fp_base), r32
+LOCAL(ct_r4_fp_base):
+       ptrel/l r32, tr2
+       movi    7, r30
+       shlli   r30, 23, r31
+       andc    r1, r31, r1
+       blink   tr2, r63
+LOCAL(ct_r4_fp_copy):
+       fmov.dq dr0, r4
+       blink   tr1, r63
+       fmov.dq dr2, r4
+       blink   tr1, r63
+       fmov.dq dr4, r4
+       blink   tr1, r63
+LOCAL(ct_r5_fp):       /* Copy r5 from an FP register.  */
+       shlri   r1, 20 - 3, r34
+       andi    r34, 3 << 3, r33
+       addi    r33, LOCAL(ct_r5_fp_copy) - datalabel LOCAL(ct_r5_fp_base), r32
+LOCAL(ct_r5_fp_base):
+       ptrel/l r32, tr2
+       movi    7, r30
+       shlli   r30, 20, r31
+       andc    r1, r31, r1
+       blink   tr2, r63
+LOCAL(ct_r5_fp_copy):
+       fmov.dq dr0, r5
+       blink   tr1, r63
+       fmov.dq dr2, r5
+       blink   tr1, r63
+       fmov.dq dr4, r5
+       blink   tr1, r63
+       fmov.dq dr6, r5
+       blink   tr1, r63
+LOCAL(ct_r6_fph):      /* Copy r6 from a high FP register.  */
+       /* It must be dr8.  */
+       fmov.dq dr8, r6
+       movi    15, r30
+       shlli   r30, 16, r31
+       andc    r1, r31, r1
+       blink   tr1, r63
+LOCAL(ct_r6_fpl):      /* Copy r6 from a low FP register.  */
+       shlri   r1, 16 - 3, r34
+       andi    r34, 3 << 3, r33
+       addi    r33, LOCAL(ct_r6_fp_copy) - datalabel LOCAL(ct_r6_fp_base), r32
+LOCAL(ct_r6_fp_base):
+       ptrel/l r32, tr2
+       movi    7, r30
+       shlli   r30, 16, r31
+       andc    r1, r31, r1
+       blink   tr2, r63
+LOCAL(ct_r6_fp_copy):
+       fmov.dq dr0, r6
+       blink   tr1, r63
+       fmov.dq dr2, r6
+       blink   tr1, r63
+       fmov.dq dr4, r6
+       blink   tr1, r63
+       fmov.dq dr6, r6
+       blink   tr1, r63
+LOCAL(ct_r7_fph):      /* Copy r7 from a high FP register.  */
+       /* It is either dr8 or dr10.  */
+       movi    15 << 12, r31
+       shlri   r1, 12, r32
+       andc    r1, r31, r1
+       fmov.dq dr8, r7
+       beqi/l  r32, 8, tr1
+       fmov.dq dr10, r7
+       blink   tr1, r63
+LOCAL(ct_r7_fpl):      /* Copy r7 from a low FP register.  */
+       shlri   r1, 12 - 3, r34
+       andi    r34, 3 << 3, r33
+       addi    r33, LOCAL(ct_r7_fp_copy) - datalabel LOCAL(ct_r7_fp_base), r32
+LOCAL(ct_r7_fp_base):
+       ptrel/l r32, tr2
+       movi    7 << 12, r31
+       andc    r1, r31, r1
+       blink   tr2, r63
+LOCAL(ct_r7_fp_copy):
+       fmov.dq dr0, r7
+       blink   tr1, r63
+       fmov.dq dr2, r7
+       blink   tr1, r63
+       fmov.dq dr4, r7
+       blink   tr1, r63
+       fmov.dq dr6, r7
+       blink   tr1, r63
+LOCAL(ct_r8_fph):      /* Copy r8 from a high FP register.  */
+       /* It is either dr8 or dr10.  */
+       movi    15 << 8, r31
+       andi    r1, 1 << 8, r32
+       andc    r1, r31, r1
+       fmov.dq dr8, r8
+       beq/l   r32, r63, tr1
+       fmov.dq dr10, r8
+       blink   tr1, r63
+LOCAL(ct_r8_fpl):      /* Copy r8 from a low FP register.  */
+       shlri   r1, 8 - 3, r34
+       andi    r34, 3 << 3, r33
+       addi    r33, LOCAL(ct_r8_fp_copy) - datalabel LOCAL(ct_r8_fp_base), r32
+LOCAL(ct_r8_fp_base):
+       ptrel/l r32, tr2
+       movi    7 << 8, r31
+       andc    r1, r31, r1
+       blink   tr2, r63
+LOCAL(ct_r8_fp_copy):
+       fmov.dq dr0, r8
+       blink   tr1, r63
+       fmov.dq dr2, r8
+       blink   tr1, r63
+       fmov.dq dr4, r8
+       blink   tr1, r63
+       fmov.dq dr6, r8
+       blink   tr1, r63
+LOCAL(ct_r9_fph):      /* Copy r9 from a high FP register.  */
+       /* It is either dr8 or dr10.  */
+       movi    15 << 4, r31
+       andi    r1, 1 << 4, r32
+       andc    r1, r31, r1
+       fmov.dq dr8, r9
+       beq/l   r32, r63, tr1
+       fmov.dq dr10, r9
+       blink   tr1, r63
+LOCAL(ct_r9_fpl):      /* Copy r9 from a low FP register.  */
+       shlri   r1, 4 - 3, r34
+       andi    r34, 3 << 3, r33
+       addi    r33, LOCAL(ct_r9_fp_copy) - datalabel LOCAL(ct_r9_fp_base), r32
+LOCAL(ct_r9_fp_base):
+       ptrel/l r32, tr2
+       movi    7 << 4, r31
+       andc    r1, r31, r1
+       blink   tr2, r63
+LOCAL(ct_r9_fp_copy):
+       fmov.dq dr0, r9
+       blink   tr1, r63
+       fmov.dq dr2, r9
+       blink   tr1, r63
+       fmov.dq dr4, r9
+       blink   tr1, r63
+       fmov.dq dr6, r9
+       blink   tr1, r63
+LOCAL(ct_r2_ld):       /* Copy r2 from a memory address.  */
+       pt/l    LOCAL(ct_r2_load), tr2
+       movi    3, r30
+       shlli   r30, 29, r31
+       and     r1, r31, r32
+       andc    r1, r31, r1
+       beq/l   r31, r32, tr2
+       addi.l  r2, 8, r3
+       ldx.q   r2, r63, r2
+       /* Fall through.  */
+LOCAL(ct_r3_ld):       /* Copy r3 from a memory address.  */
+       pt/l    LOCAL(ct_r3_load), tr2
+       movi    3, r30
+       shlli   r30, 26, r31
+       and     r1, r31, r32
+       andc    r1, r31, r1
+       beq/l   r31, r32, tr2
+       addi.l  r3, 8, r4
+       ldx.q   r3, r63, r3
+LOCAL(ct_r4_ld):       /* Copy r4 from a memory address.  */
+       pt/l    LOCAL(ct_r4_load), tr2
+       movi    3, r30
+       shlli   r30, 23, r31
+       and     r1, r31, r32
+       andc    r1, r31, r1
+       beq/l   r31, r32, tr2
+       addi.l  r4, 8, r5
+       ldx.q   r4, r63, r4
+LOCAL(ct_r5_ld):       /* Copy r5 from a memory address.  */
+       pt/l    LOCAL(ct_r5_load), tr2
+       movi    3, r30
+       shlli   r30, 20, r31
+       and     r1, r31, r32
+       andc    r1, r31, r1
+       beq/l   r31, r32, tr2
+       addi.l  r5, 8, r6
+       ldx.q   r5, r63, r5
+LOCAL(ct_r6_ld):       /* Copy r6 from a memory address.  */
+       pt/l    LOCAL(ct_r6_load), tr2
+       movi    3 << 16, r31
+       and     r1, r31, r32
+       andc    r1, r31, r1
+       beq/l   r31, r32, tr2
+       addi.l  r6, 8, r7
+       ldx.q   r6, r63, r6
+LOCAL(ct_r7_ld):       /* Copy r7 from a memory address.  */
+       pt/l    LOCAL(ct_r7_load), tr2
+       movi    3 << 12, r31
+       and     r1, r31, r32
+       andc    r1, r31, r1
+       beq/l   r31, r32, tr2
+       addi.l  r7, 8, r8
+       ldx.q   r7, r63, r7
+LOCAL(ct_r8_ld):       /* Copy r8 from a memory address.  */
+       pt/l    LOCAL(ct_r8_load), tr2
+       movi    3 << 8, r31
+       and     r1, r31, r32
+       andc    r1, r31, r1
+       beq/l   r31, r32, tr2
+       addi.l  r8, 8, r9
+       ldx.q   r8, r63, r8
+LOCAL(ct_r9_ld):       /* Copy r9 from a memory address.  */
+       pt/l    LOCAL(ct_check_tramp), tr2
+       ldx.q   r9, r63, r9
+       blink   tr2, r63
+LOCAL(ct_r2_load):
+       ldx.q   r2, r63, r2
+       blink   tr1, r63
+LOCAL(ct_r3_load):
+       ldx.q   r3, r63, r3
+       blink   tr1, r63
+LOCAL(ct_r4_load):
+       ldx.q   r4, r63, r4
+       blink   tr1, r63
+LOCAL(ct_r5_load):
+       ldx.q   r5, r63, r5
+       blink   tr1, r63
+LOCAL(ct_r6_load):
+       ldx.q   r6, r63, r6
+       blink   tr1, r63
+LOCAL(ct_r7_load):
+       ldx.q   r7, r63, r7
+       blink   tr1, r63
+LOCAL(ct_r8_load):
+       ldx.q   r8, r63, r8
+       blink   tr1, r63
+LOCAL(ct_r2_pop):      /* Pop r2 from the stack.  */
+       movi    1, r30
+       ldx.q   r15, r63, r2
+       shlli   r30, 29, r31
+       addi.l  r15, 8, r15
+       andc    r1, r31, r1
+       blink   tr1, r63
+LOCAL(ct_r3_pop):      /* Pop r3 from the stack.  */
+       movi    1, r30
+       ldx.q   r15, r63, r3
+       shlli   r30, 26, r31
+       addi.l  r15, 8, r15
+       andc    r1, r31, r1
+       blink   tr1, r63
+LOCAL(ct_r4_pop):      /* Pop r4 from the stack.  */
+       movi    1, r30
+       ldx.q   r15, r63, r4
+       shlli   r30, 23, r31
+       addi.l  r15, 8, r15
+       andc    r1, r31, r1
+       blink   tr1, r63
+LOCAL(ct_r5_pop):      /* Pop r5 from the stack.  */
+       movi    1, r30
+       ldx.q   r15, r63, r5
+       shlli   r30, 20, r31
+       addi.l  r15, 8, r15
+       andc    r1, r31, r1
+       blink   tr1, r63
+LOCAL(ct_r6_pop):      /* Pop r6 from the stack.  */
+       movi    1, r30
+       ldx.q   r15, r63, r6
+       shlli   r30, 16, r31
+       addi.l  r15, 8, r15
+       andc    r1, r31, r1
+       blink   tr1, r63
+LOCAL(ct_r7_pop):      /* Pop r7 from the stack.  */
+       ldx.q   r15, r63, r7
+       movi    1 << 12, r31
+       addi.l  r15, 8, r15
+       andc    r1, r31, r1
+       blink   tr1, r63
+LOCAL(ct_r8_pop):      /* Pop r8 from the stack.  */
+       ldx.q   r15, r63, r8
+       movi    1 << 8, r31
+       addi.l  r15, 8, r15
+       andc    r1, r31, r1
+       blink   tr1, r63
+LOCAL(ct_pop_seq):     /* Pop a sequence of registers off the stack.  */
+       andi    r1, 7 << 1, r30
+       movi    (LOCAL(ct_end_of_pop_seq) >> 16) & 65535, r32
+       shlli   r30, 2, r31
+       shori   LOCAL(ct_end_of_pop_seq) & 65535, r32
+       sub.l   r32, r31, r33
+       ptabs/l r33, tr2
+       blink   tr2, r63
+LOCAL(ct_start_of_pop_seq):    /* Beginning of pop sequence.  */
+       ldx.q   r15, r63, r3
+       addi.l  r15, 8, r15
+       ldx.q   r15, r63, r4
+       addi.l  r15, 8, r15
+       ldx.q   r15, r63, r5
+       addi.l  r15, 8, r15
+       ldx.q   r15, r63, r6
+       addi.l  r15, 8, r15
+       ldx.q   r15, r63, r7
+       addi.l  r15, 8, r15
+       ldx.q   r15, r63, r8
+       addi.l  r15, 8, r15
+LOCAL(ct_r9_pop):      /* Pop r9 from the stack.  */
+       ldx.q   r15, r63, r9
+       addi.l  r15, 8, r15
+LOCAL(ct_end_of_pop_seq): /* Label used to compute first pop instruction.  */
+LOCAL(ct_check_tramp): /* Check whether we need a trampoline.  */
+       pt/u    LOCAL(ct_ret_wide), tr2
+       andi    r1, 1, r1
+       bne/u   r1, r63, tr2
+LOCAL(ct_call_func):   /* Just branch to the function.  */
+       blink   tr0, r63
+LOCAL(ct_ret_wide):    /* Call the function, so that we can unpack its 
+                          64-bit return value.  */
+       add.l   r18, r63, r10
+       blink   tr0, r18
+       ptabs   r10, tr0
+#if __LITTLE_ENDIAN__
+       shari   r2, 32, r3
+       add.l   r2, r63, r2
+#else
+       add.l   r2, r63, r3
+       shari   r2, 32, r2
+#endif
+       blink   tr0, r63
+#endif /* L_shcompact_call_trampoline */
+
+#ifdef L_shcompact_return_trampoline
+     /* This function does the converse of the code in `ret_wide'
+       above.  It is tail-called by SHcompact functions returning
+       64-bit non-floating-point values, to pack the 32-bit values in
+       r2 and r3 into r2.  */
+
+       .mode   SHmedia
+       .section        .text..SHmedia32, "ax"
+       .align  2
+       .global GLOBAL(GCC_shcompact_return_trampoline)
+GLOBAL(GCC_shcompact_return_trampoline):
+       ptabs/l r18, tr0
+#if __LITTLE_ENDIAN__
+       addz.l  r2, r63, r2
+       shlli   r3, 32, r3
+#else
+       addz.l  r3, r63, r3
+       shlli   r2, 32, r2
+#endif
+       or      r3, r2, r2
+       blink   tr0, r63
+#endif /* L_shcompact_return_trampoline */
+
+#ifdef L_shcompact_incoming_args
+       .section        .rodata
+       .align  1
+LOCAL(ia_main_table):
+.word  1 /* Invalid, just loop */
+.word  LOCAL(ia_r2_ld) - datalabel LOCAL(ia_main_label)
+.word  LOCAL(ia_r2_push) - datalabel LOCAL(ia_main_label)
+.word  1 /* Invalid, just loop */
+.word  LOCAL(ia_r3_ld) - datalabel LOCAL(ia_main_label)
+.word  LOCAL(ia_r3_push) - datalabel LOCAL(ia_main_label)
+.word  1 /* Invalid, just loop */
+.word  LOCAL(ia_r4_ld) - datalabel LOCAL(ia_main_label)
+.word  LOCAL(ia_r4_push) - datalabel LOCAL(ia_main_label)
+.word  1 /* Invalid, just loop */
+.word  LOCAL(ia_r5_ld) - datalabel LOCAL(ia_main_label)
+.word  LOCAL(ia_r5_push) - datalabel LOCAL(ia_main_label)
+.word  1 /* Invalid, just loop */
+.word  1 /* Invalid, just loop */
+.word  LOCAL(ia_r6_ld) - datalabel LOCAL(ia_main_label)
+.word  LOCAL(ia_r6_push) - datalabel LOCAL(ia_main_label)
+.word  1 /* Invalid, just loop */
+.word  1 /* Invalid, just loop */
+.word  LOCAL(ia_r7_ld) - datalabel LOCAL(ia_main_label)
+.word  LOCAL(ia_r7_push) - datalabel LOCAL(ia_main_label)
+.word  1 /* Invalid, just loop */
+.word  1 /* Invalid, just loop */
+.word  LOCAL(ia_r8_ld) - datalabel LOCAL(ia_main_label)
+.word  LOCAL(ia_r8_push) - datalabel LOCAL(ia_main_label)
+.word  1 /* Invalid, just loop */
+.word  1 /* Invalid, just loop */
+.word  LOCAL(ia_r9_ld) - datalabel LOCAL(ia_main_label)
+.word  LOCAL(ia_r9_push) - datalabel LOCAL(ia_main_label)
+.word  LOCAL(ia_push_seq) - datalabel LOCAL(ia_main_label)
+.word  LOCAL(ia_push_seq) - datalabel LOCAL(ia_main_label)
+.word  LOCAL(ia_r9_push) - datalabel LOCAL(ia_main_label)
+.word  LOCAL(ia_return) - datalabel LOCAL(ia_main_label)
+.word  LOCAL(ia_return) - datalabel LOCAL(ia_main_label)
+       .mode   SHmedia
+       .section        .text..SHmedia32, "ax"
+       .align  2
+       
+     /* This function stores 64-bit general-purpose registers back in
+       the stack, starting at @(r1), where the cookie is supposed to
+       have been stored, and loads the address in which each register
+       was stored into itself.  Its execution time is linear on the
+       number of registers that actually have to be copied, and it is
+       optimized for structures larger than 64 bits, as opposed to
+       invidivual `long long' arguments.  See sh.h for details on the
+       actual bit pattern.  */
+       
+       .global GLOBAL(GCC_shcompact_incoming_args)
+GLOBAL(GCC_shcompact_incoming_args):
+       ptabs/l r18, tr0        /* Prepare to return.  */
+       shlri   r17, 32, r0     /* Load the cookie.  */
+       movi    ((datalabel LOCAL(ia_main_table) - 31 * 2) >> 16) & 65535, r35
+       pt/l    LOCAL(ia_loop), tr1
+       add.l   r17, r63, r17
+       shori   ((datalabel LOCAL(ia_main_table) - 31 * 2)) & 65535, r35
+LOCAL(ia_loop):
+       nsb     r0, r28
+       shlli   r28, 1, r29
+       ldx.w   r35, r29, r30
+LOCAL(ia_main_label):
+       ptrel/l r30, tr2
+       blink   tr2, r63
+LOCAL(ia_r2_ld):       /* Store r2 and load its address.  */
+       movi    3, r30
+       shlli   r30, 29, r31
+       and     r0, r31, r32
+       andc    r0, r31, r0
+       stx.q   r17, r63, r2
+       add.l   r17, r63, r2
+       addi.l  r17, 8, r17
+       beq/u   r31, r32, tr1
+LOCAL(ia_r3_ld):       /* Store r3 and load its address.  */
+       movi    3, r30
+       shlli   r30, 26, r31
+       and     r0, r31, r32
+       andc    r0, r31, r0
+       stx.q   r17, r63, r3
+       add.l   r17, r63, r3
+       addi.l  r17, 8, r17
+       beq/u   r31, r32, tr1
+LOCAL(ia_r4_ld):       /* Store r4 and load its address.  */
+       movi    3, r30
+       shlli   r30, 23, r31
+       and     r0, r31, r32
+       andc    r0, r31, r0
+       stx.q   r17, r63, r4
+       add.l   r17, r63, r4
+       addi.l  r17, 8, r17
+       beq/u   r31, r32, tr1
+LOCAL(ia_r5_ld):       /* Store r5 and load its address.  */
+       movi    3, r30
+       shlli   r30, 20, r31
+       and     r0, r31, r32
+       andc    r0, r31, r0
+       stx.q   r17, r63, r5
+       add.l   r17, r63, r5
+       addi.l  r17, 8, r17
+       beq/u   r31, r32, tr1
+LOCAL(ia_r6_ld):       /* Store r6 and load its address.  */
+       movi    3, r30
+       shlli   r30, 16, r31
+       and     r0, r31, r32
+       andc    r0, r31, r0
+       stx.q   r17, r63, r6
+       add.l   r17, r63, r6
+       addi.l  r17, 8, r17
+       beq/u   r31, r32, tr1
+LOCAL(ia_r7_ld):       /* Store r7 and load its address.  */
+       movi    3 << 12, r31
+       and     r0, r31, r32
+       andc    r0, r31, r0
+       stx.q   r17, r63, r7
+       add.l   r17, r63, r7
+       addi.l  r17, 8, r17
+       beq/u   r31, r32, tr1
+LOCAL(ia_r8_ld):       /* Store r8 and load its address.  */
+       movi    3 << 8, r31
+       and     r0, r31, r32
+       andc    r0, r31, r0
+       stx.q   r17, r63, r8
+       add.l   r17, r63, r8
+       addi.l  r17, 8, r17
+       beq/u   r31, r32, tr1
+LOCAL(ia_r9_ld):       /* Store r9 and load its address.  */
+       stx.q   r17, r63, r9
+       add.l   r17, r63, r9
+       blink   tr0, r63
+LOCAL(ia_r2_push):     /* Push r2 onto the stack.  */
+       movi    1, r30
+       shlli   r30, 29, r31
+       andc    r0, r31, r0
+       stx.q   r17, r63, r2
+       addi.l  r17, 8, r17
+       blink   tr1, r63
+LOCAL(ia_r3_push):     /* Push r3 onto the stack.  */
+       movi    1, r30
+       shlli   r30, 26, r31
+       andc    r0, r31, r0
+       stx.q   r17, r63, r3
+       addi.l  r17, 8, r17
+       blink   tr1, r63
+LOCAL(ia_r4_push):     /* Push r4 onto the stack.  */
+       movi    1, r30
+       shlli   r30, 23, r31
+       andc    r0, r31, r0
+       stx.q   r17, r63, r4
+       addi.l  r17, 8, r17
+       blink   tr1, r63
+LOCAL(ia_r5_push):     /* Push r5 onto the stack.  */
+       movi    1, r30
+       shlli   r30, 20, r31
+       andc    r0, r31, r0
+       stx.q   r17, r63, r5
+       addi.l  r17, 8, r17
+       blink   tr1, r63
+LOCAL(ia_r6_push):     /* Push r6 onto the stack.  */
+       movi    1, r30
+       shlli   r30, 16, r31
+       andc    r0, r31, r0
+       stx.q   r17, r63, r6
+       addi.l  r17, 8, r17
+       blink   tr1, r63
+LOCAL(ia_r7_push):     /* Push r7 onto the stack.  */
+       movi    1 << 12, r31
+       andc    r0, r31, r0
+       stx.q   r17, r63, r7
+       addi.l  r17, 8, r17
+       blink   tr1, r63
+LOCAL(ia_r8_push):     /* Push r8 onto the stack.  */
+       movi    1 << 8, r31
+       andc    r0, r31, r0
+       stx.q   r17, r63, r8
+       addi.l  r17, 8, r17
+       blink   tr1, r63
+LOCAL(ia_push_seq):    /* Push a sequence of registers onto the stack.  */
+       andi    r0, 7 << 1, r30
+       movi    (LOCAL(ia_end_of_push_seq) >> 16) & 65535, r32
+       shlli   r30, 2, r31
+       shori   LOCAL(ia_end_of_push_seq) & 65535, r32
+       sub.l   r32, r31, r33
+       ptabs/l r33, tr2
+       blink   tr2, r63
+LOCAL(ia_stack_of_push_seq):    /* Beginning of push sequence.  */
+       stx.q   r17, r63, r3
+       addi.l  r17, 8, r17
+       stx.q   r17, r63, r4
+       addi.l  r17, 8, r17
+       stx.q   r17, r63, r5
+       addi.l  r17, 8, r17
+       stx.q   r17, r63, r6
+       addi.l  r17, 8, r17
+       stx.q   r17, r63, r7
+       addi.l  r17, 8, r17
+       stx.q   r17, r63, r8
+       addi.l  r17, 8, r17
+LOCAL(ia_r9_push):     /* Push r9 onto the stack.  */
+       stx.q   r17, r63, r9
+LOCAL(ia_return):      /* Return.  */
+       blink   tr0, r63
+LOCAL(ia_end_of_push_seq): /* Label used to compute the first push instruction.  */
+#endif /* L_shcompact_incoming_args */
+#endif
+#if __SH5__
+#ifdef L_nested_trampoline
+#if __SH5__ == 32
+       .section        .text..SHmedia32,"ax"
+#else
+       .text
+#endif
+       .align  3 /* It is copied in units of 8 bytes in SHmedia mode.  */
+       .global GLOBAL(GCC_nested_trampoline)
+GLOBAL(GCC_nested_trampoline):
+       .mode   SHmedia
+       ptrel/u r63, tr0
+       gettr   tr0, r0
+#if __SH5__ == 64
+       ld.q    r0, 24, r1
+#else
+       ld.l    r0, 24, r1
+#endif
+       ptabs/l r1, tr1
+#if __SH5__ == 64
+       ld.q    r0, 32, r1
+#else
+       ld.l    r0, 28, r1
+#endif
+       blink   tr1, r63
+#endif /* L_nested_trampoline */
+#endif /* __SH5__ */
+#if __SH5__ == 32
+#ifdef L_push_pop_shmedia_regs
+       .section        .text..SHmedia32,"ax"
+       .mode   SHmedia
+       .align  2
+#ifndef __SH4_NOFPU__  
+       .global GLOBAL(GCC_push_shmedia_regs)
+GLOBAL(GCC_push_shmedia_regs):
+       addi.l  r15, -14*8, r15
+       fst.d   r15, 13*8, dr62
+       fst.d   r15, 12*8, dr60
+       fst.d   r15, 11*8, dr58
+       fst.d   r15, 10*8, dr56
+       fst.d   r15,  9*8, dr54
+       fst.d   r15,  8*8, dr52
+       fst.d   r15,  7*8, dr50
+       fst.d   r15,  6*8, dr48
+       fst.d   r15,  5*8, dr46
+       fst.d   r15,  4*8, dr44
+       fst.d   r15,  3*8, dr42
+       fst.d   r15,  2*8, dr40
+       fst.d   r15,  1*8, dr38
+       fst.d   r15,  0*8, dr36
+#endif
+       .global GLOBAL(GCC_push_shmedia_regs_nofpu)
+GLOBAL(GCC_push_shmedia_regs_nofpu):
+       ptabs/l r18, tr0
+       addi.l  r15, -27*8, r15
+       gettr   tr7, r62
+       gettr   tr6, r61
+       gettr   tr5, r60
+       st.q    r15, 26*8, r62
+       st.q    r15, 25*8, r61
+       st.q    r15, 24*8, r60
+       st.q    r15, 23*8, r59
+       st.q    r15, 22*8, r58
+       st.q    r15, 21*8, r57
+       st.q    r15, 20*8, r56
+       st.q    r15, 19*8, r55
+       st.q    r15, 18*8, r54
+       st.q    r15, 17*8, r53
+       st.q    r15, 16*8, r52
+       st.q    r15, 15*8, r51
+       st.q    r15, 14*8, r50
+       st.q    r15, 13*8, r49
+       st.q    r15, 12*8, r48
+       st.q    r15, 11*8, r47
+       st.q    r15, 10*8, r46
+       st.q    r15,  9*8, r45
+       st.q    r15,  8*8, r44
+       st.q    r15,  7*8, r35
+       st.q    r15,  6*8, r34
+       st.q    r15,  5*8, r33
+       st.q    r15,  4*8, r32
+       st.q    r15,  3*8, r31
+       st.q    r15,  2*8, r30
+       st.q    r15,  1*8, r29
+       st.q    r15,  0*8, r28
+       blink   tr0, r63
+
+#ifndef __SH4_NOFPU__
+       .global GLOBAL(GCC_pop_shmedia_regs)
+GLOBAL(GCC_pop_shmedia_regs):
+       pt      .L0, tr1
+       movi    41*8, r0
+       fld.d   r15, 40*8, dr62
+       fld.d   r15, 39*8, dr60
+       fld.d   r15, 38*8, dr58
+       fld.d   r15, 37*8, dr56
+       fld.d   r15, 36*8, dr54
+       fld.d   r15, 35*8, dr52
+       fld.d   r15, 34*8, dr50
+       fld.d   r15, 33*8, dr48
+       fld.d   r15, 32*8, dr46
+       fld.d   r15, 31*8, dr44
+       fld.d   r15, 30*8, dr42
+       fld.d   r15, 29*8, dr40
+       fld.d   r15, 28*8, dr38
+       fld.d   r15, 27*8, dr36
+       blink   tr1, r63
+#endif
+       .global GLOBAL(GCC_pop_shmedia_regs_nofpu)
+GLOBAL(GCC_pop_shmedia_regs_nofpu):
+       movi    27*8, r0
+.L0:
+       ptabs   r18, tr0
+       ld.q    r15, 26*8, r62
+       ld.q    r15, 25*8, r61
+       ld.q    r15, 24*8, r60
+       ptabs   r62, tr7
+       ptabs   r61, tr6
+       ptabs   r60, tr5
+       ld.q    r15, 23*8, r59
+       ld.q    r15, 22*8, r58
+       ld.q    r15, 21*8, r57
+       ld.q    r15, 20*8, r56
+       ld.q    r15, 19*8, r55
+       ld.q    r15, 18*8, r54
+       ld.q    r15, 17*8, r53
+       ld.q    r15, 16*8, r52
+       ld.q    r15, 15*8, r51
+       ld.q    r15, 14*8, r50
+       ld.q    r15, 13*8, r49
+       ld.q    r15, 12*8, r48
+       ld.q    r15, 11*8, r47
+       ld.q    r15, 10*8, r46
+       ld.q    r15,  9*8, r45
+       ld.q    r15,  8*8, r44
+       ld.q    r15,  7*8, r35
+       ld.q    r15,  6*8, r34
+       ld.q    r15,  5*8, r33
+       ld.q    r15,  4*8, r32
+       ld.q    r15,  3*8, r31
+       ld.q    r15,  2*8, r30
+       ld.q    r15,  1*8, r29
+       ld.q    r15,  0*8, r28
+       add.l   r15, r0, r15
+       blink   tr0, r63
+#endif /* __SH5__ == 32 */
+#endif /* L_push_pop_shmedia_regs */
index a8507ae..59ed9e7 100644 (file)
@@ -73,6 +73,7 @@ extern int gen_shl_and PARAMS ((rtx, rtx, rtx, rtx));
 extern int shl_sext_kind PARAMS ((rtx, rtx, int *));
 extern int shl_sext_length PARAMS ((rtx));
 extern int gen_shl_sext PARAMS ((rtx, rtx, rtx, rtx));
+extern rtx gen_datalabel_ref PARAMS ((rtx));
 extern int regs_used PARAMS ((rtx, int));
 extern void fixup_addr_diff_vecs PARAMS ((rtx));
 extern int get_dest_uid PARAMS ((rtx, int));
@@ -114,6 +115,7 @@ extern const char *output_jump_label_table PARAMS ((void));
 extern int sh_handle_pragma PARAMS ((int (*)(void), void (*)(int), const char *));
 extern struct rtx_def *get_fpscr_rtx PARAMS ((void));
 extern void output_file_start PARAMS ((FILE *));
+extern int sh_media_register_for_return PARAMS ((void));
 extern void sh_expand_prologue PARAMS ((void));
 extern void sh_expand_epilogue PARAMS ((void));
 extern int sh_need_epilogue PARAMS ((void));
index f83a1e1..c408caa 100644 (file)
@@ -47,6 +47,13 @@ int code_for_indirect_jump_scratch = CODE_FOR_indirect_jump_scratch;
 #define MSW (TARGET_LITTLE_ENDIAN ? 1 : 0)
 #define LSW (TARGET_LITTLE_ENDIAN ? 0 : 1)
 
+/* These are some macros to abstract register modes.  */
+#define CONST_OK_FOR_ADD(size) \
+  (TARGET_SHMEDIA ? CONST_OK_FOR_P (size) : CONST_OK_FOR_I (size))
+#define GEN_MOV (*(TARGET_SHMEDIA64 ? gen_movdi : gen_movsi))
+#define GEN_ADD3 (*(TARGET_SHMEDIA64 ? gen_adddi3 : gen_addsi3))
+#define GEN_SUB3 (*(TARGET_SHMEDIA64 ? gen_subdi3 : gen_subsi3))
+
 /* Set to 1 by expand_prologue() when the function is an interrupt handler.  */
 int current_function_interrupt;
 
@@ -100,31 +107,56 @@ int regno_reg_class[FIRST_PSEUDO_REGISTER] =
   GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
   GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
   GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
-  GENERAL_REGS, PR_REGS, T_REGS, NO_REGS,
-  MAC_REGS, MAC_REGS, FPUL_REGS, GENERAL_REGS,
+  GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
+  GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
+  GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
+  GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
+  GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
+  GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
+  GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
+  GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
+  GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
+  GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
+  GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
+  GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
   FP0_REGS,FP_REGS, FP_REGS, FP_REGS,
   FP_REGS, FP_REGS, FP_REGS, FP_REGS,
   FP_REGS, FP_REGS, FP_REGS, FP_REGS,
   FP_REGS, FP_REGS, FP_REGS, FP_REGS,
+  FP_REGS, FP_REGS, FP_REGS, FP_REGS,
+  FP_REGS, FP_REGS, FP_REGS, FP_REGS,
+  FP_REGS, FP_REGS, FP_REGS, FP_REGS,
+  FP_REGS, FP_REGS, FP_REGS, FP_REGS,
+  FP_REGS, FP_REGS, FP_REGS, FP_REGS,
+  FP_REGS, FP_REGS, FP_REGS, FP_REGS,
+  FP_REGS, FP_REGS, FP_REGS, FP_REGS,
+  FP_REGS, FP_REGS, FP_REGS, FP_REGS,
+  FP_REGS, FP_REGS, FP_REGS, FP_REGS,
+  FP_REGS, FP_REGS, FP_REGS, FP_REGS,
+  FP_REGS, FP_REGS, FP_REGS, FP_REGS,
+  FP_REGS, FP_REGS, FP_REGS, FP_REGS,
+  TARGET_REGS, TARGET_REGS, TARGET_REGS, TARGET_REGS,
+  TARGET_REGS, TARGET_REGS, TARGET_REGS, TARGET_REGS,
   DF_REGS, DF_REGS, DF_REGS, DF_REGS,
   DF_REGS, DF_REGS, DF_REGS, DF_REGS,
-  FPSCR_REGS,
+  NO_REGS, GENERAL_REGS, PR_REGS, T_REGS,
+  MAC_REGS, MAC_REGS, FPUL_REGS, FPSCR_REGS,
+  GENERAL_REGS,
 };
 
-char fp_reg_names[][5] =
-{
-  "fr0", "fr1", "fr2", "fr3", "fr4", "fr5", "fr6", "fr7",
-  "fr8", "fr9", "fr10", "fr11", "fr12", "fr13", "fr14", "fr15",
-  "fpul",
-  "xd0","xd2","xd4", "xd6", "xd8", "xd10", "xd12", "xd14",
-};
+char sh_register_names[FIRST_PSEUDO_REGISTER] \
+  [MAX_REGISTER_NAME_LENGTH + 1] = SH_REGISTER_NAMES_INITIALIZER;
+
+char sh_additional_register_names[ADDREGNAMES_SIZE] \
+  [MAX_ADDITIONAL_REGISTER_NAME_LENGTH + 1]
+  = SH_ADDITIONAL_REGISTER_NAMES_INITIALIZER;
 
 /* Provide reg_class from a letter such as appears in the machine
    description.  */
 
 const enum reg_class reg_class_from_letter[] =
 {
-  /* a */ ALL_REGS, /* b */ NO_REGS, /* c */ FPSCR_REGS, /* d */ DF_REGS,
+  /* a */ ALL_REGS, /* b */ TARGET_REGS, /* c */ FPSCR_REGS, /* d */ DF_REGS,
   /* e */ NO_REGS, /* f */ FP_REGS, /* g */ NO_REGS, /* h */ NO_REGS,
   /* i */ NO_REGS, /* j */ NO_REGS, /* k */ SIBCALL_REGS, /* l */ PR_REGS,
   /* m */ NO_REGS, /* n */ NO_REGS, /* o */ NO_REGS, /* p */ NO_REGS,
@@ -150,8 +182,8 @@ static rtx gen_block_redirect PARAMS ((rtx, int, int));
 static void output_stack_adjust PARAMS ((int, rtx, int));
 static void push PARAMS ((int));
 static void pop PARAMS ((int));
-static void push_regs PARAMS ((int, int));
-static int calc_live_regs PARAMS ((int *, int *));
+static void push_regs PARAMS ((HOST_WIDE_INT *));
+static void calc_live_regs PARAMS ((int *, HOST_WIDE_INT *));
 static void mark_use PARAMS ((rtx, rtx *));
 static HOST_WIDE_INT rounded_frame_size PARAMS ((int));
 static rtx mark_constant_pool_use PARAMS ((rtx));
@@ -165,6 +197,9 @@ static void sh_insert_attributes PARAMS ((tree, tree *));
 static void sh_asm_named_section PARAMS ((const char *, unsigned int));
 #endif
 static int sh_adjust_cost PARAMS ((rtx, rtx, rtx, int));
+static bool sh_cannot_modify_jumps_p PARAMS ((void));
+
+static bool sh_ms_bitfield_layout_p PARAMS ((tree));
 \f
 /* Initialize the GCC target structure.  */
 #undef TARGET_ATTRIBUTE_TABLE
@@ -176,6 +211,12 @@ static int sh_adjust_cost PARAMS ((rtx, rtx, rtx, int));
 #undef TARGET_ASM_UNALIGNED_SI_OP
 #define TARGET_ASM_UNALIGNED_SI_OP "\t.ualong\t"
 
+/* These are NULLed out on non-SH5 in OVERRIDE_OPTIONS.  */
+#undef TARGET_ASM_UNALIGNED_DI_OP
+#define TARGET_ASM_UNALIGNED_DI_OP "\t.uaquad\t"
+#undef TARGET_ASM_ALIGNED_DI_OP
+#define TARGET_ASM_ALIGNED_DI_OP "\t.quad\t"
+
 #undef TARGET_ASM_FUNCTION_EPILOGUE
 #define TARGET_ASM_FUNCTION_EPILOGUE sh_output_function_epilogue
 
@@ -185,6 +226,12 @@ static int sh_adjust_cost PARAMS ((rtx, rtx, rtx, int));
 #undef TARGET_SCHED_ADJUST_COST
 #define TARGET_SCHED_ADJUST_COST sh_adjust_cost
 
+#undef TARGET_CANNOT_MODIFY_JUMPS_P
+#define TARGET_CANNOT_MODIFY_JUMPS_P sh_cannot_modify_jumps_p
+
+#undef TARGET_MS_BITFIELD_LAYOUT_P
+#define TARGET_MS_BITFIELD_LAYOUT_P sh_ms_bitfield_layout_p
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 \f
 /* Print the operand address in x to the stream.  */
@@ -257,6 +304,9 @@ print_operand_address (stream, x)
    'R'  print the LSW of a dp value - changes if in little endian
    'S'  print the MSW of a dp value - changes if in little endian
    'T'  print the next word of a dp value - same as 'R' in big endian mode.
+   'M'  print an `x' if `m' will print `base,index'.
+   'm'  print a pair `base,offset' or `base,index', for LD and ST.
+   'u'  prints the lowest 16 bits of CONST_INT, as an unsigned value.
    'o'  output an operator.  */
 
 void
@@ -338,21 +388,120 @@ print_operand (stream, x, code)
          break;
        }
       break;
+    case 'M':
+      if (GET_CODE (x) == MEM
+         && GET_CODE (XEXP (x, 0)) == PLUS
+         && (GET_CODE (XEXP (XEXP (x, 0), 1)) == REG
+             || GET_CODE (XEXP (XEXP (x, 0), 1)) == SUBREG))
+       fputc ('x', stream);
+      break;
+
+    case 'm':
+      if (GET_CODE (x) != MEM)
+       abort ();
+      x = XEXP (x, 0);
+      switch (GET_CODE (x))
+       {
+       case REG:
+       case SUBREG:
+         print_operand (stream, x, 0);
+         fputs (", 0", stream);
+         break;
+
+       case PLUS:
+         print_operand (stream, XEXP (x, 0), 0);
+         fputs (", ", stream);
+         print_operand (stream, XEXP (x, 1), 0);
+         break;
+
+       default:
+         abort ();
+       }
+      break;
+
+    case 'u':
+      if (GET_CODE (x) == CONST_INT)
+        {
+         fprintf ((stream), "%u", (unsigned) INTVAL (x) & (0x10000 - 1));
+         break;
+       }
+      /* Fall through.  */
+
     default:
       switch (GET_CODE (x))
        {
+         /* FIXME: We need this on SHmedia32 because reload generates
+            some sign-extended HI or QI loads into DImode registers
+            but, because Pmode is SImode, the address ends up with a
+            subreg:SI of the DImode register.  Maybe reload should be
+            fixed so as to apply alter_subreg to such loads?  */
+       case SUBREG:
+         if (SUBREG_BYTE (x) != 0
+             || GET_CODE (SUBREG_REG (x)) != REG)
+           abort ();
+
+         x = SUBREG_REG (x);
+         /* Fall through.  */
+
        case REG:
          if (FP_REGISTER_P (REGNO (x))
-             && GET_MODE_SIZE (GET_MODE (x)) > 4)
-           fprintf ((stream), "d%s", reg_names[REGNO (x)]+1);
+             && GET_MODE (x) == V16SFmode)
+           fprintf ((stream), "mtrx%s", reg_names[REGNO (x)] + 2);
+         else if (FP_REGISTER_P (REGNO (x))
+                  && GET_MODE (x) == V4SFmode)
+           fprintf ((stream), "fv%s", reg_names[REGNO (x)] + 2);
+         else if (GET_CODE (x) == REG
+                  && GET_MODE (x) == V2SFmode)
+           fprintf ((stream), "fp%s", reg_names[REGNO (x)] + 2);
+         else if (FP_REGISTER_P (REGNO (x))
+                  && GET_MODE_SIZE (GET_MODE (x)) > 4)
+           fprintf ((stream), "d%s", reg_names[REGNO (x)] + 1);
          else
            fputs (reg_names[REGNO (x)], (stream));
          break;
+
        case MEM:
          output_address (XEXP (x, 0));
          break;
+         
+       case CONST:
+         if (TARGET_SHMEDIA
+             && GET_CODE (XEXP (x, 0)) == SIGN_EXTEND
+             && GET_MODE (XEXP (x, 0)) == DImode
+             && GET_CODE (XEXP (XEXP (x, 0), 0)) == TRUNCATE
+             && GET_MODE (XEXP (XEXP (x, 0), 0)) == HImode)
+           {
+             rtx val = XEXP (XEXP (XEXP (x, 0), 0), 0);
+
+             fputc ('(', stream);
+             if (GET_CODE (val) == ASHIFTRT)
+               {
+                 fputc ('(', stream);
+                 if (GET_CODE (XEXP (val, 0)) == CONST)
+                   fputc ('(', stream);
+                 output_addr_const (stream, XEXP (val, 0));
+                 if (GET_CODE (XEXP (val, 0)) == CONST)
+                   fputc (')', stream);
+                 fputs (" >> ", stream);
+                 output_addr_const (stream, XEXP (val, 1));
+                 fputc (')', stream);
+               }
+             else
+               {
+                 if (GET_CODE (val) == CONST)
+                   fputc ('(', stream);
+                 output_addr_const (stream, val);
+                 if (GET_CODE (val) == CONST)
+                   fputc (')', stream);
+               }
+             fputs (" & 65535)", stream);
+             break;
+           }
+
+         /* Fall through.  */
        default:
-         fputc ('#', stream);
+         if (TARGET_SH1)
+           fputc ('#', stream);
          output_addr_const (stream, x);
          break;
        }
@@ -498,17 +647,20 @@ prepare_move_operands (operands, mode)
      rtx operands[];
      enum machine_mode mode;
 {
-  if (mode == SImode && flag_pic)
+  if ((mode == SImode || mode == DImode) && flag_pic)
     {
       rtx temp;
       if (SYMBOLIC_CONST_P (operands[1]))
        {
          if (GET_CODE (operands[0]) == MEM)
            operands[1] = force_reg (Pmode, operands[1]);
+         else if (GET_CODE (operands[1]) == LABEL_REF
+                  && target_reg_operand (operands[0], mode))
+           /* It's ok.  */;
          else
            {
              temp = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
-             operands[1] = legitimize_pic_address (operands[1], SImode, temp);
+             operands[1] = legitimize_pic_address (operands[1], mode, temp);
            }
        }
       else if (GET_CODE (operands[1]) == CONST
@@ -517,8 +669,8 @@ prepare_move_operands (operands, mode)
        {
          temp = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
          temp = legitimize_pic_address (XEXP (XEXP (operands[1], 0), 0),
-                                        SImode, temp);
-         operands[1] = expand_binop (SImode, add_optab, temp,
+                                        mode, temp);
+         operands[1] = expand_binop (mode, add_optab, temp,
                                      XEXP (XEXP (operands[1], 0), 1),
                                      no_new_pseudos ? temp
                                      : gen_reg_rtx (Pmode),
@@ -802,9 +954,19 @@ output_far_jump (insn, op)
        print_slot (final_sequence);
 
       this.reg = gen_rtx_REG (SImode, 13);
-      output_asm_insn ("mov.l  r13,@-r15", 0);
+      /* We must keep the stack aligned to 8-byte boundaries on SH5.
+        Fortunately, MACL is fixed and call-clobbered, and we never
+        need its value across jumps, so save r13 in it instead of in
+        the stack.  */
+      if (TARGET_SH5)
+       output_asm_insn ("lds   r13, macl", 0);
+      else
+       output_asm_insn ("mov.l r13,@-r15", 0);
       output_asm_insn (jump, &this.lab);
-      output_asm_insn ("mov.l  @r15+,r13", 0);
+      if (TARGET_SH5)
+       output_asm_insn ("sts   macl, r13", 0);
+      else
+       output_asm_insn ("mov.l @r15+,r13", 0);
     }
   if (far && flag_pic && TARGET_SH2)
     {
@@ -954,6 +1116,12 @@ output_file_start (file)
 
   if (TARGET_LITTLE_ENDIAN)
     fprintf (file, "\t.little\n");
+
+  if (TARGET_SHCOMPACT)
+    fprintf (file, "\t.mode\tSHcompact\n");
+  else if (TARGET_SHMEDIA)
+    fprintf (file, "\t.mode\tSHmedia\n\t.abi\t%i\n",
+            TARGET_SHMEDIA64 ? 64 : 32);
 }
 \f
 /* Actual number of instructions used to make a shift by N.  */
@@ -1031,6 +1199,9 @@ shiftcosts (x)
 {
   int value;
 
+  if (TARGET_SHMEDIA)
+    return 1;
+
   if (GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD)
     {
       if (GET_MODE (x) == DImode
@@ -1073,6 +1244,17 @@ andcosts (x)
     return 1;
 
   i = INTVAL (XEXP (x, 1));
+
+  if (TARGET_SHMEDIA)
+    {
+      if ((GET_CODE (XEXP (x, 1)) == CONST_INT
+          && CONST_OK_FOR_J (INTVAL (XEXP (x, 1))))
+         || EXTRA_CONSTRAINT_S (XEXP (x, 1)))
+       return 1;
+      else
+       return 2;
+    }
+
   /* These constants are single cycle extu.[bw] instructions.  */
   if (i == 0xff || i == 0xffff)
     return 1;
@@ -1102,9 +1284,30 @@ addsubcosts (x)
 
   /* Likewise for small constants.  */
   if (GET_CODE (XEXP (x, 1)) == CONST_INT
-      && CONST_OK_FOR_I (INTVAL (XEXP (x, 1))))
+      && CONST_OK_FOR_ADD (INTVAL (XEXP (x, 1))))
     return 1;
 
+  if (TARGET_SHMEDIA)
+    switch (GET_CODE (XEXP (x, 1)))
+      {
+      case CONST:
+      case LABEL_REF:
+      case SYMBOL_REF:
+       return TARGET_SHMEDIA64 ? 5 : 3;
+
+      case CONST_INT:
+       if (CONST_OK_FOR_J (INTVAL (XEXP (x, 1))))
+          return 2;
+       else if (CONST_OK_FOR_J (INTVAL (XEXP (x, 1)) >> 16))
+         return 3;
+       else if (CONST_OK_FOR_J ((INTVAL (XEXP (x, 1)) >> 16) >> 16))
+         return 4;
+
+       /* Fall through.  */
+      default:
+         return 5;
+      }
+
   /* Any other constant requires a 2 cycle pc-relative load plus an
      addition.  */
   return 3;
@@ -1115,6 +1318,9 @@ int
 multcosts (x)
      rtx x ATTRIBUTE_UNUSED;
 {
+  if (TARGET_SHMEDIA)
+    return 3;
+
   if (TARGET_SH2)
     {
       /* We have a mul insn, so we can never take more than the mul and the
@@ -1916,6 +2122,27 @@ gen_shl_sext (dest, left_rtx, size_rtx, source)
     }
   return 0;
 }
+
+/* Prefix a symbol_ref name with "datalabel".  */
+
+rtx
+gen_datalabel_ref (sym)
+     rtx sym;
+{
+  if (GET_CODE (sym) == LABEL_REF)
+    return gen_rtx_CONST (GET_MODE (sym),
+                         gen_rtx_UNSPEC (GET_MODE (sym),
+                                         gen_rtvec (1, sym),
+                                         UNSPEC_DATALABEL));
+    
+  if (GET_CODE (sym) != SYMBOL_REF)
+    abort ();
+
+  XSTR (sym, 0) = concat (SH_DATALABEL_ENCODING, XSTR (sym, 0), NULL);
+
+  return sym;
+}
+
 \f
 /* The SH cannot load a large constant into a register, constants have to
    come from a pc relative load.  The reference of a pc relative load
@@ -2078,6 +2305,7 @@ dump_table (scan)
   int i;
   int need_align = 1;
   rtx lab, ref;
+  int have_di = 0;
 
   /* Do two passes, first time dump out the HI sized constants.  */
 
@@ -2102,10 +2330,87 @@ dump_table (scan)
              scan = emit_insn_after (gen_consttable_window_end (lab), scan);
            }
        }
+      else if (p->mode == DImode || p->mode == DFmode)
+       have_di = 1;
     }
 
   need_align = 1;
 
+  if (TARGET_SHCOMPACT && have_di)
+    {
+      rtx align_insn = NULL_RTX;
+
+      scan = emit_label_after (gen_label_rtx (), scan);
+      scan = emit_insn_after (gen_align_log (GEN_INT (3)), scan);
+      need_align = 0;
+
+      for (i = 0; i < pool_size; i++)
+       {
+         pool_node *p = &pool_vector[i];
+
+         switch (p->mode)
+           {
+           case HImode:
+             break;
+           case SImode:
+           case SFmode:
+             if (align_insn)
+               {
+                 for (lab = p->label; lab; lab = LABEL_REFS (lab))
+                   emit_label_before (lab, align_insn);
+                 emit_insn_before (gen_consttable_4 (p->value, const0_rtx),
+                                   align_insn);
+                 for (ref = p->wend; ref; ref = LABEL_NEXTREF (ref))
+                   {
+                     lab = XEXP (ref, 0);
+                     emit_insn_before (gen_consttable_window_end (lab),
+                                      align_insn);
+                   }
+                 delete_insn (align_insn);
+                 align_insn = NULL_RTX;
+                 continue;
+               }
+             else
+               {
+                 for (lab = p->label; lab; lab = LABEL_REFS (lab))
+                   scan = emit_label_after (lab, scan);
+                 scan = emit_insn_after (gen_consttable_4 (p->value,
+                                                           const0_rtx), scan);
+                 need_align = ! need_align;
+               }
+             break;
+           case DFmode:
+           case DImode:
+             if (need_align)
+               {
+                 scan = emit_insn_after (gen_align_log (GEN_INT (3)), scan);
+                 align_insn = scan;
+                 need_align = 0;
+               }
+             for (lab = p->label; lab; lab = LABEL_REFS (lab))
+               scan = emit_label_after (lab, scan);
+             scan = emit_insn_after (gen_consttable_8 (p->value, const0_rtx),
+                                     scan);
+             break;
+           default:
+             abort ();
+             break;
+           }
+
+         if (p->mode != HImode)
+           {
+             for (ref = p->wend; ref; ref = LABEL_NEXTREF (ref))
+               {
+                 lab = XEXP (ref, 0);
+                 scan = emit_insn_after (gen_consttable_window_end (lab),
+                                         scan);
+               }
+           }
+       }
+
+      pool_size = 0;
+    }
+  
   for (i = 0; i < pool_size; i++)
     {
       pool_node *p = &pool_vector[i];
@@ -2240,6 +2545,7 @@ find_barrier (num_mova, mova, from)
   int count_hi = 0;
   int found_hi = 0;
   int found_si = 0;
+  int found_di = 0;
   int hi_align = 2;
   int si_align = 2;
   int leading_mova = num_mova;
@@ -2321,6 +2627,18 @@ find_barrier (num_mova, mova, from)
            }
          else
            {
+             /* We dump DF/DI constants before SF/SI ones, because
+                the limit is the same, but the alignment requirements
+                are higher.  We may waste up to 4 additional bytes
+                for alignment, and the DF/DI constant may have
+                another SF/SI constant placed before it. */
+             if (TARGET_SHCOMPACT
+                 && ! found_di
+                 && (mode == DFmode || mode == DImode))
+               {
+                 found_di = 1;
+                 si_limit -= 8;
+               }
              while (si_align > 2 && found_si + si_align - 2 > count_si)
                si_align >>= 1;
              if (found_si > count_si)
@@ -2928,7 +3246,7 @@ barrier_align (barrier_or_label)
       return ((TARGET_SMALLCODE
               || (XVECLEN (pat, 1) * GET_MODE_SIZE (GET_MODE (pat))
                   <= (unsigned)1 << (CACHE_LOG - 2)))
-             ? 1 : CACHE_LOG);
+             ? 1 << TARGET_SHMEDIA : CACHE_LOG);
     }
 
   if (TARGET_SMALLCODE)
@@ -3035,6 +3353,10 @@ sh_loop_align (label)
       || GET_CODE (PATTERN (next)) == ADDR_DIFF_VEC
       || recog_memoized (next) == CODE_FOR_consttable_2)
     return 0;
+
+  if (TARGET_SH5)
+    return 3;
+
   return 2;
 }
 
@@ -3058,6 +3380,9 @@ machine_dependent_reorg (first)
   if (! optimize)
     split_all_insns_noflow ();
 
+  if (TARGET_SHMEDIA)
+    return;
+
   /* If relaxing, generate pseudo-ops to associate function calls with
      the symbols they call.  It does no harm to not generate these
      pseudo-ops.  However, when we can generate them, it enables to
@@ -3340,6 +3665,7 @@ machine_dependent_reorg (first)
             behind.  */
          rtx barrier = find_barrier (num_mova, mova, insn);
          rtx last_float_move, last_float = 0, *last_float_addr;
+         int may_need_align = 1;
 
          if (num_mova && ! mova_p (mova))
            {
@@ -3397,6 +3723,27 @@ machine_dependent_reorg (first)
                      if (last_float
                          && reg_set_between_p (r0_rtx, last_float_move, scan))
                        last_float = 0;
+                     if (TARGET_SHCOMPACT)
+                       {
+                         /* The first SFmode constant after a DFmode
+                            constant may be pulled before a sequence
+                            of DFmode constants, so the second SFmode
+                            needs a label, just in case.  */
+                         if (GET_MODE_SIZE (mode) == 4)
+                           {
+                             if (last_float && may_need_align)
+                               last_float = 0;
+                             may_need_align = 0;
+                           }
+                         if (last_float
+                             && (GET_MODE_SIZE (GET_MODE (last_float))
+                                 != GET_MODE_SIZE (mode)))
+                           {
+                             last_float = 0;
+                             if (GET_MODE_SIZE (mode) == 4)
+                               may_need_align = 1;
+                           }
+                       }
                      lab = add_constant (src, mode, last_float);
                      if (lab)
                        emit_insn_before (gen_mova (lab), scan);
@@ -3842,16 +4189,21 @@ output_stack_adjust (size, reg, temp)
 {
   if (size)
     {
-      if (CONST_OK_FOR_I (size))
-       emit_insn (gen_addsi3 (reg, reg, GEN_INT (size)));
+      HOST_WIDE_INT align = STACK_BOUNDARY / BITS_PER_UNIT;
+
+      if (size % align)
+       abort ();
+
+      if (CONST_OK_FOR_ADD (size))
+       emit_insn (GEN_ADD3 (reg, reg, GEN_INT (size)));
       /* Try to do it with two partial adjustments; however, we must make
         sure that the stack is properly aligned at all times, in case
         an interrupt occurs between the two partial adjustments.  */
-      else if (CONST_OK_FOR_I (size / 2 & -4)
-              && CONST_OK_FOR_I (size - (size / 2 & -4)))
+      else if (CONST_OK_FOR_ADD (size / 2 & -align)
+              && CONST_OK_FOR_ADD (size - (size / 2 & -align)))
        {
-         emit_insn (gen_addsi3 (reg, reg, GEN_INT (size / 2 & -4)));
-         emit_insn (gen_addsi3 (reg, reg, GEN_INT (size - (size / 2 & -4))));
+         emit_insn (GEN_ADD3 (reg, reg, GEN_INT (size / 2 & -align)));
+         emit_insn (GEN_ADD3 (reg, reg, GEN_INT (size - (size / 2 & -align))));
        }
       else
        {
@@ -3862,20 +4214,20 @@ output_stack_adjust (size, reg, temp)
             to handle this case, so just abort when we see it.  */
          if (temp < 0)
            abort ();
-         const_reg = gen_rtx_REG (SImode, temp);
+         const_reg = gen_rtx_REG (GET_MODE (reg), temp);
 
          /* If SIZE is negative, subtract the positive value.
             This sometimes allows a constant pool entry to be shared
             between prologue and epilogue code.  */
          if (size < 0)
            {
-             emit_insn (gen_movsi (const_reg, GEN_INT (-size)));
-             emit_insn (gen_subsi3 (reg, reg, const_reg));
+             emit_insn (GEN_MOV (const_reg, GEN_INT (-size)));
+             emit_insn (GEN_SUB3 (reg, reg, const_reg));
            }
          else
            {
-             emit_insn (gen_movsi (const_reg, GEN_INT (size)));
-             emit_insn (gen_addsi3 (reg, reg, const_reg));
+             emit_insn (GEN_MOV (const_reg, GEN_INT (size)));
+             emit_insn (GEN_ADD3 (reg, reg, const_reg));
            }
        }
     }
@@ -3938,21 +4290,18 @@ pop (rn)
 /* Generate code to push the regs specified in the mask.  */
 
 static void
-push_regs (mask, mask2)
-     int mask, mask2;
+push_regs (mask)
+     HOST_WIDE_INT *mask;
 {
   int i;
 
   /* Push PR last; this gives better latencies after the prologue, and
      candidates for the return delay slot when there are no general
      registers pushed.  */
-  for (i = 0; i < 32; i++)
-    if (mask & (1 << i) && i != PR_REG)
-      push (i);
-  for (i = 32; i < FIRST_PSEUDO_REGISTER; i++)
-    if (mask2 & (1 << (i - 32)))
+  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+    if (i != PR_REG && mask[i / 32] & (1 << (i % 32)))
       push (i);
-  if (mask & (1 << PR_REG))
+  if (mask[PR_REG / 32] & (1 << (PR_REG % 32)))
     push (PR_REG);
 }
 
@@ -3963,13 +4312,12 @@ push_regs (mask, mask2)
    function, and if we call another function (we can tell by looking at PR),
    make sure that all the regs it clobbers are safe too.  */
 
-static int
-calc_live_regs (count_ptr, live_regs_mask2)
+static void
+calc_live_regs (count_ptr, live_regs_mask)
      int *count_ptr;
-     int *live_regs_mask2;
+     HOST_WIDE_INT *live_regs_mask;
 {
   int reg;
-  int live_regs_mask = 0;
   int count;
   int interrupt_handler;
   rtx pr_initial;
@@ -3983,7 +4331,8 @@ calc_live_regs (count_ptr, live_regs_mask2)
   else
     interrupt_handler = 0;
 
-  *live_regs_mask2 = 0;
+  for (count = 0; 32 * count < FIRST_PSEUDO_REGISTER; count++)
+    live_regs_mask[count] = 0;
   /* If we can save a lot of saves by switching to double mode, do that.  */
   if (TARGET_SH4 && TARGET_FMOVD && TARGET_FPU_SINGLE)
     for (count = 0, reg = FIRST_FP_REG; reg <= LAST_FP_REG; reg += 2)
@@ -3998,6 +4347,13 @@ calc_live_regs (count_ptr, live_regs_mask2)
   pr_live = (pr_initial
             ? REGNO (pr_initial) != PR_REG
             : regs_ever_live[PR_REG]);
+  /* Force PR to be live if the prologue has to call the SHmedia
+     argument decoder or register saver.  */
+  if (TARGET_SHCOMPACT
+      && ((current_function_args_info.call_cookie
+          & ~ CALL_COOKIE_RET_TRAMP (1))
+         || current_function_has_nonlocal_label))
+    pr_live = 1;
   for (count = 0, reg = FIRST_PSEUDO_REGISTER - 1; reg >= 0; reg--)
     {
       if (reg == PR_REG
@@ -4014,36 +4370,30 @@ calc_live_regs (count_ptr, live_regs_mask2)
          : (/* Only push those regs which are used and need to be saved.  */
             regs_ever_live[reg] && ! call_used_regs[reg]))
        {
-         if (reg >= 32)
-           *live_regs_mask2 |= 1 << (reg - 32);
-         else
-           live_regs_mask |= 1 << reg;
-         count++;
-         if (TARGET_SH4 && TARGET_FMOVD && FP_OR_XD_REGISTER_P (reg))
+         live_regs_mask[reg / 32] |= 1 << (reg % 32);
+         count += GET_MODE_SIZE (REGISTER_NATURAL_MODE (reg));
+
+         if ((TARGET_SH4 || TARGET_SH5) && TARGET_FMOVD
+             && GET_MODE_CLASS (REGISTER_NATURAL_MODE (reg)) == MODE_FLOAT)
            {
              if (FP_REGISTER_P (reg))
                {
                  if (! TARGET_FPU_SINGLE && ! regs_ever_live[reg ^ 1])
                    {
-                     if (reg >= 32)
-                       *live_regs_mask2 |= 1 << ((reg ^ 1) - 32);
-                     else
-                       live_regs_mask |= 1 << (reg ^ 1);
-                     count++;
+                     live_regs_mask[(reg ^ 1) / 32] |= 1 << ((reg ^ 1) % 32);
+                     count += GET_MODE_SIZE (REGISTER_NATURAL_MODE (reg ^ 1));
                    }
                }
-             else /* if (XD_REGISTER_P (reg)) */
+             else if (XD_REGISTER_P (reg))
                {
                  /* Must switch to double mode to access these registers.  */
                  target_flags &= ~FPU_SINGLE_BIT;
-                 count++;
                }
            }
        }
     }
 
-  *count_ptr = count * UNITS_PER_WORD;
-  return live_regs_mask;
+  *count_ptr = count;
 }
 
 /* Code to generate prologue and epilogue sequences */
@@ -4061,12 +4411,33 @@ rounded_frame_size (pushed)
   return ((size + pushed + align - 1) & -align) - pushed;
 }
 
+/* Choose a call-clobbered target-branch register that remains
+   unchanged along the whole function.  We set it up as the return
+   value in the prologue.  */
+int
+sh_media_register_for_return ()
+{
+  int regno;
+  int tr0_used;
+
+  if (! current_function_is_leaf)
+    return -1;
+
+  tr0_used = flag_pic && regs_ever_live[PIC_OFFSET_TABLE_REGNUM];
+
+  for (regno = FIRST_TARGET_REG + tr0_used; regno <= LAST_TARGET_REG; regno++)
+    if (call_used_regs[regno] && ! regs_ever_live[regno])
+      return regno;
+
+  return -1;
+}
+
 void
 sh_expand_prologue ()
 {
-  int live_regs_mask;
+  HOST_WIDE_INT live_regs_mask[(FIRST_PSEUDO_REGISTER + 31) / 32];
   int d, i;
-  int live_regs_mask2;
+  int d_rounding = 0;
   int save_flags = target_flags;
 
   current_function_interrupt
@@ -4076,11 +4447,55 @@ sh_expand_prologue ()
 
   /* We have pretend args if we had an object sent partially in registers
      and partially on the stack, e.g. a large structure.  */
-  output_stack_adjust (-current_function_pretend_args_size,
-                      stack_pointer_rtx, 1);
+  output_stack_adjust (-current_function_pretend_args_size
+                      - current_function_args_info.stack_regs * 8,
+                      stack_pointer_rtx, TARGET_SH5 ? 0 : 1);
 
   extra_push = 0;
 
+  if (TARGET_SHCOMPACT
+      && (current_function_args_info.call_cookie & ~ CALL_COOKIE_RET_TRAMP(1)))
+    {
+      int reg;
+
+      /* First, make all registers with incoming arguments that will
+        be pushed onto the stack live, so that register renaming
+        doesn't overwrite them.  */
+      for (reg = 0; reg < NPARM_REGS (SImode); reg++)
+       if (CALL_COOKIE_STACKSEQ_GET (current_function_args_info.call_cookie)
+           >= NPARM_REGS (SImode) - reg)
+         for (; reg < NPARM_REGS (SImode); reg++)
+           emit_insn (gen_shcompact_preserve_incoming_args
+                      (gen_rtx_REG (SImode, FIRST_PARM_REG + reg)));
+       else if (CALL_COOKIE_INT_REG_GET
+                (current_function_args_info.call_cookie, reg) == 1)
+         emit_insn (gen_shcompact_preserve_incoming_args
+                    (gen_rtx_REG (SImode, FIRST_PARM_REG + reg)));
+
+      emit_move_insn (gen_rtx_REG (Pmode, MACL_REG),
+                     stack_pointer_rtx);
+      emit_move_insn (gen_rtx_REG (SImode, R0_REG),
+                     GEN_INT (current_function_args_info.call_cookie));
+      emit_move_insn (gen_rtx_REG (SImode, MACH_REG),
+                     gen_rtx_REG (SImode, R0_REG));
+    }
+  else if (TARGET_SHMEDIA)
+    {
+      int tr = sh_media_register_for_return ();
+
+      if (tr >= 0)
+       {
+         rtx insn = emit_move_insn (gen_rtx_REG (DImode, tr),
+                                    gen_rtx_REG (DImode, PR_MEDIA_REG));
+
+         /* If this function only exits with sibcalls, this copy
+            will be flagged as dead.  */
+         REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD,
+                                               const0_rtx,
+                                               REG_NOTES (insn));
+       }
+    }
+
   /* This is set by SETUP_VARARGS to indicate that this is a varargs
      routine.  Clear it here so that the next function isn't affected.  */
   if (current_function_anonymous_args)
@@ -4088,7 +4503,7 @@ sh_expand_prologue ()
       current_function_anonymous_args = 0;
 
       /* This is not used by the SH3E calling convention  */
-      if (! TARGET_SH3E && ! TARGET_HITACHI)
+      if (TARGET_SH1 && ! TARGET_SH3E && ! TARGET_HITACHI)
        {
          /* Push arg regs as if they'd been provided by caller in stack.  */
          for (i = 0; i < NPARM_REGS(SImode); i++)
@@ -4108,13 +4523,164 @@ sh_expand_prologue ()
   if (sp_switch)
     emit_insn (gen_sp_switch_1 ());
 
-  live_regs_mask = calc_live_regs (&d, &live_regs_mask2);
+  calc_live_regs (&d, live_regs_mask);
   /* ??? Maybe we could save some switching if we can move a mode switch
      that already happens to be at the function start into the prologue.  */
   if (target_flags != save_flags)
     emit_insn (gen_toggle_sz ());
     
-  push_regs (live_regs_mask, live_regs_mask2);
+  if (TARGET_SH5)
+    {
+      int i;
+      int offset;
+      int align;
+      rtx r0 = gen_rtx_REG (Pmode, R0_REG);
+      int offset_in_r0 = -1;
+      int sp_in_r0 = 0;
+
+      if (d % (STACK_BOUNDARY / BITS_PER_UNIT))
+       d_rounding = ((STACK_BOUNDARY / BITS_PER_UNIT)
+                     - d % (STACK_BOUNDARY / BITS_PER_UNIT));
+
+      offset = d + d_rounding;
+      output_stack_adjust (-offset, stack_pointer_rtx, 1);
+
+      /* We loop twice: first, we save 8-byte aligned registers in the
+        higher addresses, that are known to be aligned.  Then, we
+        proceed to saving 32-bit registers that don't need 8-byte
+        alignment.  */
+      for (align = 1; align >= 0; align--)
+       for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; i--)
+         if (live_regs_mask[i/32] & (1 << (i % 32)))
+           {
+             enum machine_mode mode = REGISTER_NATURAL_MODE (i);
+             int reg = i;
+             rtx reg_rtx, mem_rtx, pre_dec = NULL_RTX;
+
+             if (mode == SFmode && (i % 2) == 1
+                 && ! TARGET_FPU_SINGLE && FP_REGISTER_P (i)
+                 && (live_regs_mask[(i ^ 1) / 32] & (1 << ((i ^ 1) % 32))))
+               {
+                 mode = DFmode;
+                 i--;
+                 reg--;
+               }
+               
+             /* If we're doing the aligned pass and this is not aligned,
+                or we're doing the unaligned pass and this is aligned,
+                skip it.  */
+             if ((GET_MODE_SIZE (mode) % (STACK_BOUNDARY / BITS_PER_UNIT)
+                  == 0) != align)
+               continue;
+
+             offset -= GET_MODE_SIZE (mode);
+
+             reg_rtx = gen_rtx_REG (mode, reg);
+
+             mem_rtx = gen_rtx_MEM (mode,
+                                    gen_rtx_PLUS (Pmode,
+                                                  stack_pointer_rtx,
+                                                  GEN_INT (offset)));
+
+             GO_IF_LEGITIMATE_ADDRESS (mode, XEXP (mem_rtx, 0), try_pre_dec);
+
+             mem_rtx = NULL_RTX;
+
+           try_pre_dec:
+             do
+               if (HAVE_PRE_DECREMENT
+                   && (offset_in_r0 - offset == GET_MODE_SIZE (mode)
+                       || mem_rtx == NULL_RTX
+                       || i == PR_REG || SPECIAL_REGISTER_P (i)))
+                 {
+                   pre_dec = gen_rtx_MEM (mode,
+                                          gen_rtx_PRE_DEC (Pmode, r0));
+
+                   GO_IF_LEGITIMATE_ADDRESS (mode, XEXP (pre_dec, 0),
+                                             pre_dec_ok);
+
+                   pre_dec = NULL_RTX;
+
+                   break;
+
+                 pre_dec_ok:
+                   mem_rtx = NULL_RTX;
+                   offset += GET_MODE_SIZE (mode);
+                 }
+             while (0);
+
+             if (mem_rtx != NULL_RTX)
+               goto addr_ok;
+
+             if (offset_in_r0 == -1)
+               {
+                 emit_move_insn (r0, GEN_INT (offset));
+                 offset_in_r0 = offset;
+               }
+             else if (offset != offset_in_r0)
+               {
+                 emit_move_insn (r0,
+                                 gen_rtx_PLUS
+                                 (Pmode, r0,
+                                  GEN_INT (offset - offset_in_r0)));
+                 offset_in_r0 += offset - offset_in_r0;
+               }
+                                                 
+             if (pre_dec != NULL_RTX)
+               {
+                 if (! sp_in_r0)
+                   {
+                     emit_move_insn (r0,
+                                     gen_rtx_PLUS
+                                     (Pmode, r0, stack_pointer_rtx));
+                     sp_in_r0 = 1;
+                   }
+
+                 offset -= GET_MODE_SIZE (mode);
+                 offset_in_r0 -= GET_MODE_SIZE (mode);
+
+                 mem_rtx = pre_dec;
+               }
+             else if (sp_in_r0)
+               mem_rtx = gen_rtx_MEM (mode, r0);
+             else
+               mem_rtx = gen_rtx_MEM (mode,
+                                      gen_rtx_PLUS (Pmode,
+                                                    stack_pointer_rtx,
+                                                    r0));
+
+             /* We must not use an r0-based address for target-branch
+                registers or for special registers without pre-dec
+                memory addresses, since we store their values in r0
+                first.  */
+             if (TARGET_REGISTER_P (i)
+                 || ((i == PR_REG || SPECIAL_REGISTER_P (i))
+                     && mem_rtx != pre_dec))
+               abort ();
+
+           addr_ok:
+             if (TARGET_REGISTER_P (i)
+                 || ((i == PR_REG || SPECIAL_REGISTER_P (i))
+                     && mem_rtx != pre_dec))
+               {
+                 rtx r0mode = gen_rtx_REG (GET_MODE (reg_rtx), R0_REG);
+
+                 emit_move_insn (r0mode, reg_rtx);
+
+                 offset_in_r0 = -1;
+                 sp_in_r0 = 0;
+
+                 reg_rtx = r0mode;
+               }
+
+             emit_move_insn (mem_rtx, reg_rtx);
+           }
+
+      if (offset != d_rounding)
+       abort ();
+    }
+  else
+    push_regs (live_regs_mask);
 
   if (flag_pic && regs_ever_live[PIC_OFFSET_TABLE_REGNUM])
     {
@@ -4135,6 +4701,19 @@ sh_expand_prologue ()
       while (insn != last);
     }
 
+  if (SHMEDIA_REGS_STACK_ADJUST ())
+    {
+      emit_move_insn (gen_rtx_REG (Pmode, R0_REG),
+                     gen_rtx_SYMBOL_REF (Pmode,
+                                         TARGET_FPU_ANY
+                                         ? "__GCC_push_shmedia_regs"
+                                         : "__GCC_push_shmedia_regs_nofpu"));
+      /* This must NOT go through the PLT, otherwise mach and macl
+        may be clobbered.  */
+      emit_insn (gen_shmedia_save_restore_regs_compact
+                (GEN_INT (-SHMEDIA_REGS_STACK_ADJUST ())));
+    }
+
   if (target_flags != save_flags)
     {
       rtx insn = emit_insn (gen_toggle_sz ());
@@ -4149,26 +4728,48 @@ sh_expand_prologue ()
 
   target_flags = save_flags;
 
-  output_stack_adjust (-rounded_frame_size (d),
-                      stack_pointer_rtx, 1);
+  output_stack_adjust (-rounded_frame_size (d) + d_rounding,
+                      stack_pointer_rtx, TARGET_SH5 ? 0 : 1);
 
   if (frame_pointer_needed)
-    emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx));
+    emit_insn (GEN_MOV (frame_pointer_rtx, stack_pointer_rtx));
+
+  if (TARGET_SHCOMPACT && flag_pic && current_function_args_info.call_cookie)
+    /* We're going to use the PIC register to load the address of the
+       incoming-argument decoder and/or of the return trampoline from
+       the GOT, so make sure the PIC register is preserved and
+       initialized.  */
+    regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
+
+  if (TARGET_SHCOMPACT
+      && (current_function_args_info.call_cookie & ~ CALL_COOKIE_RET_TRAMP(1)))
+    {
+      /* This must NOT go through the PLT, otherwise mach and macl
+        may be clobbered.  */
+      emit_move_insn (gen_rtx_REG (Pmode, R0_REG),
+                     gen_rtx_SYMBOL_REF (Pmode,
+                                         "__GCC_shcompact_incoming_args"));
+      emit_insn (gen_shcompact_incoming_args ());
+    }
 }
 
 void
 sh_expand_epilogue ()
 {
-  int live_regs_mask;
+  HOST_WIDE_INT live_regs_mask[(FIRST_PSEUDO_REGISTER + 31) / 32];
   int d, i;
+  int d_rounding = 0;
 
-  int live_regs_mask2;
   int save_flags = target_flags;
   int frame_size;
 
-  live_regs_mask = calc_live_regs (&d, &live_regs_mask2);
+  calc_live_regs (&d, live_regs_mask);
 
-  frame_size = rounded_frame_size (d);
+  if (TARGET_SH5 && d % (STACK_BOUNDARY / BITS_PER_UNIT))
+    d_rounding = ((STACK_BOUNDARY / BITS_PER_UNIT)
+                 - d % (STACK_BOUNDARY / BITS_PER_UNIT));
+
+  frame_size = rounded_frame_size (d) - d_rounding;
 
   if (frame_pointer_needed)
     {
@@ -4179,7 +4780,7 @@ sh_expand_epilogue ()
         occur after the SP adjustment and clobber data in the local
         frame.  */
       emit_insn (gen_blockage ());
-      emit_insn (gen_movsi (stack_pointer_rtx, frame_pointer_rtx));
+      emit_insn (GEN_MOV (stack_pointer_rtx, frame_pointer_rtx));
     }
   else if (frame_size)
     {
@@ -4191,25 +4792,179 @@ sh_expand_epilogue ()
       output_stack_adjust (frame_size, stack_pointer_rtx, 7);
     }
 
+  if (SHMEDIA_REGS_STACK_ADJUST ())
+    {
+      emit_move_insn (gen_rtx_REG (Pmode, R0_REG),
+                     gen_rtx_SYMBOL_REF (Pmode,
+                                         TARGET_FPU_ANY
+                                         ? "__GCC_pop_shmedia_regs"
+                                         : "__GCC_pop_shmedia_regs_nofpu"));
+      /* This must NOT go through the PLT, otherwise mach and macl
+        may be clobbered.  */
+      emit_insn (gen_shmedia_save_restore_regs_compact
+                (GEN_INT (SHMEDIA_REGS_STACK_ADJUST ())));
+    }
+
   /* Pop all the registers.  */
 
   if (target_flags != save_flags)
     emit_insn (gen_toggle_sz ());
-  if (live_regs_mask & (1 << PR_REG))
+  if (TARGET_SH5)
+    {
+      int offset = d_rounding;
+      int offset_in_r0 = -1;
+      int sp_in_r0 = 0;
+      int align;
+      rtx r0 = gen_rtx_REG (Pmode, R0_REG);
+      
+      /* We loop twice: first, we save 8-byte aligned registers in the
+        higher addresses, that are known to be aligned.  Then, we
+        proceed to saving 32-bit registers that don't need 8-byte
+        alignment.  */
+      for (align = 0; align <= 1; align++)
+       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+         if (live_regs_mask[i/32] & (1 << (i % 32)))
+           {
+             enum machine_mode mode = REGISTER_NATURAL_MODE (i);
+             int reg = i;
+             rtx reg_rtx, mem_rtx, post_inc = NULL_RTX, insn;
+
+             if (mode == SFmode && (i % 2) == 0
+                 && ! TARGET_FPU_SINGLE && FP_REGISTER_P (i)
+                 && (live_regs_mask[(i ^ 1) / 32] & (1 << ((i ^ 1) % 32))))
+               {
+                 mode = DFmode;
+                 i++;
+               }
+
+             /* If we're doing the aligned pass and this is not aligned,
+                or we're doing the unaligned pass and this is aligned,
+                skip it.  */
+             if ((GET_MODE_SIZE (mode) % (STACK_BOUNDARY / BITS_PER_UNIT)
+                  == 0) != align)
+               continue;
+
+             reg_rtx = gen_rtx_REG (mode, reg);
+
+             mem_rtx = gen_rtx_MEM (mode,
+                                    gen_rtx_PLUS (Pmode,
+                                                  stack_pointer_rtx,
+                                                  GEN_INT (offset)));
+
+             GO_IF_LEGITIMATE_ADDRESS (mode, XEXP (mem_rtx, 0), try_post_inc);
+
+             mem_rtx = NULL_RTX;
+
+           try_post_inc:
+             do
+               if (HAVE_POST_INCREMENT
+                   && (offset == offset_in_r0
+                       || (offset + GET_MODE_SIZE (mode) != d + d_rounding
+                           && mem_rtx == NULL_RTX)
+                       || i == PR_REG || SPECIAL_REGISTER_P (i)))
+                 {
+                   post_inc = gen_rtx_MEM (mode,
+                                           gen_rtx_POST_INC (Pmode, r0));
+
+                   GO_IF_LEGITIMATE_ADDRESS (mode, XEXP (post_inc, 0),
+                                             post_inc_ok);
+
+                   post_inc = NULL_RTX;
+
+                   break;
+                   
+                 post_inc_ok:
+                   mem_rtx = NULL_RTX;
+                 }
+             while (0);
+             
+             if (mem_rtx != NULL_RTX)
+               goto addr_ok;
+
+             if (offset_in_r0 == -1)
+               {
+                 emit_move_insn (r0, GEN_INT (offset));
+                 offset_in_r0 = offset;
+               }
+             else if (offset != offset_in_r0)
+               {
+                 emit_move_insn (r0,
+                                 gen_rtx_PLUS
+                                 (Pmode, r0,
+                                  GEN_INT (offset - offset_in_r0)));
+                 offset_in_r0 += offset - offset_in_r0;
+               }
+                 
+             if (post_inc != NULL_RTX)
+               {
+                 if (! sp_in_r0)
+                   {
+                     emit_move_insn (r0,
+                                     gen_rtx_PLUS
+                                     (Pmode, r0, stack_pointer_rtx));
+                     sp_in_r0 = 1;
+                   }
+                 
+                 mem_rtx = post_inc;
+
+                 offset_in_r0 += GET_MODE_SIZE (mode);
+               }
+             else if (sp_in_r0)
+               mem_rtx = gen_rtx_MEM (mode, r0);
+             else
+               mem_rtx = gen_rtx_MEM (mode,
+                                      gen_rtx_PLUS (Pmode,
+                                                    stack_pointer_rtx,
+                                                    r0));
+
+             if ((i == PR_REG || SPECIAL_REGISTER_P (i))
+                 && mem_rtx != post_inc)
+               abort ();
+
+           addr_ok:
+             if ((i == PR_REG || SPECIAL_REGISTER_P (i))
+                 && mem_rtx != post_inc)
+               {
+                 insn = emit_move_insn (r0, mem_rtx);
+                 mem_rtx = r0;
+               }
+             else if (TARGET_REGISTER_P (i))
+               {
+                 rtx r1 = gen_rtx_REG (mode, R1_REG);
+
+                 insn = emit_move_insn (r1, mem_rtx);
+                 mem_rtx = r1;
+               }
+
+             insn = emit_move_insn (reg_rtx, mem_rtx);
+
+             offset += GET_MODE_SIZE (mode);
+           }
+
+      if (offset != d + d_rounding)
+       abort ();
+
+      goto finish;
+    }
+  else
+    d = 0;
+  if (live_regs_mask[PR_REG / 32] & (1 << (PR_REG % 32)))
     pop (PR_REG);
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     {
       int j = (FIRST_PSEUDO_REGISTER - 1) - i;
-      if (j < 32 && (live_regs_mask & (1 << j)) && j != PR_REG)
-       pop (j);
-      else if (j >= 32 && (live_regs_mask2 & (1 << (j - 32))))
+
+      if (j != PR_REG && live_regs_mask[j / 32] & (1 << (j % 32)))
        pop (j);
     }
+ finish:
   if (target_flags != save_flags)
     emit_insn (gen_toggle_sz ());
   target_flags = save_flags;
 
-  output_stack_adjust (extra_push + current_function_pretend_args_size,
+  output_stack_adjust (extra_push + current_function_pretend_args_size
+                      + d + d_rounding
+                      + current_function_args_info.stack_regs * 8,
                       stack_pointer_rtx, 7);
 
   /* Switch back to the normal stack if necessary.  */
@@ -4217,7 +4972,10 @@ sh_expand_epilogue ()
     emit_insn (gen_sp_switch_2 ());
 
   /* Tell flow the insn that pops PR isn't dead.  */
-  if (live_regs_mask & (1 << PR_REG))
+  /* PR_REG will never be live in SHmedia mode, and we don't need to
+     USE PR_MEDIA_REG, since it will be explicitly copied to TR0_REG
+     by the return pattern.  */
+  if (live_regs_mask[PR_REG / 32] & (1 << (PR_REG % 32)))
     emit_insn (gen_rtx_USE (VOIDmode, gen_rtx_REG (SImode, PR_REG)));
 }
 
@@ -4268,12 +5026,57 @@ sh_builtin_saveregs ()
   int bufsize, regno;
   HOST_WIDE_INT alias_set;
 
+  if (TARGET_SH5)
+    {
+      if (n_intregs)
+       {
+         int pushregs = n_intregs;
+
+         while (pushregs < NPARM_REGS (SImode) - 1
+                && (CALL_COOKIE_INT_REG_GET
+                       (current_function_args_info.call_cookie,
+                        NPARM_REGS (SImode) - pushregs)
+                    == 1))
+           {
+             current_function_args_info.call_cookie
+               &= ~ CALL_COOKIE_INT_REG (NPARM_REGS (SImode)
+                                         - pushregs, 1);
+             pushregs++;
+           }
+
+         if (pushregs == NPARM_REGS (SImode))
+           current_function_args_info.call_cookie
+             |= (CALL_COOKIE_INT_REG (0, 1)
+                 | CALL_COOKIE_STACKSEQ (pushregs - 1));
+         else
+           current_function_args_info.call_cookie
+             |= CALL_COOKIE_STACKSEQ (pushregs);
+
+         current_function_pretend_args_size += 8 * n_intregs;
+       }
+      if (TARGET_SHCOMPACT)
+       return const0_rtx;
+    }
+  
+  if (! TARGET_SH3E && ! TARGET_SH4 && ! TARGET_SH5)
+    {
+      error ("__builtin_saveregs not supported by this subtarget");
+      return const0_rtx;
+    }
+
+  if (TARGET_SHMEDIA)
+    n_floatregs = 0;
+
   /* Allocate block of memory for the regs.  */
   /* ??? If n_intregs + n_floatregs == 0, should we allocate at least 1 byte?
      Or can assign_stack_local accept a 0 SIZE argument?  */
   bufsize = (n_intregs * UNITS_PER_WORD) + (n_floatregs * UNITS_PER_WORD);
 
-  regbuf = assign_stack_local (BLKmode, bufsize, 0);
+  if (TARGET_SHMEDIA)
+    regbuf = gen_rtx_MEM (BLKmode,
+                         gen_rtx_REG (Pmode, ARG_POINTER_REGNUM));
+  else
+    regbuf = assign_stack_local (BLKmode, bufsize, 0);
   alias_set = get_varargs_alias_set ();
   set_mem_alias_set (regbuf, alias_set);
 
@@ -4286,6 +5089,10 @@ sh_builtin_saveregs ()
                                         n_floatregs * UNITS_PER_WORD),
                         n_intregs, n_intregs * UNITS_PER_WORD);
 
+  if (TARGET_SHMEDIA)
+    /* Return the address of the regbuf.  */
+    return XEXP (regbuf, 0);
+
   /* Save float args.
      This is optimized to only save the regs that are necessary.  Explicitly
      named args need not be saved.
@@ -4345,7 +5152,7 @@ sh_build_va_list ()
   tree f_next_o, f_next_o_limit, f_next_fp, f_next_fp_limit, f_next_stack;
   tree record;
 
-  if ((! TARGET_SH3E && ! TARGET_SH4) || TARGET_HITACHI)
+  if (TARGET_SH5 || (! TARGET_SH3E && ! TARGET_SH4) || TARGET_HITACHI)
     return ptr_type_node;
 
   record = make_node (RECORD_TYPE);
@@ -4393,6 +5200,20 @@ sh_va_start (stdarg_p, valist, nextarg)
   tree t, u;
   int nfp, nint;
 
+  if (TARGET_SH5)
+    {
+      expand_builtin_saveregs ();
+      /* When the varargs dummy argument is ``passed'' on a register,
+        we don't want std_expand_builtin_va_start() to apply any
+        correction for it, so set stdarg_p so as to pretend there's
+        no such dummy argument.  */
+      if (current_function_args_info.arg_count[(int) SH_ARG_INT]
+         < NPARM_REGS (SImode))
+       stdarg_p = 1;
+      std_expand_builtin_va_start (stdarg_p, valist, nextarg);
+      return;
+    }
+
   if ((! TARGET_SH3E && ! TARGET_SH4) || TARGET_HITACHI)
     {
       std_expand_builtin_va_start (stdarg_p, valist, nextarg);
@@ -4471,7 +5292,7 @@ sh_va_arg (valist, type)
   rsize = (size + UNITS_PER_WORD - 1) & -UNITS_PER_WORD;
   pptr_type_node = build_pointer_type (ptr_type_node);
 
-  if ((TARGET_SH3E || TARGET_SH4) && ! TARGET_HITACHI)
+  if (! TARGET_SH5 && (TARGET_SH3E || TARGET_SH4) && ! TARGET_HITACHI)
     {
       tree f_next_o, f_next_o_limit, f_next_fp, f_next_fp_limit, f_next_stack;
       tree next_o, next_o_limit, next_fp, next_fp_limit, next_stack;
@@ -4596,22 +5417,32 @@ initial_elimination_offset (from, to)
      int to;
 {
   int regs_saved;
+  int regs_saved_rounding = 0;
   int total_saved_regs_space;
   int total_auto_space;
   int save_flags = target_flags;
+  int copy_flags;
+
+  HOST_WIDE_INT live_regs_mask[(FIRST_PSEUDO_REGISTER + 31) / 32];
+  calc_live_regs (&regs_saved, live_regs_mask);
+  regs_saved += SHMEDIA_REGS_STACK_ADJUST ();
+  if (TARGET_SH5 && regs_saved % (STACK_BOUNDARY / BITS_PER_UNIT))
+    regs_saved_rounding = ((STACK_BOUNDARY / BITS_PER_UNIT)
+                          - regs_saved % (STACK_BOUNDARY / BITS_PER_UNIT));
 
-  int live_regs_mask, live_regs_mask2;
-  live_regs_mask = calc_live_regs (&regs_saved, &live_regs_mask2);
-  total_auto_space = rounded_frame_size (regs_saved);
+  total_auto_space = rounded_frame_size (regs_saved) - regs_saved_rounding;
+  copy_flags = target_flags;
   target_flags = save_flags;
 
-  total_saved_regs_space = regs_saved;
+  total_saved_regs_space = regs_saved + regs_saved_rounding;
 
   if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
-    return total_saved_regs_space + total_auto_space;
+    return total_saved_regs_space + total_auto_space
+      + current_function_args_info.byref_regs * 8;
 
   if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
-    return total_saved_regs_space + total_auto_space;
+    return total_saved_regs_space + total_auto_space
+      + current_function_args_info.byref_regs * 8;
 
   /* Initial gap between fp and sp is 0.  */
   if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
@@ -4619,6 +5450,58 @@ initial_elimination_offset (from, to)
 
   if (from == RETURN_ADDRESS_POINTER_REGNUM
       && (to == FRAME_POINTER_REGNUM || to == STACK_POINTER_REGNUM))
+      if (TARGET_SH5)
+       {
+         int i, n = total_saved_regs_space;
+         int align;
+         int pr_reg = TARGET_SHMEDIA ? PR_MEDIA_REG : PR_REG;
+         
+         n += total_auto_space;
+
+         /* If it wasn't saved, there's not much we can do.  */
+         if ((live_regs_mask[pr_reg / 32] & (1 << (pr_reg % 32))) == 0)
+           return n;
+
+         target_flags = copy_flags;
+
+         /* We loop twice: first, check 8-byte aligned registers,
+            that are stored in the higher addresses, that are known
+            to be aligned.  Then, check 32-bit registers that don't
+            need 8-byte alignment.  */
+         for (align = 1; align >= 0; align--)
+           for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; i--)
+             if (live_regs_mask[i/32] & (1 << (i % 32)))
+               {
+                 enum machine_mode mode = REGISTER_NATURAL_MODE (i);
+
+                 if (mode == SFmode && (i % 2) == 1
+                     && ! TARGET_FPU_SINGLE && FP_REGISTER_P (i)
+                     && (live_regs_mask[(i ^ 1) / 32]
+                         & (1 << ((i ^ 1) % 32))))
+                   {
+                     mode = DFmode;
+                     i--;
+                   }
+               
+                 /* If we're doing the aligned pass and this is not aligned,
+                    or we're doing the unaligned pass and this is aligned,
+                    skip it.  */
+                 if ((GET_MODE_SIZE (mode) % (STACK_BOUNDARY / BITS_PER_UNIT)
+                      == 0) != align)
+                   continue;
+
+                 n -= GET_MODE_SIZE (mode);
+
+                 if (i == pr_reg)
+                   {
+                     target_flags = save_flags;
+                     return n;
+                   }
+               }
+
+         abort ();
+       }
+      else
     return total_auto_space;
 
   abort ();
@@ -4858,6 +5741,20 @@ general_movdst_operand (op, mode)
   return general_operand (op, mode);
 }
 
+/* Accept a register, but not a subreg of any kind.  This allows us to
+   avoid pathological cases in reload wrt data movement common in 
+   int->fp conversion.  */
+
+int
+reg_no_subreg_operand (op, mode)
+     register rtx op;
+     enum machine_mode mode;
+{
+  if (GET_CODE (op) == SUBREG)
+    return 0;
+  return register_operand (op, mode);
+}
+
 /* Returns 1 if OP is a normal arithmetic register.  */
 
 int
@@ -4877,6 +5774,7 @@ arith_reg_operand (op, mode)
        return 1;
 
       return (regno != T_REG && regno != PR_REG
+             && ! TARGET_REGISTER_P (regno)
              && (regno != FPUL_REG || TARGET_SH4)
              && regno != MACH_REG && regno != MACL_REG);
     }
@@ -4915,7 +5813,20 @@ arith_operand (op, mode)
   if (arith_reg_operand (op, mode))
     return 1;
 
-  if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_I (INTVAL (op)))
+  if (TARGET_SHMEDIA)
+    {
+      /* FIXME: We should be checking whether the CONST_INT fits in a
+        CONST_OK_FOR_J here, but this causes reload_cse to crash when
+        attempting to transform a sequence of two 64-bit sets of the
+        same register from literal constants into a set and an add,
+        when the difference is too wide for an add.  */
+      if (GET_CODE (op) == CONST_INT
+         || EXTRA_CONSTRAINT_S (op))
+       return 1;
+      else
+       return 0;
+    }
+  else if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_I (INTVAL (op)))
     return 1;
 
   return 0;
@@ -4937,6 +5848,18 @@ arith_reg_or_0_operand (op, mode)
   return 0;
 }
 
+/* Return 1 if OP is a valid source operand for an SHmedia operation
+   that takes either a register or a 6-bit immediate.  */
+
+int
+shmedia_6bit_operand (op, mode)
+     rtx op;
+     enum machine_mode mode;
+{
+  return (arith_reg_operand (op, mode)
+         || (GET_CODE (op) == CONST_INT && CONST_OK_FOR_O (INTVAL (op))));
+}
+
 /* Returns 1 if OP is a valid source operand for a logical operation.  */
 
 int
@@ -4947,7 +5870,14 @@ logical_operand (op, mode)
   if (arith_reg_operand (op, mode))
     return 1;
 
-  if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_L (INTVAL (op)))
+  if (TARGET_SHMEDIA)
+    {
+      if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_P (INTVAL (op)))
+       return 1;
+      else
+       return 0;
+    }
+  else if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_L (INTVAL (op)))
     return 1;
 
   return 0;
@@ -5019,6 +5949,9 @@ fpul_operand (op, mode)
      rtx op;
      enum machine_mode mode;
 {
+  if (TARGET_SHMEDIA)
+    return fp_arith_reg_operand (op, mode);
+
   return (GET_CODE (op) == REG
          && (REGNO (op) == FPUL_REG || REGNO (op) >= FIRST_PSEUDO_REGISTER)
          && GET_MODE (op) == mode);
@@ -5087,6 +6020,50 @@ binary_float_operator (op, mode)
     }
   return 0;
 }
+
+/* Accept pseudos and branch target registers.  */
+int
+target_reg_operand (op, mode)
+     rtx op;
+     enum machine_mode mode;
+{
+  if (mode != DImode
+      || GET_MODE (op) != DImode)
+    return 0;
+
+  if (GET_CODE (op) == SUBREG)
+    op = XEXP (op, 0);
+
+  if (GET_CODE (op) != REG)
+    return 0;
+
+  /* We must protect ourselves from matching pseudos that are virtual
+     register, because they will eventually be replaced with hardware
+     registers that aren't branch-target registers.  */
+  if (REGNO (op) > LAST_VIRTUAL_REGISTER
+      || TARGET_REGISTER_P (REGNO (op)))
+    return 1;
+
+  return 0;
+}
+
+/* Same as target_reg_operand, except that label_refs and symbol_refs
+   are accepted before reload.  */
+int
+target_operand (op, mode)
+     rtx op;
+     enum machine_mode mode;
+{
+  if (mode != DImode)
+    return 0;
+
+  if ((GET_MODE (op) == DImode || GET_MODE (op) == VOIDmode)
+      && EXTRA_CONSTRAINT_T (op))
+    return ! reload_completed;
+
+  return target_reg_operand (op, mode);
+}
+
 \f
 /* Return the destination address of a branch.  */
    
@@ -5480,13 +6457,20 @@ nonpic_symbol_mentioned_p (x)
   register const char *fmt;
   register int i;
 
-  if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF)
+  if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF
+      || GET_CODE (x) == PC)
     return 1;
 
+  /* We don't want to look into the possible MEM location of a
+     CONST_DOUBLE, since we're not going to use it, in general.  */
+  if (GET_CODE (x) == CONST_DOUBLE)
+    return 0;
+
   if (GET_CODE (x) == UNSPEC
       && (XINT (x, 1) == UNSPEC_PIC
          || XINT (x, 1) == UNSPEC_GOT
          || XINT (x, 1) == UNSPEC_GOTOFF
+         || XINT (x, 1) == UNSPEC_GOTPLT
          || XINT (x, 1) == UNSPEC_PLT))
       return 0;
 
@@ -5718,3 +6702,18 @@ sh_pr_n_sets ()
 {
   return REG_N_SETS (PR_REG);
 }
+
+/* SHmedia requires registers for branches, so we can't generate new
+   branches past reload.  */
+static bool
+sh_cannot_modify_jumps_p ()
+{
+  return (TARGET_SHMEDIA && (reload_in_progress || reload_completed));
+}
+
+static bool
+sh_ms_bitfield_layout_p (record_type)
+     tree record_type ATTRIBUTE_UNUSED;
+{
+  return TARGET_SH5;
+}
index 0985a37..c33f6c0 100644 (file)
@@ -43,6 +43,11 @@ extern int code_for_indirect_jump_scratch;
 #define SDB_DELIM ";"
 
 #define CPP_SPEC " \
+%{m5-64media|m5-64media-nofpu|m5-32media|m5-32media-nofpu:-D__SHMEDIA__=1} \
+%{m5-compact|m5-compact-nofpu:-D__SHMEDIA__=0} \
+%{m5-64media|m5-64media-nofpu:-D__SH5__=64 -D__LONG_MAX__=9223372036854775807L} \
+%{m5-32media|m5-32media-nofpu|m5-compact|m5-compact-nofpu:-D__SH5__=32} \
+%{m5-64media-nofpu|m5-32media-nofpu|m5-compact-nofpu:-D__SH4_NOFPU__} \
 %{m1:-D__sh1__} \
 %{m2:-D__sh2__} \
 %{m3:-D__sh3__} \
@@ -51,8 +56,7 @@ extern int code_for_indirect_jump_scratch;
 %{m4-single:-D__SH4_SINGLE__} \
 %{m4-nofpu:-D__sh3__ -D__SH4_NOFPU__} \
 %{m4:-D__SH4__} \
-%{!m1:%{!m2:%{!m3*:%{!m4*:%(cpp_default_cpu_spec)}}}} \
-%{mnomacsave:-D__NOMACSAVE__} \
+%{!m1:%{!m2:%{!m3*:%{!m4*:%{!m5*:%(cpp_default_cpu_spec)}}}}} \
 %{mhitachi:-D__HITACHI__} \
 %(subtarget_cpp_spec) \
 %(subtarget_cpp_ptr_spec) \
@@ -71,7 +75,10 @@ extern int code_for_indirect_jump_scratch;
 #endif
 
 #ifndef SUBTARGET_CPP_PTR_SPEC
-#define SUBTARGET_CPP_PTR_SPEC "-D__SIZE_TYPE__=unsigned\\ int -D__PTRDIFF_TYPE__=int"
+#define SUBTARGET_CPP_PTR_SPEC "\
+%{m5-64media|m5-64media-nofpu|m5-32media|m5-32media-nofpu|m5-compact|m5-compact-nofpu:-D__SIZE_TYPE__=long\\ unsigned\\ int -D__PTRDIFF_TYPE__=long\\ int} \
+%{!m5-64media:%{!m5-64media-nofpu:%{!m5-32media:%{!m5-32media-nofpu:%{!m5-compact:%{!m5-compact-nofpu:-D__SIZE_TYPE__=unsigned\\ int -D__PTRDIFF_TYPE__=int}}}}}} \
+"
 #endif
 
 #define EXTRA_SPECS                                            \
@@ -92,19 +99,18 @@ extern int code_for_indirect_jump_scratch;
 #define CONDITIONAL_REGISTER_USAGE do                                  \
 {                                                                      \
   int regno;                                                           \
-  if (! TARGET_SH4 || ! TARGET_FMOVD)                                  \
+  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno ++)             \
+    if (! VALID_REGISTER_P (regno))                                    \
+      fixed_regs[regno] = call_used_regs[regno] = 1;                   \
+  /* R8 and R9 are call-clobbered on SH5, but not on earlier SH ABIs.  */ \
+  if (TARGET_SH5)                                                      \
+    call_used_regs[FIRST_GENERAL_REG + 8]                              \
+      = call_used_regs[FIRST_GENERAL_REG + 9] = 1;                     \
+  if (TARGET_SHMEDIA)                                                  \
     {                                                                  \
-      for (regno = FIRST_XD_REG; regno <= LAST_XD_REG; regno++)                \
-       fixed_regs[regno] = call_used_regs[regno] = 1;                  \
-      if (! TARGET_SH4)                                                        \
-       {                                                               \
-         if (! TARGET_SH3E)                                            \
-           {                                                           \
-             for (regno = FIRST_FP_REG; regno <= LAST_FP_REG; regno++) \
-               fixed_regs[regno] = call_used_regs[regno] = 1;          \
-             fixed_regs[FPUL_REG] = call_used_regs[FPUL_REG] = 1;      \
-           }                                                           \
-       }                                                               \
+      regno_reg_class[FIRST_GENERAL_REG] = GENERAL_REGS;               \
+      CLEAR_HARD_REG_SET (reg_class_contents[FP0_REGS]);               \
+      regno_reg_class[FIRST_FP_REG] = FP_REGS;                         \
     }                                                                  \
   if (flag_pic)                                                                \
     fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1;                           \
@@ -114,9 +120,16 @@ extern int code_for_indirect_jump_scratch;
       call_used_regs[MACH_REG] = 0;                                    \
       call_used_regs[MACL_REG] = 0;                                    \
     }                                                                  \
-  for (regno = FIRST_GENERAL_REG; regno <= LAST_GENERAL_REG; regno++)  \
-    if (! fixed_regs[regno] && call_used_regs[regno])                  \
-      SET_HARD_REG_BIT (reg_class_contents[SIBCALL_REGS], regno);      \
+  if (TARGET_SHMEDIA)                                                  \
+    {                                                                  \
+      for (regno = FIRST_TARGET_REG; regno <= LAST_TARGET_REG; regno ++)\
+       if (! fixed_regs[regno] && call_used_regs[regno])               \
+         SET_HARD_REG_BIT (reg_class_contents[SIBCALL_REGS], regno);   \
+    }                                                                  \
+  else                                                                 \
+    for (regno = FIRST_GENERAL_REG; regno <= LAST_GENERAL_REG; regno++)        \
+      if (! fixed_regs[regno] && call_used_regs[regno])                        \
+       SET_HARD_REG_BIT (reg_class_contents[SIBCALL_REGS], regno);     \
 } while (0)
 \f
 /* ??? Need to write documentation for all SH options and add it to the
@@ -135,6 +148,7 @@ extern int target_flags;
 #define FPU_SINGLE_BIT (1<<7)
 #define SH4_BIT                (1<<12)
 #define FMOVD_BIT      (1<<4)
+#define SH5_BIT                (1<<0)
 #define SPACE_BIT      (1<<13)
 #define BIGTABLE_BIT   (1<<14)
 #define RELAX_BIT      (1<<15)
@@ -162,10 +176,10 @@ extern int target_flags;
 #define TARGET_SH3 (target_flags & SH3_BIT)
 
 /* Nonzero if we should generate code using type 3E insns.  */
-#define TARGET_SH3E (target_flags & SH3E_BIT)
+#define TARGET_SH3E ((target_flags & SH3E_BIT) && (target_flags & SH1_BIT))
 
 /* Nonzero if the cache line size is 32.  */
-#define TARGET_CACHE32 (target_flags & HARD_SH4_BIT)
+#define TARGET_CACHE32 (target_flags & HARD_SH4_BIT || TARGET_SH5)
 
 /* Nonzero if we schedule for a superscalar implementation.  */
 #define TARGET_SUPERSCALAR (target_flags & HARD_SH4_BIT)
@@ -179,9 +193,38 @@ extern int target_flags;
 /* Nonzero if the default precision of th FPU is single */
 #define TARGET_FPU_SINGLE (target_flags & FPU_SINGLE_BIT)
 
+/* Nonzero if a double-precision FPU is available.  */
+#define TARGET_FPU_DOUBLE (target_flags & SH4_BIT)
+
+/* Nonzero if an FPU is available.  */
+#define TARGET_FPU_ANY (TARGET_SH3E || TARGET_FPU_DOUBLE)
+
 /* Nonzero if we should generate code using type 4 insns.  */
-#define TARGET_SH4 (target_flags & SH4_BIT)
+#define TARGET_SH4 ((target_flags & SH4_BIT) && (target_flags & SH1_BIT))
+
+/* Nonzero if we should generate code for a SH5 CPU (either ISA).  */
+#define TARGET_SH5 (target_flags & SH5_BIT)
+
+/* Nonzero if we should generate code using the SHcompact instruction
+   set and 32-bit ABI.  */
+#define TARGET_SHCOMPACT (TARGET_SH5 && TARGET_SH1)
+
+/* Nonzero if we should generate code using the SHmedia instruction
+   set and ABI.  */
+#define TARGET_SHMEDIA (TARGET_SH5 && ! TARGET_SH1)
 
+/* Nonzero if we should generate code using the SHmedia ISA and 32-bit
+   ABI.  */
+#define TARGET_SHMEDIA32 (TARGET_SH5 && ! TARGET_SH1 \
+                         && (target_flags & SH3E_BIT))
+
+/* Nonzero if we should generate code using the SHmedia ISA and 64-bit
+   ABI.  */
+#define TARGET_SHMEDIA64 (TARGET_SH5 && ! TARGET_SH1 \
+                         && ! (target_flags & SH3E_BIT))
+
+/* Nonzero if we should generate code using SHmedia FPU instructions.  */
+#define TARGET_SHMEDIA_FPU (TARGET_SHMEDIA && TARGET_FPU_DOUBLE)
 /* Nonzero if we should generate fmovd.  */
 #define TARGET_FMOVD (target_flags & FMOVD_BIT)
 
@@ -222,7 +265,7 @@ extern int target_flags;
 
 /* Reset all target-selection flags.  */
 #define TARGET_NONE -(SH1_BIT | SH2_BIT | SH3_BIT | SH3E_BIT | SH4_BIT \
-                     | HARD_SH4_BIT | FPU_SINGLE_BIT)
+                     | HARD_SH4_BIT | FPU_SINGLE_BIT | SH5_BIT)
 
 #define TARGET_SWITCHES                        \
 { {"1",                TARGET_NONE, "" },              \
@@ -241,6 +284,18 @@ extern int target_flags;
   {"4-nofpu",  SH3_BIT|SH2_BIT|SH1_BIT|HARD_SH4_BIT, "" },\
   {"4",                TARGET_NONE, "" },              \
   {"4",                SH4_BIT|SH3E_BIT|SH3_BIT|SH2_BIT|SH1_BIT|HARD_SH4_BIT, "" }, \
+  {"5-64media",        TARGET_NONE, "" },              \
+  {"5-64media", SH5_BIT|SH4_BIT, "Generate 64-bit SHmedia code" }, \
+  {"5-64media-nofpu", TARGET_NONE, "" },       \
+  {"5-64media-nofpu", SH5_BIT, "Generate 64-bit FPU-less SHmedia code" }, \
+  {"5-32media",        TARGET_NONE, "" },              \
+  {"5-32media", SH5_BIT|SH4_BIT|SH3E_BIT, "Generate 32-bit SHmedia code" }, \
+  {"5-32media-nofpu", TARGET_NONE, "" },       \
+  {"5-32media-nofpu", SH5_BIT|SH3E_BIT, "Generate 32-bit FPU-less SHmedia code" }, \
+  {"5-compact",        TARGET_NONE, "" },              \
+  {"5-compact",        SH5_BIT|SH4_BIT|SH3E_BIT|SH3_BIT|SH2_BIT|SH1_BIT|FPU_SINGLE_BIT, "Generate SHcompact code" }, \
+  {"5-compact-nofpu", TARGET_NONE, "" },       \
+  {"5-compact-nofpu", SH5_BIT|SH3_BIT|SH2_BIT|SH1_BIT, "Generate FPU-less SHcompact code" }, \
   {"b",                -LITTLE_ENDIAN_BIT, "" },       \
   {"bigtable",         BIGTABLE_BIT, "" },             \
   {"dalign",   DALIGN_BIT, "" },               \
@@ -279,6 +334,8 @@ extern int assembler_dialect;
 
 #define OVERRIDE_OPTIONS                                               \
 do {                                                                   \
+  int regno;                                                           \
+                                                                       \
   sh_cpu = CPU_SH1;                                                    \
   assembler_dialect = 0;                                               \
   if (TARGET_SH2)                                                      \
@@ -292,16 +349,40 @@ do {                                                                      \
       assembler_dialect = 1;                                           \
       sh_cpu = CPU_SH4;                                                        \
     }                                                                  \
-  if (! TARGET_SH4 || ! TARGET_FMOVD)                                  \
+  if (TARGET_SH5)                                                      \
+    {                                                                  \
+      sh_cpu = CPU_SH5;                                                        \
+      target_flags |= DALIGN_BIT;                                      \
+      if (TARGET_FPU_ANY)                                              \
+       target_flags |= FMOVD_BIT;                                      \
+      if (TARGET_SHMEDIA)                                              \
+       {                                                               \
+         /* There are no delay slots on SHmedia.  */                   \
+         flag_delayed_branch = 0;                                      \
+         /* Relaxation isn't yet supported for SHmedia */              \
+         target_flags &= ~RELAX_BIT;                                   \
+       }                                                               \
+      if (profile_flag || profile_arc_flag)                            \
+       {                                                               \
+         warning ("Profiling is not supported on this target.");       \
+         profile_flag = profile_arc_flag = 0;                          \
+       }                                                               \
+    }                                                                  \
+  else                                                                 \
     {                                                                  \
-      /* Prevent usage of explicit register names for variables                \
-        for registers not present / not addressable in the             \
-        target architecture.  */                                       \
-      int regno;                                                       \
-      for (regno = (TARGET_SH3E) ? 17 : 0;                             \
-          regno <= 24; regno++)                                        \
-       fp_reg_names[regno][0] = 0;                                     \
+       /* Only the sh64-elf assembler fully supports .quad properly.  */\
+       targetm.asm_out.aligned_op.di = NULL;                           \
+       targetm.asm_out.unaligned_op.di = NULL;                         \
     }                                                                  \
+                                                                       \
+  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)              \
+    if (! VALID_REGISTER_P (regno))                                    \
+      sh_register_names[regno][0] = '\0';                              \
+                                                                       \
+  for (regno = 0; regno < ADDREGNAMES_SIZE; regno++)                   \
+    if (! VALID_REGISTER_P (ADDREGNAMES_REGNO (regno)))                        \
+      sh_additional_register_names[regno][0] = '\0';                   \
+                                                                       \
   if (flag_omit_frame_pointer < 0)                                     \
    {                                                                   \
      /* The debugging information is sufficient,                       \
@@ -356,18 +437,34 @@ do {                                                                      \
    Note that this is not necessarily the width of data type `int';
    if using 16-bit ints on a 68000, this would still be 32.
    But on a machine with 16-bit registers, this would be 16.  */
-#define BITS_PER_WORD  32
-#define MAX_BITS_PER_WORD 32
+#define BITS_PER_WORD  (TARGET_SHMEDIA ? 64 : 32)
+#define MAX_BITS_PER_WORD 64
+
+#define MAX_LONG_TYPE_SIZE MAX_BITS_PER_WORD
+
+/* Width in bits of an `int'.  We want just 32-bits, even if words are
+   longer. */
+#define INT_TYPE_SIZE 32
+
+/* Width in bits of a `long'.  */
+#define LONG_TYPE_SIZE (TARGET_SHMEDIA64 ? 64 : 32)
+
+/* Width in bits of a `long long'.  */
+#define LONG_LONG_TYPE_SIZE 64
+
+/* Width in bits of a `long double'.  */
+#define LONG_DOUBLE_TYPE_SIZE 64
 
 /* Width of a word, in units (bytes).  */
-#define UNITS_PER_WORD 4
+#define UNITS_PER_WORD (TARGET_SHMEDIA ? 8 : 4)
+#define MIN_UNITS_PER_WORD 4
 
 /* Width in bits of a pointer.
    See also the macro `Pmode' defined below.  */
-#define POINTER_SIZE  32
+#define POINTER_SIZE  (TARGET_SHMEDIA64 ? 64 : 32)
 
 /* Allocation boundary (in *bits*) for storing arguments in argument list.  */
-#define PARM_BOUNDARY          32
+#define PARM_BOUNDARY          (TARGET_SH5 ? 64 : 32)
 
 /* Boundary (in *bits*) on which stack pointer should be aligned.  */
 #define STACK_BOUNDARY  BIGGEST_ALIGNMENT
@@ -380,7 +477,14 @@ do {                                                                       \
 /* Allocation boundary (in *bits*) for the code of a function.
    32 bit alignment is faster, because instructions are always fetched as a
    pair from a longword boundary.  */
-#define FUNCTION_BOUNDARY  (TARGET_SMALLCODE ? 16 : (1 << CACHE_LOG) * 8)
+#define FUNCTION_BOUNDARY  \
+  (TARGET_SMALLCODE ? 16 << TARGET_SHMEDIA : (1 << CACHE_LOG) * 8)
+
+/* On SH5, the lowest bit is used to indicate SHmedia functions, so
+   the vbit must go into the delta field of
+   pointers-to-member-functions.  */
+#define TARGET_PTRMEMFUNC_VBIT_LOCATION \
+  (TARGET_SH5 ? ptrmemfunc_vbit_in_delta : ptrmemfunc_vbit_in_pfn)
 
 /* Alignment of field after `int : 0' in a structure.  */
 #define EMPTY_FIELD_BOUNDARY  32
@@ -389,7 +493,7 @@ do {                                                                        \
 #define BIGGEST_ALIGNMENT  (TARGET_ALIGN_DOUBLE ? 64 : 32)
 
 /* The best alignment to use in cases where we have a choice.  */
-#define FASTEST_ALIGNMENT 32
+#define FASTEST_ALIGNMENT (TARGET_SH5 ? 64 : 32)
 
 /* Make strings word-aligned so strcpy from constants will be faster.  */
 #define CONSTANT_ALIGNMENT(EXP, ALIGN) \
@@ -440,9 +544,9 @@ do {                                                                        \
 /* The base two logarithm of the known minimum alignment of an insn length.  */
 #define INSN_LENGTH_ALIGNMENT(A_INSN)                                  \
   (GET_CODE (A_INSN) == INSN                                           \
-   ? 1                                                                 \
+   ? 1 << TARGET_SHMEDIA                                               \
    : GET_CODE (A_INSN) == JUMP_INSN || GET_CODE (A_INSN) == CALL_INSN  \
-   ? 1                                                                 \
+   ? 1 << TARGET_SHMEDIA                                               \
    : CACHE_LOG)
 \f
 /* Standard register usage.  */
@@ -467,6 +571,95 @@ do {                                                                       \
        fr4..fr11       fp args in
        fr12..fr15      call saved floating point registers  */
 
+#define MAX_REGISTER_NAME_LENGTH 5
+extern char sh_register_names[][MAX_REGISTER_NAME_LENGTH + 1];
+
+#define SH_REGISTER_NAMES_INITIALIZER                                  \
+{                                                                      \
+  "r0",   "r1",   "r2",   "r3",   "r4",   "r5",   "r6",   "r7",        \
+  "r8",   "r9",   "r10",  "r11",  "r12",  "r13",  "r14",  "r15",       \
+  "r16",  "r17",  "r18",  "r19",  "r20",  "r21",  "r22",  "r23",       \
+  "r24",  "r25",  "r26",  "r27",  "r28",  "r29",  "r30",  "r31",       \
+  "r32",  "r33",  "r34",  "r35",  "r36",  "r37",  "r38",  "r39",       \
+  "r40",  "r41",  "r42",  "r43",  "r44",  "r45",  "r46",  "r47",       \
+  "r48",  "r49",  "r50",  "r51",  "r52",  "r53",  "r54",  "r55",       \
+  "r56",  "r57",  "r58",  "r59",  "r60",  "r61",  "r62",  "r63",       \
+  "fr0",  "fr1",  "fr2",  "fr3",  "fr4",  "fr5",  "fr6",  "fr7",       \
+  "fr8",  "fr9",  "fr10", "fr11", "fr12", "fr13", "fr14", "fr15",      \
+  "fr16", "fr17", "fr18", "fr19", "fr20", "fr21", "fr22", "fr23",      \
+  "fr24", "fr25", "fr26", "fr27", "fr28", "fr29", "fr30", "fr31",      \
+  "fr32", "fr33", "fr34", "fr35", "fr36", "fr37", "fr38", "fr39",      \
+  "fr40", "fr41", "fr42", "fr43", "fr44", "fr45", "fr46", "fr47",      \
+  "fr48", "fr49", "fr50", "fr51", "fr52", "fr53", "fr54", "fr55",      \
+  "fr56", "fr57", "fr58", "fr59", "fr60", "fr61", "fr62", "fr63",      \
+  "tr0",  "tr1",  "tr2",  "tr3",  "tr4",  "tr5",  "tr6",  "tr7",       \
+  "xd0",  "xd2",  "xd4",  "xd6",  "xd8",  "xd10", "xd12", "xd14",      \
+  "gbr",  "ap",          "pr",   "t",    "mach", "macl", "fpul", "fpscr",      \
+  "rap"                                                                        \
+}
+
+#define DEBUG_REGISTER_NAMES SH_REGISTER_NAMES_INITIALIZER
+
+#define REGNAMES_ARR_INDEX_1(index) \
+  (sh_register_names[index])
+#define REGNAMES_ARR_INDEX_2(index) \
+  REGNAMES_ARR_INDEX_1 ((index)), REGNAMES_ARR_INDEX_1 ((index)+1)
+#define REGNAMES_ARR_INDEX_4(index) \
+  REGNAMES_ARR_INDEX_2 ((index)), REGNAMES_ARR_INDEX_2 ((index)+2)
+#define REGNAMES_ARR_INDEX_8(index) \
+  REGNAMES_ARR_INDEX_4 ((index)), REGNAMES_ARR_INDEX_4 ((index)+4)
+#define REGNAMES_ARR_INDEX_16(index) \
+  REGNAMES_ARR_INDEX_8 ((index)), REGNAMES_ARR_INDEX_8 ((index)+8)
+#define REGNAMES_ARR_INDEX_32(index) \
+  REGNAMES_ARR_INDEX_16 ((index)), REGNAMES_ARR_INDEX_16 ((index)+16)
+#define REGNAMES_ARR_INDEX_64(index) \
+  REGNAMES_ARR_INDEX_32 ((index)), REGNAMES_ARR_INDEX_32 ((index)+32)
+
+#define REGISTER_NAMES \
+{ \
+  REGNAMES_ARR_INDEX_64 (0), \
+  REGNAMES_ARR_INDEX_64 (64), \
+  REGNAMES_ARR_INDEX_8 (128), \
+  REGNAMES_ARR_INDEX_8 (136), \
+  REGNAMES_ARR_INDEX_8 (144), \
+  REGNAMES_ARR_INDEX_1 (152) \
+}
+
+#define ADDREGNAMES_SIZE 32
+#define MAX_ADDITIONAL_REGISTER_NAME_LENGTH 4
+extern char sh_additional_register_names[ADDREGNAMES_SIZE] \
+  [MAX_ADDITIONAL_REGISTER_NAME_LENGTH + 1];
+
+#define SH_ADDITIONAL_REGISTER_NAMES_INITIALIZER                       \
+{                                                                      \
+  "dr0",  "dr2",  "dr4",  "dr6",  "dr8",  "dr10", "dr12", "dr14",      \
+  "dr16", "dr18", "dr20", "dr22", "dr24", "dr26", "dr28", "dr30",      \
+  "dr32", "dr34", "dr36", "dr38", "dr40", "dr42", "dr44", "dr46",      \
+  "dr48", "dr50", "dr52", "dr54", "dr56", "dr58", "dr60", "dr62"       \
+}
+
+#define ADDREGNAMES_REGNO(index) \
+  ((index < 32) ? (FIRST_FP_REG + (index) * 2) \
+   : (-1))
+
+#define ADDREGNAMES_ARR_INDEX_1(index) \
+  { (sh_additional_register_names[index]), ADDREGNAMES_REGNO (index) }
+#define ADDREGNAMES_ARR_INDEX_2(index) \
+  ADDREGNAMES_ARR_INDEX_1 ((index)), ADDREGNAMES_ARR_INDEX_1 ((index)+1)
+#define ADDREGNAMES_ARR_INDEX_4(index) \
+  ADDREGNAMES_ARR_INDEX_2 ((index)), ADDREGNAMES_ARR_INDEX_2 ((index)+2)
+#define ADDREGNAMES_ARR_INDEX_8(index) \
+  ADDREGNAMES_ARR_INDEX_4 ((index)), ADDREGNAMES_ARR_INDEX_4 ((index)+4)
+#define ADDREGNAMES_ARR_INDEX_16(index) \
+  ADDREGNAMES_ARR_INDEX_8 ((index)), ADDREGNAMES_ARR_INDEX_8 ((index)+8)
+#define ADDREGNAMES_ARR_INDEX_32(index) \
+  ADDREGNAMES_ARR_INDEX_16 ((index)), ADDREGNAMES_ARR_INDEX_16 ((index)+16)
+
+#define ADDITIONAL_REGISTER_NAMES \
+{                                      \
+  ADDREGNAMES_ARR_INDEX_32 (0)         \
+}
+
 /* Number of actual hardware registers.
    The hardware registers are assigned numbers for the compiler
    from 0 to just below FIRST_PSEUDO_REGISTER.
@@ -476,11 +669,14 @@ do {                                                                      \
 /* There are many other relevant definitions in sh.md's md_constants.  */
 
 #define FIRST_GENERAL_REG R0_REG
-#define LAST_GENERAL_REG (FIRST_GENERAL_REG + 15)
+#define LAST_GENERAL_REG (FIRST_GENERAL_REG + (TARGET_SHMEDIA ? 63 : 15))
 #define FIRST_FP_REG DR0_REG
-#define LAST_FP_REG  (FIRST_FP_REG + 15)
+#define LAST_FP_REG  (FIRST_FP_REG + \
+                     (TARGET_SHMEDIA_FPU ? 63 : TARGET_SH3E ? 15 : -1))
 #define FIRST_XD_REG XD0_REG
-#define LAST_XD_REG  (FIRST_XD_REG + 7)
+#define LAST_XD_REG  (FIRST_XD_REG + ((TARGET_SH4 && TARGET_FMOVD) ? 7 : -1))
+#define FIRST_TARGET_REG TR0_REG
+#define LAST_TARGET_REG  (FIRST_TARGET_REG + (TARGET_SHMEDIA ? 7 : -1))
 
 #define GENERAL_REGISTER_P(REGNO) \
   IN_RANGE ((REGNO), FIRST_GENERAL_REG, LAST_GENERAL_REG)
@@ -504,7 +700,29 @@ do {                                                                       \
   ((REGNO) == GBR_REG || (REGNO) == T_REG \
    || (REGNO) == MACH_REG || (REGNO) == MACL_REG)
 
-#define FIRST_PSEUDO_REGISTER 49
+#define TARGET_REGISTER_P(REGNO) \
+  ((REGNO) >= FIRST_TARGET_REG && (REGNO) <= LAST_TARGET_REG)
+
+#define SHMEDIA_REGISTER_P(REGNO) \
+  (GENERAL_REGISTER_P (REGNO) || FP_REGISTER_P (REGNO) \
+   || TARGET_REGISTER_P (REGNO))
+
+/* This is to be used in CONDITIONAL_REGISTER_USAGE, to mark registers
+   that should be fixed.  */
+#define VALID_REGISTER_P(REGNO) \
+  (SHMEDIA_REGISTER_P (REGNO) || XD_REGISTER_P (REGNO) \
+   || (REGNO) == AP_REG || (REGNO) == RAP_REG \
+   || (TARGET_SH1 && (SPECIAL_REGISTER_P (REGNO) || (REGNO) == PR_REG)) \
+   || (TARGET_SH3E && (REGNO) == FPUL_REG))
+
+/* The mode that should be generally used to store a register by
+   itself in the stack, or to load it back.  */
+#define REGISTER_NATURAL_MODE(REGNO) \
+  (FP_REGISTER_P (REGNO) ? SFmode \
+   : XD_REGISTER_P (REGNO) ? DFmode \
+   : TARGET_SHMEDIA ? DImode : SImode)
+
+#define FIRST_PSEUDO_REGISTER 153
 
 /* 1 for registers that have pervasive standard uses
    and are not available for the register allocator.
@@ -512,20 +730,37 @@ do {                                                                      \
    Mach register is fixed 'cause it's only 10 bits wide for SH1.
    It is 32 bits wide for SH2.  */
 
-#define FIXED_REGISTERS        \
-  { 0,  0,  0,  0,             \
-    0,  0,  0,  0,             \
-    0,  0,  0,  0,             \
-    0,  0,  0,  1,             \
-    1,  1,  1,  1,             \
-    1,  1,  0,  1,             \
-    0,  0,  0,  0,             \
-    0,  0,  0,  0,             \
-    0,  0,  0,  0,             \
-    0,  0,  0,  0,             \
-    0,  0,  0,  0,             \
-    0,  0,  0,  0,             \
-    1,                         \
+#define FIXED_REGISTERS                                                \
+{                                                                      \
+/* Regular registers.  */                                              \
+  0,      0,      0,      0,      0,      0,      0,      0,           \
+  0,      0,      0,      0,      0,      0,      0,      1,           \
+  /* r16 is reserved, r18 is the former pr.  */                                \
+  1,      0,      0,      0,      0,      0,      0,      0,           \
+  /* r24 is reserved for the OS; r25, for the assembler or linker.  */ \
+  /* r26 is a global variable data pointer; r27 is for constants.  */  \
+  1,      1,      1,      1,      0,      0,      0,      0,           \
+  0,      0,      0,      0,      0,      0,      0,      0,           \
+  0,      0,      0,      0,      0,      0,      0,      0,           \
+  0,      0,      0,      0,      0,      0,      0,      0,           \
+  0,      0,      0,      0,      0,      0,      0,      1,           \
+/* FP registers.  */                                                   \
+  0,      0,      0,      0,      0,      0,      0,      0,           \
+  0,      0,      0,      0,      0,      0,      0,      0,           \
+  0,      0,      0,      0,      0,      0,      0,      0,           \
+  0,      0,      0,      0,      0,      0,      0,      0,           \
+  0,      0,      0,      0,      0,      0,      0,      0,           \
+  0,      0,      0,      0,      0,      0,      0,      0,           \
+  0,      0,      0,      0,      0,      0,      0,      0,           \
+  0,      0,      0,      0,      0,      0,      0,      0,           \
+/* Branch target registers.  */                                                \
+  0,      0,      0,      0,      0,      0,      0,      0,           \
+/* XD registers.  */                                                   \
+  0,      0,      0,      0,      0,      0,      0,      0,           \
+/*"gbr",  "ap",          "pr",   "t",    "mach", "macl", "fpul", "fpscr", */   \
+  1,      1,      1,      1,      1,      1,      0,      1,           \
+/*"rap" */                                                             \
+  1,                                                                   \
 }
 
 /* 1 for registers not available across function calls.
@@ -535,22 +770,50 @@ do {                                                                      \
    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,  1,  1,             \
-    1,  1,  1,  1,             \
-    0,  0,  0,  0,             \
-    0,  0,  0,  1,             \
-    1,  0,  1,  1,             \
-    1,  1,  1,  1,             \
-    1,  1,  1,  1,             \
-    1,  1,  1,  1,             \
-    1,  1,  1,  1,             \
-    0,  0,  0,  0,             \
-    1,  1,  1,  1,             \
-    1,  1,  0,  0,             \
-    1,                         \
+#define CALL_USED_REGISTERS                                            \
+{                                                                      \
+/* Regular registers.  */                                              \
+  1,      1,      1,      1,      1,      1,      1,      1,           \
+  /* R8 and R9 are call-clobbered on SH5, but not on earlier SH ABIs.  \
+     Only the lower 32bits of R10-R14 are guaranteed to be preserved   \
+     across SH5 function calls.  */                                    \
+  0,      0,      0,      0,      0,      0,      0,      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,           \
+  1,      1,      1,      1,      0,      0,      0,      0,           \
+  0,      0,      0,      0,      0,      0,      0,      0,           \
+  0,      0,      0,      0,      1,      1,      1,      1,           \
+/* FP registers.  */                                                   \
+  1,      1,      1,      1,      1,      1,      1,      1,           \
+  1,      1,      1,      1,      0,      0,      0,      0,           \
+  1,      1,      1,      1,      1,      1,      1,      1,           \
+  1,      1,      1,      1,      1,      1,      1,      1,           \
+  1,      1,      1,      1,      0,      0,      0,      0,           \
+  0,      0,      0,      0,      0,      0,      0,      0,           \
+  0,      0,      0,      0,      0,      0,      0,      0,           \
+  0,      0,      0,      0,      0,      0,      0,      0,           \
+/* Branch target registers.  */                                                \
+  1,      1,      1,      1,      1,      0,      0,      0,           \
+/* XD registers.  */                                                   \
+  1,      1,      1,      1,      1,      1,      0,      0,           \
+/*"gbr",  "ap",          "pr",   "t",    "mach", "macl", "fpul", "fpscr", */   \
+  1,      1,      0,      1,      1,      1,      1,      1,           \
+/*"rap" */                                                             \
+  1,                                                                   \
 }
 
+/* Only the lower 32-bits of R10-R14 are guaranteed to be preserved
+   across SHcompact function calls.  We can't tell whether a called
+   function is SHmedia or SHcompact, so we assume it may be when
+   compiling SHmedia code with the 32-bit ABI, since that's the only
+   ABI that can be linked with SHcompact code.  */
+#define HARD_REGNO_CALL_PART_CLOBBERED(REGNO,MODE) \
+  (TARGET_SHMEDIA32 \
+   && GET_MODE_SIZE (MODE) > 4 \
+   && (REGNO) >= FIRST_GENERAL_REG + 10 \
+   && (REGNO) <= FIRST_GENERAL_REG + 14)
+
 /* 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
@@ -561,6 +824,8 @@ do {                                                                        \
 #define HARD_REGNO_NREGS(REGNO, MODE) \
    (XD_REGISTER_P (REGNO) \
     ? (GET_MODE_SIZE (MODE) / (2 * UNITS_PER_WORD)) \
+    : (TARGET_SHMEDIA && FP_REGISTER_P (REGNO)) \
+    ? ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD/2 - 1) / (UNITS_PER_WORD/2)) \
     : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)) \
 
 /* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
@@ -580,17 +845,35 @@ do {                                                                      \
    : (REGNO) == FPUL_REG ? (MODE) == SImode || (MODE) == SFmode        \
    : FP_REGISTER_P (REGNO) && (MODE) == SFmode \
    ? 1 \
+   : (MODE) == V2SFmode \
+   ? (FP_REGISTER_P (REGNO) && ((REGNO) - FIRST_FP_REG) % 2 == 0) \
+   : (MODE) == V4SFmode \
+   ? (FP_REGISTER_P (REGNO) && ((REGNO) - FIRST_FP_REG) % 4 == 0) \
+   : (MODE) == V16SFmode \
+   ? (TARGET_SHMEDIA \
+      ? (FP_REGISTER_P (REGNO) && ((REGNO) - FIRST_FP_REG) % 16 == 0) \
+      : (REGNO) == FIRST_XD_REG) \
    : FP_REGISTER_P (REGNO) \
    ? ((MODE) == SFmode \
-      || (TARGET_SH3E && (MODE) == SCmode) \
-      || (((TARGET_SH4 && (MODE) == DFmode) || (MODE) == DCmode) \
+      || (TARGET_SHMEDIA && (MODE) == SImode) \
+      || ((TARGET_SH3E || TARGET_SHMEDIA) && (MODE) == SCmode) \
+      || (((TARGET_SH4 && (MODE) == DFmode) || (MODE) == DCmode \
+          || (TARGET_SHMEDIA && ((MODE) == DFmode || (MODE) == DImode \
+                                 || (MODE) == V2SFmode))) \
          && (((REGNO) - FIRST_FP_REG) & 1) == 0)) \
    : XD_REGISTER_P (REGNO) \
    ? (MODE) == DFmode \
+   : TARGET_REGISTER_P (REGNO) \
+   ? ((MODE) == DImode || (MODE) == SImode) \
    : (REGNO) == PR_REG ? 0                     \
    : (REGNO) == FPSCR_REG ? (MODE) == PSImode \
    : 1)
 
+/* Value is 1 if MODE is a supported vector mode.  */
+#define VECTOR_MODE_SUPPORTED_P(MODE) \
+  (TARGET_FPU_ANY \
+   && ((MODE) == V2SFmode || (MODE) == V4SFmode || (MODE) == V16SFmode))
+
 /* 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,
@@ -602,7 +885,9 @@ do {                                                                        \
 #define MODES_TIEABLE_P(MODE1, MODE2) \
   ((MODE1) == (MODE2) \
    || (GET_MODE_CLASS (MODE1) == GET_MODE_CLASS (MODE2) \
-       && (MODE1) != SFmode && (MODE2) != SFmode))
+       && (TARGET_SHMEDIA ? ((GET_MODE_SIZE (MODE1) <= 4) \
+                             && (GET_MODE_SIZE (MODE2) <= 4)) \
+                         : ((MODE1) != SFmode && (MODE2) != SFmode))))
 
 /* Specify the registers used for certain standard purposes.
    The values of these macros are register numbers.  */
@@ -677,7 +962,7 @@ do {                                                                        \
 #define ARG_POINTER_REGNUM     AP_REG
 
 /* Register in which the static-chain is passed to a function.  */
-#define STATIC_CHAIN_REGNUM    3
+#define STATIC_CHAIN_REGNUM    (TARGET_SH5 ? 1 : 3)
 
 /* The register in which a struct value address is passed.  */
 
@@ -695,13 +980,24 @@ do {                                                                      \
   (TARGET_HITACHI ? 0 : gen_rtx_REG (Pmode, STRUCT_VALUE_REGNUM))
 
 #define RETURN_IN_MEMORY(TYPE) \
-  (TYPE_MODE (TYPE) == BLKmode \
-   || TARGET_HITACHI && TREE_CODE (TYPE) == RECORD_TYPE)
+  (TARGET_SH5 \
+   ? ((TYPE_MODE (TYPE) == BLKmode \
+       ? int_size_in_bytes (TYPE) \
+       : GET_MODE_SIZE (TYPE_MODE (TYPE))) > 8) \
+   : (TYPE_MODE (TYPE) == BLKmode \
+      || TARGET_HITACHI && TREE_CODE (TYPE) == RECORD_TYPE))
 
 /* Don't default to pcc-struct-return, because we have already specified
    exactly how to return structures in the RETURN_IN_MEMORY macro.  */
 
 #define DEFAULT_PCC_STRUCT_RETURN 0
+
+#define SHMEDIA_REGS_STACK_ADJUST() \
+  (TARGET_SHCOMPACT && current_function_has_nonlocal_label \
+   ? (8 * (/* r28-r35 */ 8 + /* r44-r59 */ 16 + /* tr5-tr7 */ 3) \
+      + (TARGET_FPU_ANY ? 4 * (/* fr36 - fr63 */ 28) : 0)) \
+   : 0)
+
 \f
 /* Define the classes of registers for register constraints in the
    machine description.  Also define ranges of constants.
@@ -751,6 +1047,7 @@ enum reg_class
   DF_REGS,
   FPSCR_REGS,
   GENERAL_FP_REGS,
+  TARGET_REGS,
   ALL_REGS,
   LIM_REG_CLASSES
 };
@@ -773,6 +1070,7 @@ enum reg_class
   "DF_REGS",           \
   "FPSCR_REGS",                \
   "GENERAL_FP_REGS",   \
+  "TARGET_REGS",       \
   "ALL_REGS",          \
 }
 
@@ -780,24 +1078,39 @@ enum reg_class
    This is an initializer for a vector of HARD_REG_SET
    of length N_REG_CLASSES.  */
 
-#define REG_CLASS_CONTENTS                             \
-{                                                      \
-  { 0x00000000, 0x00000000 }, /* NO_REGS       */      \
-  { 0x00000001, 0x00000000 }, /* R0_REGS       */      \
-  { 0x00020000, 0x00000000 }, /* PR_REGS       */      \
-  { 0x00040000, 0x00000000 }, /* T_REGS                */      \
-  { 0x00300000, 0x00000000 }, /* MAC_REGS      */      \
-  { 0x00400000, 0x00000000 }, /* FPUL_REGS     */      \
-  /* SIBCALL_REGS is initialized in CONDITIONAL_REGISTER_USAGE.  */ \
-  { 0x00000000, 0x00000000 }, /* SIBCALL_REGS   */     \
-  { 0x0081FFFF, 0x00000000 }, /* GENERAL_REGS  */      \
-  { 0x01000000, 0x00000000 }, /* FP0_REGS      */      \
-  { 0xFF000000, 0x000000FF }, /* FP_REGS       */      \
-  { 0xFF000000, 0x0000FFFF }, /* DF_REGS       */      \
-  { 0x00000000, 0x00010000 }, /* FPSCR_REGS    */      \
-  { 0xFF81FFFF, 0x0000FFFF }, /* GENERAL_FP_REGS */    \
-  { 0xFFFFFFFF, 0x0001FFFF }, /* ALL_REGS      */      \
-}
+#define REG_CLASS_CONTENTS                                             \
+{                                                                      \
+/* NO_REGS:  */                                                                \
+  { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },      \
+/* R0_REGS:  */                                                                \
+  { 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },      \
+/* PR_REGS:  */                                                                \
+  { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00040000 },      \
+/* T_REGS:  */                                                         \
+  { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00080000 },      \
+/* MAC_REGS:  */                                                       \
+  { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00300000 },      \
+/* FPUL_REGS:  */                                                      \
+  { 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00400000 },      \
+/* SIBCALL_REGS: Initialized in CONDITIONAL_REGISTER_USAGE.  */        \
+  { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },      \
+/* GENERAL_REGS:  */                                                   \
+  { 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x01020000 },      \
+/* FP0_REGS:  */                                                       \
+  { 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000 },      \
+/* FP_REGS:  */                                                                \
+  { 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000 },      \
+/* DF_REGS:  */                                                                \
+  { 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x0000ff00 },      \
+/* FPSCR_REGS:  */                                                     \
+  { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00800000 },      \
+/* GENERAL_FP_REGS:  */                                                        \
+  { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0102ff00 },      \
+/* TARGET_REGS:  */                                                    \
+  { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x000000ff },      \
+/* ALL_REGS:  */                                                       \
+  { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff },      \
+}                                                                       
 
 /* The same information, inverted:
    Return the class number of the smallest class containing
@@ -811,20 +1124,36 @@ extern int regno_reg_class[FIRST_PSEUDO_REGISTER];
    rtl to be used as spill registers but prevents the compiler from
    extending the lifetime of these registers.  */
 
-#define SMALL_REGISTER_CLASSES 1
+#define SMALL_REGISTER_CLASSES (! TARGET_SHMEDIA)
 
 /* The order in which register should be allocated.  */
 /* Sometimes FP0_REGS becomes the preferred class of a floating point pseudo,
    and GENERAL_FP_REGS the alternate class.  Since FP0 is likely to be
    spilled or used otherwise, we better have the FP_REGS allocated first.  */
 #define REG_ALLOC_ORDER \
-  { 25,26,27,28,29,30,31,24,32,33,34,35,36,37,38,39,   \
-    40,41,42,43,44,45,46,47,48,                                \
-    1,2,3,7,6,5,4,0,8,9,10,11,12,13,14,                        \
-    22,15,16,17,18,19,20,21,23 }
+  { 65, 66, 67, 68, 69, 70, 71, 64, \
+    72, 73, 74, 75, 76, 77, 78, 79, \
+   136,137,138,139,140,141,142,143, \
+    80, 81, 82, 83, 84, 85, 86, 87, \
+    88, 89, 90, 91, 92, 93, 94, 95, \
+    96, 97, 98, 99,100,101,102,103, \
+   104,105,106,107,108,109,110,111, \
+   112,113,114,115,116,117,118,119, \
+   120,121,122,123,124,125,126,127, \
+   151,  1,  2,  3,  7,  6,  5,  4, \
+     0,  8,  9, 10, 11, 12, 13, 14, \
+    16, 17, 18, 19, 20, 21, 22, 23, \
+    24, 25, 26, 27, 28, 29, 30, 31, \
+    32, 33, 34, 35, 36, 37, 38, 39, \
+    40, 41, 42, 43, 44, 45, 46, 47, \
+    48, 49, 50, 51, 52, 53, 54, 55, \
+    56, 57, 58, 59, 60, 61, 62, 63, \
+   150, 15,145,146,147,144,148,149, \
+   128,129,130,131,132,133,134,135, \
+   152 }
 
 /* The class value for index registers, and the one for base regs.  */
-#define INDEX_REG_CLASS  R0_REGS
+#define INDEX_REG_CLASS  (TARGET_SHMEDIA ? GENERAL_REGS : R0_REGS)
 #define BASE_REG_CLASS  GENERAL_REGS
 
 /* Get reg_class from a letter such as appears in the machine
@@ -840,24 +1169,37 @@ extern const enum reg_class reg_class_from_letter[];
    C is the letter, and VALUE is a constant value.
    Return 1 if VALUE is in the range specified by C.
        I: arithmetic operand -127..128, as used in add, sub, etc
+       J: arithmetic operand -32768..32767, as used in SHmedia movi and shori
        K: shift operand 1,2,8 or 16
        L: logical operand 0..255, as used in and, or, etc.
        M: constant 1
-       N: constant 0  */
+       N: constant 0
+       O: arithmetic operand -32..31, as used in SHmedia beqi, bnei and xori
+       P: arithmetic operand -512..511, as used in SHmedia andi, ori
+*/
 
 #define CONST_OK_FOR_I(VALUE) (((HOST_WIDE_INT)(VALUE))>= -128 \
                               && ((HOST_WIDE_INT)(VALUE)) <= 127)
+#define CONST_OK_FOR_J(VALUE) (((HOST_WIDE_INT)(VALUE)) >= -32768 \
+                              && ((HOST_WIDE_INT)(VALUE)) <= 32767)
 #define CONST_OK_FOR_K(VALUE) ((VALUE)==1||(VALUE)==2||(VALUE)==8||(VALUE)==16)
 #define CONST_OK_FOR_L(VALUE) (((HOST_WIDE_INT)(VALUE))>= 0 \
                               && ((HOST_WIDE_INT)(VALUE)) <= 255)
 #define CONST_OK_FOR_M(VALUE) ((VALUE)==1)
 #define CONST_OK_FOR_N(VALUE) ((VALUE)==0)
+#define CONST_OK_FOR_O(VALUE) (((HOST_WIDE_INT)(VALUE)) >= -32 \
+                              && ((HOST_WIDE_INT)(VALUE)) <= 31)
+#define CONST_OK_FOR_P(VALUE) (((HOST_WIDE_INT)(VALUE)) >= -512 \
+                              && ((HOST_WIDE_INT)(VALUE)) <= 511)
 #define CONST_OK_FOR_LETTER_P(VALUE, C)                \
      ((C) == 'I' ? CONST_OK_FOR_I (VALUE)      \
+    : (C) == 'J' ? CONST_OK_FOR_J (VALUE)      \
     : (C) == 'K' ? CONST_OK_FOR_K (VALUE)      \
     : (C) == 'L' ? CONST_OK_FOR_L (VALUE)      \
     : (C) == 'M' ? CONST_OK_FOR_M (VALUE)      \
     : (C) == 'N' ? CONST_OK_FOR_N (VALUE)      \
+    : (C) == 'O' ? CONST_OK_FOR_O (VALUE)      \
+    : (C) == 'P' ? CONST_OK_FOR_P (VALUE)      \
     : 0)
 
 /* Similar, but for floating constants, and defining letters G and H.
@@ -873,7 +1215,12 @@ extern const enum reg_class reg_class_from_letter[];
    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)
+#define PREFERRED_RELOAD_CLASS(X, CLASS) \
+  ((CLASS) == NO_REGS && TARGET_SHMEDIA \
+   && (GET_CODE (X) == CONST_DOUBLE \
+       || GET_CODE (X) == SYMBOL_REF) \
+   ? GENERAL_REGS \
+   : (CLASS)) \
 
 #define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS,MODE,X) \
   ((((((CLASS) == FP_REGS || (CLASS) == FP0_REGS                       \
@@ -882,6 +1229,7 @@ extern const enum reg_class reg_class_from_letter[];
      || (((CLASS) == GENERAL_REGS || (CLASS) == R0_REGS)               \
         && GET_CODE (X) == REG                                         \
         && FP_REGISTER_P (REGNO (X))))                                 \
+    && ! TARGET_SHMEDIA                                                        \
     && MODE == SFmode)                                                 \
    ? FPUL_REGS                                                         \
    : ((CLASS) == FPUL_REGS                                             \
@@ -891,6 +1239,14 @@ extern const enum reg_class reg_class_from_letter[];
                  || REGNO (X) == T_REG                                 \
                  || system_reg_operand (X, VOIDmode)))))               \
    ? GENERAL_REGS                                                      \
+   : (((CLASS) == FP_REGS || (CLASS) == DF_REGS) && TARGET_SHMEDIA     \
+      && immediate_operand ((X), (MODE)))                              \
+   ? GENERAL_REGS                                                      \
+   : ((CLASS) == TARGET_REGS                                           \
+      || (TARGET_SHMEDIA && (CLASS) == SIBCALL_REGS))                  \
+   ? ((target_operand ((X), (MODE))                                    \
+       && ! target_reg_operand ((X), (MODE)))                          \
+      ? NO_REGS : GENERAL_REGS)                                                \
    : (((CLASS) == MAC_REGS || (CLASS) == PR_REGS)                      \
       && GET_CODE (X) == REG && ! GENERAL_REGISTER_P (REGNO (X))       \
       && (CLASS) != REGNO_REG_CLASS (REGNO (X)))                       \
@@ -898,6 +1254,7 @@ extern const enum reg_class reg_class_from_letter[];
 
 #define SECONDARY_INPUT_RELOAD_CLASS(CLASS,MODE,X)  \
   ((((CLASS) == FP_REGS || (CLASS) == FP0_REGS || (CLASS) == DF_REGS)  \
+    && ! TARGET_SHMEDIA                                                        \
     && immediate_operand ((X), (MODE))                                 \
     && ! ((fp_zero_operand (X) || fp_one_operand (X))                  \
          && (MODE) == SFmode && fldi_ok ()))                           \
@@ -940,17 +1297,17 @@ extern const enum reg_class reg_class_from_letter[];
    These macros are used only in other macro definitions below.  */
 
 #define NPARM_REGS(MODE) \
-  (TARGET_SH3E && (MODE) == SFmode \
-   ? 8 \
+  (TARGET_FPU_ANY && (MODE) == SFmode \
+   ? (TARGET_SH5 ? 12 : 8) \
    : TARGET_SH4 && (GET_MODE_CLASS (MODE) == MODE_FLOAT \
                    || GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT) \
-   ? 8 \
-   : 4)
+   ? (TARGET_SH5 ? 12 : 8) \
+   : (TARGET_SH5 ? 8 : 4))
 
-#define FIRST_PARM_REG (FIRST_GENERAL_REG + 4)
-#define FIRST_RET_REG  FIRST_GENERAL_REG
+#define FIRST_PARM_REG (FIRST_GENERAL_REG + (TARGET_SH5 ? 2 : 4))
+#define FIRST_RET_REG  (FIRST_GENERAL_REG + (TARGET_SH5 ? 2 : 0))
 
-#define FIRST_FP_PARM_REG (FIRST_FP_REG + 4)
+#define FIRST_FP_PARM_REG (FIRST_FP_REG + (TARGET_SH5 ? 0 : 4))
 #define FIRST_FP_RET_REG FIRST_FP_REG
 
 /* Define this if pushing a word on the stack
@@ -990,6 +1347,13 @@ extern const enum reg_class reg_class_from_letter[];
    on the stack.  */
 #define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE)  0
 
+/* Value is the number of bytes of arguments automatically popped when
+   calling a subroutine.
+   CUM is the accumulated argument list.
+
+   On SHcompact, the call trampoline pops arguments off the stack.  */
+#define CALL_POPS_ARGS(CUM) (TARGET_SHCOMPACT ? (CUM).stack_regs * 8 : 0)
+
 /* Nonzero if we do not know how to pass TYPE solely in registers.
    Values that come in registers with inconvenient padding are stored
    to memory at the function start.  */
@@ -1001,11 +1365,11 @@ extern const enum reg_class reg_class_from_letter[];
 /* Some subroutine macros specific to this machine.  */
 
 #define BASE_RETURN_VALUE_REG(MODE) \
-  ((TARGET_SH3E && ((MODE) == SFmode))                 \
+  ((TARGET_FPU_ANY && ((MODE) == SFmode))                      \
    ? FIRST_FP_RET_REG                                  \
-   : TARGET_SH3E && (MODE) == SCmode           \
+   : TARGET_FPU_ANY && (MODE) == SCmode                \
    ? FIRST_FP_RET_REG                                  \
-   : (TARGET_SH4                                       \
+   : (TARGET_FPU_DOUBLE                                        \
       && ((MODE) == DFmode || (MODE) == SFmode         \
          || (MODE) == DCmode || (MODE) == SCmode ))    \
    ? FIRST_FP_RET_REG                                  \
@@ -1038,7 +1402,7 @@ extern const enum reg_class reg_class_from_letter[];
                 || TREE_CODE (VALTYPE) == CHAR_TYPE                    \
                 || TREE_CODE (VALTYPE) == REAL_TYPE                    \
                 || TREE_CODE (VALTYPE) == OFFSET_TYPE))                \
-           ? SImode : TYPE_MODE (VALTYPE)),                            \
+           ? (TARGET_SHMEDIA ? DImode : SImode) : TYPE_MODE (VALTYPE)), \
           BASE_RETURN_VALUE_REG (TYPE_MODE (VALTYPE)))
      
 /* Define how to find the value returned by a library function
@@ -1048,13 +1412,16 @@ extern const enum reg_class reg_class_from_letter[];
 
 /* 1 if N is a possible register number for a function value.  */
 #define FUNCTION_VALUE_REGNO_P(REGNO) \
-  ((REGNO) == FIRST_RET_REG || (TARGET_SH3E && (REGNO) == FIRST_FP_RET_REG))
+  ((REGNO) == FIRST_RET_REG || (TARGET_SH3E && (REGNO) == FIRST_FP_RET_REG) \
+   || (TARGET_SHMEDIA_FPU && (REGNO) == FIRST_FP_RET_REG))
 
 /* 1 if N is a possible register number for function argument passing.  */
 #define FUNCTION_ARG_REGNO_P(REGNO) \
-  (((REGNO) >= FIRST_PARM_REG && (REGNO) < (FIRST_PARM_REG + 4))        \
-   || (TARGET_SH3E                                                      \
-       && (REGNO) >= FIRST_FP_PARM_REG && (REGNO) < (FIRST_FP_PARM_REG + 8)))
+  (((REGNO) >= FIRST_PARM_REG && (REGNO) < (FIRST_PARM_REG             \
+                                           + NPARM_REGS (SImode))      \
+   || (TARGET_FPU_ANY                                                   \
+       && (REGNO) >= FIRST_FP_PARM_REG && (REGNO) < (FIRST_FP_PARM_REG \
+                                                    + NPARM_REGS (SFmode)))))
 \f
 /* Define a data type for recording info about an argument list
    during the scan of that argument list.  This data type should
@@ -1071,15 +1438,112 @@ enum sh_arg_class { SH_ARG_INT = 0, SH_ARG_FLOAT = 1 };
 struct sh_args {
     int arg_count[2];
     int force_mem;
+  /* Non-zero if a prototype is available for the function.  */
+    int prototype_p;
+  /* The number of an odd floating-point register, that should be used
+     for the next argument of type float.  */
+    int free_single_fp_reg;
+  /* Whether we're processing an outgoing function call.  */
+    int outgoing;
+  /* The number of general-purpose registers that should have been
+     used to pass partial arguments, that are passed totally on the
+     stack.  On SHcompact, a call trampoline will pop them off the
+     stack before calling the actual function, and, if the called
+     function is implemented in SHcompact mode, the incoming arguments
+     decoder will push such arguments back onto the stack.  For
+     incoming arguments, STACK_REGS also takes into account other
+     arguments passed by reference, that the decoder will also push
+     onto the stack.  */
+    int stack_regs;
+  /* The number of general-purpose registers that should have been
+     used to pass arguments, if the arguments didn't have to be passed
+     by reference.  */
+    int byref_regs;
+  /* Set by SHCOMPACT_BYREF if the current argument is to be passed by
+     reference.  */
+    int byref;
+
+  /* call_cookie is a bitmask used by call expanders, as well as
+     function prologue and epilogues, to allow SHcompact to comply
+     with the SH5 32-bit ABI, that requires 64-bit registers to be
+     used even though only the lower 32-bit half is visible in
+     SHcompact mode.  The strategy is to call SHmedia trampolines.
+
+     The alternatives for each of the argument-passing registers are
+     (a) leave it unchanged; (b) pop it off the stack; (c) load its
+     contents from the address in it; (d) add 8 to it, storing the
+     result in the next register, then (c); (e) copy it from some
+     floating-point register,
+
+     Regarding copies from floating-point registers, r2 may only be
+     copied from dr0.  r3 may be copied from dr0 or dr2.  r4 maybe
+     copied from dr0, dr2 or dr4.  r5 maybe copied from dr0, dr2,
+     dr4 or dr6.  r6 may be copied from dr0, dr2, dr4, dr6 or dr8.
+     r7 through to r9 may be copied from dr0, dr2, dr4, dr8, dr8 or
+     dr10.
+
+     The bit mask is structured as follows:
+
+     - 1 bit to tell whether to set up a return trampoline.
+
+     - 3 bits to count the number consecutive registers to pop off the
+       stack.
+
+     - 4 bits for each of r9, r8, r7 and r6.
+
+     - 3 bits for each of r5, r4, r3 and r2.
+
+     - 3 bits set to 0 (the most significant ones)
+
+        3           2            1           0
+       1098 7654 3210 9876 5432 1098 7654 3210
+       FLPF LPFL PFLP FFLP FFLP FFLP FFLP SSST
+       2223 3344 4555 6666 7777 8888 9999 SSS-
+
+     - If F is set, the register must be copied from an FP register,
+       whose number is encoded in the remaining bits.
+
+     - Else, if L is set, the register must be loaded from the address
+       contained in it.  If the P bit is *not* set, the address of the
+       following dword should be computed first, and stored in the
+       following register.
+
+     - Else, if P is set, the register alone should be popped off the
+       stack.
+
+     - After all this processing, the number of registers represented
+       in SSS will be popped off the stack.  This is an optimization
+       for pushing/popping consecutive registers, typically used for
+       varargs and large arguments partially passed in registers.
+
+     - If T is set, a return trampoline will be set up for 64-bit
+     return values to be split into 2 32-bit registers.  */
+#define CALL_COOKIE_RET_TRAMP_SHIFT 0
+#define CALL_COOKIE_RET_TRAMP(VAL) ((VAL) << CALL_COOKIE_RET_TRAMP_SHIFT)
+#define CALL_COOKIE_STACKSEQ_SHIFT 1
+#define CALL_COOKIE_STACKSEQ(VAL) ((VAL) << CALL_COOKIE_STACKSEQ_SHIFT)
+#define CALL_COOKIE_STACKSEQ_GET(COOKIE) \
+  (((COOKIE) >> CALL_COOKIE_STACKSEQ_SHIFT) & 7)
+#define CALL_COOKIE_INT_REG_SHIFT(REG) \
+  (4 * (7 - (REG)) + (((REG) <= 2) ? ((REG) - 2) : 1) + 3)
+#define CALL_COOKIE_INT_REG(REG, VAL) \
+  ((VAL) << CALL_COOKIE_INT_REG_SHIFT (REG))
+#define CALL_COOKIE_INT_REG_GET(COOKIE, REG) \
+  (((COOKIE) >> CALL_COOKIE_INT_REG_SHIFT (REG)) & ((REG) < 4 ? 7 : 15))
+    long call_cookie;
 };
 
 #define CUMULATIVE_ARGS  struct sh_args
 
 #define GET_SH_ARG_CLASS(MODE) \
-  ((TARGET_SH3E && (MODE) == SFmode) \
+  ((TARGET_FPU_ANY && (MODE) == SFmode) \
    ? SH_ARG_FLOAT \
-   : TARGET_SH4 && (GET_MODE_CLASS (MODE) == MODE_FLOAT \
-                   || GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT) \
+   /* There's no mention of complex float types in the SH5 ABI, so we
+      should presumably handle them as aggregate types.  */ \
+   : TARGET_SH5 && GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT \
+   ? SH_ARG_INT \
+   : TARGET_FPU_DOUBLE && (GET_MODE_CLASS (MODE) == MODE_FLOAT \
+                          || GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT) \
    ? SH_ARG_FLOAT : SH_ARG_INT)
 
 #define ROUND_ADVANCE(SIZE) \
@@ -1116,7 +1580,48 @@ struct sh_args {
     (CUM).force_mem                                            \
       = (TARGET_HITACHI && FNTYPE                              \
         && aggregate_value_p (TREE_TYPE (FNTYPE)));            \
+    (CUM).prototype_p = (FNTYPE) && TYPE_ARG_TYPES (FNTYPE);   \
+    (CUM).arg_count[(int) SH_ARG_INT]                          \
+      = (TARGET_SH5 && (FNTYPE)                                        \
+        && aggregate_value_p (TREE_TYPE (FNTYPE)));            \
+    (CUM).free_single_fp_reg = 0;                              \
+    (CUM).outgoing = 1;                                                \
+    (CUM).stack_regs = 0;                                      \
+    (CUM).byref_regs = 0;                                      \
+    (CUM).byref = 0;                                           \
+    (CUM).call_cookie                                          \
+      = (CALL_COOKIE_RET_TRAMP                                 \
+        (TARGET_SHCOMPACT && (FNTYPE)                          \
+         && (CUM).arg_count[(int) SH_ARG_INT] == 0             \
+         && (TYPE_MODE (TREE_TYPE (FNTYPE)) == BLKmode         \
+             ? int_size_in_bytes (TREE_TYPE (FNTYPE))          \
+             : GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (FNTYPE)))) > 4 \
+         && (BASE_RETURN_VALUE_REG (TYPE_MODE (TREE_TYPE       \
+                                               (FNTYPE)))      \
+             == FIRST_RET_REG)));                              \
+  } while (0)
+
+#define INIT_CUMULATIVE_LIBCALL_ARGS(CUM, MODE, LIBNAME) \
+  do {                                                         \
+    INIT_CUMULATIVE_ARGS ((CUM), NULL_TREE, (LIBNAME), 0);     \
+    (CUM).call_cookie                                          \
+      = (CALL_COOKIE_RET_TRAMP                                 \
+        (TARGET_SHCOMPACT && GET_MODE_SIZE (MODE) > 4          \
+         && BASE_RETURN_VALUE_REG (MODE) == FIRST_RET_REG));   \
+  } while (0)
+
+#define INIT_CUMULATIVE_INCOMING_ARGS(CUM, FNTYPE, LIBNAME) \
+  do {                                                         \
+    INIT_CUMULATIVE_ARGS ((CUM), (FNTYPE), (LIBNAME), 0);      \
+    (CUM).outgoing = 0;                                                \
   } while (0)
+/* FIXME: This is overly conservative.  A SHcompact function that
+   receives arguments ``by reference'' will have them stored in its
+   own stack frame, so it must not pass pointers or references to
+   these arguments to other functions by means of sibling calls.  */
+#define FUNCTION_OK_FOR_SIBCALL(DECL) \
+  (! TARGET_SHCOMPACT || current_function_args_info.stack_regs == 0)
 
 /* Update the data in CUM to advance over an argument
    of mode MODE and data type TYPE.
@@ -1126,6 +1631,109 @@ struct sh_args {
 #define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED)   \
  if ((CUM).force_mem)                                  \
    (CUM).force_mem = 0;                                        \
+ else if (TARGET_SH5)                                  \
+   {                                                   \
+     tree TYPE_ = ((CUM).byref && (TYPE)               \
+                  ? TREE_TYPE (TYPE)                   \
+                  : (TYPE));                           \
+     enum machine_mode MODE_ = ((CUM).byref && (TYPE)  \
+                               ? TYPE_MODE (TYPE_)     \
+                               : (MODE));              \
+     int dwords = (((CUM).byref                                \
+                   ? (CUM).byref                       \
+                   : (MODE_) == BLKmode                \
+                   ? int_size_in_bytes (TYPE_)         \
+                   : GET_MODE_SIZE (MODE_)) + 7) / 8;  \
+     int numregs = MIN (dwords, NPARM_REGS (SImode)    \
+                       - (CUM).arg_count[(int) SH_ARG_INT]); \
+                                                       \
+     if (numregs)                                      \
+       {                                               \
+        (CUM).arg_count[(int) SH_ARG_INT] += numregs;  \
+        if (TARGET_SHCOMPACT                           \
+            && SHCOMPACT_FORCE_ON_STACK (MODE_, TYPE_)) \
+          (CUM).call_cookie                            \
+            |= CALL_COOKIE_INT_REG (((CUM).arg_count[(int) SH_ARG_INT] \
+                                     - numregs), 1);   \
+        else if ((CUM).byref)                          \
+          {                                            \
+            if (! (CUM).outgoing)                      \
+              (CUM).stack_regs += numregs;             \
+            (CUM).byref_regs += numregs;               \
+            (CUM).byref = 0;                           \
+            do                                         \
+              (CUM).call_cookie                        \
+                |= CALL_COOKIE_INT_REG (((CUM).arg_count[(int) SH_ARG_INT] \
+                                         - numregs), 2); \
+            while (--numregs);                         \
+            (CUM).call_cookie                          \
+              |= CALL_COOKIE_INT_REG (((CUM).arg_count[(int) SH_ARG_INT] \
+                                       - 1), 1); \
+          }                                            \
+        else if (dwords > numregs)                     \
+          {                                            \
+            int pushregs = numregs;                    \
+                                                       \
+            if (TARGET_SHCOMPACT)                      \
+              (CUM).stack_regs += numregs;             \
+            while (pushregs < NPARM_REGS (SImode) - 1  \
+                   && (CALL_COOKIE_INT_REG_GET         \
+                       ((CUM).call_cookie,             \
+                       NPARM_REGS (SImode) - pushregs) \
+                       == 1))                          \
+              {                                        \
+                (CUM).call_cookie                      \
+                  &= ~ CALL_COOKIE_INT_REG (NPARM_REGS (SImode) \
+                                            - pushregs, 1); \
+                pushregs++;                            \
+              }                                        \
+            if (numregs == NPARM_REGS (SImode))        \
+              (CUM).call_cookie                        \
+                |= CALL_COOKIE_INT_REG (0, 1)          \
+                   | CALL_COOKIE_STACKSEQ (numregs - 1); \
+            else                                       \
+              (CUM).call_cookie                        \
+                |= CALL_COOKIE_STACKSEQ (numregs);     \
+          }                                            \
+       }                                               \
+     if (GET_SH_ARG_CLASS (MODE_) == SH_ARG_FLOAT      \
+        && ((NAMED) || ! (CUM).prototype_p))           \
+       {                                               \
+        if ((MODE_) == SFmode && (CUM).free_single_fp_reg) \
+          (CUM).free_single_fp_reg = 0;                \
+        else if ((CUM).arg_count[(int) SH_ARG_FLOAT]   \
+                 < NPARM_REGS (SFmode))                \
+          {                                            \
+            int numfpregs                              \
+              = MIN ((GET_MODE_SIZE (MODE_) + 7) / 8 * 2, \
+                     NPARM_REGS (SFmode)               \
+                     - (CUM).arg_count[(int) SH_ARG_FLOAT]); \
+                                                       \
+            (CUM).arg_count[(int) SH_ARG_FLOAT] += numfpregs; \
+                                                       \
+            if (TARGET_SHCOMPACT && ! (CUM).prototype_p) \
+              {                                        \
+                if ((CUM).outgoing && numregs > 0)     \
+                  do                                   \
+                    {                                  \
+                      (CUM).call_cookie                \
+                        |= (CALL_COOKIE_INT_REG        \
+                            ((CUM).arg_count[(int) SH_ARG_INT] \
+                             - numregs + ((numfpregs - 2) / 2), \
+                             4 + ((CUM).arg_count[(int) SH_ARG_FLOAT] \
+                                  - numfpregs) / 2));  \
+                    }                                  \
+                  while (numfpregs -= 2);              \
+              }                                        \
+            else if ((MODE_) == SFmode && (NAMED)      \
+                     && ((CUM).arg_count[(int) SH_ARG_FLOAT] \
+                         < NPARM_REGS (SFmode)))       \
+              (CUM).free_single_fp_reg                 \
+                = FIRST_FP_PARM_REG - numfpregs        \
+                + (CUM).arg_count[(int) SH_ARG_FLOAT] + 1; \
+          }                                            \
+       }                                               \
+   }                                                   \
  else if (! TARGET_SH4 || PASS_IN_REG_P ((CUM), (MODE), (TYPE))) \
    ((CUM).arg_count[(int) GET_SH_ARG_CLASS (MODE)]     \
     = (ROUND_REG ((CUM), (MODE))                       \
@@ -1170,16 +1778,136 @@ struct sh_args {
    its data type forbids.  */
 
 #define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
-  ((PASS_IN_REG_P ((CUM), (MODE), (TYPE))                              \
+  ((! TARGET_SH5 \
+    && PASS_IN_REG_P ((CUM), (MODE), (TYPE))                           \
     && ((NAMED)                                                                \
        || (! TARGET_HITACHI && (TARGET_SH3E || ! current_function_varargs)))) \
    ? gen_rtx_REG ((MODE),                                              \
                  ((BASE_ARG_REG (MODE) + ROUND_REG ((CUM), (MODE)))    \
                   ^ ((MODE) == SFmode && TARGET_SH4                    \
                      && TARGET_LITTLE_ENDIAN != 0)))                   \
+   : TARGET_SH5                                                                \
+   ? ((MODE) == VOIDmode && TARGET_SHCOMPACT                           \
+      ? GEN_INT ((CUM).call_cookie)                                    \
+      /* The following test assumes unnamed arguments are promoted to  \
+        DFmode.  */                                                    \
+      : (MODE) == SFmode && (CUM).free_single_fp_reg                   \
+      ? SH5_PROTOTYPED_FLOAT_ARG ((CUM), (MODE), (CUM).free_single_fp_reg) \
+      : (GET_SH_ARG_CLASS (MODE) == SH_ARG_FLOAT                       \
+         && ((NAMED) || ! (CUM).prototype_p)                           \
+         && (CUM).arg_count[(int) SH_ARG_FLOAT] < NPARM_REGS (SFmode)) \
+      ? ((! (CUM).prototype_p && TARGET_SHMEDIA)                       \
+        ? SH5_PROTOTYPELESS_FLOAT_ARG ((CUM), (MODE))                  \
+        : SH5_PROTOTYPED_FLOAT_ARG ((CUM), (MODE),                     \
+                                    FIRST_FP_PARM_REG                  \
+                                    + (CUM).arg_count[(int) SH_ARG_FLOAT])) \
+      : ((CUM).arg_count[(int) SH_ARG_INT] < NPARM_REGS (SImode)       \
+        && (! TARGET_SHCOMPACT                                         \
+            || (! SHCOMPACT_FORCE_ON_STACK ((MODE), (TYPE))            \
+                && ! SH5_WOULD_BE_PARTIAL_NREGS ((CUM), (MODE),        \
+                                                 (TYPE), (NAMED)))))   \
+      ? gen_rtx_REG ((MODE), (FIRST_PARM_REG                           \
+                             + (CUM).arg_count[(int) SH_ARG_INT]))     \
+      : 0)                                                             \
    : 0)
 
-#define PRETEND_OUTGOING_VARARGS_NAMED (! TARGET_HITACHI)
+/* Whether an argument must be passed by reference.  On SHcompact, we
+   pretend arguments wider than 32-bits that would have been passed in
+   registers are passed by reference, so that an SHmedia trampoline
+   loads them into the full 64-bits registers.  */
+#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM,MODE,TYPE,NAMED) \
+  (MUST_PASS_IN_STACK ((MODE), (TYPE)) \
+   || SHCOMPACT_BYREF ((CUM), (MODE), (TYPE), (NAMED)))
+
+#define SHCOMPACT_BYREF(CUM, MODE, TYPE, NAMED) \
+  ((CUM).byref                                                         \
+   = (TARGET_SHCOMPACT                                                 \
+      && (CUM).arg_count[(int) SH_ARG_INT] < NPARM_REGS (SImode)       \
+      && (! (NAMED) || GET_SH_ARG_CLASS (MODE) == SH_ARG_INT           \
+         || (GET_SH_ARG_CLASS (MODE) == SH_ARG_FLOAT                   \
+             && ((CUM).arg_count[(int) SH_ARG_FLOAT]                   \
+                 >= NPARM_REGS (SFmode))))                             \
+      && ((MODE) == BLKmode ? int_size_in_bytes (TYPE)                 \
+         : GET_MODE_SIZE (MODE)) > 4                                   \
+      && ! SHCOMPACT_FORCE_ON_STACK ((MODE), (TYPE))                   \
+      && ! SH5_WOULD_BE_PARTIAL_NREGS ((CUM), (MODE),                  \
+                                      (TYPE), (NAMED)))                \
+      ? ((MODE) == BLKmode ? int_size_in_bytes (TYPE)                  \
+        : GET_MODE_SIZE (MODE))                                        \
+      : 0)
+
+/* If an argument of size 5, 6 or 7 bytes is to be passed in a 64-bit
+   register in SHcompact mode, it must be padded in the most
+   significant end.  This means that passing it by reference wouldn't
+   pad properly on a big-endian machine.  In this particular case, we
+   pass this argument on the stack, in a way that the call trampoline
+   will load its value into the appropriate register.  */
+#define SHCOMPACT_FORCE_ON_STACK(MODE,TYPE) \
+  ((MODE) == BLKmode \
+   && TARGET_SHCOMPACT \
+   && ! TARGET_LITTLE_ENDIAN \
+   && int_size_in_bytes (TYPE) > 4 \
+   && int_size_in_bytes (TYPE) < 8)
+
+/* Minimum alignment for an argument to be passed by callee-copy
+   reference.  We need such arguments to be aligned to 8 byte
+   boundaries, because they'll be loaded using quad loads.  */
+#define SH_MIN_ALIGN_FOR_CALLEE_COPY (8 * BITS_PER_UNIT)
+
+#define FUNCTION_ARG_CALLEE_COPIES(CUM,MODE,TYPE,NAMED) \
+  ((CUM).outgoing                                                      \
+   && (((MODE) == BLKmode ? TYPE_ALIGN (TYPE)                          \
+       : GET_MODE_ALIGNMENT (MODE))                                    \
+       % SH_MIN_ALIGN_FOR_CALLEE_COPY == 0))
+
+/* The SH5 ABI requires floating-point arguments to be passed to
+   functions without a prototype in both an FP register and a regular
+   register or the stack.  When passing the argument in both FP and
+   general-purpose registers, list the FP register first.  */
+#define SH5_PROTOTYPELESS_FLOAT_ARG(CUM,MODE) \
+  (gen_rtx_PARALLEL                                                    \
+   ((MODE),                                                            \
+    gen_rtvec (2,                                                      \
+              gen_rtx_EXPR_LIST                                        \
+              (VOIDmode,                                               \
+               ((CUM).arg_count[(int) SH_ARG_INT] < NPARM_REGS (SImode) \
+                ? gen_rtx_REG ((MODE), FIRST_FP_PARM_REG               \
+                               + (CUM).arg_count[(int) SH_ARG_FLOAT])  \
+                : NULL_RTX),                                           \
+               const0_rtx),                                            \
+              gen_rtx_EXPR_LIST                                        \
+              (VOIDmode,                                               \
+               ((CUM).arg_count[(int) SH_ARG_INT] < NPARM_REGS (SImode) \
+                ? gen_rtx_REG ((MODE), FIRST_PARM_REG                  \
+                               + (CUM).arg_count[(int) SH_ARG_INT])    \
+                : gen_rtx_REG ((MODE), FIRST_FP_PARM_REG               \
+                               + (CUM).arg_count[(int) SH_ARG_FLOAT])), \
+               const0_rtx))))
+
+/* The SH5 ABI requires regular registers or stack slots to be
+   reserved for floating-point arguments.  Registers are taken care of
+   in FUNCTION_ARG_ADVANCE, but stack slots must be reserved here.
+   Unfortunately, there's no way to just reserve a stack slot, so
+   we'll end up needlessly storing a copy of the argument in the
+   stack.  For incoming arguments, however, the PARALLEL will be
+   optimized to the register-only form, and the value in the stack
+   slot won't be used at all.  */
+#define SH5_PROTOTYPED_FLOAT_ARG(CUM,MODE,REG) \
+  ((CUM).arg_count[(int) SH_ARG_INT] < NPARM_REGS (SImode)             \
+   ? gen_rtx_REG ((MODE), (REG))                                       \
+   : gen_rtx_PARALLEL ((MODE),                                         \
+                      gen_rtvec (2,                                    \
+                                 gen_rtx_EXPR_LIST                     \
+                                 (VOIDmode, NULL_RTX,                  \
+                                  const0_rtx),                         \
+                                 gen_rtx_EXPR_LIST                     \
+                                 (VOIDmode, gen_rtx_REG ((MODE),       \
+                                                         (REG)),       \
+                                  const0_rtx))))
+
+#define STRICT_ARGUMENT_NAMING TARGET_SH5
+
+#define PRETEND_OUTGOING_VARARGS_NAMED (! TARGET_HITACHI && ! TARGET_SH5)
 
 /* For an arg passed partly in registers and partly in memory,
    this is the number of registers used.
@@ -1188,7 +1916,8 @@ struct sh_args {
    We sometimes split args.  */
 
 #define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \
-  ((PASS_IN_REG_P ((CUM), (MODE), (TYPE))                      \
+  ((! TARGET_SH5 \
+    && PASS_IN_REG_P ((CUM), (MODE), (TYPE))                   \
     && ! TARGET_SH4                                            \
     && (ROUND_REG ((CUM), (MODE))                              \
        + ((MODE) != BLKmode                                    \
@@ -1196,15 +1925,23 @@ struct sh_args {
           : ROUND_ADVANCE (int_size_in_bytes (TYPE)))          \
        > NPARM_REGS (MODE)))                                   \
    ? NPARM_REGS (MODE) - ROUND_REG ((CUM), (MODE))             \
+   : (SH5_WOULD_BE_PARTIAL_NREGS ((CUM), (MODE), (TYPE), (NAMED)) \
+      && ! TARGET_SHCOMPACT)                                   \
+   ? NPARM_REGS (SImode) - (CUM).arg_count[(int) SH_ARG_INT]   \
    : 0)
 
+#define SH5_WOULD_BE_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \
+  (TARGET_SH5 && (MODE) == BLKmode                             \
+   && ((CUM).arg_count[(int) SH_ARG_INT]                       \
+       + (int_size_in_bytes (TYPE) + 7) / 8) > NPARM_REGS (SImode))
+
 extern int current_function_anonymous_args;
 
 /* Perform any needed actions needed for a function that is receiving a
    variable number of arguments.  */
 
 #define SETUP_INCOMING_VARARGS(ASF, MODE, TYPE, PAS, ST) \
-  current_function_anonymous_args = 1;
+  current_function_anonymous_args = ! TARGET_SH5
 
 /* Define the `__builtin_va_list' type for the ABI.  */
 #define BUILD_VA_LIST_TYPE(VALIST) \
@@ -1254,7 +1991,7 @@ extern int current_function_anonymous_args;
    6 000c 00000000     l2:     .long   function  */
 
 /* Length in units of the trampoline for entering a nested function.  */
-#define TRAMPOLINE_SIZE  16
+#define TRAMPOLINE_SIZE  (TARGET_SHMEDIA64 ? 40 : TARGET_SH5 ? 32 : 16)
 
 /* Alignment required for a trampoline in bits .  */
 #define TRAMPOLINE_ALIGNMENT \
@@ -1266,6 +2003,27 @@ extern int current_function_anonymous_args;
 
 #define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) do                   \
 {                                                                      \
+  if (TARGET_SH5)                                                      \
+    {                                                                  \
+      rtx tramp_templ = gen_rtx_SYMBOL_REF (Pmode,                     \
+                                           "__GCC_nested_trampoline"); \
+      int fixed_len = TRAMPOLINE_SIZE - 2 * GET_MODE_SIZE (Pmode);     \
+                                                                       \
+      tramp_templ = gen_datalabel_ref (tramp_templ);                   \
+      emit_block_move (gen_rtx_MEM (BLKmode, (TRAMP)),                 \
+                      gen_rtx_MEM (BLKmode, tramp_templ),              \
+                      GEN_INT (fixed_len));                            \
+      emit_move_insn (gen_rtx_MEM (Pmode, plus_constant ((TRAMP),      \
+                                                        fixed_len)),   \
+                     (FNADDR));                                        \
+      emit_move_insn (gen_rtx_MEM (Pmode,                              \
+                                  plus_constant ((TRAMP),              \
+                                                 fixed_len             \
+                                                 + GET_MODE_SIZE (Pmode))), \
+                     (CXT));                                           \
+      emit_insn (gen_ic_invalidate_line (TRAMP));                      \
+      break;                                                           \
+    }                                                                  \
   emit_move_insn (gen_rtx_MEM (SImode, (TRAMP)),                       \
                   GEN_INT (trunc_int_for_mode                                  \
                          (TARGET_LITTLE_ENDIAN ? 0xd301d202 : 0xd202d301,\
@@ -1286,6 +2044,16 @@ extern int current_function_anonymous_args;
     }                                                                  \
 } while (0)
 
+/* On SH5, trampolines are SHmedia code, so add 1 to the address.  */
+
+#define TRAMPOLINE_ADJUST_ADDRESS(TRAMP) do                            \
+{                                                                      \
+  if (TARGET_SH5)                                                      \
+    (TRAMP) = expand_simple_binop (Pmode, PLUS, (TRAMP), GEN_INT (1),  \
+                                  gen_reg_rtx (Pmode), 0,              \
+                                  OPTAB_LIB_WIDEN);                    \
+} while (0)
+
 /* A C expression whose value is RTL representing the value of the return
    address for the frame COUNT steps up from the current frame.
    FRAMEADDR is already the frame pointer of the COUNT frame, so we
@@ -1300,17 +2068,17 @@ extern int current_function_anonymous_args;
 #define EXPAND_BUILTIN_SAVEREGS() sh_builtin_saveregs ()
 \f
 /* Addressing modes, and classification of registers for them.  */
-#define HAVE_POST_INCREMENT  1
+#define HAVE_POST_INCREMENT  TARGET_SH1
 /*#define HAVE_PRE_INCREMENT   1*/
 /*#define HAVE_POST_DECREMENT  1*/
-#define HAVE_PRE_DECREMENT   1
+#define HAVE_PRE_DECREMENT   TARGET_SH1
 
 #define USE_LOAD_POST_INCREMENT(mode)    ((mode == SImode || mode == DImode) \
-                                           ? 0 : 1)
+                                           ? 0 : TARGET_SH1)
 #define USE_LOAD_PRE_DECREMENT(mode)     0
 #define USE_STORE_POST_INCREMENT(mode)   0
 #define USE_STORE_PRE_DECREMENT(mode)    ((mode == SImode || mode == DImode) \
-                                           ? 0 : 1)
+                                           ? 0 : TARGET_SH1)
 
 #define MOVE_BY_PIECES_P(SIZE, ALIGN)  (move_by_pieces_ninsns (SIZE, ALIGN) \
                                         < (TARGET_SMALLCODE ? 2 :           \
@@ -1328,7 +2096,10 @@ extern int current_function_anonymous_args;
   (GENERAL_OR_AP_REGISTER_P (REGNO) \
    || GENERAL_OR_AP_REGISTER_P (reg_renumber[(REGNO)]))
 #define REGNO_OK_FOR_INDEX_P(REGNO) \
-  ((REGNO) == R0_REG || (unsigned) reg_renumber[(REGNO)] == R0_REG)
+  (TARGET_SHMEDIA \
+   ? (GENERAL_REGISTER_P (REGNO) \
+      || GENERAL_REGISTER_P ((unsigned) reg_renumber[(REGNO)])) \
+   : (REGNO) == R0_REG || (unsigned) reg_renumber[(REGNO)] == R0_REG)
 
 /* Maximum number of registers that can appear in a valid memory
    address.  */
@@ -1342,9 +2113,14 @@ extern int current_function_anonymous_args;
 /* Nonzero if the constant value X is a legitimate general operand.  */
 
 #define LEGITIMATE_CONSTANT_P(X) \
-  (GET_CODE (X) != CONST_DOUBLE                                                \
-   || GET_MODE (X) == DFmode || GET_MODE (X) == SFmode                 \
-   || (TARGET_SH3E && (fp_zero_operand (X) || fp_one_operand (X))))
+  (TARGET_SHMEDIA                                                      \
+   ? (GET_MODE (X) != DFmode                                           \
+      || (X) == CONST0_RTX (GET_MODE (X))                              \
+      || ! TARGET_SHMEDIA_FPU                                          \
+      || TARGET_SHMEDIA64)                                             \
+   : (GET_CODE (X) != CONST_DOUBLE                                     \
+      || GET_MODE (X) == DFmode || GET_MODE (X) == SFmode              \
+      || (TARGET_SH3E && (fp_zero_operand (X) || fp_one_operand (X)))))
 
 /* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
    and check its validity for a certain class.
@@ -1363,12 +2139,14 @@ extern int current_function_anonymous_args;
 /* Nonzero if X is a hard reg that can be used as an index
    or if it is a pseudo reg.  */
 #define REG_OK_FOR_INDEX_P(X) \
-  (REGNO (X) == R0_REG || REGNO (X) >= FIRST_PSEUDO_REGISTER)
+  ((TARGET_SHMEDIA ? GENERAL_REGISTER_P (REGNO (X)) \
+    : REGNO (X) == R0_REG) || REGNO (X) >= FIRST_PSEUDO_REGISTER)
 
 /* Nonzero if X/OFFSET is a hard reg that can be used as an index
    or if X is a pseudo reg.  */
 #define SUBREG_OK_FOR_INDEX_P(X, OFFSET) \
-  ((REGNO (X) == R0_REG && OFFSET == 0) || REGNO (X) >= FIRST_PSEUDO_REGISTER)
+  ((TARGET_SHMEDIA ? GENERAL_REGISTER_P (REGNO (X)) \
+    : REGNO (X) == R0_REG && OFFSET == 0) || REGNO (X) >= FIRST_PSEUDO_REGISTER)
 
 #else
 
@@ -1395,8 +2173,73 @@ extern int current_function_anonymous_args;
           && GET_CODE (XEXP (XEXP (XEXP ((OP), 0), 0), 0)) == LABEL_REF \
           && GET_CODE (XEXP (XEXP (XEXP ((OP), 0), 0), 1)) == CONST_INT)))
 
+/* The `S' constraint is a 16-bit constant, literal or symbolic.  */
+#define EXTRA_CONSTRAINT_S(OP) \
+  (GET_CODE (OP) == CONST \
+   && GET_CODE (XEXP ((OP), 0)) == SIGN_EXTEND \
+   && GET_MODE (XEXP ((OP), 0)) == DImode \
+   && GET_CODE (XEXP (XEXP ((OP), 0), 0)) == TRUNCATE \
+   && GET_MODE (XEXP (XEXP ((OP), 0), 0)) == HImode \
+   && (MOVI_SHORI_BASE_OPERAND_P (XEXP (XEXP (XEXP ((OP), 0), 0), 0)) \
+       || (GET_CODE (XEXP (XEXP (XEXP ((OP), 0), 0), 0)) == ASHIFTRT \
+          && (MOVI_SHORI_BASE_OPERAND_P \
+              (XEXP (XEXP (XEXP (XEXP ((OP), 0), 0), 0), 0))) \
+          && GET_CODE (XEXP (XEXP (XEXP (XEXP ((OP), 0), 0), 0), \
+                             1)) == CONST_INT)))
+
+/* Check whether OP is a datalabel unspec.  */
+#define DATALABEL_REF_NO_CONST_P(OP) \
+  (GET_CODE (OP) == UNSPEC \
+   && XINT ((OP), 1) == UNSPEC_DATALABEL \
+   && XVECLEN ((OP), 0) == 1 \
+   && (GET_CODE (XVECEXP ((OP), 0, 0)) == SYMBOL_REF \
+       || GET_CODE (XVECEXP ((OP), 0, 0)) == LABEL_REF))
+
+/* Check whether OP is a datalabel unspec, possibly enclosed within a
+   CONST.  */
+#define DATALABEL_REF_P(OP) \
+  ((GET_CODE (OP) == CONST && DATALABEL_REF_NO_CONST_P (XEXP ((OP), 0))) \
+   || DATALABEL_REF_NO_CONST_P (OP))
+
+#define GOT_ENTRY_P(OP) \
+  (GET_CODE (OP) == CONST && GET_CODE (XEXP ((OP), 0)) == UNSPEC \
+   && XINT (XEXP ((OP), 0), 1) == UNSPEC_GOT)
+
+#define GOTPLT_ENTRY_P(OP) \
+  (GET_CODE (OP) == CONST && GET_CODE (XEXP ((OP), 0)) == UNSPEC \
+   && XINT (XEXP ((OP), 0), 1) == UNSPEC_GOTPLT)
+
+#define GOTOFF_P(OP) \
+  (GET_CODE (OP) == CONST && GET_CODE (XEXP ((OP), 0)) == UNSPEC \
+   && XINT (XEXP ((OP), 0), 1) == UNSPEC_GOTOFF)
+
+#define PIC_ADDR_P(OP) \
+  (GET_CODE (OP) == CONST && GET_CODE (XEXP ((OP), 0)) == UNSPEC \
+   && XINT (XEXP ((OP), 0), 1) == UNSPEC_PIC)
+
+#define NON_PIC_REFERENCE_P(OP) \
+  (GET_CODE (OP) == LABEL_REF || GET_CODE (OP) == SYMBOL_REF \
+   || DATALABEL_REF_P (OP) \
+   || (GET_CODE (OP) == CONST && GET_CODE (XEXP ((OP), 0)) == PLUS \
+       && (GET_CODE (XEXP (XEXP ((OP), 0), 0)) == SYMBOL_REF \
+          || DATALABEL_REF_P (XEXP (XEXP ((OP), 0), 0))) \
+       && GET_CODE (XEXP (XEXP ((OP), 0), 1)) == CONST_INT))
+
+#define PIC_REFERENCE_P(OP) \
+  (GOT_ENTRY_P (OP) || GOTPLT_ENTRY_P (OP) \
+   || GOTOFF_P (OP) || PIC_ADDR_P (OP))
+
+#define MOVI_SHORI_BASE_OPERAND_P(OP) \
+  (flag_pic ? PIC_REFERENCE_P (OP) : NON_PIC_REFERENCE_P (OP))
+
+/* The `T' constraint is a label or a symbol.  */
+#define EXTRA_CONSTRAINT_T(OP) \
+  (NON_PIC_REFERENCE_P (OP))
+
 #define EXTRA_CONSTRAINT(OP, C)                \
   ((C) == 'Q' ? EXTRA_CONSTRAINT_Q (OP)        \
+   : (C) == 'S' ? EXTRA_CONSTRAINT_S (OP) \
+   : (C) == 'T' ? EXTRA_CONSTRAINT_T (OP) \
    : 0)
 \f
 /* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
@@ -1453,6 +2296,16 @@ extern int current_function_anonymous_args;
   do {                                                                 \
     if (GET_CODE (OP) == CONST_INT)                                    \
       {                                                                        \
+       if (TARGET_SHMEDIA)                                             \
+         {                                                             \
+           int MODE_SIZE = GET_MODE_SIZE (MODE);                       \
+           if (! (INTVAL (OP) & (MODE_SIZE - 1))                       \
+               && INTVAL (OP) >= -512 * MODE_SIZE                      \
+               && INTVAL (OP) < 512 * MODE_SIZE)                       \
+             goto LABEL;                                               \
+           else                                                        \
+             break;                                                    \
+         }                                                             \
        if (MODE_DISP_OK_4 ((OP), (MODE)))  goto LABEL;                 \
        if (MODE_DISP_OK_8 ((OP), (MODE)))  goto LABEL;                 \
       }                                                                        \
@@ -1463,6 +2316,7 @@ extern int current_function_anonymous_args;
   if (BASE_REGISTER_RTX_P (X))                                         \
     goto LABEL;                                                                \
   else if ((GET_CODE (X) == POST_INC || GET_CODE (X) == PRE_DEC)       \
+          && ! TARGET_SHMEDIA                                          \
           && BASE_REGISTER_RTX_P (XEXP ((X), 0)))                      \
     goto LABEL;                                                                \
   else if (GET_CODE (X) == PLUS                                                \
@@ -1473,6 +2327,7 @@ extern int current_function_anonymous_args;
       if (GET_MODE_SIZE (MODE) <= 8 && BASE_REGISTER_RTX_P (xop0))     \
        GO_IF_LEGITIMATE_INDEX ((MODE), xop1, LABEL);                   \
       if (GET_MODE_SIZE (MODE) <= 4                                    \
+         || (TARGET_SHMEDIA && GET_MODE_SIZE (MODE) <= 8)              \
          || (TARGET_SH4 && TARGET_FMOVD && MODE == DFmode))            \
        {                                                               \
          if (BASE_REGISTER_RTX_P (xop1) && INDEX_REGISTER_RTX_P (xop0))\
@@ -1509,6 +2364,7 @@ extern int current_function_anonymous_args;
          || GET_MODE_SIZE (MODE) == 8)                         \
       && GET_CODE (XEXP ((X), 1)) == CONST_INT                 \
       && BASE_REGISTER_RTX_P (XEXP ((X), 0))                   \
+      && ! TARGET_SHMEDIA                                      \
       && ! (TARGET_SH4 && (MODE) == DFmode)                    \
       && ! (TARGET_SH3E && (MODE) == SFmode))                  \
     {                                                          \
@@ -1557,6 +2413,7 @@ extern int current_function_anonymous_args;
       && (GET_MODE_SIZE (MODE) == 4 || GET_MODE_SIZE (MODE) == 8)      \
       && GET_CODE (XEXP (X, 1)) == CONST_INT                           \
       && BASE_REGISTER_RTX_P (XEXP (X, 0))                             \
+      && ! TARGET_SHMEDIA                                              \
       && ! (TARGET_SH4 && (MODE) == DFmode)                            \
       && ! ((MODE) == PSImode && (TYPE) == RELOAD_FOR_INPUT_ADDRESS))  \
     {                                                                  \
@@ -1602,6 +2459,7 @@ extern int current_function_anonymous_args;
           && GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT             \
           && BASE_REGISTER_RTX_P (XEXP (XEXP (X, 0), 0))               \
           && GET_CODE (XEXP (X, 1)) == CONST_INT                       \
+          && ! TARGET_SHMEDIA                                          \
           && ! (TARGET_SH3E && MODE == SFmode))                        \
     {                                                                  \
       /* Because this address is so complex, we know it must have      \
@@ -1645,6 +2503,9 @@ extern int current_function_anonymous_args;
    Do not define this if the table should contain absolute addresses.  */
 #define CASE_VECTOR_PC_RELATIVE 1
 
+/* Define it here, so that it doesn't get bumped to 64-bits on SHmedia.  */
+#define FLOAT_TYPE_SIZE 32
+
 /* Since the SH3e has only `float' support, it is desirable to make all
    floating point types equivalent to `float'.  */
 #define DOUBLE_TYPE_SIZE ((TARGET_SH3E && ! TARGET_SH4) ? 32 : 64)
@@ -1652,8 +2513,16 @@ extern int current_function_anonymous_args;
 /* 'char' is signed by default.  */
 #define DEFAULT_SIGNED_CHAR  1
 
+/* We -Define SIZE_TYPE in CPP_SPEC.  */
+#define NO_BUILTIN_SIZE_TYPE 1
+
 /* The type of size_t unsigned int.  */
-#define SIZE_TYPE "unsigned int"
+#define SIZE_TYPE (TARGET_SH5 ? "long unsigned int" : "unsigned int")
+
+#define NO_BUILTIN_PTRDIFF_TYPE 1
+
+#undef  PTRDIFF_TYPE
+#define PTRDIFF_TYPE (TARGET_SH5 ? "long int" : "int")
 
 #define WCHAR_TYPE "short unsigned int"
 #define WCHAR_TYPE_SIZE 16
@@ -1663,11 +2532,15 @@ extern int current_function_anonymous_args;
 
 /* Max number of bytes we can move from memory to memory
    in one reasonably fast instruction.  */
-#define MOVE_MAX 4
+#define MOVE_MAX (TARGET_SHMEDIA ? 8 : 4)
+
+/* Maximum value possibly taken by MOVE_MAX.  Must be defined whenever
+   MOVE_MAX is not a compile-time constant.  */
+#define MAX_MOVE_MAX 8
 
 /* Max number of bytes we want move_by_pieces to be able to copy
    efficiently.  */
-#define MOVE_MAX_PIECES (TARGET_SH4 ? 8 : 4)
+#define MOVE_MAX_PIECES (TARGET_SH4 || TARGET_SHMEDIA ? 8 : 4)
 
 /* Define if operations between registers always perform the operation
    on the full register even if a narrower mode is specified.  */
@@ -1714,13 +2587,24 @@ extern int current_function_anonymous_args;
 #define PROMOTE_PROTOTYPES 1
 
 /* The machine modes of pointers and functions.  */
-#define Pmode  SImode
+#define Pmode  (TARGET_SHMEDIA64 ? DImode : SImode)
 #define FUNCTION_MODE  Pmode
 
 /* The relative costs of various types of constants.  */
 
 #define CONST_COSTS(RTX, CODE, OUTER_CODE)     \
   case CONST_INT:                              \
+    if (TARGET_SHMEDIA)                                \
+      {                                                \
+       if (CONST_OK_FOR_J (INTVAL (RTX)))      \
+          return COSTS_N_INSNS (1);            \
+       else if (CONST_OK_FOR_J (INTVAL (RTX) >> 16)) \
+         return COSTS_N_INSNS (2);             \
+       else if (CONST_OK_FOR_J ((INTVAL (RTX) >> 16) >> 16)) \
+         return COSTS_N_INSNS (3);             \
+        else                                   \
+         return COSTS_N_INSNS (4);             \
+      }                                                \
     if (CONST_OK_FOR_I (INTVAL (RTX)))         \
       return 0;                                        \
     else if (((OUTER_CODE) == AND || (OUTER_CODE) == IOR || (OUTER_CODE) == XOR) \
@@ -1731,8 +2615,15 @@ extern int current_function_anonymous_args;
   case CONST:                                  \
   case LABEL_REF:                              \
   case SYMBOL_REF:                             \
+    if (TARGET_SHMEDIA64)                      \
+      return COSTS_N_INSNS (4);                        \
+    if (TARGET_SHMEDIA32)                      \
+      return COSTS_N_INSNS (2);                        \
     return 5;                                  \
   case CONST_DOUBLE:                           \
+    if (TARGET_SHMEDIA)                                \
+      return COSTS_N_INSNS (4);                        \
+    else                                       \
       return 10;
 
 #define RTX_COSTS(X, CODE, OUTER_CODE)                 \
@@ -1804,9 +2695,39 @@ do                                                                       \
          (TREE_CODE_CLASS (TREE_CODE (DECL)) != 'd'                    \
           || ! TREE_PUBLIC (DECL));                                    \
       }                                                                        \
+    if (TARGET_SH5)                                                    \
+      {                                                                        \
+       rtx rtl = (TREE_CODE_CLASS (TREE_CODE (DECL)) != 'd'            \
+                  ? TREE_CST_RTL (DECL)                                \
+                  : TREE_CODE (DECL) != VAR_DECL                       \
+                  ? NULL_RTX                                           \
+                  : DECL_RTL (DECL));                                  \
+                                                                       \
+        if (rtl && GET_CODE (rtl) == MEM                               \
+           && GET_CODE (XEXP (rtl, 0)) == SYMBOL_REF)                  \
+         XEXP (rtl, 0) = gen_datalabel_ref (XEXP (rtl, 0));            \
+      }                                                                        \
   }                                                                    \
 while (0)
 
+/* The prefix used to mark SYMBOL_REFs that refer to data symbols.  */
+#define SH_DATALABEL_ENCODING "#"
+
+/* Return true if SYM_NAME starts with SH_DATALABEL_ENCODING.  */
+#define DATALABEL_SYMNAME_P(SYM_NAME) \
+  (SH_DATALABEL_ENCODING[1] ? (abort (), 0) : \
+   (SYM_NAME)[0] == SH_DATALABEL_ENCODING[0])
+
+/* Skip an optional SH_DATALABEL_ENCODING in the beginning of
+   SYM_NAME.  Then, remove a leading *, like the default definition in
+   output.h.  */
+#define STRIP_DATALABEL_ENCODING(VAR, SYM_NAME) \
+  (VAR) = (SYM_NAME) + (DATALABEL_SYMNAME_P (SYM_NAME) \
+                       ? strlen (SH_DATALABEL_ENCODING) : 0)
+#define STRIP_NAME_ENCODING(VAR, SYM_NAME) \
+  STRIP_DATALABEL_ENCODING((VAR), (SYM_NAME)), \
+  (VAR) += (*(VAR) == '*')
+
 /* We can't directly access anything that contains a symbol,
    nor can we indirect via the constant pool.  */
 #define LEGITIMATE_PIC_OPERAND_P(X)                            \
@@ -1823,6 +2744,7 @@ while (0)
    since it increases pressure on r0.  */
 
 #define ADDRESS_COST(X) (GET_CODE (X) == PLUS && ! CONSTANT_P (XEXP (X, 1)) \
+                        && ! TARGET_SHMEDIA \
                         ? 1 : 0)
 
 /* Compute extra cost of moving data between one register class
@@ -1833,13 +2755,14 @@ while (0)
    it uses this information.  Hence, the general register <-> floating point
    register information here is not used for SFmode.  */
 #define REGISTER_MOVE_COST(MODE, SRCCLASS, DSTCLASS) \
 ((((DSTCLASS) == T_REGS) || ((DSTCLASS) == PR_REGS)) ? 10            \
(((((DSTCLASS) == T_REGS) || ((DSTCLASS) == PR_REGS)) ? 10            \
    : ((((DSTCLASS) == FP0_REGS || (DSTCLASS) == FP_REGS || (DSTCLASS) == DF_REGS) \
        && ((SRCCLASS) == GENERAL_REGS || (SRCCLASS) == R0_REGS))       \
       || (((DSTCLASS) == GENERAL_REGS || (DSTCLASS) == R0_REGS)                \
          && ((SRCCLASS) == FP0_REGS || (SRCCLASS) == FP_REGS           \
              || (SRCCLASS) == DF_REGS)))                               \
-   ? TARGET_FMOVD ? 8 : 12                                             \
+   ? (TARGET_SHMEDIA ? 2                                               \
+      : TARGET_FMOVD ? 8 : 12)                                         \
    : (((DSTCLASS) == FPUL_REGS                                         \
        && ((SRCCLASS) == GENERAL_REGS || (SRCCLASS) == R0_REGS))       \
       || (SRCCLASS == FPUL_REGS                                                \
@@ -1851,7 +2774,13 @@ while (0)
       || ((SRCCLASS) == FPUL_REGS                                      \
          && ((DSTCLASS) == PR_REGS || (DSTCLASS) == MAC_REGS)))        \
    ? 7                                                                 \
-   : 2)
+   : (((SRCCLASS) == TARGET_REGS && (DSTCLASS) != GENERAL_REGS)                \
+      || ((DSTCLASS) == TARGET_REGS && (SRCCLASS) != GENERAL_REGS))    \
+   ? 20                                                                        \
+   : (((SRCCLASS) == FPSCR_REGS && (DSTCLASS) != GENERAL_REGS)         \
+      || ((DSTCLASS) == FPSCR_REGS && (SRCCLASS) != GENERAL_REGS))     \
+   ? 4                                                                 \
+   : 2) * ((MODE) == V16SFmode ? 8 : (MODE) == V4SFmode ? 2 : 1))
 
 /* ??? Perhaps make MEMORY_MOVE_COST depend on compiler option?  This
    would be so that people with slow memory systems could generate
@@ -1862,7 +2791,7 @@ while (0)
    The SH1 does not have delay slots, hence we get a pipeline stall
    at every branch.  The SH4 is superscalar, so the single delay slot
    is not sufficient to keep both pipelines filled.  */
-#define BRANCH_COST (! TARGET_SH2 || TARGET_HARD_SH4 ? 2 : 1)
+#define BRANCH_COST (TARGET_SH5 ? 1 : ! TARGET_SH2 || TARGET_HARD_SH4 ? 2 : 1)
 \f
 /* Assembler output control.  */
 
@@ -1885,9 +2814,20 @@ while (0)
 
 /* How to change between sections.  */
 
-#define TEXT_SECTION_ASM_OP            "\t.text"
+#define TEXT_SECTION_ASM_OP            (TARGET_SHMEDIA32 ? "\t.section\t.text..SHmedia32,\"ax\"" : "\t.text")
 #define DATA_SECTION_ASM_OP            "\t.data"
 
+#if defined CRT_BEGIN || defined CRT_END
+/* Arrange for TEXT_SECTION_ASM_OP to be a compile-time constant.  */
+# undef TEXT_SECTION_ASM_OP
+# if __SHMEDIA__ == 1 && __SH5__ == 32
+#  define TEXT_SECTION_ASM_OP "\t.section\t.text..SHmedia32,\"ax\""
+# else
+#  define TEXT_SECTION_ASM_OP "\t.text"
+# endif
+#endif
+
+
 /* If defined, a C expression whose value is a string containing the
    assembler operation to identify the following data as
    uninitialized global data.  If not defined, and neither
@@ -1951,43 +2891,60 @@ while (0)
 #define ASM_OUTPUT_REG_POP(file, v) \
   fprintf ((file), "\tmov.l\t@r15+,r%d\n", (v));
 
-/* The assembler's names for the registers.  RFP need not always be used as
-   the Real framepointer; it can also be used as a normal general register.
-   Note that the name `fp' is horribly misleading since `fp' is in fact only
-   the argument-and-return-context pointer.  */
-
-extern char fp_reg_names[][5];
-
-#define REGISTER_NAMES                                 \
-{                                                      \
-  "r0", "r1", "r2",  "r3",  "r4",  "r5",  "r6",  "r7",         \
-  "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",        \
-  "ap", "pr", "t",   "gbr", "mach","macl", fp_reg_names[16], "rap", \
-  fp_reg_names[0],  fp_reg_names[1] , fp_reg_names[2],  fp_reg_names[3], \
-  fp_reg_names[4],  fp_reg_names[5],  fp_reg_names[6],  fp_reg_names[7], \
-  fp_reg_names[8],  fp_reg_names[9],  fp_reg_names[10], fp_reg_names[11], \
-  fp_reg_names[12], fp_reg_names[13], fp_reg_names[14], fp_reg_names[15], \
-  fp_reg_names[17], fp_reg_names[18], fp_reg_names[19], fp_reg_names[20], \
-  fp_reg_names[21], fp_reg_names[22], fp_reg_names[23], fp_reg_names[24], \
-  "fpscr", \
-}
-
-#define DEBUG_REGISTER_NAMES                           \
-{                                                      \
-  "r0", "r1", "r2",  "r3",  "r4",  "r5",  "r6",  "r7",         \
-  "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",        \
-  "ap", "pr", "t",  "gbr", "mach","macl", "fpul","rap", \
-  "fr0","fr1","fr2", "fr3", "fr4", "fr5", "fr6", "fr7", \
-  "fr8","fr9","fr10","fr11","fr12","fr13","fr14","fr15",\
-  "xd0","xd2","xd4", "xd6", "xd8", "xd10","xd12","xd14", \
-  "fpscr", \
-}
-
 /* DBX register number for a given compiler register number.  */
 /* GDB has FPUL at 23 and FP0 at 25, so we must add one to all FP registers
    to match gdb.  */
-#define DBX_REGISTER_NUMBER(REGNO)     \
-  (((REGNO) >= 22 && (REGNO) <= 39) ? ((REGNO) + 1) : (REGNO))
+/* If you change this macro, make sure you update it in elf.h too.  */
+#define DBX_REGISTER_NUMBER(REGNO) \
+  (GENERAL_REGISTER_P (REGNO) \
+   ? ((REGNO) - FIRST_GENERAL_REG) \
+   : FP_REGISTER_P (REGNO) \
+   ? ((REGNO) - FIRST_FP_REG + (TARGET_SH5 ? (TARGET_SHCOMPACT ? 245 \
+                                             : 77) : 25)) \
+   : XD_REGISTER_P (REGNO) \
+   ? ((REGNO) - FIRST_XD_REG + (TARGET_SH5 ? 289 : 87)) \
+   : TARGET_REGISTER_P (REGNO) \
+   ? ((REGNO) - FIRST_TARGET_REG + 68) \
+   : (REGNO) == PR_REG \
+   ? (TARGET_SH5 ? 241 : 17) \
+   : (REGNO) == T_REG \
+   ? (TARGET_SH5 ? 242 : 18) \
+   : (REGNO) == GBR_REG \
+   ? (TARGET_SH5 ? 238 : 19) \
+   : (REGNO) == MACH_REG \
+   ? (TARGET_SH5 ? 239 : 20) \
+   : (REGNO) == MACL_REG \
+   ? (TARGET_SH5 ? 240 : 21) \
+   : (REGNO) == FPUL_REG \
+   ? (TARGET_SH5 ? 244 : 23) \
+   : (abort(), -1))
+
+/* This is how to output a reference to a user-level label named NAME.  */
+#define ASM_OUTPUT_LABELREF(FILE, NAME)                        \
+  do                                                   \
+    {                                                  \
+      char * lname;                                    \
+                                                       \
+      STRIP_DATALABEL_ENCODING (lname, (NAME));                \
+      if (lname[0] == '*')                             \
+       fputs (lname + 1, (FILE));                      \
+      else                                             \
+       asm_fprintf ((FILE), "%U%s", lname);            \
+    }                                                  \
+  while (0)
+
+/* This is how to output a reference to a symbol_ref.  On SH5,
+   references to non-code symbols must be preceded by `datalabel'.  */
+#define ASM_OUTPUT_SYMBOL_REF(FILE,SYM)                        \
+  do                                                   \
+    {                                                  \
+      if (TARGET_SH5                                   \
+         && (DATALABEL_SYMNAME_P (XSTR ((SYM), 0))     \
+             || CONSTANT_POOL_ADDRESS_P (SYM)))        \
+       fputs ("datalabel ", (FILE));                   \
+      assemble_name ((FILE), XSTR ((SYM), 0));         \
+    }                                                  \
+  while (0)
 
 /* Output a label definition.  */
 #define ASM_OUTPUT_LABEL(FILE,NAME) \
@@ -2040,12 +2997,30 @@ extern char fp_reg_names[][5];
   switch (GET_MODE (BODY))                                             \
     {                                                                  \
     case SImode:                                                       \
+      if (TARGET_SH5)                                                  \
+       {                                                               \
+         asm_fprintf ((STREAM), "\t.long\t%LL%d-datalabel %LL%d\n",    \
+                      (VALUE), (REL));                                 \
+         break;                                                        \
+       }                                                               \
       asm_fprintf ((STREAM), "\t.long\t%LL%d-%LL%d\n", (VALUE),(REL)); \
       break;                                                           \
     case HImode:                                                       \
+      if (TARGET_SH5)                                                  \
+       {                                                               \
+         asm_fprintf ((STREAM), "\t.word\t%LL%d-datalabel %LL%d\n",    \
+                      (VALUE), (REL));                                 \
+         break;                                                        \
+       }                                                               \
       asm_fprintf ((STREAM), "\t.word\t%LL%d-%LL%d\n", (VALUE),(REL)); \
       break;                                                           \
     case QImode:                                                       \
+      if (TARGET_SH5)                                                  \
+       {                                                               \
+         asm_fprintf ((STREAM), "\t.byte\t%LL%d-datalabel %LL%d\n",    \
+                      (VALUE), (REL));                                 \
+         break;                                                        \
+       }                                                               \
       asm_fprintf ((STREAM), "\t.byte\t%LL%d-%LL%d\n", (VALUE),(REL)); \
       break;                                                           \
     default:                                                           \
@@ -2119,10 +3094,14 @@ extern char fp_reg_names[][5];
    constants.  Used for PIC-specific UNSPECs.  */
 #define OUTPUT_ADDR_CONST_EXTRA(STREAM, X, FAIL) \
   do                                                                   \
-    if (flag_pic && GET_CODE (X) == UNSPEC && XVECLEN ((X), 0) == 1)   \
+    if (GET_CODE (X) == UNSPEC && XVECLEN ((X), 0) == 1)       \
       {                                                                        \
        switch (XINT ((X), 1))                                          \
          {                                                             \
+         case UNSPEC_DATALABEL:                                        \
+           fputs ("datalabel ", (STREAM));                             \
+           output_addr_const ((STREAM), XVECEXP ((X), 0, 0));          \
+           break;                                                      \
          case UNSPEC_PIC:                                              \
            /* GLOBAL_OFFSET_TABLE or local symbols, no suffix.  */     \
            output_addr_const ((STREAM), XVECEXP ((X), 0, 0));          \
@@ -2139,6 +3118,10 @@ extern char fp_reg_names[][5];
            output_addr_const ((STREAM), XVECEXP ((X), 0, 0));          \
            fputs ("@PLT", (STREAM));                                   \
            break;                                                      \
+         case UNSPEC_GOTPLT:                                           \
+           output_addr_const ((STREAM), XVECEXP ((X), 0, 0));          \
+           fputs ("@GOTPLT", (STREAM));                                \
+           break;                                                      \
          case UNSPEC_CALLER:                                           \
            {                                                           \
              char name[32];                                            \
@@ -2169,7 +3152,8 @@ enum processor_type {
   PROCESSOR_SH2,
   PROCESSOR_SH3,
   PROCESSOR_SH3E,
-  PROCESSOR_SH4
+  PROCESSOR_SH4,
+  PROCESSOR_SH5
 };
 
 #define sh_cpu_attr ((enum attr_cpu)sh_cpu)
@@ -2239,6 +3223,9 @@ extern struct rtx_def *fpscr_rtx;
   {"general_movdst_operand", {SUBREG, REG, MEM}},                      \
   {"logical_operand", {SUBREG, REG, CONST_INT}},                       \
   {"noncommutative_float_operator", {MINUS, DIV}},                     \
+  {"shmedia_6bit_operand", {SUBREG, REG, CONST_INT}},                  \
+  {"target_reg_operand", {SUBREG, REG}},                               \
+  {"target_operand", {SUBREG, REG, LABEL_REF, SYMBOL_REF}},            \
   {"register_operand", {SUBREG, REG}},                                 \
   {"symbol_ref_operand", {SYMBOL_REF}},
 
@@ -2254,7 +3241,8 @@ extern struct rtx_def *fpscr_rtx;
 #define PROMOTE_MODE(MODE, UNSIGNEDP, TYPE) \
   if (GET_MODE_CLASS (MODE) == MODE_INT                        \
       && GET_MODE_SIZE (MODE) < UNITS_PER_WORD)                \
-    (MODE) = SImode;
+    (UNSIGNEDP) = ((MODE) == SImode ? 0 : (UNSIGNEDP)),        \
+    (MODE) = (TARGET_SH1 ? SImode : DImode);
 
 /* Defining PROMOTE_FUNCTION_ARGS eliminates some unnecessary zero/sign
    extensions applied to char/short functions arguments.  Defining
@@ -2299,6 +3287,7 @@ extern struct rtx_def *fpscr_rtx;
 
 #define DWARF_LINE_MIN_INSTR_LENGTH 2
 
+#if (defined CRT_BEGIN || defined CRT_END) && ! __SHMEDIA__
 /* SH constant pool breaks the devices in crtstuff.c to control section
    in where code resides.  We have to write it as asm code.  */
 #define CRT_CALL_STATIC_FUNCTION(SECTION_OP, FUNC) \
@@ -2310,6 +3299,7 @@ extern struct rtx_def *fpscr_rtx;
 0:     .p2align 2\n\
 1:     .long   " USER_LABEL_PREFIX #FUNC " - 0b\n\
 2:\n" TEXT_SECTION_ASM_OP);
+#endif /* (defined CRT_BEGIN || defined CRT_END) && ! __SHMEDIA__ */
 
 #define ALLOCATE_INITIAL_VALUE(hard_reg) \
   (REGNO (hard_reg) == PR_REG \
index 24fbacc..01c7aba 100644 (file)
 ;; -------------------------------------------------------------------------
 
 (define_constants [
-  (AP_REG      16)
-  (PR_REG      17)
-  (T_REG       18)
-  (GBR_REG     19)
-  (MACH_REG    20)
-  (MACL_REG    21)
-  (FPUL_REG    22)
-  (RAP_REG     23)
+  (AP_REG      145)
+  (PR_REG      146)
+  (T_REG       147)
+  (GBR_REG     144)
+  (MACH_REG    148)
+  (MACL_REG    149)
+  (FPUL_REG    150)
+  (RAP_REG     152)
 
-  (FPSCR_REG   48)
+  (FPSCR_REG   151)
 
   (PIC_REG     12)
   (FP_REG      14)
   (SP_REG      15)
 
+  (PR_MEDIA_REG        18)
+  (T_MEDIA_REG 19)
+
   (R0_REG      0)
   (R1_REG      1)
   (R2_REG      2)
   (R4_REG      4)
   (R5_REG      5)
   (R6_REG      6)
+  (R7_REG      7)
+  (R8_REG      8)
+  (R9_REG      9)
+  (R10_REG     10)
+
+  (DR0_REG     64)
+  (DR2_REG     66)
+  (DR4_REG     68)
 
-  (DR0_REG     24)
-  (DR2_REG     26)
-  (DR4_REG     28)
+  (TR0_REG     128)
+  (TR1_REG     129)
+  (TR2_REG     130)
 
-  (XD0_REG     40)
+  (XD0_REG     136)
 
   ;; These are used with unspec.
+  (UNSPEC_COMPACT_ARGS 0)
   (UNSPEC_MOVA         1)
   (UNSPEC_CASESI       2)
+  (UNSPEC_DATALABEL    3)
   (UNSPEC_BBR          4)
   (UNSPEC_SFUNC                5)
   (UNSPEC_PIC          6)
   (UNSPEC_GOTOFF       8)
   (UNSPEC_PLT          9)
   (UNSPEC_CALLER       10)
+  (UNSPEC_GOTPLT       11)
   (UNSPEC_ICACHE       12)
 
   ;; These are used with unspec_volatile.
 ;; Target CPU.
 
 (define_attr "cpu"
- "sh1,sh2,sh3,sh3e,sh4"
+ "sh1,sh2,sh3,sh3e,sh4,sh5"
   (const (symbol_ref "sh_cpu_attr")))
 
 (define_attr "endian" "big,little"
 ;; nil         no-op move, will be deleted.
 
 (define_attr "type"
- "cbranch,jump,jump_ind,arith,arith3,arith3b,dyn_shift,other,load,load_si,store,move,fmove,smpy,dmpy,return,pload,prset,pstore,prget,pcload,pcload_si,rte,sfunc,call,fp,fdiv,dfp_arith,dfp_cmp,dfp_conv,dfdiv,gp_fpul,nil"
+ "cbranch,jump,jump_ind,arith,arith3,arith3b,dyn_shift,other,load,load_si,store,move,fmove,smpy,dmpy,return,pload,prset,pstore,prget,pcload,pcload_si,pt,ptabs,rte,sfunc,call,fp,fdiv,dfp_arith,dfp_cmp,dfp_conv,dfdiv,gp_fpul,nil"
   (const_string "other"))
 
 ;; Indicate what precision must be selected in fpscr for this insn, if any.
                (ne (symbol_ref ("flag_pic")) (const_int 0))
                (const_int 22)
                ] (const_int 14))
-        ] (const_int 2)))
+        (eq_attr "type" "pt")
+        (if_then_else (ne (symbol_ref "TARGET_SHMEDIA64") (const_int 0))
+                      (const_int 20) (const_int 12))
+        ] (if_then_else (ne (symbol_ref "TARGET_SHMEDIA") (const_int 0))
+                        (const_int 4)
+                        (const_int 2))))
 
 ;; (define_function_unit {name} {num-units} {n-users} {test}
 ;;                       {ready-delay} {issue-delay} [{conflict-list}])
 (define_function_unit "fdiv"     1 0
   (and (eq_attr "issues" "2") (eq_attr "type" "dfdiv")) 230 210)
 
+;; This should be enough for pt insns to be moved 5 insns ahead of
+;; corresponding branches.
+(define_function_unit "pt" 1 0
+  (eq_attr "type" "pt,ptabs") 10 2)
+
 ; Definitions for filling branch delay slots.
 
 (define_attr "needs_delay_slot" "yes,no" (const_string "no"))
        (eq:SI (and:SI (match_operand:SI 0 "arith_reg_operand" "z,r")
                       (match_operand:SI 1 "arith_operand" "L,r"))
               (const_int 0)))]
-  ""
+  "TARGET_SH1"
   "tst %1,%0")
 
 ;; ??? Perhaps should only accept reg/constant if the register is reg 0.
   [(set (reg:SI T_REG)
        (eq:SI (match_operand:SI 0 "arith_reg_operand" "r,z,r")
               (match_operand:SI 1 "arith_operand" "N,rI,r")))]
-  ""
+  "TARGET_SH1"
   "@
        tst     %0,%0
        cmp/eq  %1,%0
   [(set (reg:SI T_REG)
        (gt:SI (match_operand:SI 0 "arith_reg_operand" "r,r")
               (match_operand:SI 1 "arith_reg_or_0_operand" "r,N")))]
-  ""
+  "TARGET_SH1"
   "@
        cmp/gt  %1,%0
        cmp/pl  %0")
   [(set (reg:SI T_REG)
        (ge:SI (match_operand:SI 0 "arith_reg_operand" "r,r")
               (match_operand:SI 1 "arith_reg_or_0_operand" "r,N")))]
-  ""
+  "TARGET_SH1"
   "@
        cmp/ge  %1,%0
        cmp/pz  %0")
   [(set (reg:SI T_REG)
        (geu:SI (match_operand:SI 0 "arith_reg_operand" "r")
                (match_operand:SI 1 "arith_reg_operand" "r")))]
-  ""
+  "TARGET_SH1"
   "cmp/hs      %1,%0")
 
 (define_insn "cmpgtusi_t"
   [(set (reg:SI T_REG)
        (gtu:SI (match_operand:SI 0 "arith_reg_operand" "r")
                (match_operand:SI 1 "arith_reg_operand" "r")))]
-  ""
+  "TARGET_SH1"
   "cmp/hi      %1,%0")
 
 ;; We save the compare operands in the cmpxx patterns and use them when
   [(set (reg:SI T_REG)
        (compare (match_operand:SI 0 "arith_operand" "")
                 (match_operand:SI 1 "arith_operand" "")))]
-  ""
+  "TARGET_SH1"
   "
 {
   sh_compare_op0 = operands[0];
        (eq:SI (and:DI (match_operand:DI 0 "arith_reg_operand" "r")
                       (match_operand:DI 1 "arith_operand" "r"))
               (const_int 0)))]
-  ""
+  "TARGET_SH1"
   "* return output_branchy_insn (EQ, \"tst\\t%S1,%S0\;bf\\t%l9\;tst\\t%R1,%R0\",
                                 insn, operands);"
   [(set_attr "length" "6")
   [(set (reg:SI T_REG)
        (eq:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
               (match_operand:DI 1 "arith_reg_or_0_operand" "N,r")))]
-  ""
+  "TARGET_SH1"
   "@
        tst     %S0,%S0\;bf     %,Ldi%=\;tst    %R0,%R0\\n%,Ldi%=:
        cmp/eq  %S1,%S0\;bf     %,Ldi%=\;cmp/eq %R1,%R0\\n%,Ldi%=:"
 ;; If we applied this split when not optimizing, it would only be
 ;; applied during the machine-dependent reorg, when no new basic blocks
 ;; may be created.
-  "reload_completed && optimize"
+  "TARGET_SH1 && reload_completed && optimize"
   [(set (reg:SI T_REG) (eq:SI (match_dup 2) (match_dup 3)))
    (set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
                           (label_ref (match_dup 6))
   [(set_attr "length" "8")
    (set_attr "type" "arith3")])
 
+(define_insn "cmpeqdi_media"
+  [(set (match_operand:DI 0 "register_operand" "=r,r")
+       (eq:DI (match_operand:DI 1 "register_operand" "%r,r")
+              (match_operand:DI 2 "arith_reg_or_0_operand" "N,r")))]
+  "TARGET_SHMEDIA"
+  "@
+       cmpeq   %1, r63, %0
+       cmpeq   %1, %2, %0")
+
+(define_insn "cmpgtdi_media"
+  [(set (match_operand:DI 0 "register_operand" "=r,r,r")
+       (gt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "N,r,r")
+              (match_operand:DI 2 "arith_reg_or_0_operand" "r,N,r")))]
+  "TARGET_SHMEDIA"
+  "@
+       cmpgt   r63, %2, %0
+       cmpgt   %1, r63, %0
+       cmpgt   %1, %2, %0")
+
+(define_insn "cmpgtudi_media"
+  [(set (match_operand:DI 0 "register_operand" "=r,r,r")
+       (gtu:DI (match_operand:DI 1 "arith_reg_or_0_operand" "N,r,r")
+               (match_operand:DI 2 "arith_reg_or_0_operand" "r,N,r")))]
+  "TARGET_SHMEDIA"
+  "@
+       cmpgtu  r63, %2, %0
+       cmpgtu  %1, r63, %0
+       cmpgtu  %1, %2, %0")
+
 ;; We save the compare operands in the cmpxx patterns and use them when
 ;; we generate the branch.
 
   [(set (reg:SI T_REG)
        (compare (match_operand:DI 0 "arith_operand" "")
                 (match_operand:DI 1 "arith_operand" "")))]
-  "TARGET_SH2"
+  "TARGET_SH2 || TARGET_SHMEDIA"
   "
 {
   sh_compare_op0 = operands[0];
   sh_compare_op1 = operands[1];
   DONE;
 }")
+;; -------------------------------------------------------------------------
+;; Conditional move instructions
+;; -------------------------------------------------------------------------
+
+;; The insn names may seem reversed, but note that cmveq performs the move
+;; if op1 == 0, and cmvne does it if op1 != 0.
+
+(define_insn "movdicc_false"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (if_then_else:DI (eq (match_operand:DI 1 "register_operand" "r")
+                            (const_int 0))
+        (match_operand:DI 2 "register_operand" "r")
+        (match_operand:DI 3 "register_operand" "0")))]
+  "TARGET_SHMEDIA"
+  "cmveq       %1, %2, %0")
+
+(define_insn "movdicc_true"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (if_then_else:DI (ne (match_operand:DI 1 "register_operand" "r")
+                            (const_int 0))
+        (match_operand:DI 2 "register_operand" "r")
+        (match_operand:DI 3 "register_operand" "0")))]
+  "TARGET_SHMEDIA"
+  "cmvne       %1, %2, %0")
+
+(define_expand "movdicc"
+  [(set (match_operand:DI 0 "register_operand" "")
+       (if_then_else:DI (match_operand 1 "comparison_operator" "")
+                        (match_operand:DI 2 "register_operand" "")
+                        (match_operand:DI 3 "register_operand" "")))]
+  "TARGET_SHMEDIA"
+  "
+{
+  if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
+      && GET_MODE (sh_compare_op0) == DImode
+      && sh_compare_op1 == const0_rtx)
+    operands[1] = gen_rtx (GET_CODE (operands[1]), VOIDmode,
+                          sh_compare_op0, sh_compare_op1);
+  else
+    {
+      rtx tmp;
+
+      if (no_new_pseudos)
+       FAIL;
+
+      tmp = gen_reg_rtx (DImode);
+
+      switch (GET_CODE (operands[1]))
+       {
+       case EQ:
+         emit_insn (gen_seq (tmp));
+         operands[1] = gen_rtx (NE, VOIDmode, tmp, const0_rtx);
+         break;
+
+       case NE:
+         emit_insn (gen_seq (tmp));
+         operands[1] = gen_rtx (EQ, VOIDmode, tmp, const0_rtx);
+         break;
+
+       case GT:
+         emit_insn (gen_sgt (tmp));
+         operands[1] = gen_rtx (NE, VOIDmode, tmp, const0_rtx);
+         break;
+
+       case LT:
+         emit_insn (gen_slt (tmp));
+         operands[1] = gen_rtx (NE, VOIDmode, tmp, const0_rtx);
+         break;
+
+       case GE:
+         emit_insn (gen_slt (tmp));
+         operands[1] = gen_rtx (EQ, VOIDmode, tmp, const0_rtx);
+         break;
+
+       case LE:
+         emit_insn (gen_sgt (tmp));
+         operands[1] = gen_rtx (EQ, VOIDmode, tmp, const0_rtx);
+         break;
+
+       case GTU:
+         emit_insn (gen_sgtu (tmp));
+         operands[1] = gen_rtx (NE, VOIDmode, tmp, const0_rtx);
+         break;
+
+       case LTU:
+         emit_insn (gen_sltu (tmp));
+         operands[1] = gen_rtx (NE, VOIDmode, tmp, const0_rtx);
+         break;
+
+       case GEU:
+         emit_insn (gen_sltu (tmp));
+         operands[1] = gen_rtx (EQ, VOIDmode, tmp, const0_rtx);
+         break;
+
+       case LEU:
+         emit_insn (gen_sgtu (tmp));
+         operands[1] = gen_rtx (EQ, VOIDmode, tmp, const0_rtx);
+         break;
+
+       case UNORDERED:
+         emit_insn (gen_sunordered (tmp));
+         operands[1] = gen_rtx (NE, VOIDmode, tmp, const0_rtx);
+         break;
+
+       case ORDERED:
+         emit_insn (gen_sunordered (tmp));
+         operands[1] = gen_rtx (EQ, VOIDmode, tmp, const0_rtx);
+         break;
+
+       case UNEQ:
+       case UNGE:
+       case UNGT:
+       case UNLE:
+       case UNLT:
+       case LTGT:
+         FAIL;
+
+       default:
+         abort ();
+       }
+    }
+}")
 \f
 ;; -------------------------------------------------------------------------
 ;; Addition instructions
 ;; -------------------------------------------------------------------------
 
-;; ??? This should be a define expand.
+(define_expand "adddi3"
+  [(set (match_operand:DI 0 "arith_reg_operand" "")
+       (plus:DI (match_operand:DI 1 "arith_reg_operand" "")
+                (match_operand:DI 2 "arith_operand" "")))]
+  ""
+  "
+{
+  if (TARGET_SH1)
+    {
+      if (no_new_pseudos && ! arith_reg_operand (operands[2], DImode))
+        FAIL;
+      operands[2] = force_reg (DImode, operands[2]);
+      emit_insn (gen_adddi3_compact (operands[0], operands[1], operands[2]));
+      DONE;
+    }
+}")
 
-(define_insn "adddi3"
+(define_insn "*adddi3_media"
+  [(set (match_operand:DI 0 "arith_reg_operand" "=r,r")
+       (plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
+                (match_operand:DI 2 "arith_operand" "r,P")))]
+  "TARGET_SHMEDIA"
+  "@
+       add     %1, %2, %0
+       addi    %1, %2, %0")
+
+(define_insn "*adddi3z_media"
+  [(set (match_operand:DI 0 "arith_reg_operand" "=r,r")
+       (zero_extend:DI
+        (plus:SI (match_operand:SI 1 "arith_reg_operand" "r,r")
+                 (match_operand:SI 2 "arith_reg_or_0_operand" "r,n"))))]
+  "TARGET_SHMEDIA"
+  "@
+       addz.l  %1, %2, %0
+       addz.l  %1, r63, %0")
+                
+(define_insn "adddi3_compact"
   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
        (plus:DI (match_operand:DI 1 "arith_reg_operand" "%0")
                 (match_operand:DI 2 "arith_reg_operand" "r")))
    (clobber (reg:SI T_REG))]
-  ""
+  "TARGET_SH1"
   "#"
   [(set_attr "length" "6")])
 
        (plus:DI (match_operand:DI 1 "arith_reg_operand" "%0")
                 (match_operand:DI 2 "arith_reg_operand" "r")))
    (clobber (reg:SI T_REG))]
-  "reload_completed"
+  "TARGET_SH1 && reload_completed"
   [(const_int 0)]
   "
 {
                 (reg:SI T_REG)))
    (set (reg:SI T_REG)
        (ltu:SI (plus:SI (match_dup 1) (match_dup 2)) (match_dup 1)))]
-  ""
+  "TARGET_SH1"
   "addc        %2,%0"
   [(set_attr "type" "arith")])
 
                          (match_operand:SI 2 "arith_reg_operand" "r"))
                 (reg:SI T_REG)))
    (clobber (reg:SI T_REG))]
-  ""
+  "TARGET_SH1"
   "addc        %2,%0"
   [(set_attr "type" "arith")])
 
-(define_insn "addsi3"
+(define_expand "addsi3"
+  [(set (match_operand:SI 0 "arith_reg_operand" "")
+       (plus:SI (match_operand:SI 1 "arith_operand" "")
+                (match_operand:SI 2 "arith_operand" "")))]
+  ""
+  "
+{
+  if (TARGET_SHMEDIA)
+    operands[1] = force_reg (SImode, operands[1]);
+}")
+
+(define_insn "addsi3_media"
+  [(set (match_operand:SI 0 "arith_reg_operand" "=r,r")
+       (plus:SI (match_operand:SI 1 "arith_reg_operand" "%r,r")
+                (match_operand:SI 2 "arith_operand" "r,P")))]
+  "TARGET_SHMEDIA"
+  "@
+       add.l   %1, %2, %0
+       addi.l  %1, %2, %0")
+  
+(define_insn "*addsi3_compact"
   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
        (plus:SI (match_operand:SI 1 "arith_operand" "%0")
                 (match_operand:SI 2 "arith_operand" "rI")))]
-  ""
+  "TARGET_SH1"
   "add %2,%0"
   [(set_attr "type" "arith")])
 \f
 ;; Subtraction instructions
 ;; -------------------------------------------------------------------------
 
-;; ??? This should be a define expand.
-
-(define_insn "subdi3"
+(define_expand "subdi3"
+  [(set (match_operand:DI 0 "arith_reg_operand" "")
+       (minus:DI (match_operand:DI 1 "arith_reg_operand" "")
+                 (match_operand:DI 2 "arith_reg_operand" "")))]
+  ""
+  "
+{
+  if (TARGET_SH1)
+    {
+      emit_insn (gen_subdi3_compact (operands[0], operands[1], operands[2]));
+      DONE;
+    }
+}")
+  
+(define_insn "*subdi3_media"
+  [(set (match_operand:DI 0 "arith_reg_operand" "=r")
+       (minus:DI (match_operand:DI 1 "arith_reg_operand" "r")
+                 (match_operand:DI 2 "arith_reg_operand" "r")))]
+  "TARGET_SHMEDIA"
+  "sub %1, %2, %0")
+  
+(define_insn "subdi3_compact"
   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
        (minus:DI (match_operand:DI 1 "arith_reg_operand" "0")
                 (match_operand:DI 2 "arith_reg_operand" "r")))
    (clobber (reg:SI T_REG))]
-  ""
+  "TARGET_SH1"
   "#"
   [(set_attr "length" "6")])
 
        (minus:DI (match_operand:DI 1 "arith_reg_operand" "0")
                  (match_operand:DI 2 "arith_reg_operand" "r")))
    (clobber (reg:SI T_REG))]
-  "reload_completed"
+  "TARGET_SH1 && reload_completed"
   [(const_int 0)]
   "
 {
                  (reg:SI T_REG)))
    (set (reg:SI T_REG)
        (gtu:SI (minus:SI (match_dup 1) (match_dup 2)) (match_dup 1)))]
-  ""
+  "TARGET_SH1"
   "subc        %2,%0"
   [(set_attr "type" "arith")])
 
                            (match_operand:SI 2 "arith_reg_operand" "r"))
                  (reg:SI T_REG)))
    (clobber (reg:SI T_REG))]
-  ""
+  "TARGET_SH1"
   "subc        %2,%0"
   [(set_attr "type" "arith")])
 
   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
        (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
                  (match_operand:SI 2 "arith_reg_operand" "r")))]
-  ""
+  "TARGET_SH1"
   "sub %2,%0"
   [(set_attr "type" "arith")])
 
+(define_insn "*subsi3_media"
+  [(set (match_operand:SI 0 "arith_reg_operand" "=r")
+       (minus:SI (match_operand:SI 1 "arith_reg_operand" "r")
+                 (match_operand:SI 2 "arith_reg_operand" "r")))]
+  "TARGET_SHMEDIA"
+  "sub.l       %1, %2, %0")
+
 ;; Convert `constant - reg' to `neg rX; add rX, #const' since this
 ;; will sometimes save one instruction.  Otherwise we might get
 ;; `mov #const, rY; sub rY,rX; mov rX, rY' if the source and dest regs
   ""
   "
 {
-  if (GET_CODE (operands[1]) == CONST_INT)
+  if (TARGET_SH1 && GET_CODE (operands[1]) == CONST_INT)
     {
       emit_insn (gen_negsi2 (operands[0], operands[2]));
       emit_insn (gen_addsi3 (operands[0], operands[0], operands[1]));
       DONE;
     }
+  if (TARGET_SHMEDIA)
+    {
+      if (no_new_pseudos && ! arith_reg_operand (operands[1], SImode))
+       FAIL;
+      operands[1] = force_reg (SImode, operands[1]);
+    }
 }")
 \f
 ;; -------------------------------------------------------------------------
 (define_insn "use_sfunc_addr"
   [(set (reg:SI PR_REG)
        (unspec [(match_operand:SI 0 "register_operand" "r")] UNSPEC_SFUNC))]
-  ""
+  "TARGET_SH1"
   ""
   [(set_attr "length" "0")])
 
    (clobber (reg:SI PR_REG))
    (clobber (reg:SI R4_REG))
    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
-  "! TARGET_SH4"
+  "TARGET_SH1 && ! TARGET_SH4"
   "jsr @%1%#"
   [(set_attr "type" "sfunc")
    (set_attr "needs_delay_slot" "yes")])
 
+(define_insn "udivsi3_i1_media"
+  [(set (match_operand:SI 0 "register_operand" "=z")
+       (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
+   (clobber (reg:SI T_MEDIA_REG))
+   (clobber (reg:SI PR_MEDIA_REG))
+   (clobber (reg:SI R4_REG))
+   (clobber (reg:DI TR0_REG))
+   (clobber (reg:DI TR1_REG))
+   (clobber (reg:DI TR2_REG))
+   (use (match_operand:DI 1 "target_operand" "b"))]
+  "TARGET_SHMEDIA && ! TARGET_SHMEDIA_FPU"
+  "blink       %1, r18"
+  [(set_attr "type" "sfunc")
+   (set_attr "needs_delay_slot" "yes")])
+
+(define_expand "udivsi3_i4_media"
+  [(set (match_dup 2) (zero_extend:DI (reg:SI R4_REG)))
+   (set (match_dup 3) (zero_extend:DI (reg:SI R5_REG)))
+   (set (match_dup 4) (float:DF (match_dup 2)))
+   (set (match_dup 5) (float:DF (match_dup 3)))
+   (set (match_dup 6) (div:DF (match_dup 4) (match_dup 5)))
+   (set (subreg:DI (match_operand:SI 0 "register_operand" "=r") 0)
+       (fix:DI (match_dup 6)))]
+  "TARGET_SHMEDIA_FPU"
+  "
+{
+  operands[2] = gen_reg_rtx (DImode);
+  operands[3] = gen_reg_rtx (DImode);
+  operands[4] = gen_reg_rtx (DFmode);
+  operands[5] = gen_reg_rtx (DFmode);
+  operands[6] = gen_reg_rtx (DFmode);
+}")
+
 (define_insn "udivsi3_i4"
   [(set (match_operand:SI 0 "register_operand" "=y")
        (udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
    (clobber (reg:SI R4_REG))
    (clobber (reg:SI R5_REG))
    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
-  "TARGET_HARD_SH4 && TARGET_FPU_SINGLE"
+  "(TARGET_HARD_SH4 || TARGET_SHCOMPACT) && TARGET_FPU_SINGLE"
   "jsr @%1%#"
   [(set_attr "type" "sfunc")
    (set_attr "needs_delay_slot" "yes")])
 {
   rtx first, last;
 
-  operands[3] = gen_reg_rtx(SImode);
+  operands[3] = gen_reg_rtx (Pmode);
   /* Emit the move of the address to a pseudo outside of the libcall.  */
   if (TARGET_HARD_SH4 && TARGET_SH3E)
     {
       else
        last = gen_udivsi3_i4 (operands[0], operands[3]);
     }
+  else if (TARGET_SHMEDIA_FPU)
+    last = gen_udivsi3_i4_media (operands[0]);
+  else if (TARGET_SH5)
+    {
+      emit_move_insn (operands[3],
+                     gen_rtx_SYMBOL_REF (Pmode,
+                                         (TARGET_FPU_ANY
+                                          ? \"__udivsi3_i4\"
+                                          : \"__udivsi3\")));
+
+      if (TARGET_SHMEDIA)
+       last = gen_udivsi3_i1_media (operands[0],
+                                    Pmode == DImode
+                                    ? operands[3]
+                                    : gen_rtx_SUBREG (DImode, operands[3],
+                                                      0));
+      else if (TARGET_FPU_ANY)
+       last = gen_udivsi3_i4_single (operands[0], operands[3]);
+      else
+       last = gen_udivsi3_i1 (operands[0], operands[3]);
+    }
   else
     {
       emit_move_insn (operands[3],
    (clobber (reg:SI R2_REG))
    (clobber (reg:SI R3_REG))
    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
-  "! TARGET_SH4"
+  "TARGET_SH1 && ! TARGET_SH4"
   "jsr @%1%#"
   [(set_attr "type" "sfunc")
    (set_attr "needs_delay_slot" "yes")])
 
+(define_insn "divsi3_i1_media"
+  [(set (match_operand:SI 0 "register_operand" "=z")
+       (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
+   (clobber (reg:SI T_MEDIA_REG))
+   (clobber (reg:SI PR_MEDIA_REG))
+   (clobber (reg:SI R1_REG))
+   (clobber (reg:SI R2_REG))
+   (clobber (reg:SI R3_REG))
+   (clobber (reg:DI TR0_REG))
+   (clobber (reg:DI TR1_REG))
+   (clobber (reg:DI TR2_REG))
+   (use (match_operand:DI 1 "target_operand" "b"))]
+  "TARGET_SHMEDIA && ! TARGET_SHMEDIA_FPU"
+  "blink       %1, r18")
+
+(define_expand "divsi3_i4_media"
+  [(set (match_dup 2) (reg:SI R4_REG))
+   (set (match_dup 3) (reg:SI R5_REG))
+   (set (match_dup 4) (float:DF (match_dup 2)))
+   (set (match_dup 5) (float:DF (match_dup 3)))
+   (set (match_dup 6) (div:DF (match_dup 4) (match_dup 5)))
+   (set (match_operand:SI 0 "register_operand" "=r")
+       (fix:SI (match_dup 6)))]
+  "TARGET_SHMEDIA_FPU"
+  "
+{
+  operands[2] = gen_reg_rtx (SImode);
+  operands[3] = gen_reg_rtx (SImode);
+  operands[4] = gen_reg_rtx (DFmode);
+  operands[5] = gen_reg_rtx (DFmode);
+  operands[6] = gen_reg_rtx (DFmode);
+}")
+
 (define_insn "divsi3_i4"
   [(set (match_operand:SI 0 "register_operand" "=y")
        (div:SI (reg:SI R4_REG) (reg:SI R5_REG)))
    (clobber (reg:DF DR2_REG))
    (clobber (reg:SI R2_REG))
    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
-  "TARGET_HARD_SH4 && TARGET_FPU_SINGLE"
+  "(TARGET_HARD_SH4 || TARGET_SHCOMPACT) && TARGET_FPU_SINGLE"
   "jsr @%1%#"
   [(set_attr "type" "sfunc")
    (set_attr "needs_delay_slot" "yes")])
 {
   rtx first, last;
 
-  operands[3] = gen_reg_rtx(SImode);
+  operands[3] = gen_reg_rtx (Pmode);
   /* Emit the move of the address to a pseudo outside of the libcall.  */
   if (TARGET_HARD_SH4 && TARGET_SH3E)
     {
       else
        last = gen_divsi3_i4 (operands[0], operands[3]);
     }
+  else if (TARGET_SHMEDIA_FPU)
+    last = gen_divsi3_i4_media (operands[0]);
+  else if (TARGET_SH5)
+    {
+      emit_move_insn (operands[3],
+                     gen_rtx_SYMBOL_REF (Pmode,
+                                         (TARGET_FPU_ANY
+                                          ? \"__sdivsi3_i4\"
+                                          : \"__sdivsi3\")));
+
+      if (TARGET_SHMEDIA)
+       last = gen_divsi3_i1_media (operands[0], 
+                                   Pmode == DImode
+                                   ? operands[3]
+                                   : gen_rtx_SUBREG (DImode, operands[3],
+                                                     0));
+      else if (TARGET_FPU_ANY)
+       last = gen_divsi3_i4_single (operands[0], operands[3]);
+      else
+       last = gen_divsi3_i1 (operands[0], operands[3]);
+    }
   else
     {
       emit_move_insn (operands[3], gen_rtx_SYMBOL_REF (SImode, \"__sdivsi3\"));
                  (match_operand:HI 0 "arith_reg_operand" "r"))
                 (zero_extend:SI
                  (match_operand:HI 1 "arith_reg_operand" "r"))))]
-  ""
+  "TARGET_SH1"
   "mulu.w      %1,%0"
   [(set_attr "type" "smpy")])
 
                  (match_operand:HI 0 "arith_reg_operand" "r"))
                 (sign_extend:SI
                  (match_operand:HI 1 "arith_reg_operand" "r"))))]
-  ""
+  "TARGET_SH1"
   "muls.w      %1,%0"
   [(set_attr "type" "smpy")])
 
                  (match_operand:HI 2 "arith_reg_operand" ""))))
    (set (match_operand:SI 0 "arith_reg_operand" "")
        (reg:SI MACL_REG))]
-  ""
+  "TARGET_SH1"
   "
 {
   rtx first, last;
                  (match_operand:HI 2 "arith_reg_operand" ""))))
    (set (match_operand:SI 0 "arith_reg_operand" "")
        (reg:SI MACL_REG))]
-  ""
+  "TARGET_SH1"
   "
 {
   rtx first, last;
    (clobber (reg:SI R2_REG))
    (clobber (reg:SI R1_REG))
    (use (match_operand:SI 0 "arith_reg_operand" "r"))]
-  ""
+  "TARGET_SH1"
   "jsr @%0%#"
   [(set_attr "type" "sfunc")
    (set_attr "needs_delay_slot" "yes")])
             (clobber (reg:SI R2_REG))
             (clobber (reg:SI R1_REG))
             (use (match_operand:SI 3 "register_operand" ""))])]
-  ""
+  "TARGET_SH1"
   "")
 
 (define_insn "mul_l"
                  (match_operand:SI 2 "arith_reg_operand" "")))
    (set (match_operand:SI 0 "arith_reg_operand" "")
        (reg:SI MACL_REG))]
-  ""
+  "TARGET_SH1"
   "
 {
   rtx first, last;
   "dmuls.l     %1,%0"
   [(set_attr "type" "dmpy")])
 
-(define_insn "mulsidi3"
+(define_expand "mulsidi3"
+  [(set (match_operand:DI 0 "arith_reg_operand" "=r")
+       (mult:DI (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
+                (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))]
+  "TARGET_SH2 || TARGET_SHMEDIA"
+  "
+{
+  if (TARGET_SH2)
+    {
+       emit_insn (gen_mulsidi3_compact (operands[0], operands[1],
+                                       operands[2]));
+       DONE;
+    }
+}")
+
+(define_insn "mulsidi3_media"
+  [(set (match_operand:DI 0 "arith_reg_operand" "=r")
+       (mult:DI (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "%r"))
+                (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))]
+  "TARGET_SHMEDIA"
+  "muls.l      %1, %2, %0")
+  
+(define_insn "mulsidi3_compact"
   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
        (mult:DI
         (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
   "dmulu.l     %1,%0"
   [(set_attr "type" "dmpy")])
 
-(define_insn "umulsidi3"
+(define_expand "umulsidi3"
+  [(set (match_operand:DI 0 "arith_reg_operand" "=r")
+       (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
+                (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))]
+  "TARGET_SH2 || TARGET_SHMEDIA"
+  "
+{
+  if (TARGET_SH2)
+    {
+       emit_insn (gen_umulsidi3_compact (operands[0], operands[1],
+                                        operands[2]));
+       DONE;
+    }
+}")
+
+(define_insn "umulsidi3_media"
+  [(set (match_operand:DI 0 "arith_reg_operand" "=r")
+       (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "%r"))
+                (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))]
+  "TARGET_SHMEDIA"
+  "mulu.l      %1, %2, %0")
+  
+(define_insn "umulsidi3_compact"
   [(set (match_operand:DI 0 "arith_reg_operand" "=r")
        (mult:DI
         (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
   [(set (match_operand:SI 0 "arith_reg_operand" "=r,z")
        (and:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
                (match_operand:SI 2 "logical_operand" "r,L")))]
-  ""
+  "TARGET_SH1"
   "and %2,%0"
   [(set_attr "type" "arith")])
 
   [(set (match_operand:SI 0 "arith_reg_operand" "")
        (and:SI (match_operand:SI 1 "arith_reg_operand" "")
                (match_operand:SI 2 "logical_operand" "")))]
-  ""
+  "TARGET_SH1"
   "
 {
   if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 255)
     }
 }")
 
+(define_insn "anddi3"
+  [(set (match_operand:DI 0 "arith_reg_operand" "=r,r")
+       (and:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
+               (match_operand:DI 2 "logical_operand" "r,P")))]
+  "TARGET_SHMEDIA"
+  "@
+       and     %1, %2, %0
+       andi    %1, %2, %0")
+
+(define_insn "*andcdi3"
+  [(set (match_operand:DI 0 "arith_reg_operand" "=r")
+       (and:DI (match_operand:DI 1 "arith_reg_operand" "r")
+               (not:DI (match_operand:DI 2 "arith_reg_operand" "r"))))]
+  "TARGET_SHMEDIA"
+  "andc        %1,%2,%0")
+
 (define_insn "iorsi3"
   [(set (match_operand:SI 0 "arith_reg_operand" "=r,z")
        (ior:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
                (match_operand:SI 2 "logical_operand" "r,L")))]
-  ""
+  "TARGET_SH1"
   "or  %2,%0"
   [(set_attr "type" "arith")])
 
+(define_insn "iordi3"
+  [(set (match_operand:DI 0 "arith_reg_operand" "=r,r")
+       (ior:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
+               (match_operand:DI 2 "logical_operand" "r,P")))]
+  "TARGET_SHMEDIA"
+  "@
+       or      %1, %2, %0
+       ori     %1, %2, %0")
+
 (define_insn "xorsi3"
   [(set (match_operand:SI 0 "arith_reg_operand" "=z,r")
        (xor:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
                (match_operand:SI 2 "logical_operand" "L,r")))]
-  ""
+  "TARGET_SH1"
   "xor %2,%0"
   [(set_attr "type" "arith")])
+
+(define_insn "xordi3"
+  [(set (match_operand:DI 0 "arith_reg_operand" "=r,r")
+       (xor:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
+               (match_operand:DI 2 "shmedia_6bit_operand" "r,O")))]
+  "TARGET_SHMEDIA"
+  "@
+       xor     %1, %2, %0
+       xori    %1, %2, %0")
 \f
 ;; -------------------------------------------------------------------------
 ;; Shifts and rotates
                   (const_int 1)))
    (set (reg:SI T_REG)
        (lshiftrt:SI (match_dup 1) (const_int 31)))]
-  ""
+  "TARGET_SH1"
   "rotl        %0"
   [(set_attr "type" "arith")])
 
        (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0")
                   (const_int 31)))
    (clobber (reg:SI T_REG))]
-  ""
+  "TARGET_SH1"
   "rotr        %0"
   [(set_attr "type" "arith")])
 
   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
        (rotate:SI (match_operand:SI 1 "arith_reg_operand" "r")
                   (const_int 16)))]
-  ""
+  "TARGET_SH1"
   "swap.w      %1,%0"
   [(set_attr "type" "arith")])
 
   [(set (match_operand:SI 0 "arith_reg_operand" "")
        (rotate:SI (match_operand:SI 1 "arith_reg_operand" "")
                   (match_operand:SI 2 "immediate_operand" "")))]
-  ""
+  "TARGET_SH1"
   "
 {
   static char rot_tab[] = {
   [(set (match_operand:HI 0 "arith_reg_operand" "=r")
        (rotate:HI (match_operand:HI 1 "arith_reg_operand" "r")
                   (const_int 8)))]
-  ""
+  "TARGET_SH1"
   "swap.b      %1,%0"
   [(set_attr "type" "arith")])
 
   [(set (match_operand:HI 0 "arith_reg_operand" "")
        (rotate:HI (match_operand:HI 1 "arith_reg_operand" "")
                   (match_operand:HI 2 "immediate_operand" "")))]
-  ""
+  "TARGET_SH1"
   "
 {
   if (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 8)
                   (match_operand:SI 2 "nonmemory_operand" "r,M,K,?ri")))
    (clobber (match_scratch:SI 3 "=X,X,X,&r"))]
   "TARGET_SH3
-   || (GET_CODE (operands[2]) == CONST_INT
+   || (TARGET_SH1 && GET_CODE (operands[2]) == CONST_INT
        && CONST_OK_FOR_K (INTVAL (operands[2])))"
   "@
    shld        %2,%0
   [(set (match_operand:HI 0 "arith_reg_operand" "=r,r")
        (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0,0")
                   (match_operand:HI 2 "const_int_operand" "M,K")))]
-  "CONST_OK_FOR_K (INTVAL (operands[2]))"
+  "TARGET_SH1 && CONST_OK_FOR_K (INTVAL (operands[2]))"
   "@
        add     %0,%0
        shll%O2 %0"
        (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
                   (match_operand:SI 2 "const_int_operand" "n")))
    (clobber (reg:SI T_REG))]
-  "! sh_dynamicalize_shift_p (operands[2])"
+  "TARGET_SH1 && ! sh_dynamicalize_shift_p (operands[2])"
   "#"
   [(set (attr "length")
        (cond [(eq (symbol_ref "shift_insns_rtx (insn)") (const_int 1))
        (ashift:SI (match_operand:SI 1 "arith_reg_operand" "")
                   (match_operand:SI 2 "const_int_operand" "n")))
    (clobber (reg:SI T_REG))]
-  "reload_completed"
+  "TARGET_SH1 && reload_completed"
   [(use (reg:SI R0_REG))]
   "
 {
   DONE;
 }")
 
+(define_insn "ashlsi3_media"
+  [(set (match_operand:SI 0 "arith_reg_operand" "=r,r")
+       (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r,r")
+                  (match_operand:SI 2 "nonmemory_operand" "r,n")))]
+  "TARGET_SHMEDIA"
+  "@
+       shlld.l %1, %2, %0
+       shlli.l %1, %2, %0")
+
 (define_expand "ashlsi3"
   [(parallel [(set (match_operand:SI 0 "arith_reg_operand" "")
                   (ashift:SI (match_operand:SI 1 "arith_reg_operand" "")
   ""
   "
 {
+  if (TARGET_SHMEDIA)
+    {
+      emit_insn (gen_ashlsi3_media (operands[0], operands[1], operands[2]));
+      DONE;
+    }
   if (GET_CODE (operands[2]) == CONST_INT
       && sh_dynamicalize_shift_p (operands[2]))
     operands[2] = force_reg (SImode, operands[2]);
        (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0")
                   (match_operand:HI 2 "const_int_operand" "n")))
    (clobber (reg:SI T_REG))]
-  ""
+  "TARGET_SH1"
   "#"
   [(set (attr "length")
        (cond [(eq (symbol_ref "shift_insns_rtx (insn)") (const_int 1))
        (ashift:HI (match_operand:HI 1 "arith_reg_operand" "")
                   (match_operand:HI 2 "const_int_operand" "n")))
    (clobber (reg:SI T_REG))]
-  "reload_completed"
+  "TARGET_SH1 && reload_completed"
   [(use (reg:SI R0_REG))]
   "
 {
        (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
                     (match_operand:SI 2 "const_int_operand" "M")))
    (clobber (reg:SI T_REG))]
-  "INTVAL (operands[2]) == 1"
+  "TARGET_SH1 && INTVAL (operands[2]) == 1"
   "shar        %0"
   [(set_attr "type" "arith")])
 
   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "r")
                      (const_int 16)))]
-  ""
+  "TARGET_SH1"
   "#"
   [(set_attr "length" "4")])
 
   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
         (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "r")
                     (const_int 16)))]
-  ""
+  "TARGET_SH1"
   [(set (match_dup 0) (rotate:SI (match_dup 1) (const_int 16)))
    (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
   "operands[2] = gen_lowpart (HImode, operands[0]);")
        (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
                     (const_int 31)))
    (clobber (reg:SI T_REG))]
-  ""
+  "TARGET_SH1"
   "#"
   [(set_attr "length" "4")])
 
        (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
                     (const_int 31)))
    (clobber (reg:SI T_REG))]
-  ""
+  "TARGET_SH1"
   [(const_int 0)]
   "
 {
        (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") (const_int 1)))
    (set (reg:SI T_REG)
        (lt:SI (match_dup 1) (const_int 0)))]
-  ""
+  "TARGET_SH1"
   "shll        %0"
   [(set_attr "type" "arith")])
 
    (clobber (reg:SI T_REG))
    (clobber (reg:SI PR_REG))
    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
-  ""
+  "TARGET_SH1"
   "jsr @%1%#"
   [(set_attr "type" "sfunc")
    (set_attr "needs_delay_slot" "yes")])
 
+(define_insn "ashrsi3_media"
+  [(set (match_operand:SI 0 "arith_reg_operand" "=r,r")
+       (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "r,r")
+                    (match_operand:SI 2 "nonmemory_operand" "r,n")))]
+  "TARGET_SHMEDIA"
+  "@
+       shard.l %1, %2, %0
+       shari.l %1, %2, %0")
+
 (define_expand "ashrsi3"
   [(parallel [(set (match_operand:SI 0 "arith_reg_operand" "")
                   (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
                                (match_operand:SI 2 "nonmemory_operand" "")))
              (clobber (reg:SI T_REG))])]
   ""
-  "if (expand_ashiftrt (operands)) DONE; else FAIL;")
+  "
+{
+  if (TARGET_SHMEDIA)
+    {
+      emit_insn (gen_ashrsi3_media (operands[0], operands[1], operands[2]));
+      DONE;
+    }
+  if (expand_ashiftrt (operands))
+    DONE;
+  else
+    FAIL;
+}")
 
 ;; logical shift right
 
        (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
                     (match_operand:SI 2 "const_int_operand" "M")))
    (clobber (reg:SI T_REG))]
-  "CONST_OK_FOR_M (INTVAL (operands[2]))"
+  "TARGET_SH1 && CONST_OK_FOR_M (INTVAL (operands[2]))"
   "shlr        %0"
   [(set_attr "type" "arith")])
 
   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
        (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
                     (match_operand:SI 2 "const_int_operand" "K")))]
-  "CONST_OK_FOR_K (INTVAL (operands[2]))
+  "TARGET_SH1 && CONST_OK_FOR_K (INTVAL (operands[2]))
    && ! CONST_OK_FOR_M (INTVAL (operands[2]))"
   "shlr%O2     %0"
   [(set_attr "type" "arith")])
        (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
                     (match_operand:SI 2 "const_int_operand" "n")))
    (clobber (reg:SI T_REG))]
-  "! sh_dynamicalize_shift_p (operands[2])"
+  "TARGET_SH1 && ! sh_dynamicalize_shift_p (operands[2])"
   "#"
   [(set (attr "length")
        (cond [(eq (symbol_ref "shift_insns_rtx (insn)") (const_int 1))
        (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
                     (match_operand:SI 2 "const_int_operand" "n")))
    (clobber (reg:SI T_REG))]
-  "reload_completed"
+  "TARGET_SH1 && reload_completed"
   [(use (reg:SI R0_REG))]
   "
 {
   DONE;
 }")
 
+(define_insn "lshrsi3_media"
+  [(set (match_operand:SI 0 "arith_reg_operand" "=r,r")
+       (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "r,r")
+                    (match_operand:SI 2 "nonmemory_operand" "r,n")))]
+  "TARGET_SHMEDIA"
+  "@
+       shlrd.l %1, %2, %0
+       shlri.l %1, %2, %0")
+
 (define_expand "lshrsi3"
   [(parallel [(set (match_operand:SI 0 "arith_reg_operand" "")
                   (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
   ""
   "
 {
+  if (TARGET_SHMEDIA)
+    {
+      emit_insn (gen_lshrsi3_media (operands[0], operands[1], operands[2]));
+      DONE;
+    }
   if (GET_CODE (operands[2]) == CONST_INT
       && sh_dynamicalize_shift_p (operands[2]))
     operands[2] = force_reg (SImode, operands[2]);
        (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0")
                   (const_int 1)))
    (clobber (reg:SI T_REG))]
-  ""
+  "TARGET_SH1"
   "shll        %R0\;rotcl      %S0"
   [(set_attr "length" "4")
    (set_attr "type" "arith")])
 
+(define_insn "ashldi3_media"
+  [(set (match_operand:DI 0 "arith_reg_operand" "=r,r")
+       (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
+                  (match_operand:DI 2 "nonmemory_operand" "r,n")))]
+  "TARGET_SHMEDIA"
+  "@
+       shlld   %1, %2, %0
+       shlli   %1, %2, %0")
+
 (define_expand "ashldi3"
   [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
                   (ashift:DI (match_operand:DI 1 "arith_reg_operand" "")
                              (match_operand:DI 2 "immediate_operand" "")))
              (clobber (reg:SI T_REG))])]
   ""
-  "{ if (GET_CODE (operands[2]) != CONST_INT
-        || INTVAL (operands[2]) != 1) FAIL;} ")
+  "
+{
+  if (TARGET_SHMEDIA)
+    {
+      emit_insn (gen_ashldi3_media (operands[0], operands[1], operands[2]));
+      DONE;
+    }
+  if (GET_CODE (operands[2]) != CONST_INT
+      || INTVAL (operands[2]) != 1)
+    FAIL;
+}")
 
 ;; ??? This should be a define expand.
 
        (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
                     (const_int 1)))
    (clobber (reg:SI T_REG))]
-  ""
+  "TARGET_SH1"
   "shlr        %S0\;rotcr      %R0"
   [(set_attr "length" "4")
    (set_attr "type" "arith")])
 
+(define_insn "lshrdi3_media"
+  [(set (match_operand:DI 0 "arith_reg_operand" "=r,r")
+       (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
+                    (match_operand:DI 2 "nonmemory_operand" "r,n")))]
+  "TARGET_SHMEDIA"
+  "@
+       shlrd   %1, %2, %0
+       shlri   %1, %2, %0")
+
 (define_expand "lshrdi3"
   [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
                   (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "")
                               (match_operand:DI 2 "immediate_operand" "")))
             (clobber (reg:SI T_REG))])]
   ""
-  "{ if (GET_CODE (operands[2]) != CONST_INT
-        || INTVAL (operands[2]) != 1) FAIL;} ")
+  "
+{
+  if (TARGET_SHMEDIA)
+    {
+      emit_insn (gen_lshrdi3_media (operands[0], operands[1], operands[2]));
+      DONE;
+    }
+  if (GET_CODE (operands[2]) != CONST_INT
+      || INTVAL (operands[2]) != 1)
+    FAIL;
+}")
 
 ;; ??? This should be a define expand.
 
        (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
                     (const_int 1)))
    (clobber (reg:SI T_REG))]
-  ""
+  "TARGET_SH1"
   "shar        %S0\;rotcr      %R0"
   [(set_attr "length" "4")
    (set_attr "type" "arith")])
 
+(define_insn "ashrdi3_media"
+  [(set (match_operand:DI 0 "arith_reg_operand" "=r,r")
+       (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
+                    (match_operand:DI 2 "nonmemory_operand" "r,n")))]
+  "TARGET_SHMEDIA"
+  "@
+       shard   %1, %2, %0
+       shari   %1, %2, %0")
+
 (define_expand "ashrdi3"
   [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
                   (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "")
                                (match_operand:DI 2 "immediate_operand" "")))
              (clobber (reg:SI T_REG))])]
   ""
-  "{ if (GET_CODE (operands[2]) != CONST_INT
-        || INTVAL (operands[2]) != 1) FAIL; } ")
+  "
+{
+  if (TARGET_SHMEDIA)
+    {
+      emit_insn (gen_ashrdi3_media (operands[0], operands[1], operands[2]));
+      DONE;
+    }
+  if (GET_CODE (operands[2]) != CONST_INT
+      || INTVAL (operands[2]) != 1)
+    FAIL;
+}")
 
 ;; combined left/right shift
 
        (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
                           (match_operand:SI 2 "const_int_operand" "n"))
                (match_operand:SI 3 "const_int_operand" "n")))]
-  "(unsigned)INTVAL (operands[2]) < 32"
+  "TARGET_SH1 && (unsigned)INTVAL (operands[2]) < 32"
   [(use (reg:SI R0_REG))]
   "if (gen_shl_and (operands[0], operands[2], operands[3], operands[1])) FAIL;
    DONE;")
                           (match_operand:SI 2 "const_int_operand" "n"))
                (match_operand:SI 3 "const_int_operand" "n")))
    (clobber (reg:SI T_REG))]
-  "(unsigned)INTVAL (operands[2]) < 32"
+  "TARGET_SH1 && (unsigned)INTVAL (operands[2]) < 32"
   [(use (reg:SI R0_REG))]
   "if (gen_shl_and (operands[0], operands[2], operands[3], operands[1])) FAIL;
    DONE;")
                           (match_operand:SI 2 "const_int_operand" "n"))
                (match_operand:SI 3 "const_int_operand" "n")))
    (clobber (reg:SI T_REG))]
-  "shl_and_kind (operands[2], operands[3], 0) == 1"
+  "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 1"
  "#"
   [(set (attr "length")
        (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
                           (match_operand:SI 2 "const_int_operand" "n"))
                (match_operand:SI 3 "const_int_operand" "n")))
    (clobber (reg:SI T_REG))]
-  "shl_and_kind (operands[2], operands[3], 0) == 2"
+  "TARGET_SH1 && shl_and_kind (operands[2], operands[3], 0) == 2"
  "#"
   [(set (attr "length")
        (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
          (match_operand:SI 4 "const_int_operand" "n,n"))
         (match_operand:SI 5 "const_int_operand" "n,n")))
    (clobber (reg:SI T_REG))]
-  ""
+  "TARGET_SH1"
   "#"
   [(set (attr "length")
        (cond [(eq (symbol_ref "shl_and_scr_length (insn)") (const_int 2))
          (match_operand:SI 4 "const_int_operand" "n,n"))
         (match_operand:SI 5 "const_int_operand" "n,n")))
    (clobber (reg:SI T_REG))]
-  ""
+  "TARGET_SH1"
   [(use (reg:SI R0_REG))]
   "
 {
         (match_operand:SI 3 "const_int_operand" "n")
         (const_int 0)))
    (clobber (reg:SI T_REG))]
-  ""
+  "TARGET_SH1"
   [(use (reg:SI R0_REG))]
   "if (gen_shl_sext (operands[0], operands[2], operands[3], operands[1])) FAIL;
    DONE;")
         (match_operand:SI 3 "const_int_operand" "n")
         (const_int 0)))
    (clobber (reg:SI T_REG))]
-  "(unsigned)shl_sext_kind (operands[2], operands[3], 0) - 1 < 5"
+  "TARGET_SH1 && (unsigned)shl_sext_kind (operands[2], operands[3], 0) - 1 < 5"
   "#"
   [(set (attr "length")
        (cond [(eq (symbol_ref "shl_sext_length (insn)") (const_int 1))
         (match_operand:SI 3 "const_int_operand" "n")
         (const_int 0)))
    (clobber (reg:SI T_REG))]
-  "(shl_sext_kind (operands[2], operands[3], 0) & ~1) == 6"
+  "TARGET_SH1 && (shl_sext_kind (operands[2], operands[3], 0) & ~1) == 6"
   "#"
   [(set (attr "length")
        (cond [(eq (symbol_ref "shl_sext_length (insn)") (const_int 3))
                           (const_int 16))
                (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand" "0")
                             (const_int 16))))]
-  ""
+  "TARGET_SH1"
   "xtrct       %1,%0"
   [(set_attr "type" "arith")])
 
                             (const_int 16))
                (ashift:SI (match_operand:SI 2 "arith_reg_operand" "r")
                           (const_int 16))))]
-  ""
+  "TARGET_SH1"
   "xtrct       %2,%0"
   [(set_attr "type" "arith")])
 \f
    (set (reg:SI T_REG)
        (ne:SI (ior:SI (reg:SI T_REG) (match_dup 1))
               (const_int 0)))]
-  ""
+  "TARGET_SH1"
   "negc        %1,%0"
   [(set_attr "type" "arith")])
 
+(define_insn "*negdi_media"
+  [(set (match_operand:DI 0 "arith_reg_operand" "=r")
+       (neg:DI (match_operand:DI 1 "arith_reg_operand" "r")))]
+  "TARGET_SHMEDIA"
+  "sub r63, %1, %0")
+
 (define_expand "negdi2"
   [(set (match_operand:DI 0 "arith_reg_operand" "")
        (neg:DI (match_operand:DI 1 "arith_reg_operand" "")))
   ""
   "
 {
-  int low_word = (TARGET_LITTLE_ENDIAN ? 0 : 1);
-  int high_word = (TARGET_LITTLE_ENDIAN ? 1 : 0);
+  if (TARGET_SH1)
+    {
+      int low_word = (TARGET_LITTLE_ENDIAN ? 0 : 1);
+      int high_word = (TARGET_LITTLE_ENDIAN ? 1 : 0);
 
-  rtx low_src = operand_subword (operands[1], low_word, 0, DImode);
-  rtx high_src = operand_subword (operands[1], high_word, 0, DImode);
+      rtx low_src = operand_subword (operands[1], low_word, 0, DImode);
+      rtx high_src = operand_subword (operands[1], high_word, 0, DImode);
 
-  rtx low_dst = operand_subword (operands[0], low_word, 1, DImode);
-  rtx high_dst = operand_subword (operands[0], high_word, 1, DImode);
+      rtx low_dst = operand_subword (operands[0], low_word, 1, DImode);
+      rtx high_dst = operand_subword (operands[0], high_word, 1, DImode);
 
-  emit_insn (gen_clrt ());
-  emit_insn (gen_negc (low_dst, low_src));
-  emit_insn (gen_negc (high_dst, high_src));
-  DONE;
+      emit_insn (gen_clrt ());
+      emit_insn (gen_negc (low_dst, low_src));
+      emit_insn (gen_negc (high_dst, high_src));
+      DONE;
+    }
 }")
 
 (define_insn "negsi2"
   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
        (neg:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
-  ""
+  "TARGET_SH1"
   "neg %1,%0"
   [(set_attr "type" "arith")])
 
 (define_insn "one_cmplsi2"
   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
        (not:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
-  ""
+  "TARGET_SH1"
   "not %1,%0"
   [(set_attr "type" "arith")])
+
+(define_expand "one_cmpldi2"
+  [(set (match_operand:DI 0 "arith_reg_operand" "")
+       (xor:DI (match_operand:DI 1 "arith_reg_operand" "")
+               (const_int -1)))]
+  "TARGET_SHMEDIA" "")
 \f
 ;; -------------------------------------------------------------------------
 ;; Zero extension instructions
 ;; -------------------------------------------------------------------------
 
+(define_insn "zero_extendsidi2"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (zero_extend:DI (match_operand:SI 1 "register_operand" "r")))]
+  "TARGET_SHMEDIA"
+  "addz.l      %1, r63, %0")
+
+(define_insn "zero_extendhidi2"
+  [(set (match_operand:DI 0 "register_operand" "=r,r")
+       (zero_extend:DI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
+  "TARGET_SHMEDIA"
+  "@
+       #
+       ld%M1.uw        %m1, %0")
+
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (zero_extend:DI (match_operand:HI 1 "register_operand" "r")))]
+  "TARGET_SHMEDIA && reload_completed"
+  [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48)))
+   (set (match_dup 0) (lshiftrt:DI (match_dup 0) (const_int 48)))])
+
+(define_insn "zero_extendqidi2"
+  [(set (match_operand:DI 0 "register_operand" "=r,r")
+       (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
+  "TARGET_SHMEDIA"
+  "@
+       andi    %1, 255, %0
+       ld%M1.ub        %m1, %0")
+
 (define_insn "zero_extendhisi2"
   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
        (zero_extend:SI (match_operand:HI 1 "arith_reg_operand" "r")))]
-  ""
+  "TARGET_SH1"
   "extu.w      %1,%0"
   [(set_attr "type" "arith")])
 
 (define_insn "zero_extendqisi2"
   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
        (zero_extend:SI (match_operand:QI 1 "arith_reg_operand" "r")))]
-  ""
+  "TARGET_SH1"
   "extu.b      %1,%0"
   [(set_attr "type" "arith")])
 
 (define_insn "zero_extendqihi2"
   [(set (match_operand:HI 0 "arith_reg_operand" "=r")
        (zero_extend:HI (match_operand:QI 1 "arith_reg_operand" "r")))]
-  ""
+  "TARGET_SH1"
   "extu.b      %1,%0"
   [(set_attr "type" "arith")])
 \f
 ;; ??? This should be a define expand.
 ;; ??? Or perhaps it should be dropped?
 
-/* There is no point in defining extendsidi2; convert_move generates good
-   code for that.  */
+;; convert_move generates good code for SH[1-4].
+(define_insn "extendsidi2"
+  [(set (match_operand:DI 0 "register_operand" "=r,r")
+       (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
+  "TARGET_SHMEDIA"
+  "@
+       add.l   %1, r63, %0
+       ld%M1.l %m1, %0")
+
+(define_insn "extendhidi2"
+  [(set (match_operand:DI 0 "register_operand" "=r,r")
+       (sign_extend:DI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
+  "TARGET_SHMEDIA"
+  "@
+       #
+       ld%M1.w %m1, %0")
+
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (sign_extend:DI (match_operand:HI 1 "register_operand" "r")))]
+  "TARGET_SHMEDIA && reload_completed"
+  [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 48)))
+   (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 48)))])
+
+(define_insn "extendqidi2"
+  [(set (match_operand:DI 0 "register_operand" "=r,r")
+       (sign_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
+  "TARGET_SHMEDIA"
+  "@
+       #
+       ld%M1.b %m1, %0")
+
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (sign_extend:DI (match_operand:QI 1 "register_operand" "r")))]
+  "TARGET_SHMEDIA && reload_completed"
+  [(set (match_dup 0) (ashift:DI (subreg:DI (match_dup 1) 0) (const_int 56)))
+   (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 56)))])
 
 (define_insn "extendhisi2"
   [(set (match_operand:SI 0 "arith_reg_operand" "=r,r")
        (sign_extend:SI (match_operand:HI 1 "general_movsrc_operand" "r,m")))]
-  ""
+  "TARGET_SH1"
   "@
        exts.w  %1,%0
        mov.w   %1,%0"
 (define_insn "extendqisi2"
   [(set (match_operand:SI 0 "arith_reg_operand" "=r,r")
        (sign_extend:SI (match_operand:QI 1 "general_movsrc_operand" "r,m")))]
-  ""
+  "TARGET_SH1"
   "@
        exts.b  %1,%0
        mov.b   %1,%0"
 (define_insn "extendqihi2"
   [(set (match_operand:HI 0 "arith_reg_operand" "=r,r")
        (sign_extend:HI (match_operand:QI 1 "general_movsrc_operand" "r,m")))]
-  ""
+  "TARGET_SH1"
   "@
        exts.b  %1,%0
        mov.b   %1,%0"
 ;; -------------------------------------------------------------------------
 
 ;; define push and pop so it is easy for sh.c
+;; We can't use push and pop on SHcompact because the stack must always
+;; be 8-byte aligned.
 
 (define_expand "push"
   [(set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
        (match_operand:SI 0 "register_operand" "r,l,x"))]
-  ""
+  "TARGET_SH1 && ! TARGET_SH5"
   "")
 
 (define_expand "pop"
   [(set (match_operand:SI 0 "register_operand" "=r,l,x")
        (mem:SI (post_inc:SI (reg:SI SP_REG))))]
-  ""
+  "TARGET_SH1 && ! TARGET_SH5"
   "")
 
 (define_expand "push_e"
                   (match_operand:SF 0 "" ""))
              (use (reg:PSI FPSCR_REG))
              (clobber (scratch:SI))])]
-  ""
+  "TARGET_SH1 && ! TARGET_SH5"
   "")
 
 (define_insn "push_fpul"
   [(set (mem:SF (pre_dec:SI (reg:SI SP_REG))) (reg:SF FPUL_REG))]
-  "TARGET_SH3E"
+  "TARGET_SH3E && ! TARGET_SH5"
   "sts.l       fpul,@-r15"
   [(set_attr "type" "store")
    (set_attr "hit_stack" "yes")])
                   (match_operand:DF 0 "" ""))
              (use (reg:PSI FPSCR_REG))
              (clobber (scratch:SI))])]
-  ""
+  "TARGET_SH1 && ! TARGET_SH5"
   "")
 
 (define_expand "pop_e"
              (mem:SF (post_inc:SI (reg:SI SP_REG))))
              (use (reg:PSI FPSCR_REG))
              (clobber (scratch:SI))])]
-  ""
+  "TARGET_SH1 && ! TARGET_SH5"
   "")
 
 (define_insn "pop_fpul"
   [(set (reg:SF FPUL_REG) (mem:SF (post_inc:SI (reg:SI SP_REG))))]
-  "TARGET_SH3E"
+  "TARGET_SH3E && ! TARGET_SH5"
   "lds.l       @r15+,fpul"
   [(set_attr "type" "load")
    (set_attr "hit_stack" "yes")])
                   (mem:DF (post_inc:SI (reg:SI SP_REG))))
              (use (reg:PSI FPSCR_REG))
              (clobber (scratch:SI))])]
-  ""
+  "TARGET_SH1 && ! TARGET_SH5"
   "")
 
 ;; These two patterns can happen as the result of optimization, when
 
 (define_insn "clrt"
   [(set (reg:SI T_REG) (const_int 0))]
-  ""
+  "TARGET_SH1"
   "clrt")
 
 (define_insn "sett"
   [(set (reg:SI T_REG) (const_int 1))]
-  ""
+  "TARGET_SH1"
   "sett")
 
 ;; t/r must come after r/r, lest reload will try to reload stuff like
 (define_insn "movsi_i"
   [(set (match_operand:SI 0 "general_movdst_operand" "=r,r,t,r,r,r,r,m,<,<,x,l,x,l,r")
        (match_operand:SI 1 "general_movsrc_operand" "Q,rI,r,mr,x,l,t,r,x,l,r,r,>,>,i"))]
-  "
-   ! TARGET_SH3E
+  "TARGET_SH1
+   && ! TARGET_SH3E
    && (register_operand (operands[0], SImode)
        || register_operand (operands[1], SImode))"
   "@
 (define_insn "movsi_i_lowpart"
   [(set (strict_low_part (match_operand:SI 0 "general_movdst_operand" "+r,r,r,r,r,r,m,r"))
        (match_operand:SI 1 "general_movsrc_operand" "Q,rI,mr,x,l,t,r,i"))]
-   "register_operand (operands[0], SImode)
-    || register_operand (operands[1], SImode)"
+   "TARGET_SH1
+    && (register_operand (operands[0], SImode)
+        || register_operand (operands[1], SImode))"
   "@
        mov.l   %1,%0
        mov     %1,%0
        fake    %1,%0"
   [(set_attr "type" "pcload,move,load,move,prget,move,store,pcload")])
 
+(define_insn "*movsi_media"
+  [(set (match_operand:SI 0 "general_movdst_operand" "=r,r,r,r,m,f,m,f,r,f,*b*k,r,b*k")
+       (match_operand:SI 1 "general_movsrc_operand" "r,JS,ns,m,r,m,f,r,f,f,r,*b*k,T"))]
+  "TARGET_SHMEDIA_FPU
+   && (register_operand (operands[0], SImode)
+       || register_operand (operands[1], SImode))"
+  "@
+       add.l   %1, r63, %0
+       movi    %1, %0
+       #
+       ld%M1.l %m1, %0
+       st%M0.l %m0, %1
+       fld%M1.s        %m1, %0
+       fst%M0.s        %m0, %1
+       fmov.ls %1, %0
+       fmov.sl %1, %0
+       fmov.s  %1, %0
+       ptabs   %1, %0
+       gettr   %1, %0
+       pt      %1, %0"
+  [(set_attr "type"   "move,move,*,load,store,load,store,move,move,move,ptabs,move,pt")
+   (set_attr "length" "4,4,8,4,4,4,4,4,4,4,4,4,12")])
+
+(define_insn "*movsi_media_nofpu"
+  [(set (match_operand:SI 0 "general_movdst_operand" "=r,r,r,r,m,*b*k,r,b*k")
+       (match_operand:SI 1 "general_movsrc_operand" "r,JS,ns,m,r,r,*b*k,T"))]
+  "TARGET_SHMEDIA
+   && (register_operand (operands[0], SImode)
+       || register_operand (operands[1], SImode))"
+  "@
+       add.l   %1, r63, %0
+       movi    %1, %0
+       #
+       ld%M1.l %m1, %0
+       st%M0.l %m0, %1
+       ptabs   %1, %0
+       gettr   %1, %0
+       pt      %1, %0"
+  [(set_attr "type"   "move,move,*,load,store,ptabs,move,pt")
+   (set_attr "length" "4,4,8,4,4,4,4,12")])
+
+(define_split
+  [(set (match_operand:SI 0 "arith_reg_operand" "=r")
+       (match_operand:SI 1 "immediate_operand" "s"))]
+  "TARGET_SHMEDIA && reload_completed
+   && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
+  [(set (subreg:DI (match_dup 0) 0) (match_dup 2))]
+  "
+{
+  operands[2] = shallow_copy_rtx (operands[1]);
+  PUT_MODE (operands[2], DImode);
+}")
+
+(define_split
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (match_operand:SI 1 "immediate_operand" "n"))]
+  "TARGET_SHMEDIA
+   && ((GET_CODE (operands[1]) == CONST_INT
+       && ! CONST_OK_FOR_J (INTVAL (operands[1])))
+       || GET_CODE (operands[1]) == CONST_DOUBLE)"
+  [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
+
 (define_expand "movsi"
   [(set (match_operand:SI 0 "general_movdst_operand" "")
        (match_operand:SI 1 "general_movsrc_operand" ""))]
   [(parallel [(unspec_volatile [(match_operand:SI 0 "register_operand" "+r")
                                (match_dup 1)] UNSPEC_ICACHE)
              (clobber (scratch:SI))])]
-  "TARGET_HARD_SH4"
+  "TARGET_HARD_SH4 || TARGET_SH5"
   "
 {
+  if (TARGET_SHMEDIA)
+    {
+      emit_insn (gen_ic_invalidate_line_media (operands[0]));
+      DONE;
+    }
+  else if (TARGET_SHCOMPACT)
+    {
+      operands[1] = gen_rtx_SYMBOL_REF (Pmode, \"__ic_invalidate\");
+      operands[1] = force_reg (Pmode, operands[1]);
+      emit_insn (gen_ic_invalidate_line_compact (operands[0], operands[1]));
+      DONE;
+    }
   operands[0] = force_reg (Pmode, operands[0]);
   operands[1] = force_reg (Pmode, GEN_INT (trunc_int_for_mode (0xf0000008,
                                                               Pmode)));
   "ocbwb\\t@%0\;extu.w\\t%0,%2\;or\\t%1,%2\;mov.l\\t%0,@%2"
   [(set_attr "length" "8")])
 
+(define_insn "ic_invalidate_line_media"
+  [(unspec_volatile [(match_operand 0 "register_operand" "r")]
+                   UNSPEC_ICACHE)]
+  "TARGET_SHMEDIA"
+  "icbi        %0, 0\;synci"
+  [(set_attr "length" "8")])
+
+(define_insn "ic_invalidate_line_compact"
+  [(unspec_volatile [(match_operand:SI 0 "register_operand" "z")
+                    (match_operand:SI 1 "register_operand" "r")]
+                   UNSPEC_ICACHE)
+   (clobber (reg:SI PR_REG))]
+  "TARGET_SHCOMPACT"
+  "jsr @%1%#"
+  [(set_attr "type" "sfunc")
+   (set_attr "needs_delay_slot" "yes")])
+
 (define_insn "movqi_i"
   [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,m,r,r,l")
        (match_operand:QI 1 "general_movsrc_operand"  "ri,m,r,t,l,r"))]
-  "arith_reg_operand (operands[0], QImode)
-   || arith_reg_operand (operands[1], QImode)"
+  "TARGET_SH1
+   && (arith_reg_operand (operands[0], QImode)
+       || arith_reg_operand (operands[1], QImode))"
   "@
        mov     %1,%0
        mov.b   %1,%0
        lds     %1,%0"
  [(set_attr "type" "move,load,store,move,move,move")])
 
+(define_insn "*movqi_media"
+  [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,r,m")
+       (match_operand:QI 1 "general_movsrc_operand" "r,JS,m,r"))]
+  "TARGET_SHMEDIA
+   && (arith_reg_operand (operands[0], QImode)
+       || arith_reg_operand (operands[1], QImode))"
+  "@
+       add.l   %1, r63, %0
+       movi    %1, %0
+       ld%M1.b %m1, %0
+       st%M0.b %m0, %1")
+
 (define_expand "movqi"
   [(set (match_operand:QI 0 "general_operand" "")
        (match_operand:QI 1 "general_operand"  ""))]
 (define_insn "movhi_i"
   [(set (match_operand:HI 0 "general_movdst_operand" "=r,r,r,r,m,r,l,r")
        (match_operand:HI 1 "general_movsrc_operand" "Q,rI,m,t,r,l,r,i"))]
-  "arith_reg_operand (operands[0], HImode)
-   || arith_reg_operand (operands[1], HImode)"
+  "TARGET_SH1
+   && (arith_reg_operand (operands[0], HImode)
+       || arith_reg_operand (operands[1], HImode))"
   "@
        mov.w   %1,%0
        mov     %1,%0
        fake    %1,%0"
   [(set_attr "type" "pcload,move,load,move,store,move,move,pcload")])
 
+(define_insn "*movhi_media"
+  [(set (match_operand:HI 0 "general_movdst_operand" "=r,r,r,r,m")
+       (match_operand:HI 1 "general_movsrc_operand" "r,JS,n,m,r"))]
+  "TARGET_SHMEDIA
+   && (arith_reg_operand (operands[0], HImode)
+       || arith_reg_operand (operands[1], HImode))"
+  "@
+       add.l   %1, r63, %0
+       movi    %1, %0
+       #
+       ld%M1.w %m1, %0
+       st%M0.w %m0, %1")
+
+(define_split
+  [(set (match_operand:HI 0 "register_operand" "=r")
+       (match_operand:HI 1 "immediate_operand" "n"))]
+  "TARGET_SHMEDIA && ! CONST_OK_FOR_J (INTVAL (operands[1]))"
+  [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
+
 (define_expand "movhi"
   [(set (match_operand:HI 0 "general_movdst_operand" "")
        (match_operand:HI 1 "general_movsrc_operand"  ""))]
 (define_insn ""
   [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,m,r,r,r,*!x")
        (match_operand:DI 1 "general_movsrc_operand" "Q,r,m,r,I,i,x,r"))]
-  "arith_reg_operand (operands[0], DImode)
-   || arith_reg_operand (operands[1], DImode)"
+  "TARGET_SH1
+   && (arith_reg_operand (operands[0], DImode)
+       || arith_reg_operand (operands[1], DImode))"
   "* return output_movedouble (insn, operands, DImode);"
   [(set_attr "length" "4")
    (set_attr "type" "pcload,move,load,store,move,pcload,move,move")])
 (define_split
   [(set (match_operand:DI 0 "general_movdst_operand" "")
        (match_operand:DI 1 "general_movsrc_operand" ""))]
-  "reload_completed"
+  "TARGET_SH1 && reload_completed"
   [(set (match_dup 2) (match_dup 3))
    (set (match_dup 4) (match_dup 5))]
   "
     FAIL;
 }")
 
+(define_insn "*movdi_media"
+  [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,rl,m,f,m,f,r,f,*b*k,r,b*k")
+       (match_operand:DI 1 "general_movsrc_operand" "r,JS,iF,m,rl,m,f,r,f,f,r,*b*k,T"))]
+  "TARGET_SHMEDIA_FPU
+   && (register_operand (operands[0], DImode)
+       || register_operand (operands[1], DImode))"
+  "@
+       add     %1, r63, %0
+       movi    %1, %0
+       #
+       ld%M1.q %m1, %0
+       st%M0.q %m0, %1
+       fld%M1.d        %m1, %0
+       fst%M0.d        %m0, %1
+       fmov.qd %1, %0
+       fmov.dq %1, %0
+       fmov.d  %1, %0
+       ptabs   %1, %0
+       gettr   %1, %0
+       pt      %1, %0"
+  [(set_attr "type"   "move,move,*,load,store,load,store,move,move,move,ptabs,move,pt")
+   (set_attr "length" "4,4,16,4,4,4,4,4,4,4,4,4,*")])
+
+(define_insn "*movdi_media_nofpu"
+  [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,rl,m,*b*k,r,b*k")
+       (match_operand:DI 1 "general_movsrc_operand" "r,JS,iF,m,rl,r,*b*k,T"))]
+  "TARGET_SHMEDIA
+   && (register_operand (operands[0], DImode)
+       || register_operand (operands[1], DImode))"
+  "@
+       add     %1, r63, %0
+       movi    %1, %0
+       #
+       ld%M1.q %m1, %0
+       st%M0.q %m0, %1
+       ptabs   %1, %0
+       gettr   %1, %0
+       pt      %1, %0"
+  [(set_attr "type"   "move,move,*,load,store,ptabs,move,pt")
+   (set_attr "length" "4,4,16,4,4,4,4,*")])
+
+(define_split
+  [(set (match_operand:DI 0 "arith_reg_operand" "=r")
+       (match_operand:DI 1 "immediate_operand" "s"))]
+  "TARGET_SHMEDIA && reload_completed
+   && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
+  [(set (match_dup 0) (match_dup 1))]
+  "
+{
+  rtx insn;
+
+  if (TARGET_SHMEDIA64)
+    insn = emit_insn (gen_movdi_const (operands[0], operands[1]));
+  else
+    insn = emit_insn (gen_movdi_const_32bit (operands[0], operands[1]));
+
+  REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, operands[1],
+                                       REG_NOTES (insn));
+
+  DONE;
+}")
+
+(define_expand "movdi_const"
+  [(set (match_operand:DI 0 "arith_reg_operand" "=r")
+       (const:DI (sign_extend:DI
+                  (truncate:HI
+                   (ashiftrt:DI
+                    (match_operand:DI 1 "immediate_operand" "s")
+                    (const_int 48))))))
+   (set (match_dup 0)
+       (ior:DI (ashift:DI (match_dup 0) (const_int 16))
+               (zero_extend:DI
+                (truncate:HI
+                 (const:DI
+                  (sign_extend:DI
+                   (truncate:HI
+                    (ashiftrt:SI
+                     (match_dup 1)
+                     (const_int 32)))))))))
+   (set (match_dup 0)
+       (ior:DI (ashift:DI (match_dup 0) (const_int 16))
+               (zero_extend:DI
+                (truncate:HI
+                 (const:DI
+                  (sign_extend:DI
+                   (truncate:HI
+                    (ashiftrt:SI
+                     (match_dup 1)
+                     (const_int 16)))))))))
+   (set (match_dup 0)
+       (ior:DI (ashift:DI (match_dup 0) (const_int 16))
+               (zero_extend:DI
+                (truncate:HI
+                 (const:DI
+                  (sign_extend:DI
+                   (truncate:HI
+                    (match_dup 1))))))))]
+  "TARGET_SHMEDIA64 && reload_completed
+   && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
+  "
+{
+  if (GET_CODE (operands[1]) == LABEL_REF
+      && GET_CODE (XEXP (operands[1], 0)) == CODE_LABEL)
+    LABEL_NUSES (XEXP (operands[1], 0)) += 4;
+  else if (GOTOFF_P (operands[1])
+          && GET_CODE (XVECEXP (XEXP (operands[1], 0), 0, 0)) == LABEL_REF
+          && (GET_CODE (XEXP (XVECEXP (XEXP (operands[1], 0), 0, 0), 0))
+              == CODE_LABEL))
+    LABEL_NUSES (XEXP (XVECEXP (XEXP (operands[1], 0), 0, 0), 0)) += 4;
+}")
+
+(define_expand "movdi_const_32bit"
+  [(set (match_operand:DI 0 "arith_reg_operand" "=r")
+       (const:DI (sign_extend:DI
+                  (truncate:HI
+                   (ashiftrt:DI
+                    (match_operand:DI 1 "immediate_operand" "s")
+                    (const_int 16))))))
+   (set (match_dup 0)
+       (ior:DI (ashift:DI (match_dup 0) (const_int 16))
+               (zero_extend:DI
+                (truncate:HI
+                 (const:DI
+                  (sign_extend:DI
+                   (truncate:HI
+                    (match_dup 1))))))))]
+  "TARGET_SHMEDIA32 && reload_completed
+   && MOVI_SHORI_BASE_OPERAND_P (operands[1])"
+  "
+{
+  if (GET_CODE (operands[1]) == LABEL_REF
+      && GET_CODE (XEXP (operands[1], 0)) == CODE_LABEL)
+    LABEL_NUSES (XEXP (operands[1], 0)) += 2;
+  else if (GOTOFF_P (operands[1])
+          && GET_CODE (XVECEXP (XEXP (operands[1], 0), 0, 0)) == LABEL_REF
+          && (GET_CODE (XEXP (XVECEXP (XEXP (operands[1], 0), 0, 0), 0))
+              == CODE_LABEL))
+    LABEL_NUSES (XEXP (XVECEXP (XEXP (operands[1], 0), 0, 0), 0)) += 2;
+}")
+
+(define_expand "movdi_const_16bit"
+  [(set (match_operand:DI 0 "arith_reg_operand" "=r")
+       (const:DI (sign_extend:DI
+                  (truncate:HI
+                   (match_operand:DI 1 "immediate_operand" "s")))))]
+  "TARGET_SHMEDIA && flag_pic && reload_completed
+   && GET_CODE (operands[1]) == SYMBOL_REF"
+  "")
+
+(define_split
+  [(set (match_operand:DI 0 "arith_reg_operand" "=r")
+       (match_operand:DI 1 "immediate_operand" "i"))]
+  "TARGET_SHMEDIA && reload_completed
+   && GET_CODE (operands[1]) == CONST_INT
+   && ! CONST_OK_FOR_J (INTVAL (operands[1]))"
+  [(set (match_dup 0) (match_dup 2))
+  (set (match_dup 0)
+       (ior:DI (ashift:DI (match_dup 0) (const_int 16))
+              (zero_extend:DI (truncate:HI (match_dup 1)))))]
+  "
+{
+  unsigned HOST_WIDE_INT low = INTVAL (operands[1]);
+  unsigned HOST_WIDE_INT val = low;
+  unsigned HOST_WIDE_INT sign;
+
+  /* Sign-extend the 16 least-significant bits.  */
+  val &= 0xffff;
+  val ^= 0x8000;
+  val -= 0x8000;
+  operands[1] = GEN_INT (val);
+
+  /* Arithmetic shift right the word by 16 bits.  */
+  low >>= 16;
+  sign = 1;
+  sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
+  low ^= sign;
+  low -= sign;
+  operands[2] = GEN_INT (low);
+}")
+
+(define_split
+  [(set (match_operand:DI 0 "arith_reg_operand" "=r")
+       (match_operand:DI 1 "immediate_operand" "F"))]
+  "TARGET_SHMEDIA && reload_completed
+   && GET_CODE (operands[1]) == CONST_DOUBLE"
+  [(set (match_dup 0) (match_dup 2))
+  (set (match_dup 0)
+       (ior:DI (ashift:DI (match_dup 0) (const_int 16))
+              (zero_extend:DI (truncate:HI (match_dup 1)))))]
+  "
+{
+  unsigned HOST_WIDE_INT low = CONST_DOUBLE_LOW (operands[1]);
+  unsigned HOST_WIDE_INT high = CONST_DOUBLE_HIGH (operands[1]);
+  unsigned HOST_WIDE_INT val = low;
+  unsigned HOST_WIDE_INT sign;
+
+  /* Sign-extend the 16 least-significant bits.  */
+  val &= 0xffff;
+  val ^= 0x8000;
+  val -= 0x8000;
+  operands[1] = GEN_INT (val);
+
+  /* Arithmetic shift right the double-word by 16 bits.  */
+  low >>= 16;
+  low |= (high & 0xffff) << (HOST_BITS_PER_WIDE_INT - 16);
+  high >>= 16;
+  sign = 1;
+  sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1);
+  high ^= sign;
+  high -= sign;
+
+  /* This will only be true if high is a sign-extension of low, i.e.,
+     it must be either 0 or (unsigned)-1, and be zero iff the
+     most-significant bit of low is set.  */
+  if (high + (low >> (HOST_BITS_PER_WIDE_INT - 1)) == 0)
+    operands[2] = GEN_INT (low);
+  else
+    operands[2] = immed_double_const (low, high, DImode);
+}")
+
+(define_insn "*shori_media"
+  [(set (match_operand:DI 0 "arith_reg_operand" "=r,r")
+       (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0,0")
+                          (const_int 16))
+               (zero_extend:DI
+                (truncate:HI
+                 (match_operand:DI 2 "immediate_operand" "JS,nF")))))]
+  "TARGET_SHMEDIA"
+  "@
+       shori   %u2, %0
+       #")
+
 (define_expand "movdi"
   [(set (match_operand:DI 0 "general_movdst_operand" "")
        (match_operand:DI 1 "general_movsrc_operand" ""))]
   ""
   "{ if (prepare_move_operands (operands, DImode)) DONE; }")
 
+(define_insn "movdf_media"
+  [(set (match_operand:DF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
+       (match_operand:DF 1 "general_movsrc_operand" "f,r,f,r,F,m,f,m,r"))]
+  "TARGET_SHMEDIA_FPU
+   && (register_operand (operands[0], DFmode)
+       || register_operand (operands[1], DFmode))"
+  "@
+       fmov.d  %1, %0
+       fmov.qd %1, %0
+       fmov.dq %1, %0
+       add     %1, r63, %0
+       #
+       fld%M1.d        %m1, %0
+       fst%M0.d        %m0, %1
+       ld%M1.q %m1, %0
+       st%M0.q %m0, %1"
+  [(set_attr "type" "move,move,move,move,*,load,store,load,store")])
+
+(define_insn "movdf_media_nofpu"
+  [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
+       (match_operand:DF 1 "general_movsrc_operand" "r,F,m,r"))]
+  "TARGET_SHMEDIA
+   && (register_operand (operands[0], DFmode)
+       || register_operand (operands[1], DFmode))"
+  "@
+       add     %1, r63, %0
+       #
+       ld%M1.q %m1, %0
+       st%M0.q %m0, %1"
+  [(set_attr "type" "move,*,load,store")])
+
+(define_split
+  [(set (match_operand:DF 0 "arith_reg_operand" "")
+       (match_operand:DF 1 "immediate_operand" ""))]
+  "TARGET_SHMEDIA && reload_completed"
+  [(set (match_dup 3) (match_dup 2))]
+  "
+{
+  int endian = WORDS_BIG_ENDIAN ? 1 : 0;
+  long values[2];
+  REAL_VALUE_TYPE value;
+
+  REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]);
+  REAL_VALUE_TO_TARGET_DOUBLE (value, values);
+
+  if (HOST_BITS_PER_WIDE_INT >= 64)
+    operands[2] = immed_double_const ((unsigned long) values[endian]
+                                     | ((HOST_WIDE_INT) values[1 - endian]
+                                        << 32), 0, DImode);
+  else if (HOST_BITS_PER_WIDE_INT == 32)
+    operands[2] = immed_double_const (values[endian], values[1 - endian],
+                                     DImode);
+  else
+    abort ();
+
+  operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
+}")
+
 ;; ??? This should be a define expand.
 
 (define_insn "movdf_k"
   [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
        (match_operand:DF 1 "general_movsrc_operand" "r,FQ,m,r"))]
-  "(! TARGET_SH4 || reload_completed
-    /* ??? We provide some insn so that direct_{load,store}[DFmode] get set */
-    || (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == 3)
-    || (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == 3))
+  "TARGET_SH1
+   && (! TARGET_SH4 || reload_completed
+       /* ??? We provide some insn so that direct_{load,store}[DFmode] get set */
+       || (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == 3)
+       || (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == 3))
    && (arith_reg_operand (operands[0], DFmode)
        || arith_reg_operand (operands[1], DFmode))"
   "* return output_movedouble (insn, operands, DFmode);"
       (if_then_else (eq_attr "fmovd" "yes") (const_int 2) (const_int 6))
       (const_int 4)
       (const_int 8) (const_int 8) ;; these need only 8 bytes for @(r0,rn)
-      (const_int 8) (const_int 8)])
+      ;; We can't use 4-byte push/pop on SHcompact, so we have to
+      ;; increment or decrement r15 explicitly.
+      (if_then_else
+       (ne (symbol_ref "TARGET_SHCOMPACT") (const_int 0))
+       (const_int 10) (const_int 8))
+      (if_then_else
+       (ne (symbol_ref "TARGET_SHCOMPACT") (const_int 0))
+       (const_int 10) (const_int 8))])
    (set_attr "type" "fmove,move,pcload,load,store,pcload,load,store,load,load")
    (set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
                                           (const_string "double")
 {
   rtx insn, tos;
 
-  tos = gen_rtx (MEM, DFmode, gen_rtx (PRE_DEC, Pmode, stack_pointer_rtx));
+  if (TARGET_SH5 && true_regnum (operands[1]) < 16)
+    {
+      emit_move_insn (stack_pointer_rtx,
+                     plus_constant (stack_pointer_rtx, -8));
+      tos = gen_rtx_MEM (DFmode, stack_pointer_rtx);
+    }
+  else
+    tos = gen_rtx (MEM, DFmode, gen_rtx (PRE_DEC, Pmode, stack_pointer_rtx));
   insn = emit_insn (gen_movdf_i4 (tos, operands[1], operands[2]));
-  REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_INC, stack_pointer_rtx, NULL_RTX);
-  tos = gen_rtx (MEM, DFmode, gen_rtx (POST_INC, Pmode, stack_pointer_rtx));
+  if (! (TARGET_SH5 && true_regnum (operands[1]) < 16))
+    REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_INC, stack_pointer_rtx, NULL_RTX);
+  if (TARGET_SH5 && true_regnum (operands[0]) < 16)
+    tos = gen_rtx_MEM (DFmode, stack_pointer_rtx);
+  else
+    tos = gen_rtx (MEM, DFmode, gen_rtx (POST_INC, Pmode, stack_pointer_rtx));
   insn = emit_insn (gen_movdf_i4 (operands[0], tos, operands[2]));
-  REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_INC, stack_pointer_rtx, NULL_RTX);
+  if (TARGET_SH5 && true_regnum (operands[0]) < 16)
+    emit_move_insn (stack_pointer_rtx, plus_constant (stack_pointer_rtx, 8));
+  else
+    REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_INC, stack_pointer_rtx, NULL_RTX);
   DONE;
 }")
 
                   (match_operand:DF 1 "immediate_operand" "FQ"))
              (use (reg:PSI FPSCR_REG))
              (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
-  ""
+  "TARGET_SH1"
   "")
 
 (define_expand "reload_outdf"
   [(parallel [(set (match_operand:DF 0 "register_operand" "=r,f")
                   (match_operand:DF 1 "register_operand" "af,r"))
              (clobber (match_operand:SI 2 "register_operand" "=&y,y"))])]
-  ""
+  "TARGET_SH1"
   "")
 
 ;; Simplify no-op moves.
 (define_split
   [(set (match_operand:DF 0 "general_movdst_operand" "")
        (match_operand:DF 1 "general_movsrc_operand" ""))]
-  "reload_completed"
+  "TARGET_SH1 && reload_completed"
   [(set (match_dup 2) (match_dup 3))
    (set (match_dup 4) (match_dup 5))]
   "
   [(set (match_operand:SI 0 "register_operand" "")
        (match_operand:SI 1 "" ""))
    (clobber (match_operand 2 "register_operand" ""))]
-  "! reload_in_progress && ! reload_completed"
+  "TARGET_SH1 && ! reload_in_progress && ! reload_completed"
   [(use (reg:SI R0_REG))]
   "
 {
   [(set (match_operand:SI 1 "" "")
        (match_operand:SI 0 "register_operand" ""))
    (clobber (match_operand 2 "register_operand" ""))]
-  "! reload_in_progress && ! reload_completed"
+  "TARGET_SH1 && ! reload_in_progress && ! reload_completed"
   [(use (reg:SI R0_REG))]
   "
 {
   "
 {
   if (prepare_move_operands (operands, DFmode)) DONE;
+  if (TARGET_SHMEDIA)
+    {
+      if (TARGET_SHMEDIA_FPU)
+       emit_insn (gen_movdf_media (operands[0], operands[1]));
+      else
+       emit_insn (gen_movdf_media_nofpu (operands[0], operands[1]));
+      DONE;
+    }
   if (TARGET_SH4)
     {
       emit_df_insn (gen_movdf_i4 (operands[0], operands[1], get_fpscr_rtx ()));
     }
 }")
 
+(define_insn "movv2sf_i"
+  [(set (match_operand:V2SF 0 "nonimmediate_operand" "=f,f,m")
+       (match_operand:V2SF 1 "nonimmediate_operand" "f,m,f"))]
+  "TARGET_SHMEDIA_FPU
+   && (fp_arith_reg_operand (operands[0], V2SFmode)
+       || fp_arith_reg_operand (operands[1], V2SFmode))"
+  "@
+       #
+       fld%M1.p        %m1, %0
+       fst%M0.p        %m0, %1")
+
+(define_split
+  [(set (match_operand:V2SF 0 "nonimmediate_operand" "=f")
+       (match_operand:V2SF 1 "nonimmediate_operand" "f"))]
+  "TARGET_SHMEDIA_FPU && reload_completed
+   && fp_arith_reg_operand (operands[0], V2SFmode)
+   && fp_arith_reg_operand (operands[1], V2SFmode)"
+  [(set (subreg:DF (match_dup 0) 0) (subreg:DF (match_dup 1) 0))])
+
+(define_expand "movv2sf"
+  [(set (match_operand:V2SF 0 "nonimmediate_operand" "=f,f,m")
+       (match_operand:V2SF 1 "nonimmediate_operand" "f,m,f"))]
+  "TARGET_SHMEDIA_FPU"
+  "
+{
+  if (prepare_move_operands (operands, V2SFmode))
+    DONE;
+}")
+
+(define_insn_and_split "*movv4sf_i"
+  [(set (match_operand:V4SF 0 "nonimmediate_operand" "=f,f,m")
+       (match_operand:V4SF 1 "nonimmediate_operand" "f,m,f"))]
+  "TARGET_SHMEDIA_FPU"
+  "#"
+  "&& reload_completed"
+  [(const_int 0)]
+  "
+{
+  int i;
+
+  for (i = 0; i < 4/2; i++)
+    {
+      rtx x, y;
+
+      if (GET_CODE (operands[0]) == MEM)
+       x = gen_rtx_MEM (V2SFmode,
+                        plus_constant (XEXP (operands[0], 0),
+                                       i * GET_MODE_SIZE (V2SFmode)));
+      else
+       {
+         x = gen_rtx_SUBREG (V2SFmode, operands[0], i * 2);
+         alter_subreg (&x);
+       }
+
+      if (GET_CODE (operands[1]) == MEM)
+       y = gen_rtx_MEM (V2SFmode,
+                        plus_constant (XEXP (operands[1], 0),
+                                       i * GET_MODE_SIZE (V2SFmode)));
+      else
+       {
+         y = gen_rtx_SUBREG (V2SFmode, operands[1], i * 2);
+         alter_subreg (&y);
+       }
+
+      emit_insn (gen_movv2sf_i (x, y));
+    }
+
+  DONE;
+}"
+  [(set_attr "length" "8")])
+  
+(define_expand "movv4sf"
+  [(set (match_operand:V4SF 0 "nonimmediate_operand" "=f,f,m")
+       (match_operand:V4SF 1 "nonimmediate_operand" "f,m,f"))]
+  "TARGET_SHMEDIA_FPU"
+  "
+{
+  if (prepare_move_operands (operands, V4SFmode))
+    DONE;
+}")
+
+(define_insn_and_split "*movv16sf_i"
+  [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
+       (match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
+  "TARGET_SHMEDIA_FPU"
+  "#"
+  "&& reload_completed"
+  [(const_int 0)]
+  "
+{
+  int i;
+
+  for (i = 0; i < 16/2; i++)
+    {
+      rtx x,y;
+
+      if (GET_CODE (operands[0]) == MEM)
+       x = gen_rtx_MEM (V2SFmode,
+                        plus_constant (XEXP (operands[0], 0),
+                                       i * GET_MODE_SIZE (V2SFmode)));
+      else
+       {
+         x = gen_rtx_SUBREG (V2SFmode, operands[0], i * 2);
+         alter_subreg (&x);
+       }
+
+      if (GET_CODE (operands[1]) == MEM)
+       y = gen_rtx_MEM (V2SFmode,
+                        plus_constant (XEXP (operands[1], 0),
+                                       i * GET_MODE_SIZE (V2SFmode)));
+      else
+       {
+         y = gen_rtx_SUBREG (V2SFmode, operands[1], i * 2);
+         alter_subreg (&y);
+       }
+
+      emit_insn (gen_movv2sf_i (x, y));
+    }
+
+  DONE;
+}"
+  [(set_attr "length" "32")])
+  
+(define_expand "movv16sf"
+  [(set (match_operand:V16SF 0 "nonimmediate_operand" "=f,f,m")
+       (match_operand:V16SF 1 "nonimmediate_operand" "f,m,f"))]
+  "TARGET_SHMEDIA_FPU"
+  "
+{
+  if (prepare_move_operands (operands, V16SFmode))
+    DONE;
+}")
+
+(define_insn "movsf_media"
+  [(set (match_operand:SF 0 "general_movdst_operand" "=f,f,r,r,r,f,m,r,m")
+       (match_operand:SF 1 "general_movsrc_operand" "f,r,f,r,F,m,f,m,r"))]
+  "TARGET_SHMEDIA_FPU
+   && (register_operand (operands[0], SFmode)
+       || register_operand (operands[1], SFmode))"
+  "@
+       fmov.s  %1, %0
+       fmov.ls %1, %0
+       fmov.sl %1, %0
+       add     %1, r63, %0
+       #
+       fld%M1.s        %m1, %0
+       fst%M0.s        %m0, %1
+       ld%M1.l %m1, %0
+       st%M0.l %m0, %1"
+  [(set_attr "type" "move,move,move,move,*,load,store,load,store")])
+
+(define_insn "movsf_media_nofpu"
+  [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,m")
+       (match_operand:SF 1 "general_movsrc_operand" "r,F,m,r"))]
+  "TARGET_SHMEDIA
+   && (register_operand (operands[0], SFmode)
+       || register_operand (operands[1], SFmode))"
+  "@
+       add     %1, r63, %0
+       #
+       ld%M1.l %m1, %0
+       st%M0.l %m0, %1"
+  [(set_attr "type" "move,*,load,store")])
+
+(define_split
+  [(set (match_operand:SF 0 "arith_reg_operand" "")
+       (match_operand:SF 1 "immediate_operand" ""))]
+  "TARGET_SHMEDIA && reload_completed"
+  [(set (match_dup 3) (match_dup 2))]
+  "
+{
+  long values;
+  REAL_VALUE_TYPE value;
+
+  REAL_VALUE_FROM_CONST_DOUBLE (value, operands[1]);
+  REAL_VALUE_TO_TARGET_SINGLE (value, values);
+  operands[2] = GEN_INT (values);
+  
+  operands[3] = gen_rtx_REG (DImode, true_regnum (operands[0]));
+}")
 
 (define_insn "movsf_i"
   [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,r,m,l,r")
        (match_operand:SF 1 "general_movsrc_operand"  "r,I,FQ,mr,r,r,l"))]
-  "
-   (! TARGET_SH3E
-    /* ??? We provide some insn so that direct_{load,store}[SFmode] get set */
-    || (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == 3)
-    || (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == 3))
+  "TARGET_SH1
+   && (! TARGET_SH3E
+       /* ??? We provide some insn so that direct_{load,store}[SFmode] get set */
+       || (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == 3)
+       || (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == 3))
    && (arith_reg_operand (operands[0], SFmode)
        || arith_reg_operand (operands[1], SFmode))"
   "@
        (match_operand:SF 1 "register_operand" ""))
    (use (match_operand:PSI 2 "fpscr_operand" "c"))
    (clobber (reg:SI FPUL_REG))]
-  ""
+  "TARGET_SH1"
   [(parallel [(set (reg:SF FPUL_REG) (match_dup 1))
              (use (match_dup 2))
              (clobber (scratch:SI))])
 {
   if (prepare_move_operands (operands, SFmode))
     DONE;
+  if (TARGET_SHMEDIA)
+    {
+      if (TARGET_SHMEDIA_FPU)
+       emit_insn (gen_movsf_media (operands[0], operands[1]));
+      else
+       emit_insn (gen_movsf_media_nofpu (operands[0], operands[1]));
+      DONE;
+    }
   if (TARGET_SH3E)
     {
       emit_sf_insn (gen_movsf_ie (operands[0], operands[1], get_fpscr_rtx ()));
                   (match_operand:SF 1 "immediate_operand" "FQ"))
              (use (reg:PSI FPSCR_REG))
              (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
-  ""
+  "TARGET_SH1"
   "")
 
 (define_expand "reload_insi"
   [(parallel [(set (match_operand:SF 0 "register_operand" "=y")
                   (match_operand:SF 1 "immediate_operand" "FQ"))
              (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
-  ""
+  "TARGET_SH1"
   "")
 
 (define_insn "*movsi_y"
   [(set (match_operand:SI 0 "register_operand" "")
        (match_operand:SI 1 "immediate_operand" ""))
    (clobber (match_operand:SI 2 "register_operand" ""))]
-  ""
+  "TARGET_SH1"
   [(set (match_dup 2) (match_dup 1))
    (set (match_dup 0) (match_dup 2))]
   "")
   [(set (match_operand:SI 0 "register_operand" "")
        (match_operand:SI 1 "memory_operand" ""))
    (clobber (reg:SI R0_REG))]
-  ""
+  "TARGET_SH1"
   [(set (match_dup 0) (match_dup 1))]
   "")
 \f
   [(set (pc) (if_then_else (ne (reg:SI T_REG) (const_int 0))
                           (label_ref (match_operand 0 "" ""))
                           (pc)))]
-  ""
+  "TARGET_SH1"
   "* return output_branch (1, insn, operands);"
   [(set_attr "type" "cbranch")])
 
   [(set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
                           (label_ref (match_operand 0 "" ""))
                           (pc)))]
-  ""
+  "TARGET_SH1"
   "* return output_branch (0, insn, operands);"
   [(set_attr "type" "cbranch")])
 
 ;; unwanted matches with redundant_insn.
 (define_insn "block_branch_redirect"
   [(set (pc) (unspec [(match_operand 0 "const_int_operand" "")] UNSPEC_BBR))]
-  ""
+  "TARGET_SH1"
   ""
   [(set_attr "length" "0")])
 
 (define_insn "indirect_jump_scratch"
   [(set (match_operand 0 "register_operand" "=r")
        (unspec [(match_operand 1 "const_int_operand" "")] UNSPEC_BBR))]
-  ""
+  "TARGET_SH1"
   ""
   [(set_attr "length" "0")])
 \f
 ;; Conditional branch insns
 
-(define_expand "beq"
+(define_expand "beq_media"
   [(set (pc)
-       (if_then_else (ne (reg:SI T_REG) (const_int 0))
-                     (label_ref (match_operand 0 "" ""))
+       (if_then_else (eq (match_operand:DI 1 "arith_reg_operand" "r,r")
+                         (match_operand:DI 2 "arith_operand" "r,O"))
+                     (label_ref:DI (match_operand 0 "" ""))
                      (pc)))]
-  ""
-  "from_compare (operands, EQ);")
+  "TARGET_SHMEDIA"
+  "")
 
-(define_expand "bne"
+(define_insn "beq_media_i"
   [(set (pc)
-       (if_then_else (eq (reg:SI T_REG) (const_int 0))
-                     (label_ref (match_operand 0 "" ""))
+       (if_then_else (eq (match_operand:DI 1 "arith_reg_operand" "r,r")
+                         (match_operand:DI 2 "arith_operand" "r,O"))
+                     (match_operand:DI 0 "target_operand" "b,b")
                      (pc)))]
-  ""
-  "from_compare (operands, EQ);")
+  "TARGET_SHMEDIA"
+  "@
+       beq     %1, %2, %0
+       beqi    %1, %2, %0")
 
-(define_expand "bgt"
+(define_expand "bne_media"
   [(set (pc)
-       (if_then_else (ne (reg:SI T_REG) (const_int 0))
-                     (label_ref (match_operand 0 "" ""))
+       (if_then_else (ne (match_operand:DI 1 "arith_reg_operand" "r,r")
+                         (match_operand:DI 2 "arith_operand" "r,O"))
+                     (label_ref:DI (match_operand 0 "" ""))
                      (pc)))]
-  ""
-  "from_compare (operands, GT);")
+  "TARGET_SHMEDIA"
+  "")
 
-(define_expand "blt"
+(define_insn "bne_media_i"
   [(set (pc)
-       (if_then_else (eq (reg:SI T_REG) (const_int 0))
-                     (label_ref (match_operand 0 "" ""))
+       (if_then_else (ne (match_operand:DI 1 "arith_reg_operand" "r,r")
+                         (match_operand:DI 2 "arith_operand" "r,O"))
+                     (match_operand:DI 0 "target_operand" "b,b")
                      (pc)))]
-  ""
-  "
-{
-  if (GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT)
-    {
-      rtx tmp = sh_compare_op0;
-      sh_compare_op0 = sh_compare_op1;
-      sh_compare_op1 = tmp;
-      emit_insn (gen_bgt (operands[0]));
-      DONE;
-    }
-  from_compare (operands, GE);
-}")
+  "TARGET_SHMEDIA"
+  "@
+       bne     %1, %2, %0
+       bnei    %1, %2, %0")
 
-(define_expand "ble"
+(define_expand "bgt_media"
   [(set (pc)
-       (if_then_else (eq (reg:SI T_REG) (const_int 0))
-                     (label_ref (match_operand 0 "" ""))
+       (if_then_else (gt (match_operand:DI 1 "arith_reg_operand" "r")
+                         (match_operand:DI 2 "arith_reg_operand" "r"))
+                     (label_ref:DI (match_operand 0 "" ""))
                      (pc)))]
-  ""
-  "
-{
-  if (TARGET_SH3E
-      && TARGET_IEEE
+  "TARGET_SHMEDIA"
+  "")
+
+(define_insn "bgt_media_i"
+  [(set (pc)
+       (if_then_else (gt (match_operand:DI 1 "arith_reg_operand" "r")
+                         (match_operand:DI 2 "arith_reg_operand" "r"))
+                     (match_operand:DI 0 "target_operand" "b")
+                     (pc)))]
+  "TARGET_SHMEDIA"
+  "bgt %1, %2, %0")
+
+(define_expand "bge_media"
+  [(set (pc)
+       (if_then_else (ge (match_operand:DI 1 "arith_reg_operand" "r")
+                         (match_operand:DI 2 "arith_reg_operand" "r"))
+                     (label_ref:DI (match_operand 0 "" ""))
+                     (pc)))]
+  "TARGET_SHMEDIA"
+  "")
+
+(define_insn "bge_media_i"
+  [(set (pc)
+       (if_then_else (ge (match_operand:DI 1 "arith_reg_operand" "r")
+                         (match_operand:DI 2 "arith_reg_operand" "r"))
+                     (match_operand:DI 0 "target_operand" "b")
+                     (pc)))]
+  "TARGET_SHMEDIA"
+  "bge %1, %2, %0")
+
+(define_expand "bgtu_media"
+  [(set (pc)
+       (if_then_else (gtu (match_operand:DI 1 "arith_reg_operand" "r")
+                          (match_operand:DI 2 "arith_reg_operand" "r"))
+                     (label_ref:DI (match_operand 0 "" ""))
+                     (pc)))]
+  "TARGET_SHMEDIA"
+  "")
+
+(define_insn "bgtu_media_i"
+  [(set (pc)
+       (if_then_else (gtu (match_operand:DI 1 "arith_reg_operand" "r")
+                          (match_operand:DI 2 "arith_reg_operand" "r"))
+                     (match_operand:DI 0 "target_operand" "b")
+                     (pc)))]
+  "TARGET_SHMEDIA"
+  "bgtu        %1, %2, %0")
+
+(define_expand "bgeu_media"
+  [(set (pc)
+       (if_then_else (geu (match_operand:DI 1 "arith_reg_operand" "r")
+                          (match_operand:DI 2 "arith_reg_operand" "r"))
+                     (label_ref:DI (match_operand 0 "" ""))
+                     (pc)))]
+  "TARGET_SHMEDIA"
+  "")
+
+(define_insn "bgeu_media_i"
+  [(set (pc)
+       (if_then_else (geu (match_operand:DI 1 "arith_reg_operand" "r")
+                          (match_operand:DI 2 "arith_reg_operand" "r"))
+                     (match_operand:DI 0 "target_operand" "b")
+                     (pc)))]
+  "TARGET_SHMEDIA"
+  "bgeu        %1, %2, %0")
+
+;; These are only needed to make invert_jump() happy.
+(define_insn "*ble_media_i"
+  [(set (pc)
+       (if_then_else (le (match_operand:DI 1 "arith_reg_operand" "r")
+                         (match_operand:DI 2 "arith_reg_operand" "r"))
+                     (match_operand:DI 0 "target_operand" "b")
+                     (pc)))]
+  "TARGET_SHMEDIA"
+  "bge %2, %1, %0")
+
+(define_insn "*blt_media_i"
+  [(set (pc)
+       (if_then_else (lt (match_operand:DI 1 "arith_reg_operand" "r")
+                         (match_operand:DI 2 "arith_reg_operand" "r"))
+                     (match_operand:DI 0 "target_operand" "b")
+                     (pc)))]
+  "TARGET_SHMEDIA"
+  "bgt %2, %1, %0")
+
+(define_insn "*bleu_media_i"
+  [(set (pc)
+       (if_then_else (leu (match_operand:DI 1 "arith_reg_operand" "r")
+                          (match_operand:DI 2 "arith_reg_operand" "r"))
+                     (match_operand:DI 0 "target_operand" "b")
+                     (pc)))]
+  "TARGET_SHMEDIA"
+  "bgeu        %2, %1, %0")
+
+(define_insn "*bltu_media_i"
+  [(set (pc)
+       (if_then_else (ltu (match_operand:DI 1 "arith_reg_operand" "r")
+                          (match_operand:DI 2 "arith_reg_operand" "r"))
+                     (match_operand:DI 0 "target_operand" "b")
+                     (pc)))]
+  "TARGET_SHMEDIA"
+  "bgtu        %2, %1, %0")
+
+(define_expand "beq"
+  [(set (pc)
+       (if_then_else (ne (reg:SI T_REG) (const_int 0))
+                     (label_ref (match_operand 0 "" ""))
+                     (pc)))]
+  ""
+  "
+{
+  if (TARGET_SHMEDIA)
+    {
+      if (GET_MODE (sh_compare_op0) != DImode)
+       {
+         rtx tmp = gen_reg_rtx (DImode);
+
+         emit_insn (gen_seq (tmp));
+         emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
+         DONE;
+       }
+
+      sh_compare_op0 = force_reg (DImode, sh_compare_op0);
+      emit_jump_insn (gen_beq_media (operands[0],
+                                    sh_compare_op0, sh_compare_op1));
+      DONE;
+    }
+
+  from_compare (operands, EQ);
+}")
+
+(define_expand "bne"
+  [(set (pc)
+       (if_then_else (eq (reg:SI T_REG) (const_int 0))
+                     (label_ref (match_operand 0 "" ""))
+                     (pc)))]
+  ""
+  "
+{
+  if (TARGET_SHMEDIA)
+    {
+      if (GET_MODE (sh_compare_op0) != DImode)
+       {
+         rtx tmp = gen_reg_rtx (DImode);
+
+         emit_insn (gen_seq (tmp));
+         emit_jump_insn (gen_beq_media (operands[0], tmp, const0_rtx));
+         DONE;
+       }
+
+      sh_compare_op0 = force_reg (DImode, sh_compare_op0);
+      emit_jump_insn (gen_bne_media (operands[0],
+                                    sh_compare_op0, sh_compare_op1));
+      DONE;
+    }
+
+  from_compare (operands, EQ);
+}")
+
+(define_expand "bgt"
+  [(set (pc)
+       (if_then_else (ne (reg:SI T_REG) (const_int 0))
+                     (label_ref (match_operand 0 "" ""))
+                     (pc)))]
+  ""
+  "
+{
+  if (TARGET_SHMEDIA)
+    {
+      if (GET_MODE (sh_compare_op0) != DImode)
+       {
+         rtx tmp = gen_reg_rtx (DImode);
+
+         emit_insn (gen_sgt (tmp));
+         emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
+         DONE;
+       }
+
+      sh_compare_op0 = force_reg (DImode, sh_compare_op0);
+      sh_compare_op1 = force_reg (DImode, sh_compare_op1);
+      emit_jump_insn (gen_bgt_media (operands[0],
+                                    sh_compare_op0, sh_compare_op1));
+      DONE;
+    }
+
+  from_compare (operands, GT);
+}")
+
+(define_expand "blt"
+  [(set (pc)
+       (if_then_else (eq (reg:SI T_REG) (const_int 0))
+                     (label_ref (match_operand 0 "" ""))
+                     (pc)))]
+  ""
+  "
+{
+  if (TARGET_SHMEDIA)
+    {
+      if (GET_MODE (sh_compare_op0) != DImode)
+       {
+         rtx tmp = gen_reg_rtx (DImode);
+
+         emit_insn (gen_slt (tmp));
+         emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
+         DONE;
+       }
+
+      sh_compare_op0 = force_reg (DImode, sh_compare_op0);
+      sh_compare_op1 = force_reg (DImode, sh_compare_op1);
+      emit_jump_insn (gen_bgt_media (operands[0],
+                                    sh_compare_op1, sh_compare_op0));
+      DONE;
+    }
+
+  if (GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT)
+    {
+      rtx tmp = sh_compare_op0;
+      sh_compare_op0 = sh_compare_op1;
+      sh_compare_op1 = tmp;
+      emit_insn (gen_bgt (operands[0]));
+      DONE;
+    }
+  from_compare (operands, GE);
+}")
+
+(define_expand "ble"
+  [(set (pc)
+       (if_then_else (eq (reg:SI T_REG) (const_int 0))
+                     (label_ref (match_operand 0 "" ""))
+                     (pc)))]
+  ""
+  "
+{
+  if (TARGET_SHMEDIA)
+    {
+      if (GET_MODE (sh_compare_op0) != DImode)
+       {
+         rtx tmp = gen_reg_rtx (DImode);
+
+         emit_insn (gen_sle (tmp));
+         emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
+         DONE;
+       }
+
+      sh_compare_op0 = force_reg (DImode, sh_compare_op0);
+      sh_compare_op1 = force_reg (DImode, sh_compare_op1);
+      emit_jump_insn (gen_bge_media (operands[0],
+                                    sh_compare_op1, sh_compare_op0));
+      DONE;
+    }
+
+  if (TARGET_SH3E
+      && TARGET_IEEE
       && GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT)
     {
       rtx tmp = sh_compare_op0;
   ""
   "
 {
+  if (TARGET_SHMEDIA)
+    {
+      if (GET_MODE (sh_compare_op0) != DImode)
+       {
+         rtx tmp = gen_reg_rtx (DImode);
+
+         emit_insn (gen_sge (tmp));
+         emit_jump_insn (gen_bne_media (operands[0], tmp, const0_rtx));
+         DONE;
+       }
+
+      sh_compare_op0 = force_reg (DImode, sh_compare_op0);
+      sh_compare_op1 = force_reg (DImode, sh_compare_op1);
+      emit_jump_insn (gen_bge_media (operands[0],
+                                    sh_compare_op0, sh_compare_op1));
+      DONE;
+    }
+
   if (TARGET_SH3E
       && ! TARGET_IEEE
       && GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT)
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
   ""
-  "from_compare (operands, GTU); ")
+  "
+{
+  if (TARGET_SHMEDIA)
+    {
+      sh_compare_op0 = force_reg (DImode, sh_compare_op0);
+      sh_compare_op1 = force_reg (DImode, sh_compare_op1);
+      emit_jump_insn (gen_bgtu_media (operands[0],
+                                     sh_compare_op0, sh_compare_op1));
+      DONE;
+    }
+
+  from_compare (operands, GTU);
+}")
 
 (define_expand "bltu"
   [(set (pc)
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
   ""
-  "from_compare (operands, GEU);")
+  "
+{
+  if (TARGET_SHMEDIA)
+    {
+      sh_compare_op0 = force_reg (DImode, sh_compare_op0);
+      sh_compare_op1 = force_reg (DImode, sh_compare_op1);
+      emit_jump_insn (gen_bgtu_media (operands[0],
+                                     sh_compare_op1, sh_compare_op0));
+      DONE;
+    }
+
+  from_compare (operands, GEU);
+}")
 
 (define_expand "bgeu"
   [(set (pc)
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
   ""
-  "from_compare (operands, GEU);")
+  "
+{
+  if (TARGET_SHMEDIA)
+    {
+      sh_compare_op0 = force_reg (DImode, sh_compare_op0);
+      sh_compare_op1 = force_reg (DImode, sh_compare_op1);
+      emit_jump_insn (gen_bgeu_media (operands[0],
+                                     sh_compare_op0, sh_compare_op1));
+      DONE;
+    }
+
+  from_compare (operands, GEU);
+}")
 
 (define_expand "bleu"
   [(set (pc)
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
   ""
-  "from_compare (operands, GTU);")
+  "
+{
+  if (TARGET_SHMEDIA)
+    {
+      sh_compare_op0 = force_reg (DImode, sh_compare_op0);
+      sh_compare_op1 = force_reg (DImode, sh_compare_op1);
+      emit_jump_insn (gen_bgeu_media (operands[0],
+                                     sh_compare_op1, sh_compare_op0));
+      DONE;
+    }
+
+  from_compare (operands, GTU);
+}")
+
+(define_expand "bunordered"
+  [(set (match_dup 1) (unordered:DI (match_dup 2) (match_dup 3)))
+   (set (pc)
+       (if_then_else (ne (match_dup 1) (const_int 0))
+                     (label_ref:DI (match_operand 0 "" ""))
+                     (pc)))]
+  "TARGET_SHMEDIA"
+  "
+{
+  operands[1] = gen_reg_rtx (DImode);
+  operands[2] = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
+  operands[3] = force_reg (GET_MODE (sh_compare_op1), sh_compare_op1);
+}")
 \f
 ;; ------------------------------------------------------------------------
 ;; Jump and linkage insns
 ;; ------------------------------------------------------------------------
 
-(define_insn "jump"
+(define_insn "jump_compact"
   [(set (pc)
        (label_ref (match_operand 0 "" "")))]
-  ""
+  "TARGET_SH1"
   "*
 {
   /* The length is 16 if the delay slot is unfilled.  */
   [(set_attr "type" "jump")
    (set_attr "needs_delay_slot" "yes")])
 
+(define_insn "jump_media"
+  [(set (pc)
+       (match_operand:DI 0 "target_operand" "b"))]
+  "TARGET_SHMEDIA"
+  "blink       %0, r63")
+
+(define_expand "jump"
+  [(set (pc)
+       (label_ref (match_operand 0 "" "")))]
+  ""
+  "
+{
+  if (TARGET_SH1)
+    emit_insn (gen_jump_compact (operands[0]));
+  else if (TARGET_SHMEDIA)
+    {
+      if (reload_in_progress || reload_completed)
+       FAIL;
+      emit_insn (gen_jump_media (gen_rtx_LABEL_REF (DImode, operands[0])));
+    }
+  DONE;
+}")
+
+(define_insn "force_mode_for_call"
+  [(use (reg:PSI FPSCR_REG))]
+  "TARGET_SHCOMPACT"
+  ""
+  [(set_attr "length" "0")
+   (set (attr "fp_mode")
+       (if_then_else (eq_attr "fpu_single" "yes")
+                     (const_string "single") (const_string "double")))])
+
 (define_insn "calli"
   [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
         (match_operand 1 "" ""))
    (use (reg:PSI FPSCR_REG))
    (clobber (reg:SI PR_REG))]
-  ""
+  "TARGET_SH1"
   "jsr @%0%#"
   [(set_attr "type" "call")
    (set (attr "fp_mode")
                      (const_string "single") (const_string "double")))
    (set_attr "needs_delay_slot" "yes")])
 
+(define_insn "call_compact"
+  [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
+        (match_operand 1 "" ""))
+   (match_operand 2 "immediate_operand" "n")
+   (use (reg:SI R0_REG))
+   (use (reg:SI R1_REG))
+   (use (reg:PSI FPSCR_REG))
+   (clobber (reg:SI PR_REG))]
+  "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
+  "jsr @%0%#"
+  [(set_attr "type" "call")
+   (set (attr "fp_mode")
+       (if_then_else (eq_attr "fpu_single" "yes")
+                     (const_string "single") (const_string "double")))
+   (set_attr "needs_delay_slot" "yes")])
+
+(define_insn "call_compact_rettramp"
+  [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
+        (match_operand 1 "" ""))
+   (match_operand 2 "immediate_operand" "n")
+   (use (reg:SI R0_REG))
+   (use (reg:SI R1_REG))
+   (use (reg:PSI FPSCR_REG))
+   (clobber (reg:SI R10_REG))
+   (clobber (reg:SI PR_REG))]
+  "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
+  "jsr @%0%#"
+  [(set_attr "type" "call")
+   (set (attr "fp_mode")
+       (if_then_else (eq_attr "fpu_single" "yes")
+                     (const_string "single") (const_string "double")))
+   (set_attr "needs_delay_slot" "yes")])
+
+(define_insn "call_media"
+  [(call (mem:DI (match_operand:DI 0 "target_reg_operand" "b"))
+        (match_operand 1 "" ""))
+   (clobber (reg:DI PR_MEDIA_REG))]
+  "TARGET_SHMEDIA"
+  "blink       %0, r18")
+
 (define_insn "call_valuei"
   [(set (match_operand 0 "" "=rf")
        (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
              (match_operand 2 "" "")))
    (use (reg:PSI FPSCR_REG))
    (clobber (reg:SI PR_REG))]
-  ""
+  "TARGET_SH1"
   "jsr @%1%#"
   [(set_attr "type" "call")
    (set (attr "fp_mode")
                      (const_string "single") (const_string "double")))
    (set_attr "needs_delay_slot" "yes")])
 
+(define_insn "call_value_compact"
+  [(set (match_operand 0 "" "=rf")
+       (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
+             (match_operand 2 "" "")))
+   (match_operand 3 "immediate_operand" "n")
+   (use (reg:SI R0_REG))
+   (use (reg:SI R1_REG))
+   (use (reg:PSI FPSCR_REG))
+   (clobber (reg:SI PR_REG))]
+  "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
+  "jsr @%1%#"
+  [(set_attr "type" "call")
+   (set (attr "fp_mode")
+       (if_then_else (eq_attr "fpu_single" "yes")
+                     (const_string "single") (const_string "double")))
+   (set_attr "needs_delay_slot" "yes")])
+
+(define_insn "call_value_compact_rettramp"
+  [(set (match_operand 0 "" "=rf")
+       (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
+             (match_operand 2 "" "")))
+   (match_operand 3 "immediate_operand" "n")
+   (use (reg:SI R0_REG))
+   (use (reg:SI R1_REG))
+   (use (reg:PSI FPSCR_REG))
+   (clobber (reg:SI R10_REG))
+   (clobber (reg:SI PR_REG))]
+  "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
+  "jsr @%1%#"
+  [(set_attr "type" "call")
+   (set (attr "fp_mode")
+       (if_then_else (eq_attr "fpu_single" "yes")
+                     (const_string "single") (const_string "double")))
+   (set_attr "needs_delay_slot" "yes")])
+
+(define_insn "call_value_media"
+  [(set (match_operand 0 "" "=rf")
+       (call (mem:DI (match_operand:DI 1 "target_reg_operand" "b"))
+             (match_operand 2 "" "")))
+   (clobber (reg:DI PR_MEDIA_REG))]
+  "TARGET_SHMEDIA"
+  "blink       %1, r18")
+
 (define_expand "call"
   [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
                            (match_operand 1 "" ""))
+             (match_operand 2 "" "")
              (use (reg:PSI FPSCR_REG))
              (clobber (reg:SI PR_REG))])]
   ""
   "
 {
+  if (TARGET_SHMEDIA)
+    {
+      operands[0] = XEXP (operands[0], 0);
+      if (flag_pic && GET_CODE (operands[0]) == SYMBOL_REF)
+       {
+         if (! SYMBOL_REF_FLAG (operands[0]))
+           {
+             rtx reg = gen_reg_rtx (Pmode);
+             
+             emit_insn (gen_symGOTPLT2reg (reg, operands[0]));
+             operands[0] = reg;
+           }
+         else
+           {
+             operands[0] = gen_sym2PIC (operands[0]);
+             PUT_MODE (operands[0], Pmode);
+           }
+       }
+      if (GET_MODE (operands[0]) == SImode)
+       {
+         if (GET_CODE (operands[0]) == REG)
+           operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
+         else if (GET_CODE (operands[0]) == SUBREG)
+           {
+             operands[0] = SUBREG_REG (operands[0]);
+             if (GET_MODE (operands[0]) != DImode)
+               operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
+           }
+         else
+           {
+             operands[0] = shallow_copy_rtx (operands[0]);
+             PUT_MODE (operands[0], DImode);
+           }
+       }
+      if (! target_reg_operand (operands[0], DImode))
+       operands[0] = copy_to_mode_reg (DImode, operands[0]);
+      emit_call_insn (gen_call_media (operands[0], operands[1]));
+      DONE;
+    }
+  else if (TARGET_SHCOMPACT && operands[2] && INTVAL (operands[2]))
+    {
+      rtx cookie_rtx = operands[2];
+      long cookie = INTVAL (cookie_rtx);
+      rtx func = XEXP (operands[0], 0);
+      rtx r0, r1;
+
+      if (flag_pic)
+       {
+         if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_FLAG (func))
+           {
+             rtx reg = gen_reg_rtx (Pmode);
+
+             emit_insn (gen_symGOTPLT2reg (reg, func));
+             func = reg;
+           }
+         else
+           func = legitimize_pic_address (func, Pmode, 0);
+       }
+
+      r0 = gen_rtx_REG (SImode, R0_REG);
+      r1 = gen_rtx_REG (SImode, R1_REG);
+
+      /* Since such a call function may use all call-clobbered
+        registers, we force a mode switch earlier, so that we don't
+        run out of registers when adjusting fpscr for the call.  */
+      emit_insn (gen_force_mode_for_call ());
+
+      operands[0] = gen_rtx_SYMBOL_REF (SImode,
+                                       \"__GCC_shcompact_call_trampoline\");
+      if (flag_pic)
+       {
+         rtx reg = gen_reg_rtx (Pmode);
+
+         emit_insn (gen_symGOTPLT2reg (reg, operands[0]));
+         operands[0] = reg;
+       }
+      operands[0] = force_reg (SImode, operands[0]);
+
+      emit_move_insn (r0, func);
+      emit_move_insn (r1, cookie_rtx);
+
+      if (cookie & CALL_COOKIE_RET_TRAMP (1))
+       emit_call_insn (gen_call_compact_rettramp (operands[0], operands[1],
+                                                  operands[2]));
+      else
+       emit_call_insn (gen_call_compact (operands[0], operands[1],
+                                         operands[2]));
+
+      DONE;
+    }
+  else if (TARGET_SHCOMPACT && flag_pic
+          && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
+          && ! SYMBOL_REF_FLAG (XEXP (operands[0], 0)))
+    {
+      rtx reg = gen_reg_rtx (Pmode);
+
+      emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[0], 0)));
+      XEXP (operands[0], 0) = reg;
+    }
   if (flag_pic && TARGET_SH2
       && GET_CODE (operands[0]) == MEM
       && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
     }
   else
     operands[0] = force_reg (SImode, XEXP (operands[0], 0));
+
+  emit_call_insn (gen_calli (operands[0], operands[1]));
+  DONE;
+}")
+
+(define_insn "call_pop_compact"
+  [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
+        (match_operand 1 "" ""))
+   (match_operand 2 "immediate_operand" "n")
+   (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
+                                (match_operand 3 "immediate_operand" "n")))
+   (use (reg:SI R0_REG))
+   (use (reg:SI R1_REG))
+   (use (reg:PSI FPSCR_REG))
+   (clobber (reg:SI PR_REG))]
+  "TARGET_SHCOMPACT && ! (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
+  "jsr @%0%#"
+  [(set_attr "type" "call")
+   (set (attr "fp_mode")
+       (if_then_else (eq_attr "fpu_single" "yes")
+                     (const_string "single") (const_string "double")))
+   (set_attr "needs_delay_slot" "yes")])
+
+(define_insn "call_pop_compact_rettramp"
+  [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r"))
+        (match_operand 1 "" ""))
+   (match_operand 2 "immediate_operand" "n")
+   (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
+                                (match_operand 3 "immediate_operand" "n")))
+   (use (reg:SI R0_REG))
+   (use (reg:SI R1_REG))
+   (use (reg:PSI FPSCR_REG))
+   (clobber (reg:SI R10_REG))
+   (clobber (reg:SI PR_REG))]
+  "TARGET_SHCOMPACT && (INTVAL (operands[2]) & CALL_COOKIE_RET_TRAMP (1))"
+  "jsr @%0%#"
+  [(set_attr "type" "call")
+   (set (attr "fp_mode")
+       (if_then_else (eq_attr "fpu_single" "yes")
+                     (const_string "single") (const_string "double")))
+   (set_attr "needs_delay_slot" "yes")])
+
+(define_expand "call_pop"
+  [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
+                   (match_operand 1 "" ""))
+            (match_operand 2 "" "")
+            (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
+                                          (match_operand 3 "" "")))])]
+  "TARGET_SHCOMPACT"
+  "
+{
+  if (operands[2] && INTVAL (operands[2]))
+    {
+      rtx cookie_rtx = operands[2];
+      long cookie = INTVAL (cookie_rtx);
+      rtx func = XEXP (operands[0], 0);
+      rtx r0, r1;
+
+      if (flag_pic)
+       {
+         if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_FLAG (func))
+           {
+             rtx reg = gen_reg_rtx (Pmode);
+
+             emit_insn (gen_symGOTPLT2reg (reg, func));
+             func = reg;
+           }
+         else
+           func = legitimize_pic_address (func, Pmode, 0);
+       }
+
+      r0 = gen_rtx_REG (SImode, R0_REG);
+      r1 = gen_rtx_REG (SImode, R1_REG);
+
+      /* Since such a call function may use all call-clobbered
+        registers, we force a mode switch earlier, so that we don't
+        run out of registers when adjusting fpscr for the call.  */
+      emit_insn (gen_force_mode_for_call ());
+
+      operands[0] = gen_rtx_SYMBOL_REF (SImode,
+                                       \"__GCC_shcompact_call_trampoline\");
+      if (flag_pic)
+       {
+         rtx reg = gen_reg_rtx (Pmode);
+
+         emit_insn (gen_symGOTPLT2reg (reg, operands[0]));
+         operands[0] = reg;
+       }
+      operands[0] = force_reg (SImode, operands[0]);
+
+      emit_move_insn (r0, func);
+      emit_move_insn (r1, cookie_rtx);
+
+      if (cookie & CALL_COOKIE_RET_TRAMP (1))
+       emit_call_insn (gen_call_pop_compact_rettramp
+                       (operands[0], operands[1], operands[2], operands[3]));
+      else
+       emit_call_insn (gen_call_pop_compact
+                       (operands[0], operands[1], operands[2], operands[3]));
+
+      DONE;
+    }
+
+  abort ();
 }")
 
 (define_expand "call_value"
   [(parallel [(set (match_operand 0 "arith_reg_operand" "")
                   (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
                                 (match_operand 2 "" "")))
+             (match_operand 3 "" "")
              (use (reg:PSI FPSCR_REG))
              (clobber (reg:SI PR_REG))])]
   ""
   "
 {
+  if (TARGET_SHMEDIA)
+    {
+      operands[1] = XEXP (operands[1], 0);
+      if (flag_pic && GET_CODE (operands[1]) == SYMBOL_REF)
+       {
+         if (! SYMBOL_REF_FLAG (operands[1]))
+           {
+             rtx reg = gen_reg_rtx (Pmode);
+             
+             emit_insn (gen_symGOTPLT2reg (reg, operands[1]));
+             operands[1] = reg;
+           }
+         else
+           {
+             operands[1] = gen_sym2PIC (operands[1]);
+             PUT_MODE (operands[1], Pmode);
+           }
+       }
+      if (GET_MODE (operands[1]) == SImode)
+       {
+         if (GET_CODE (operands[1]) == REG)
+           operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
+         else if (GET_CODE (operands[1]) == SUBREG)
+           {
+             operands[1] = SUBREG_REG (operands[1]);
+             if (GET_MODE (operands[1]) != DImode)
+               operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
+           }
+         else
+           {
+             operands[1] = shallow_copy_rtx (operands[1]);
+             PUT_MODE (operands[1], DImode);
+           }
+       }
+      if (! target_reg_operand (operands[1], DImode))
+       operands[1] = copy_to_mode_reg (DImode, operands[1]);
+      emit_call_insn (gen_call_value_media (operands[0], operands[1],
+                                           operands[2]));
+      DONE;
+    }
+  else if (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]))
+    {
+      rtx cookie_rtx = operands[3];
+      long cookie = INTVAL (cookie_rtx);
+      rtx func = XEXP (operands[1], 0);
+      rtx r0, r1;
+
+      if (flag_pic)
+       {
+         if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_FLAG (func))
+           {
+             rtx reg = gen_reg_rtx (Pmode);
+
+             emit_insn (gen_symGOTPLT2reg (reg, func));
+             func = reg;
+           }
+         else
+           func = legitimize_pic_address (func, Pmode, 0);
+       }
+
+      r0 = gen_rtx_REG (SImode, R0_REG);
+      r1 = gen_rtx_REG (SImode, R1_REG);
+
+      /* Since such a call function may use all call-clobbered
+        registers, we force a mode switch earlier, so that we don't
+        run out of registers when adjusting fpscr for the call.  */
+      emit_insn (gen_force_mode_for_call ());
+
+      operands[1] = gen_rtx_SYMBOL_REF (SImode,
+                                       \"__GCC_shcompact_call_trampoline\");
+      if (flag_pic)
+       {
+         rtx reg = gen_reg_rtx (Pmode);
+
+         emit_insn (gen_symGOTPLT2reg (reg, operands[1]));
+         operands[1] = reg;
+       }
+      operands[1] = force_reg (SImode, operands[1]);
+
+      emit_move_insn (r0, func);
+      emit_move_insn (r1, cookie_rtx);
+
+      if (cookie & CALL_COOKIE_RET_TRAMP (1))
+       emit_call_insn (gen_call_value_compact_rettramp (operands[0],
+                                                        operands[1],
+                                                        operands[2],
+                                                        operands[3]));
+      else
+       emit_call_insn (gen_call_value_compact (operands[0], operands[1],
+                                               operands[2], operands[3]));
+
+      DONE;
+    }
+  else if (TARGET_SHCOMPACT && flag_pic
+          && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
+          && ! SYMBOL_REF_FLAG (XEXP (operands[1], 0)))
+    {
+      rtx reg = gen_reg_rtx (Pmode);
+
+      emit_insn (gen_symGOTPLT2reg (reg, XEXP (operands[1], 0)));
+      XEXP (operands[1], 0) = reg;
+    }
   if (flag_pic && TARGET_SH2
       && GET_CODE (operands[1]) == MEM
       && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
     }
   else
     operands[1] = force_reg (SImode, XEXP (operands[1], 0));
+
+  emit_call_insn (gen_call_valuei (operands[0], operands[1], operands[2]));
+  DONE;
 }")
 
 (define_insn "sibcalli"
         (match_operand 1 "" ""))
    (use (reg:PSI FPSCR_REG))
    (return)]
-  ""
+  "TARGET_SH1"
   "jmp @%0%#"
   [(set_attr "needs_delay_slot" "yes")
    (set (attr "fp_mode")
   rtx lab = gen_call_site ();
   rtx call_insn;
 
-  emit_insn (gen_sym_label2reg (operands[2], operands[0], lab));
-  call_insn = emit_call_insn (gen_sibcalli_pcrel (operands[2], operands[1],
-                                                 lab));
-  SIBLING_CALL_P (call_insn) = 1;
-  DONE;
-}"
-  [(set_attr "needs_delay_slot" "yes")
-   (set (attr "fp_mode")
-       (if_then_else (eq_attr "fpu_single" "yes")
-                     (const_string "single") (const_string "double")))
-   (set_attr "type" "jump_ind")])
+  emit_insn (gen_sym_label2reg (operands[2], operands[0], lab));
+  call_insn = emit_call_insn (gen_sibcalli_pcrel (operands[2], operands[1],
+                                                 lab));
+  SIBLING_CALL_P (call_insn) = 1;
+  DONE;
+}"
+  [(set_attr "needs_delay_slot" "yes")
+   (set (attr "fp_mode")
+       (if_then_else (eq_attr "fpu_single" "yes")
+                     (const_string "single") (const_string "double")))
+   (set_attr "type" "jump_ind")])
+
+(define_insn "sibcall_compact"
+  [(call (mem:SI (match_operand:SI 0 "register_operand" "k,k"))
+        (match_operand 1 "" ""))
+   (return)
+   (use (match_operand 2 "register_operand" "z,x"))
+   (use (reg:SI R1_REG))
+   (use (reg:PSI FPSCR_REG))
+   ;; We want to make sure the `x' above will only match MACH_REG
+   ;; because sibcall_epilogue may clobber MACL_REG.
+   (clobber (reg:SI MACL_REG))]
+  "TARGET_SHCOMPACT"
+  "@
+       jmp     @%0%#
+       jmp     @%0\\n  sts     %2, r0"
+  [(set_attr "needs_delay_slot" "yes,no")
+   (set_attr "length" "2,4")
+   (set (attr "fp_mode") (const_string "single"))
+   (set_attr "type" "jump_ind")])
+
+(define_insn "sibcall_media"
+  [(call (mem:DI (match_operand:DI 0 "target_reg_operand" "k"))
+        (match_operand 1 "" ""))
+   (return)]
+  "TARGET_SHMEDIA"
+  "blink       %0, r63")
+
+(define_expand "sibcall"
+  [(parallel
+    [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
+          (match_operand 1 "" ""))
+     (match_operand 2 "" "")
+     (use (reg:PSI FPSCR_REG))
+     (return)])]
+  ""
+  "
+{
+  if (TARGET_SHMEDIA)
+    {
+      operands[0] = XEXP (operands[0], 0);
+      if (flag_pic && GET_CODE (operands[0]) == SYMBOL_REF)
+       {
+         if (! SYMBOL_REF_FLAG (operands[0]))
+           {
+             rtx reg = gen_reg_rtx (Pmode);
+             
+             /* We must not use GOTPLT for sibcalls, because PIC_REG
+                must be restored before the PLT code gets to run.  */
+             emit_insn (gen_symGOT2reg (reg, operands[0]));
+             operands[0] = reg;
+           }
+         else
+           {
+             operands[0] = gen_sym2PIC (operands[0]);
+             PUT_MODE (operands[0], Pmode);
+           }
+       }
+      if (GET_MODE (operands[0]) == SImode)
+       {
+         if (GET_CODE (operands[0]) == REG)
+           operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
+         else if (GET_CODE (operands[0]) == SUBREG)
+           {
+             operands[0] = SUBREG_REG (operands[0]);
+             if (GET_MODE (operands[0]) != DImode)
+               operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
+           }
+         else
+           {
+             operands[0] = shallow_copy_rtx (operands[0]);
+             PUT_MODE (operands[0], DImode);
+           }
+       }
+      if (! target_reg_operand (operands[0], DImode))
+       operands[0] = copy_to_mode_reg (DImode, operands[0]);
+      emit_call_insn (gen_sibcall_media (operands[0], operands[1]));
+      DONE;
+    }
+  else if (TARGET_SHCOMPACT && operands[2]
+          && (INTVAL (operands[2]) & ~ CALL_COOKIE_RET_TRAMP (1)))
+    {
+      rtx cookie_rtx = operands[2];
+      long cookie = INTVAL (cookie_rtx);
+      rtx func = XEXP (operands[0], 0);
+      rtx mach, r1;
+
+      if (flag_pic)
+       {
+         if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_FLAG (func))
+           {
+             rtx reg = gen_reg_rtx (Pmode);
+
+             emit_insn (gen_symGOT2reg (reg, func));
+             func = reg;
+           }
+         else
+           func = legitimize_pic_address (func, Pmode, 0);
+       }
 
-(define_expand "sibcall"
-  [(parallel
-    [(call (mem:SI (match_operand 0 "arith_reg_operand" ""))
-          (match_operand 1 "" ""))
-     (use (reg:PSI FPSCR_REG))
-     (return)])]
-  ""
-  "
-{
+      /* FIXME: if we could tell whether all argument registers are
+        already taken, we could decide whether to force the use of
+        MACH_REG or to stick to R0_REG.  Unfortunately, there's no
+        simple way to tell.  We could use the CALL_COOKIE, but we
+        can't currently tell a register used for regular argument
+        passing from one that is unused.  If we leave it up to reload
+        to decide which register to use, it seems to always choose
+        R0_REG, which leaves no available registers in SIBCALL_REGS
+        to hold the address of the trampoline.  */
+      mach = gen_rtx_REG (SImode, MACH_REG);
+      r1 = gen_rtx_REG (SImode, R1_REG);
+
+      /* Since such a call function may use all call-clobbered
+        registers, we force a mode switch earlier, so that we don't
+        run out of registers when adjusting fpscr for the call.  */
+      emit_insn (gen_force_mode_for_call ());
+
+      operands[0] = gen_rtx_SYMBOL_REF (SImode,
+                                       \"__GCC_shcompact_call_trampoline\");
+      if (flag_pic)
+       {
+         rtx reg = gen_reg_rtx (Pmode);
+
+         emit_insn (gen_symGOT2reg (reg, operands[0]));
+         operands[0] = reg;
+       }
+      operands[0] = force_reg (SImode, operands[0]);
+
+      /* We don't need a return trampoline, since the callee will
+        return directly to the upper caller.  */
+      if (cookie & CALL_COOKIE_RET_TRAMP (1))
+       {
+         cookie &= ~ CALL_COOKIE_RET_TRAMP (1);
+         cookie_rtx = GEN_INT (cookie);
+       }
+
+      emit_move_insn (mach, func);
+      emit_move_insn (r1, cookie_rtx);
+
+      emit_call_insn (gen_sibcall_compact (operands[0], operands[1], mach));
+      DONE;
+    }
+  else if (TARGET_SHCOMPACT && flag_pic
+          && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
+          && ! SYMBOL_REF_FLAG (XEXP (operands[0], 0)))
+    {
+      rtx reg = gen_reg_rtx (Pmode);
+
+      emit_insn (gen_symGOT2reg (reg, XEXP (operands[0], 0)));
+      XEXP (operands[0], 0) = reg;
+    }
   if (flag_pic && TARGET_SH2
       && GET_CODE (operands[0]) == MEM
       && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
     }
   else
     operands[0] = force_reg (SImode, XEXP (operands[0], 0));
+
+  emit_call_insn (gen_sibcalli (operands[0], operands[1]));
+  DONE;
 }")
 
 (define_expand "sibcall_value"
   [(set (match_operand 0 "" "")
        (call (match_operand 1 "" "")
-             (match_operand 2 "" "")))]
+             (match_operand 2 "" "")))
+   (match_operand 3 "" "")]
   ""
   "
 {
-  emit_call_insn (gen_sibcall (operands[1], operands[2]));
+  emit_call_insn (gen_sibcall (operands[1], operands[2], operands[3]));
   DONE;
 }")
 
+(define_insn "call_value_pop_compact"
+  [(set (match_operand 0 "" "=rf")
+       (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
+             (match_operand 2 "" "")))
+   (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
+                                (match_operand 4 "immediate_operand" "n")))
+   (match_operand 3 "immediate_operand" "n")
+   (use (reg:SI R0_REG))
+   (use (reg:SI R1_REG))
+   (use (reg:PSI FPSCR_REG))
+   (clobber (reg:SI PR_REG))]
+  "TARGET_SHCOMPACT && ! (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
+  "jsr @%1%#"
+  [(set_attr "type" "call")
+   (set (attr "fp_mode")
+       (if_then_else (eq_attr "fpu_single" "yes")
+                     (const_string "single") (const_string "double")))
+   (set_attr "needs_delay_slot" "yes")])
+
+(define_insn "call_value_pop_compact_rettramp"
+  [(set (match_operand 0 "" "=rf")
+       (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r"))
+             (match_operand 2 "" "")))
+   (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
+                                (match_operand 4 "immediate_operand" "n")))
+   (match_operand 3 "immediate_operand" "n")
+   (use (reg:SI R0_REG))
+   (use (reg:SI R1_REG))
+   (use (reg:PSI FPSCR_REG))
+   (clobber (reg:SI R10_REG))
+   (clobber (reg:SI PR_REG))]
+  "TARGET_SHCOMPACT && (INTVAL (operands[3]) & CALL_COOKIE_RET_TRAMP (1))"
+  "jsr @%1%#"
+  [(set_attr "type" "call")
+   (set (attr "fp_mode")
+       (if_then_else (eq_attr "fpu_single" "yes")
+                     (const_string "single") (const_string "double")))
+   (set_attr "needs_delay_slot" "yes")])
+
+(define_expand "call_value_pop"
+  [(parallel [(set (match_operand 0 "arith_reg_operand" "")
+                  (call (mem:SI (match_operand 1 "arith_reg_operand" ""))
+                                (match_operand 2 "" "")))
+             (match_operand 3 "" "")
+             (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG)
+                                           (match_operand 4 "" "")))])]
+  "TARGET_SHCOMPACT"
+  "
+{
+  if (TARGET_SHCOMPACT && operands[3] && INTVAL (operands[3]))
+    {
+      rtx cookie_rtx = operands[3];
+      long cookie = INTVAL (cookie_rtx);
+      rtx func = XEXP (operands[1], 0);
+      rtx r0, r1;
+
+      if (flag_pic)
+       {
+         if (GET_CODE (func) == SYMBOL_REF && ! SYMBOL_REF_FLAG (func))
+           {
+             rtx reg = gen_reg_rtx (Pmode);
+
+             emit_insn (gen_symGOTPLT2reg (reg, func));
+             func = reg;
+           }
+         else
+           func = legitimize_pic_address (func, Pmode, 0);
+       }
+
+      r0 = gen_rtx_REG (SImode, R0_REG);
+      r1 = gen_rtx_REG (SImode, R1_REG);
+
+      /* Since such a call function may use all call-clobbered
+        registers, we force a mode switch earlier, so that we don't
+        run out of registers when adjusting fpscr for the call.  */
+      emit_insn (gen_force_mode_for_call ());
+
+      operands[1] = gen_rtx_SYMBOL_REF (SImode,
+                                       \"__GCC_shcompact_call_trampoline\");
+      if (flag_pic)
+       {
+         rtx reg = gen_reg_rtx (Pmode);
+
+         emit_insn (gen_symGOTPLT2reg (reg, operands[1]));
+         operands[1] = reg;
+       }
+      operands[1] = force_reg (SImode, operands[1]);
+
+      emit_move_insn (r0, func);
+      emit_move_insn (r1, cookie_rtx);
+
+      if (cookie & CALL_COOKIE_RET_TRAMP (1))
+       emit_call_insn (gen_call_value_pop_compact_rettramp
+                       (operands[0], operands[1], operands[2],
+                        operands[3], operands[4]));
+      else
+       emit_call_insn (gen_call_value_pop_compact
+                       (operands[0], operands[1], operands[2],
+                        operands[3], operands[4]));
+
+      DONE;
+    }
+
+  abort ();
+}")
+
 (define_expand "sibcall_epilogue"
   [(return)]
   ""
   "
 {
   sh_expand_epilogue ();
+  if (TARGET_SHCOMPACT)
+    {
+      rtx insn, set;
+
+      /* If epilogue clobbers r0, preserve it in macl.  */
+      for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+       if ((set = single_set (insn))
+           && GET_CODE (SET_DEST (set)) == REG
+           && REGNO (SET_DEST (set)) == R0_REG)
+         {
+           rtx r0 = gen_rtx_REG (SImode, R0_REG);
+           rtx tmp = gen_rtx_REG (SImode, MACL_REG);
+           rtx i;
+
+           /* We can't tell at this point whether the sibcall is a
+              sibcall_compact and, if it is, whether it uses r0 or
+              mach as operand 2, so let the instructions that
+              preserve r0 be optimized away if r0 turns out to be
+              dead.  */
+           i = emit_insn_before (gen_rtx_SET (SImode, tmp, r0), insn);
+           REG_NOTES (i) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
+                                              REG_NOTES (i));
+           i = emit_move_insn (r0, tmp);
+           REG_NOTES (i) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
+                                              REG_NOTES (i));
+           break;
+         }
+    }
   DONE;
 }")
 
-(define_insn "indirect_jump"
+(define_insn "indirect_jump_compact"
   [(set (pc)
        (match_operand:SI 0 "arith_reg_operand" "r"))]
-  ""
+  "TARGET_SH1"
   "jmp @%0%#"
   [(set_attr "needs_delay_slot" "yes")
    (set_attr "type" "jump_ind")])
 
+(define_expand "indirect_jump"
+  [(set (pc)
+       (match_operand 0 "register_operand" ""))]
+  ""
+  "
+{
+  if (TARGET_SHMEDIA && GET_MODE (operands[0]) == SImode)
+    operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
+}")
+
 ;; The use of operand 1 / 2 helps us distinguish case table jumps
 ;; which can be present in structured code from indirect jumps which can not
 ;; be present in structured code.  This allows -fprofile-arcs to work.
   [(set (pc)
        (match_operand:SI 0 "register_operand" "r"))
    (use (label_ref (match_operand 1 "" "")))]
-  ""
+  "TARGET_SH1"
   "jmp  @%0%#"
   [(set_attr "needs_delay_slot" "yes")
    (set_attr "type" "jump_ind")])
   [(set_attr "needs_delay_slot" "yes")
    (set_attr "type" "jump_ind")])
 
+(define_insn "casesi_jump_media"
+  [(set (pc) (match_operand:DI 0 "target_reg_operand" "b"))
+   (use (label_ref (match_operand 1 "" "")))]
+  "TARGET_SHMEDIA"
+  "blink       %0, r63")
+  
 ;; Call subroutine returning any type.
 ;; ??? This probably doesn't work.
 
                    (const_int 0))
              (match_operand 1 "" "")
              (match_operand 2 "" "")])]
-  "TARGET_SH3E"
+  "TARGET_SH3E || TARGET_SHMEDIA"
   "
 {
   int i;
 
-  emit_call_insn (gen_call (operands[0], const0_rtx));
+  emit_call_insn (gen_call (operands[0], const0_rtx, const0_rtx));
 
   for (i = 0; i < XVECLEN (operands[2], 0); i++)
     {
 (define_insn "mova"
   [(set (reg:SI R0_REG)
        (unspec [(label_ref (match_operand 0 "" ""))] UNSPEC_MOVA))]
-  ""
+  "TARGET_SH1"
   "mova        %O0,r0"
   [(set_attr "in_delay_slot" "no")
    (set_attr "type" "arith")])
 (define_insn "mova_const"
   [(set (reg:SI R0_REG)
        (unspec [(match_operand 0 "immediate_operand" "i")] UNSPEC_MOVA))]
-  ""
+  "TARGET_SH1"
   "#"
   [(set_attr "in_delay_slot" "no")
    (set_attr "type" "arith")])
    (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))]
   "" "
 {
-  operands[0] = pic_offset_table_rtx;
+  operands[0] = gen_rtx_REG (Pmode, PIC_REG);
   operands[1] = gen_rtx_SYMBOL_REF (VOIDmode, GOT_SYMBOL_NAME);
+
+  if (TARGET_SH5)
+    operands[1] = gen_datalabel_ref (operands[1]);
+
+  if (TARGET_SHMEDIA)
+    {
+      rtx tr = gen_rtx_REG (DImode, TR0_REG);
+      rtx dipic = operands[0];
+      rtx lab = gen_call_site ();
+      rtx insn, equiv;
+
+      equiv = operands[1];
+      operands[1] = gen_rtx_MINUS (DImode,
+                                  operands[1],
+                                  gen_rtx_CONST
+                                  (DImode,
+                                   gen_rtx_MINUS (DImode,
+                                                  gen_rtx_CONST (DImode,
+                                                                 lab),
+                                                  pc_rtx)));
+      operands[1] = gen_sym2PIC (operands[1]);
+      PUT_MODE (operands[1], DImode);
+
+      if (GET_MODE (dipic) != DImode)
+       dipic = gen_rtx_SUBREG (DImode, dipic, 0);
+
+      if (TARGET_SHMEDIA64)
+       emit_insn (gen_movdi_const (dipic, operands[1]));
+      else
+       emit_insn (gen_movdi_const_32bit (dipic, operands[1]));
+
+      emit_insn (gen_ptrel (tr, dipic, lab));
+
+      if (GET_MODE (operands[0]) != GET_MODE (tr))
+       tr = gen_rtx_SUBREG (GET_MODE (operands[0]), tr, 0);
+
+      insn = emit_move_insn (operands[0], tr);
+      
+      REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, equiv,
+                                           REG_NOTES (insn));
+
+      DONE;
+    }
 }
 ")
 
+;; When generating PIC, we must match label_refs especially, because
+;; they do not satisfy LEGITIMATE_PIC_OPERAND_P(), and we don't want
+;; them to do, because they can't be loaded directly into
+;; non-branch-target registers.
+(define_insn "*pt"
+  [(set (match_operand:DI 0 "target_reg_operand" "=b*k")
+       (match_operand:DI 1 "" "T"))]
+  "TARGET_SHMEDIA && flag_pic
+   && EXTRA_CONSTRAINT_T (operands[1])"
+  "pt  %1, %0"
+  [(set_attr "type" "pt")
+   (set_attr "length" "*")])
+
+(define_insn "*ptb"
+  [(set (match_operand:DI 0 "target_reg_operand" "=b*k")
+       (const:DI (unspec:DI [(match_operand:DI 1 "" "T")]
+                            UNSPEC_DATALABEL)))]
+  "TARGET_SHMEDIA && flag_pic
+   && EXTRA_CONSTRAINT_T (operands[1])"
+  "ptb/u       datalabel %1, %0"
+  [(set_attr "type" "pt")
+   (set_attr "length" "*")])
+
+(define_insn "ptrel"
+  [(set (match_operand:DI 0 "target_reg_operand" "=bk")
+       (plus (match_operand:DI 1 "register_operand" "r")
+             (pc)))
+   (match_operand:DI 2 "" "")]
+  "TARGET_SHMEDIA"
+  "%O2: ptrel/u        %1, %0"
+  [(set_attr "type" "ptabs")])
+
 (define_expand "builtin_setjmp_receiver"
   [(match_operand 0 "" "")]
   "flag_pic"
 
 (define_expand "call_site"
   [(unspec [(match_dup 0)] UNSPEC_CALLER)]
-  ""
+  "TARGET_SH1"
   "
 {
   static HOST_WIDE_INT i = 0;
                    (plus:SI
                     (match_operand:SI 2 "" "")
                     (const_int 2))))))]
-  "" "")
+  "TARGET_SH1" "")
 
 (define_expand "symGOT_load"
   [(set (match_dup 2) (match_operand 1 "" ""))
   operands[2] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
   operands[3] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
 
-  emit_move_insn (operands[2], operands[1]);
+  if (TARGET_SHMEDIA)
+    {
+      rtx reg = operands[2];
+      
+      if (GET_MODE (reg) != DImode)
+       reg = gen_rtx_SUBREG (DImode, reg, 0);
+      
+      if (flag_pic > 1)
+       emit_insn (gen_movdi_const_32bit (reg, operands[1]));
+      else
+       emit_insn (gen_movdi_const_16bit (reg, operands[1]));
+    }
+  else
+    emit_move_insn (operands[2], operands[1]);
 
   emit_move_insn (operands[3], gen_rtx_PLUS (Pmode,
                                             operands[2],
   DONE;
 }")
 
+(define_expand "sym2GOTPLT"
+  [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTPLT))]
+  ""
+  "")
+
+(define_expand "symGOTPLT2reg"
+  [(match_operand 0 "" "") (match_operand 1 "" "")]
+  ""
+  "
+{
+  emit_insn (gen_symGOT_load (operands[0], gen_sym2GOTPLT (operands[1])));
+  DONE;
+}")
+
 (define_expand "sym2GOTOFF"
   [(const (unspec [(match_operand 0 "" "")] UNSPEC_GOTOFF))]
   ""
    ;; same function might not compare equal, should they be set by
    ;; different shared libraries.
    (use (reg:SI PIC_REG))]
+  "TARGET_SH1"
+  "")
+
+(define_expand "sym2PIC"
+  [(const (unspec [(match_operand:SI 0 "" "")] UNSPEC_PIC))]
   ""
   "")
 
 {
   rtx reg = gen_reg_rtx (SImode);
   rtx reg2 = gen_reg_rtx (SImode);
+  if (TARGET_SHMEDIA)
+    {
+      rtx reg = gen_reg_rtx (DImode);
+      rtx reg2 = gen_reg_rtx (DImode);
+      rtx reg3 = gen_reg_rtx (DImode);
+      rtx reg4 = gen_reg_rtx (DImode);
+      rtx reg5 = gen_reg_rtx (DImode);
+
+      operands[0] = convert_modes (DImode, SImode, operands[0], 0);
+      operands[1] = convert_modes (DImode, SImode, operands[1], 0);
+      operands[2] = convert_modes (DImode, SImode, operands[2], 1);
+
+      emit_jump_insn (gen_bgt_media (operands[4], operands[1], operands[0]));
+      emit_move_insn (reg, gen_rtx_MINUS (DImode, operands[0], operands[1]));
+      emit_jump_insn (gen_bgtu_media (operands[4], reg, operands[2]));
+      emit_insn (gen_casesi_shift_media (reg2, reg, operands[3]));
+      emit_move_insn (reg3, gen_datalabel_ref (gen_rtx_LABEL_REF
+                                              (DImode, operands[3])));
+      emit_insn (gen_casesi_load_media (reg4, reg3, reg2, operands[3]));
+      emit_move_insn (reg5, gen_rtx_PLUS (DImode, reg3, reg4));
+      emit_jump_insn (gen_casesi_jump_media (reg5, operands[3]));
+      emit_barrier ();
+      DONE;
+    }
   operands[1] = copy_to_mode_reg (SImode, operands[1]);
   operands[2] = copy_to_mode_reg (SImode, operands[2]);
   /* If optimizing, casesi_worker depends on the mode of the instruction
                          (const_int 0))
                      (label_ref (match_operand 3 "" ""))
                      (pc)))]
-  ""
+  "TARGET_SH1"
   "")
 
 ;; ??? reload might clobber r0 if we use it explicitly in the RTL before
                 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
    (clobber (match_scratch:SI 3 "=X,1"))
    (clobber (match_scratch:SI 4 "=&z,z"))]
-  ""
+  "TARGET_SH1"
   "#")
 
 (define_split
                 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
    (clobber (match_scratch:SI 3 ""))
    (clobber (match_scratch:SI 4 ""))]
-  "! TARGET_SH2 && reload_completed"
+  "TARGET_SH1 && ! TARGET_SH2 && reload_completed"
   [(set (reg:SI R0_REG) (unspec [(label_ref (match_dup 2))] UNSPEC_MOVA))
    (parallel [(set (match_dup 0)
              (unspec [(reg:SI R0_REG) (match_dup 1)
        (unspec [(reg:SI R0_REG) (match_operand 1 "register_operand" "0,r")
                 (label_ref (match_operand 2 "" ""))] UNSPEC_CASESI))
    (clobber (match_scratch:SI 3 "=X,1"))]
-  ""
+  "TARGET_SH1"
   "*
 {
   rtx diff_vec = PATTERN (next_real_insn (operands[2]));
 }"
   [(set_attr "length" "4")])
 
+(define_insn "casesi_shift_media"
+  [(set (match_operand 0 "arith_reg_operand" "=r")
+       (ashift (match_operand 1 "arith_reg_operand" "r")
+               (unspec [(label_ref:DI (match_operand 2 "" ""))] 2)))]
+  "TARGET_SHMEDIA"
+  "*
+{
+  rtx diff_vec = PATTERN (next_real_insn (operands[2]));
+
+  if (GET_CODE (diff_vec) != ADDR_DIFF_VEC)
+    abort ();
+
+  switch (GET_MODE (diff_vec))
+    {
+    case SImode:
+      return \"shlli   %1, 2, %0\";
+    case HImode:
+      return \"shlli   %1, 1, %0\";
+    case QImode:
+      if (rtx_equal_p (operands[0], operands[1]))
+       return \"\";
+      return \"add     %1, r63, %0\";
+    default:
+      abort ();
+    }
+}")
+
+(define_insn "casesi_load_media"
+  [(set (match_operand:DI 0 "arith_reg_operand" "=r")
+       (mem:DI (unspec [(match_operand 1 "arith_reg_operand" "r")
+                        (match_operand 2 "arith_reg_operand" "r")
+                        (label_ref:DI (match_operand 3 "" ""))] 2)))]
+  "TARGET_SHMEDIA"
+  "*
+{
+  rtx diff_vec = PATTERN (next_real_insn (operands[3]));
+
+  if (GET_CODE (diff_vec) != ADDR_DIFF_VEC)
+    abort ();
+
+  switch (GET_MODE (diff_vec))
+    {
+    case SImode:
+      return \"ldx.l   %1, %2, %0\";
+    case HImode:
+#if 0
+      if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
+       return \"ldx.uw %1, %2, %0\";
+#endif
+      return \"ldx.w   %1, %2, %0\";
+    case QImode:
+      if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
+       return \"ldx.ub %1, %2, %0\";
+      return \"ldx.b   %1, %2, %0\";
+    default:
+      abort ();
+    }
+}")
+
 (define_expand "return"
   [(return)]
   "reload_completed && ! sh_need_epilogue ()"
-  "")
+  "
+{
+  if (TARGET_SHMEDIA)
+    {
+      emit_jump_insn (gen_return_media ());
+      DONE;
+    }
+
+  if (TARGET_SHCOMPACT
+      && (current_function_args_info.call_cookie & CALL_COOKIE_RET_TRAMP (1)))
+    {
+      emit_jump_insn (gen_shcompact_return_tramp ());
+      DONE;
+    }
+}")
 
 (define_insn "*return_i"
   [(return)]
-  "reload_completed"
+  "TARGET_SH1 && ! (TARGET_SHCOMPACT
+                   && (current_function_args_info.call_cookie
+                       & CALL_COOKIE_RET_TRAMP (1)))
+   && reload_completed"
   "%@  %#"
   [(set_attr "type" "return")
    (set_attr "needs_delay_slot" "yes")])
 
+(define_expand "shcompact_return_tramp"
+  [(return)]
+  "TARGET_SHCOMPACT
+   && (current_function_args_info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
+  "
+{
+  rtx reg = gen_rtx_REG (Pmode, R0_REG);
+  rtx sym = gen_rtx_SYMBOL_REF (Pmode,
+                               \"__GCC_shcompact_return_trampoline\");
+
+  if (flag_pic)
+    emit_insn (gen_symGOTPLT2reg (reg, sym));
+  else
+    emit_move_insn (reg, sym);
+
+  emit_jump_insn (gen_shcompact_return_tramp_i ());
+  DONE;
+}")
+
+(define_insn "shcompact_return_tramp_i"
+  [(parallel [(return) (use (reg:SI R0_REG))])]
+  "TARGET_SHCOMPACT
+   && (current_function_args_info.call_cookie & CALL_COOKIE_RET_TRAMP (1))"
+  "jmp @r0%#"
+  [(set_attr "type" "jump_ind")
+   (set_attr "needs_delay_slot" "yes")])
+
+(define_insn "return_media_i"
+  [(parallel [(return) (use (match_operand:DI 0 "target_reg_operand" "k"))])]
+  "TARGET_SHMEDIA && reload_completed"
+  "blink       %0, r63")
+
+(define_expand "return_media"
+  [(return)]
+  "TARGET_SHMEDIA && reload_completed"
+  "
+{
+  int tr_regno = sh_media_register_for_return ();
+  rtx tr;
+
+  if (tr_regno < 0)
+    {
+      rtx r18 = gen_rtx_REG (DImode, PR_MEDIA_REG);
+
+      tr_regno = TR0_REG;
+      tr = gen_rtx_REG (DImode, tr_regno);
+      emit_move_insn (tr, r18);
+    }
+  else
+    tr = gen_rtx_REG (DImode, tr_regno);
+
+  emit_jump_insn (gen_return_media_i (tr));
+  DONE;
+}")
+
+(define_insn "shcompact_preserve_incoming_args"
+  [(set (match_operand 0 "register_operand" "+r")
+       (unspec [(match_dup 0)] UNSPEC_COMPACT_ARGS))]
+  "TARGET_SHCOMPACT"
+  ""
+  [(set_attr "length" "0")])
+
+(define_insn "shcompact_incoming_args"
+  [(set (reg:SI R2_REG) (unspec [(reg:SI R2_REG)] UNSPEC_COMPACT_ARGS))
+   (set (reg:SI R3_REG) (unspec [(reg:SI R3_REG)] UNSPEC_COMPACT_ARGS))
+   (set (reg:SI R4_REG) (unspec [(reg:SI R4_REG)] UNSPEC_COMPACT_ARGS))
+   (set (reg:SI R5_REG) (unspec [(reg:SI R5_REG)] UNSPEC_COMPACT_ARGS))
+   (set (reg:SI R6_REG) (unspec [(reg:SI R6_REG)] UNSPEC_COMPACT_ARGS))
+   (set (reg:SI R7_REG) (unspec [(reg:SI R7_REG)] UNSPEC_COMPACT_ARGS))
+   (set (reg:SI R8_REG) (unspec [(reg:SI R8_REG)] UNSPEC_COMPACT_ARGS))
+   (set (reg:SI R9_REG) (unspec [(reg:SI R9_REG)] UNSPEC_COMPACT_ARGS))
+   (set (mem:BLK (reg:SI MACL_REG))
+       (unspec [(reg:SI MACH_REG)] UNSPEC_COMPACT_ARGS))
+   (use (reg:SI R0_REG))
+   (clobber (reg:SI R0_REG))
+   (clobber (reg:SI MACL_REG))
+   (clobber (reg:SI MACH_REG))
+   (clobber (reg:SI PR_REG))]
+  "TARGET_SHCOMPACT"
+  "jsr @r0%#"
+  [(set_attr "needs_delay_slot" "yes")])
+
+(define_insn "shmedia_save_restore_regs_compact"
+  [(set (reg:SI SP_REG)
+       (plus:SI (reg:SI SP_REG)
+                (match_operand:SI 0 "immediate_operand" "i")))
+   (use (reg:SI R0_REG))
+   (clobber (reg:SI PR_REG))]
+  "TARGET_SHCOMPACT
+   && (INTVAL (operands[0]) == SHMEDIA_REGS_STACK_ADJUST ()
+       || INTVAL (operands[0]) == - SHMEDIA_REGS_STACK_ADJUST ())"
+  "jsr @r0%#"
+  [(set_attr "needs_delay_slot" "yes")])
+
 (define_expand "prologue"
   [(const_int 0)]
   ""
 (define_expand "epilogue"
   [(return)]
   ""
-  "sh_expand_epilogue ();")
+  "
+{
+  sh_expand_epilogue ();
+  emit_jump_insn (gen_return ());
+  DONE;
+}")
 
 (define_insn "blockage"
   [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
 (define_insn "movt"
   [(set (match_operand:SI 0 "arith_reg_operand" "=r")
        (eq:SI (reg:SI T_REG) (const_int 1)))]
-  ""
+  "TARGET_SH1"
   "movt        %0"
   [(set_attr "type" "arith")])
 
   [(set (match_operand:SI 0 "arith_reg_operand" "")
        (match_dup 1))]
   ""
-  "operands[1] = prepare_scc_operands (EQ);")
+  "
+{
+  if (TARGET_SHMEDIA)
+    {
+      if (GET_MODE (operands[0]) != DImode)
+       operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
+      sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
+      if (sh_compare_op1 != const0_rtx)
+       sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
+                                   ? GET_MODE (sh_compare_op0)
+                                   : GET_MODE (sh_compare_op1),
+                                   sh_compare_op1);
+
+      switch (GET_MODE (sh_compare_op0))
+       {
+       case DImode:
+         emit_insn (gen_cmpeqdi_media (operands[0],
+                                       sh_compare_op0, sh_compare_op1));
+         break;
+
+       case SFmode:
+         if (! TARGET_SHMEDIA_FPU)
+           FAIL;
+         emit_insn (gen_cmpeqsf_media (operands[0],
+                                       sh_compare_op0, sh_compare_op1));
+         break;
+
+       case DFmode:
+         if (! TARGET_SHMEDIA_FPU)
+           FAIL;
+         emit_insn (gen_cmpeqdf_media (operands[0],
+                                       sh_compare_op0, sh_compare_op1));
+         break;
+
+       default:
+         FAIL;
+       }
+      DONE;
+    }
+  operands[1] = prepare_scc_operands (EQ);
+}")
 
 (define_expand "slt"
   [(set (match_operand:SI 0 "arith_reg_operand" "")
        (match_dup 1))]
   ""
-  "operands[1] = prepare_scc_operands (LT);")
+  "
+{
+  if (TARGET_SHMEDIA)
+    {
+      if (GET_MODE (operands[0]) != DImode)
+       operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
+      sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
+      if (sh_compare_op1 != const0_rtx)
+       sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
+                                   ? GET_MODE (sh_compare_op0)
+                                   : GET_MODE (sh_compare_op1),
+                                   sh_compare_op1);
+
+      switch (GET_MODE (sh_compare_op0))
+       {
+       case DImode:
+         emit_insn (gen_cmpgtdi_media (operands[0],
+                                       sh_compare_op1, sh_compare_op0));
+         break;
+
+       case SFmode:
+         if (! TARGET_SHMEDIA_FPU)
+           FAIL;
+         emit_insn (gen_cmpgtsf_media (operands[0],
+                                       sh_compare_op1, sh_compare_op0));
+         break;
+
+       case DFmode:
+         if (! TARGET_SHMEDIA_FPU)
+           FAIL;
+         emit_insn (gen_cmpgtdf_media (operands[0],
+                                       sh_compare_op1, sh_compare_op0));
+         break;
+
+       default:
+         FAIL;
+       }
+      DONE;
+    }
+  operands[1] = prepare_scc_operands (LT);
+}")
 
 (define_expand "sle"
   [(match_operand:SI 0 "arith_reg_operand" "")]
   "
 {
   rtx tmp = sh_compare_op0;
+
+  if (TARGET_SHMEDIA)
+    {
+      if (GET_MODE (operands[0]) != DImode)
+       operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
+      sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
+      if (sh_compare_op1 != const0_rtx)
+       sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
+                                   ? GET_MODE (sh_compare_op0)
+                                   : GET_MODE (sh_compare_op1),
+                                   sh_compare_op1);
+
+      switch (GET_MODE (sh_compare_op0))
+       {
+       case DImode:
+         {
+           tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
+
+           emit_insn (gen_cmpgtdi_media (tmp,
+                                         sh_compare_op0, sh_compare_op1));
+           emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx));
+           break;
+         }
+
+       case SFmode:
+         if (! TARGET_SHMEDIA_FPU)
+           FAIL;
+         emit_insn (gen_cmpgesf_media (operands[0],
+                                       sh_compare_op1, sh_compare_op0));
+         break;
+
+       case DFmode:
+         if (! TARGET_SHMEDIA_FPU)
+           FAIL;
+         emit_insn (gen_cmpgedf_media (operands[0],
+                                       sh_compare_op1, sh_compare_op0));
+         break;
+
+       default:
+         FAIL;
+       }
+      DONE;
+    }
+
   sh_compare_op0 = sh_compare_op1;
   sh_compare_op1 = tmp;
   emit_insn (gen_sge (operands[0]));
   [(set (match_operand:SI 0 "arith_reg_operand" "")
        (match_dup 1))]
   ""
-  "operands[1] = prepare_scc_operands (GT);")
+  "
+{
+  if (TARGET_SHMEDIA)
+    {
+      if (GET_MODE (operands[0]) != DImode)
+       operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
+      sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
+      if (sh_compare_op1 != const0_rtx)
+       sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
+                                   ? GET_MODE (sh_compare_op0)
+                                   : GET_MODE (sh_compare_op1),
+                                   sh_compare_op1);
+
+      switch (GET_MODE (sh_compare_op0))
+       {
+       case DImode:
+         emit_insn (gen_cmpgtdi_media (operands[0],
+                                       sh_compare_op0, sh_compare_op1));
+         break;
+
+       case SFmode:
+         if (! TARGET_SHMEDIA_FPU)
+           FAIL;
+         emit_insn (gen_cmpgtsf_media (operands[0],
+                                       sh_compare_op0, sh_compare_op1));
+         break;
+
+       case DFmode:
+         if (! TARGET_SHMEDIA_FPU)
+           FAIL;
+         emit_insn (gen_cmpgtdf_media (operands[0],
+                                       sh_compare_op0, sh_compare_op1));
+         break;
+
+       default:
+         FAIL;
+       }
+      DONE;
+    }
+  operands[1] = prepare_scc_operands (GT);
+}")
 
 (define_expand "sge"
   [(set (match_operand:SI 0 "arith_reg_operand" "")
   ""
   "
 {
+  if (TARGET_SHMEDIA)
+    {
+      if (GET_MODE (operands[0]) != DImode)
+       operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
+      sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
+      if (sh_compare_op1 != const0_rtx)
+       sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
+                                   ? GET_MODE (sh_compare_op0)
+                                   : GET_MODE (sh_compare_op1),
+                                   sh_compare_op1);
+
+      switch (GET_MODE (sh_compare_op0))
+       {
+       case DImode:
+         {
+           rtx tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
+
+           emit_insn (gen_cmpgtdi_media (tmp,
+                                         sh_compare_op1, sh_compare_op0));
+           emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx));
+           break;
+         }
+
+       case SFmode:
+         if (! TARGET_SHMEDIA_FPU)
+           FAIL;
+         emit_insn (gen_cmpgesf_media (operands[0],
+                                       sh_compare_op0, sh_compare_op1));
+         break;
+
+       case DFmode:
+         if (! TARGET_SHMEDIA_FPU)
+           FAIL;
+         emit_insn (gen_cmpgedf_media (operands[0],
+                                       sh_compare_op0, sh_compare_op1));
+         break;
+
+       default:
+         FAIL;
+       }
+      DONE;
+    }
+
   if (GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT)
     {
       if (TARGET_IEEE)
   [(set (match_operand:SI 0 "arith_reg_operand" "")
        (match_dup 1))]
   ""
-  "operands[1] = prepare_scc_operands (GTU);")
+  "
+{
+  if (TARGET_SHMEDIA)
+    {
+      if (GET_MODE (operands[0]) != DImode)
+       operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
+      sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
+      if (sh_compare_op1 != const0_rtx)
+       sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
+                                   ? GET_MODE (sh_compare_op0)
+                                   : GET_MODE (sh_compare_op1),
+                                   sh_compare_op1);
+
+      emit_insn (gen_cmpgtudi_media (operands[0],
+                                    sh_compare_op0, sh_compare_op1));
+      DONE;
+    }
+  operands[1] = prepare_scc_operands (GTU);
+}")
 
 (define_expand "sltu"
   [(set (match_operand:SI 0 "arith_reg_operand" "")
        (match_dup 1))]
   ""
-  "operands[1] = prepare_scc_operands (LTU);")
+  "
+{
+  if (TARGET_SHMEDIA)
+    {
+      if (GET_MODE (operands[0]) != DImode)
+       operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
+      sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
+      if (sh_compare_op1 != const0_rtx)
+       sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
+                                   ? GET_MODE (sh_compare_op0)
+                                   : GET_MODE (sh_compare_op1),
+                                   sh_compare_op1);
+
+      emit_insn (gen_cmpgtudi_media (operands[0],
+                                    sh_compare_op1, sh_compare_op0));
+      DONE;
+    }
+  operands[1] = prepare_scc_operands (LTU);
+}")
 
 (define_expand "sleu"
   [(set (match_operand:SI 0 "arith_reg_operand" "")
        (match_dup 1))]
   ""
-  "operands[1] = prepare_scc_operands (LEU);")
+  "
+{
+  if (TARGET_SHMEDIA)
+    {
+      rtx tmp;
+
+      if (GET_MODE (operands[0]) != DImode)
+       operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
+      sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
+      if (sh_compare_op1 != const0_rtx)
+       sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
+                                   ? GET_MODE (sh_compare_op0)
+                                   : GET_MODE (sh_compare_op1),
+                                   sh_compare_op1);
+
+      tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
+
+      emit_insn (gen_cmpgtudi_media (tmp, sh_compare_op0, sh_compare_op1));
+      emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx));
+
+      DONE;
+    }
+  operands[1] = prepare_scc_operands (LEU);
+}")
 
 (define_expand "sgeu"
   [(set (match_operand:SI 0 "arith_reg_operand" "")
        (match_dup 1))]
   ""
-  "operands[1] = prepare_scc_operands (GEU);")
+  "
+{
+  if (TARGET_SHMEDIA)
+    {
+      rtx tmp;
+
+      if (GET_MODE (operands[0]) != DImode)
+       operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
+      sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
+      if (sh_compare_op1 != const0_rtx)
+       sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
+                                   ? GET_MODE (sh_compare_op0)
+                                   : GET_MODE (sh_compare_op1),
+                                   sh_compare_op1);
+
+      tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
+
+      emit_insn (gen_cmpgtudi_media (tmp, sh_compare_op1, sh_compare_op0));
+      emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx));
+
+      DONE;
+    }
+
+  operands[1] = prepare_scc_operands (GEU);
+}")
 
 ;; sne moves the complement of the T reg to DEST like this:
 ;;      cmp/eq ...
   ""
   "
 {
+  if (TARGET_SHMEDIA)
+    {
+      rtx tmp;
+
+      if (GET_MODE (operands[0]) != DImode)
+       operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
+
+      if (! TARGET_SHMEDIA_FPU && GET_MODE (sh_compare_op0) != DImode)
+       FAIL;
+
+      sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
+      if (sh_compare_op1 != const0_rtx)
+       sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode
+                                   ? GET_MODE (sh_compare_op0)
+                                   : GET_MODE (sh_compare_op1),
+                                   sh_compare_op1);
+
+      tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
+
+      emit_insn (gen_seq (tmp));
+      emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx));
+
+      DONE;
+    }
+
    operands[1] = prepare_scc_operands (EQ);
    operands[2] = gen_reg_rtx (SImode);
 }")
 
+(define_expand "sunordered"
+  [(set (match_operand:DI 0 "arith_reg_operand" "")
+       (unordered:DI (match_dup 1) (match_dup 2)))]
+  "TARGET_SHMEDIA_FPU"
+  "
+{
+  operands[1] = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0);
+  operands[2] = force_reg (GET_MODE (sh_compare_op1), sh_compare_op1);
+}")
+
 ;; Use the same trick for FP sle / sge
 (define_expand "movnegt"
   [(set (match_dup 2) (const_int -1))
              (set (reg:SI T_REG)
                   (ne:SI (ior:SI (match_operand 1 "" "") (match_dup 2))
                          (const_int 0)))])]  
-  ""
+  "TARGET_SH1"
   "operands[2] = gen_reg_rtx (SImode);")
 
 ;; Recognize mov #-1/negc/neg sequence, and change it to movt/add #-1.
   [(set (match_operand:SI 0 "arith_reg_operand" "")
        (plus:SI (reg:SI T_REG)
                 (const_int -1)))]
-  ""
+  "TARGET_SH1"
   [(set (match_dup 0) (eq:SI (reg:SI T_REG) (const_int 1)))
    (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))]
   "")
              (clobber (reg:SI R4_REG))
              (clobber (reg:SI R5_REG))
              (clobber (reg:SI R0_REG))])]
-  ""
+  "TARGET_SH1 && ! TARGET_SH5"
   "
 {
   if(expand_block_move (operands))
              (use (match_operand:SI 0 "arith_reg_operand" "r"))
              (clobber (reg:SI PR_REG))
              (clobber (reg:SI R0_REG))])]
-  "! TARGET_HARD_SH4"
+  "TARGET_SH1 && ! TARGET_HARD_SH4"
   "jsr @%0%#"
   [(set_attr "type" "sfunc")
    (set_attr "needs_delay_slot" "yes")])
              (clobber (reg:SI R5_REG))
              (clobber (reg:SI R6_REG))
              (clobber (reg:SI R0_REG))])]
-  "! TARGET_HARD_SH4"
+  "TARGET_SH1 && ! TARGET_HARD_SH4"
   "jsr @%0%#"
   [(set_attr "type" "sfunc")
    (set_attr "needs_delay_slot" "yes")])
   "fschg")
 
 (define_expand "addsf3"
-  [(match_operand:SF 0 "arith_reg_operand" "")
-   (match_operand:SF 1 "arith_reg_operand" "")
-   (match_operand:SF 2 "arith_reg_operand" "")]
-  "TARGET_SH3E"
-  "{ expand_sf_binop (&gen_addsf3_i, operands); DONE; }")
+  [(set (match_operand:SF 0 "arith_reg_operand" "")
+       (plus:SF (match_operand:SF 1 "arith_reg_operand" "")
+                (match_operand:SF 2 "arith_reg_operand" "")))]
+  "TARGET_SH3E || TARGET_SHMEDIA_FPU"
+  "
+{
+  if (TARGET_SH3E)
+    {
+      expand_sf_binop (&gen_addsf3_i, operands);
+      DONE;
+    }
+}")
+
+(define_insn "*addsf3_media"
+  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
+       (plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
+                (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
+  "TARGET_SHMEDIA_FPU"
+  "fadd.s      %1, %2, %0")
 
 (define_insn "addsf3_i"
   [(set (match_operand:SF 0 "arith_reg_operand" "=f")
    (set_attr "fp_mode" "single")])
 
 (define_expand "subsf3"
-  [(match_operand:SF 0 "fp_arith_reg_operand" "")
-   (match_operand:SF 1 "fp_arith_reg_operand" "")
-   (match_operand:SF 2 "fp_arith_reg_operand" "")]
-  "TARGET_SH3E"
-  "{ expand_sf_binop (&gen_subsf3_i, operands); DONE; }")
+  [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
+       (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
+                 (match_operand:SF 2 "fp_arith_reg_operand" "")))]
+  "TARGET_SH3E || TARGET_SHMEDIA_FPU"
+  "
+{
+  if (TARGET_SH3E)
+    {
+      expand_sf_binop (&gen_subsf3_i, operands);
+      DONE;
+    }
+}")
+
+(define_insn "*subsf3_media"
+  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
+       (minus:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
+                 (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
+  "TARGET_SHMEDIA_FPU"
+  "fsub.s      %1, %2, %0")
 
 (define_insn "subsf3_i"
   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
 ;; SH3E, we use a separate insn for SH3E mulsf3.
 
 (define_expand "mulsf3"
-  [(match_operand:SF 0 "fp_arith_reg_operand" "")
-   (match_operand:SF 1 "fp_arith_reg_operand" "")
-   (match_operand:SF 2 "fp_arith_reg_operand" "")]
-  "TARGET_SH3E"
+  [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
+       (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "")
+                (match_operand:SF 2 "fp_arith_reg_operand" "")))]
+  "TARGET_SH3E || TARGET_SHMEDIA_FPU"
   "
 {
   if (TARGET_SH4)
     expand_sf_binop (&gen_mulsf3_i4, operands);
-  else
+  else if (TARGET_SH3E)
     emit_insn (gen_mulsf3_ie (operands[0], operands[1], operands[2]));
-  DONE;
+  if (! TARGET_SHMEDIA)
+    DONE;
 }")
 
+(define_insn "*mulsf3_media"
+  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
+       (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
+                (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
+  "TARGET_SHMEDIA_FPU"
+  "fmul.s      %1, %2, %0")
+
 (define_insn "mulsf3_i4"
   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
        (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0")
   "fmul        %2,%0"
   [(set_attr "type" "fp")])
 
+(define_insn "*mac_media"
+  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
+       (plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f")
+                         (match_operand:SF 2 "fp_arith_reg_operand" "f"))
+                (match_operand:SF 3 "fp_arith_reg_operand" "0")))]
+  "TARGET_SHMEDIA_FPU"
+  "fmac.s %1, %2, %0")
+
 (define_insn "*macsf3"
   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
        (plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%w")
    (set_attr "fp_mode" "single")])
 
 (define_expand "divsf3"
-  [(match_operand:SF 0 "arith_reg_operand" "")
-   (match_operand:SF 1 "arith_reg_operand" "")
-   (match_operand:SF 2 "arith_reg_operand" "")]
-  "TARGET_SH3E"
-  "{ expand_sf_binop (&gen_divsf3_i, operands); DONE; }")
+  [(set (match_operand:SF 0 "arith_reg_operand" "")
+       (div:SF (match_operand:SF 1 "arith_reg_operand" "")
+               (match_operand:SF 2 "arith_reg_operand" "")))]
+  "TARGET_SH3E || TARGET_SHMEDIA_FPU"
+  "
+{
+  if (TARGET_SH3E)
+    {
+      expand_sf_binop (&gen_divsf3_i, operands);
+      DONE;
+    }
+}")
+
+(define_insn "*divsf3_media"
+  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
+       (div:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")
+               (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
+  "TARGET_SHMEDIA_FPU"
+  "fdiv.s      %1, %2, %0")
 
 (define_insn "divsf3_i"
   [(set (match_operand:SF 0 "arith_reg_operand" "=f")
   [(set_attr "type" "fdiv")
    (set_attr "fp_mode" "single")])
 
+(define_insn "floatdisf2"
+  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
+       (float:SF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
+  "TARGET_SHMEDIA_FPU"
+  "float.qs %1, %0")
+
 (define_expand "floatsisf2"
   [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
        (float:SF (match_operand:SI 1 "fpul_operand" "")))]
-  "TARGET_SH3E"
+  "TARGET_SH3E || TARGET_SHMEDIA_FPU"
   "
 {
   if (TARGET_SH4)
     }
 }")
 
+(define_insn "*floatsisf2_media"
+  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
+       (float:SF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
+  "TARGET_SHMEDIA_FPU"
+  "float.ls    %1, %0")
+
 (define_insn "floatsisf2_i4"
   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
        (float:SF (match_operand:SI 1 "fpul_operand" "y")))
   "float       %1,%0"
   [(set_attr "type" "fp")])
 
+(define_insn "fix_truncsfdi2"
+  [(set (match_operand:DI 0 "fp_arith_reg_operand" "=f")
+       (fix:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
+  "TARGET_SHMEDIA_FPU"
+  "ftrc.sq %1, %0")
+
 (define_expand "fix_truncsfsi2"
   [(set (match_operand:SI 0 "fpul_operand" "=y")
        (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
-  "TARGET_SH3E"
+  "TARGET_SH3E || TARGET_SHMEDIA_FPU"
   "
 {
   if (TARGET_SH4)
     }
 }")
 
+(define_insn "*fix_truncsfsi2_media"
+  [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
+       (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
+  "TARGET_SHMEDIA_FPU"
+  "ftrc.sl     %1, %0")
+
 (define_insn "fix_truncsfsi2_i4"
   [(set (match_operand:SI 0 "fpul_operand" "=y")
        (fix:SI (match_operand:SF 1 "fp_arith_reg_operand" "f")))
   [(set_attr "length" "4")
    (set_attr "fp_mode" "single")])
 
+(define_insn "cmpeqsf_media"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (eq:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")
+              (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
+  "TARGET_SHMEDIA_FPU"
+  "fcmpeq.s    %1, %2, %0")
+
+(define_insn "cmpgtsf_media"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (gt:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")
+              (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
+  "TARGET_SHMEDIA_FPU"
+  "fcmpgt.s    %1, %2, %0")
+
+(define_insn "cmpgesf_media"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (ge:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")
+              (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
+  "TARGET_SHMEDIA_FPU"
+  "fcmpge.s    %1, %2, %0")
+
+(define_insn "cmpunsf_media"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (unordered:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")
+                     (match_operand:SF 2 "fp_arith_reg_operand" "f")))]
+  "TARGET_SHMEDIA_FPU"
+  "fcmpun.s    %1, %2, %0")
+
 (define_expand "cmpsf"
   [(set (reg:SI T_REG)
        (compare (match_operand:SF 0 "arith_operand" "")
                 (match_operand:SF 1 "arith_operand" "")))]
-  "TARGET_SH3E"
+  "TARGET_SH3E || TARGET_SHMEDIA_FPU"
   "
 {
   sh_compare_op0 = operands[0];
 }")
 
 (define_expand "negsf2"
-  [(match_operand:SF 0 "fp_arith_reg_operand" "")
-   (match_operand:SF 1 "fp_arith_reg_operand" "")]
-  "TARGET_SH3E"
-  "{ expand_sf_unop (&gen_negsf2_i, operands); DONE; }")
+  [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
+       (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
+  "TARGET_SH3E || TARGET_SHMEDIA_FPU"
+  "
+{
+  if (TARGET_SH3E)
+    {
+      expand_sf_unop (&gen_negsf2_i, operands);
+      DONE;
+    }
+}")
+
+(define_insn "*negsf2_media"
+  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
+       (neg:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
+  "TARGET_SHMEDIA_FPU"
+  "fneg.s      %1, %0")
 
 (define_insn "negsf2_i"
   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
    (set_attr "fp_mode" "single")])
 
 (define_expand "sqrtsf2"
-  [(match_operand:SF 0 "fp_arith_reg_operand" "")
-   (match_operand:SF 1 "fp_arith_reg_operand" "")]
-  "TARGET_SH3E"
-  "{ expand_sf_unop (&gen_sqrtsf2_i, operands); DONE; }")
+  [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
+       (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
+  "TARGET_SH3E || TARGET_SHMEDIA_FPU"
+  "
+{
+  if (TARGET_SH3E)
+    {
+      expand_sf_unop (&gen_sqrtsf2_i, operands);
+      DONE;
+    }
+}")
+
+(define_insn "*sqrtsf2_media"
+  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
+       (sqrt:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
+  "TARGET_SHMEDIA_FPU"
+  "fsqrt.s     %1, %0")
 
 (define_insn "sqrtsf2_i"
   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
    (set_attr "fp_mode" "single")])
 
 (define_expand "abssf2"
-  [(match_operand:SF 0 "fp_arith_reg_operand" "")
-   (match_operand:SF 1 "fp_arith_reg_operand" "")]
-  "TARGET_SH3E"
-  "{ expand_sf_unop (&gen_abssf2_i, operands); DONE; }")
+  [(set (match_operand:SF 0 "fp_arith_reg_operand" "")
+       (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "")))]
+  "TARGET_SH3E || TARGET_SHMEDIA_FPU"
+  "
+{
+  if (TARGET_SH3E)
+    {
+      expand_sf_unop (&gen_abssf2_i, operands);
+      DONE;
+    }
+}")
+
+(define_insn "*abssf2_media"
+  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
+       (abs:SF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
+  "TARGET_SHMEDIA_FPU"
+  "fabs.s      %1, %0")
 
 (define_insn "abssf2_i"
   [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
    (set_attr "fp_mode" "single")])
 
 (define_expand "adddf3"
-  [(match_operand:DF 0 "fp_arith_reg_operand" "")
-   (match_operand:DF 1 "fp_arith_reg_operand" "")
-   (match_operand:DF 2 "fp_arith_reg_operand" "")]
-  "TARGET_SH4"
-  "{ expand_df_binop (&gen_adddf3_i, operands); DONE; }")
+  [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
+       (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
+                (match_operand:DF 2 "fp_arith_reg_operand" "")))]
+  "TARGET_SH4 || TARGET_SHMEDIA_FPU"
+  "
+{
+  if (TARGET_SH4)
+    {
+      expand_df_binop (&gen_adddf3_i, operands);
+      DONE;
+    }
+}")
+
+(define_insn "*adddf3_media"
+  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
+       (plus:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
+                (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
+  "TARGET_SHMEDIA_FPU"
+  "fadd.d      %1, %2, %0")
 
 (define_insn "adddf3_i"
   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
    (set_attr "fp_mode" "double")])
 
 (define_expand "subdf3"
-  [(match_operand:DF 0 "fp_arith_reg_operand" "")
-   (match_operand:DF 1 "fp_arith_reg_operand" "")
-   (match_operand:DF 2 "fp_arith_reg_operand" "")]
-  "TARGET_SH4"
-  "{ expand_df_binop (&gen_subdf3_i, operands); DONE; }")
+  [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
+       (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
+                 (match_operand:DF 2 "fp_arith_reg_operand" "")))]
+  "TARGET_SH4 || TARGET_SHMEDIA_FPU"
+  "
+{
+  if (TARGET_SH4)
+    {
+      expand_df_binop (&gen_subdf3_i, operands);
+      DONE;
+    }
+}")
+
+(define_insn "*subdf3_media"
+  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
+       (minus:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
+                 (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
+  "TARGET_SHMEDIA_FPU"
+  "fsub.d      %1, %2, %0")
 
 (define_insn "subdf3_i"
   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
    (set_attr "fp_mode" "double")])
 
 (define_expand "muldf3"
-  [(match_operand:DF 0 "fp_arith_reg_operand" "")
-   (match_operand:DF 1 "fp_arith_reg_operand" "")
-   (match_operand:DF 2 "fp_arith_reg_operand" "")]
-  "TARGET_SH4"
-  "{ expand_df_binop (&gen_muldf3_i, operands); DONE; }")
+  [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
+       (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
+                (match_operand:DF 2 "fp_arith_reg_operand" "")))]
+  "TARGET_SH4 || TARGET_SHMEDIA_FPU"
+  "
+{
+  if (TARGET_SH4)
+    {
+      expand_df_binop (&gen_muldf3_i, operands);
+      DONE;
+    }
+}")
+
+(define_insn "*muldf3_media"
+  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
+       (mult:DF (match_operand:DF 1 "fp_arith_reg_operand" "%f")
+                (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
+  "TARGET_SHMEDIA_FPU"
+  "fmul.d      %1, %2, %0")
 
 (define_insn "muldf3_i"
   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
    (set_attr "fp_mode" "double")])
 
 (define_expand "divdf3"
-  [(match_operand:DF 0 "fp_arith_reg_operand" "")
-   (match_operand:DF 1 "fp_arith_reg_operand" "")
-   (match_operand:DF 2 "fp_arith_reg_operand" "")]
-  "TARGET_SH4"
-  "{ expand_df_binop (&gen_divdf3_i, operands); DONE; }")
+  [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
+       (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "")
+               (match_operand:DF 2 "fp_arith_reg_operand" "")))]
+  "TARGET_SH4 || TARGET_SHMEDIA_FPU"
+  "
+{
+  if (TARGET_SH4)
+    {
+      expand_df_binop (&gen_divdf3_i, operands);
+      DONE;
+    }
+}")
+
+(define_insn "*divdf3_media"
+  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
+       (div:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")
+               (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
+  "TARGET_SHMEDIA_FPU"
+  "fdiv.d      %1, %2, %0")
 
 (define_insn "divdf3_i"
   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
   [(set_attr "type" "dfdiv")
    (set_attr "fp_mode" "double")])
 
+(define_insn "floatdidf2"
+  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
+       (float:DF (match_operand:DI 1 "fp_arith_reg_operand" "f")))]
+  "TARGET_SHMEDIA_FPU"
+  "float.qd    %1, %0")
+
 (define_expand "floatsidf2"
-  [(match_operand:DF 0 "fp_arith_reg_operand" "")
-   (match_operand:SI 1 "fpul_operand" "")]
-  "TARGET_SH4"
+  [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
+       (float:DF (match_operand:SI 1 "fpul_operand" "")))]
+  "TARGET_SH4 || TARGET_SHMEDIA_FPU"
   "
 {
-  emit_df_insn (gen_floatsidf2_i (operands[0], operands[1], get_fpscr_rtx ()));
-  DONE;
+  if (TARGET_SH4)
+    {
+      emit_df_insn (gen_floatsidf2_i (operands[0], operands[1],
+                                     get_fpscr_rtx ()));
+      DONE;
+    }
 }")
 
+(define_insn "*floatsidf2_media"
+  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
+       (float:DF (match_operand:SI 1 "fp_arith_reg_operand" "f")))]
+  "TARGET_SHMEDIA_FPU"
+  "float.ld    %1, %0")
+
 (define_insn "floatsidf2_i"
   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
        (float:DF (match_operand:SI 1 "fpul_operand" "y")))
   [(set_attr "type" "dfp_conv")
    (set_attr "fp_mode" "double")])
 
+(define_insn "fix_truncdfdi2"
+  [(set (match_operand:DI 0 "fp_arith_reg_operand" "=f")
+       (fix:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
+  "TARGET_SHMEDIA_FPU"
+  "ftrc.dq     %1, %0")
+
 (define_expand "fix_truncdfsi2"
-  [(match_operand:SI 0 "fpul_operand" "")
-   (match_operand:DF 1 "fp_arith_reg_operand" "")]
-  "TARGET_SH4"
+  [(set (match_operand:SI 0 "fpul_operand" "")
+       (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "")))]
+  "TARGET_SH4 || TARGET_SHMEDIA_FPU"
   "
 {
-  emit_df_insn (gen_fix_truncdfsi2_i (operands[0], operands[1], get_fpscr_rtx ()));
-  DONE;
+  if (TARGET_SH4)
+    {
+      emit_df_insn (gen_fix_truncdfsi2_i (operands[0], operands[1],
+                                         get_fpscr_rtx ()));
+      DONE;
+    }
 }")
 
+(define_insn "*fix_truncdfsi2_media"
+  [(set (match_operand:SI 0 "fp_arith_reg_operand" "=f")
+       (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
+  "TARGET_SHMEDIA_FPU"
+  "ftrc.dl     %1, %0")
+
 (define_insn "fix_truncdfsi2_i"
   [(set (match_operand:SI 0 "fpul_operand" "=y")
        (fix:SI (match_operand:DF 1 "fp_arith_reg_operand" "f")))
   [(set_attr "length" "4")
    (set_attr "fp_mode" "double")])
    
+(define_insn "cmpeqdf_media"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (eq:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")
+              (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
+  "TARGET_SHMEDIA_FPU"
+  "fcmpeq.d    %1,%2,%0")
+
+(define_insn "cmpgtdf_media"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (gt:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")
+              (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
+  "TARGET_SHMEDIA_FPU"
+  "fcmpgt.d    %1,%2,%0")
+
+(define_insn "cmpgedf_media"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (ge:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")
+              (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
+  "TARGET_SHMEDIA_FPU"
+  "fcmpge.d    %1,%2,%0")
+
+(define_insn "cmpundf_media"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (unordered:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")
+                     (match_operand:DF 2 "fp_arith_reg_operand" "f")))]
+  "TARGET_SHMEDIA_FPU"
+  "fcmpun.d    %1,%2,%0")
+
 (define_expand "cmpdf"
   [(set (reg:SI T_REG)
        (compare (match_operand:DF 0 "arith_operand" "")
                 (match_operand:DF 1 "arith_operand" "")))]
-  "TARGET_SH4"
+  "TARGET_SH4 || TARGET_SHMEDIA_FPU"
   "
 {
   sh_compare_op0 = operands[0];
 }")
 
 (define_expand "negdf2"
-  [(match_operand:DF 0 "arith_reg_operand" "")
-   (match_operand:DF 1 "arith_reg_operand" "")]
-  "TARGET_SH4"
-  "{ expand_df_unop (&gen_negdf2_i, operands); DONE; }")
+  [(set (match_operand:DF 0 "arith_reg_operand" "")
+       (neg:DF (match_operand:DF 1 "arith_reg_operand" "")))]
+  "TARGET_SH4 || TARGET_SHMEDIA_FPU"
+  "
+{
+  if (TARGET_SH4)
+    {
+      expand_df_unop (&gen_negdf2_i, operands);
+      DONE;
+    }
+}")
+
+(define_insn "*negdf2_media"
+  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
+       (neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
+  "TARGET_SHMEDIA_FPU"
+  "fneg.d      %1, %0")
 
 (define_insn "negdf2_i"
   [(set (match_operand:DF 0 "arith_reg_operand" "=f")
    (set_attr "fp_mode" "double")])
 
 (define_expand "sqrtdf2"
-  [(match_operand:DF 0 "arith_reg_operand" "")
-   (match_operand:DF 1 "arith_reg_operand" "")]
-  "TARGET_SH4"
-  "{ expand_df_unop (&gen_sqrtdf2_i, operands); DONE; }")
+  [(set (match_operand:DF 0 "arith_reg_operand" "")
+       (sqrt:DF (match_operand:DF 1 "arith_reg_operand" "")))]
+  "TARGET_SH4 || TARGET_SHMEDIA_FPU"
+  "
+{
+  if (TARGET_SH4)
+    {
+      expand_df_unop (&gen_sqrtdf2_i, operands);
+      DONE;
+    }
+}")
+
+(define_insn "*sqrtdf2_media"
+  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
+       (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
+  "TARGET_SHMEDIA_FPU"
+  "fsqrt.d     %1, %0")
 
 (define_insn "sqrtdf2_i"
   [(set (match_operand:DF 0 "arith_reg_operand" "=f")
    (set_attr "fp_mode" "double")])
 
 (define_expand "absdf2"
-  [(match_operand:DF 0 "arith_reg_operand" "")
-   (match_operand:DF 1 "arith_reg_operand" "")]
-  "TARGET_SH4"
-  "{ expand_df_unop (&gen_absdf2_i, operands); DONE; }")
+  [(set (match_operand:DF 0 "arith_reg_operand" "")
+       (abs:DF (match_operand:DF 1 "arith_reg_operand" "")))]
+  "TARGET_SH4 || TARGET_SHMEDIA_FPU"
+  "
+{
+  if (TARGET_SH4)
+    {
+      expand_df_unop (&gen_absdf2_i, operands);
+      DONE;
+    }
+}")
+
+(define_insn "*absdf2_media"
+  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
+       (abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
+  "TARGET_SHMEDIA_FPU"
+  "fabs.d      %1, %0")
 
 (define_insn "absdf2_i"
   [(set (match_operand:DF 0 "arith_reg_operand" "=f")
    (set_attr "fp_mode" "double")])
 
 (define_expand "extendsfdf2"
-  [(match_operand:DF 0 "fp_arith_reg_operand" "")
-   (match_operand:SF 1 "fpul_operand" "")]
-  "TARGET_SH4"
+  [(set (match_operand:DF 0 "fp_arith_reg_operand" "")
+       (float_extend:DF (match_operand:SF 1 "fpul_operand" "")))]
+  "TARGET_SH4 || TARGET_SHMEDIA_FPU"
   "
 {
-  emit_df_insn (gen_extendsfdf2_i4 (operands[0], operands[1], get_fpscr_rtx ()));
-  DONE;
+  if (TARGET_SH4)
+    {
+      emit_df_insn (gen_extendsfdf2_i4 (operands[0], operands[1],
+                                       get_fpscr_rtx ()));
+      DONE;
+    }
 }")
 
+(define_insn "*extendsfdf2_media"
+  [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
+       (float_extend:DF (match_operand:SF 1 "fp_arith_reg_operand" "f")))]
+  "TARGET_SHMEDIA_FPU"
+  "fcnv.sd     %1, %0")
+
 (define_insn "extendsfdf2_i4"
   [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f")
        (float_extend:DF (match_operand:SF 1 "fpul_operand" "y")))
    (set_attr "fp_mode" "double")])
 
 (define_expand "truncdfsf2"
-  [(match_operand:SF 0 "fpul_operand" "")
-   (match_operand:DF 1 "fp_arith_reg_operand" "")]
-  "TARGET_SH4"
+  [(set (match_operand:SF 0 "fpul_operand" "")
+       (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "")))]
+  "TARGET_SH4 || TARGET_SHMEDIA_FPU"
   "
 {
-  emit_df_insn (gen_truncdfsf2_i4 (operands[0], operands[1], get_fpscr_rtx ()));
-  DONE;
+  if (TARGET_SH4)
+    {
+      emit_df_insn (gen_truncdfsf2_i4 (operands[0], operands[1],
+                                      get_fpscr_rtx ()));
+      DONE;
+    }
 }")
 
+(define_insn "*truncdfsf2_media"
+  [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
+       (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))]
+  "TARGET_SHMEDIA_FPU"
+  "fcnv.ds     %1, %0")
+
 (define_insn "truncdfsf2_i4"
   [(set (match_operand:SF 0 "fpul_operand" "=y")
        (float_truncate:SF (match_operand:DF 1 "fp_arith_reg_operand" "f")))
                         (match_operand:SI 1 "immediate_operand" "")
                         (match_operand:SI 2 "immediate_operand" ""))
        (match_operand:SI 3 "general_operand" ""))]
-  "! TARGET_LITTLE_ENDIAN"
+  "TARGET_SH1 && ! TARGET_LITTLE_ENDIAN"
   "
 {
   rtx addr_target, orig_address, shift_reg;
   [(set (match_operand:SI 0 "arith_reg_operand" "")
        (mem:SI (match_operand:SI 1 "arith_reg_operand" "")))
    (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))]
-  "REGNO (operands[1]) != REGNO (operands[0])"
+  "TARGET_SH1 && REGNO (operands[1]) != REGNO (operands[0])"
   "mov.l       @%1+,%0")
 
 ;; See the comment on the dt combiner pattern above.
        (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
    (set (mem:SI (match_dup 0))
        (match_operand:SI 2 "general_movsrc_operand" ""))]
-  "REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
+  "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
   "mov.l       %2,@(%0,%1)")
 
 (define_peephole
        (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
    (set (match_operand:SI 2 "general_movdst_operand" "")
        (mem:SI (match_dup 0)))]
-  "REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
+  "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
   "mov.l       @(%0,%1),%2")
 
 (define_peephole
        (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
    (set (mem:HI (match_dup 0))
        (match_operand:HI 2 "general_movsrc_operand" ""))]
-  "REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
+  "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
   "mov.w       %2,@(%0,%1)")
 
 (define_peephole
        (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
    (set (match_operand:HI 2 "general_movdst_operand" "")
        (mem:HI (match_dup 0)))]
-  "REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
+  "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
   "mov.w       @(%0,%1),%2")
 
 (define_peephole
        (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
    (set (mem:QI (match_dup 0))
        (match_operand:QI 2 "general_movsrc_operand" ""))]
-  "REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
+  "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
   "mov.b       %2,@(%0,%1)")
 
 (define_peephole
        (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
    (set (match_operand:QI 2 "general_movdst_operand" "")
        (mem:QI (match_dup 0)))]
-  "REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
+  "TARGET_SH1 && REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
   "mov.b       @(%0,%1),%2")
 
 (define_peephole
        (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
    (set (mem:SF (match_dup 0))
        (match_operand:SF 2 "general_movsrc_operand" ""))]
-  "REGNO (operands[0]) == 0
+  "TARGET_SH1 && REGNO (operands[0]) == 0
    && ((GET_CODE (operands[2]) == REG && REGNO (operands[2]) < 16)
        || (GET_CODE (operands[2]) == SUBREG
           && REGNO (SUBREG_REG (operands[2])) < 16))
    (set (match_operand:SF 2 "general_movdst_operand" "")
 
        (mem:SF (match_dup 0)))]
-  "REGNO (operands[0]) == 0
+  "TARGET_SH1 && REGNO (operands[0]) == 0
    && ((GET_CODE (operands[2]) == REG && REGNO (operands[2]) < 16)
        || (GET_CODE (operands[2]) == SUBREG
           && REGNO (SUBREG_REG (operands[2])) < 16))
        (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
    (set (mem:SF (match_dup 0))
        (match_operand:SF 2 "general_movsrc_operand" ""))]
-  "REGNO (operands[0]) == 0
+  "TARGET_SH3E && REGNO (operands[0]) == 0
    && ((GET_CODE (operands[2]) == REG
         && FP_OR_XD_REGISTER_P (REGNO (operands[2])))
        || (GET_CODE (operands[2]) == SUBREG
    (set (match_operand:SF 2 "general_movdst_operand" "")
 
        (mem:SF (match_dup 0)))]
-  "REGNO (operands[0]) == 0
+  "TARGET_SH3E && REGNO (operands[0]) == 0
    && ((GET_CODE (operands[2]) == REG
        && FP_OR_XD_REGISTER_P (REGNO (operands[2])))
        || (GET_CODE (operands[2]) == SUBREG
 ;; Switch to a new stack with its address in sp_switch (a SYMBOL_REF).  */
 (define_insn "sp_switch_1"
   [(const_int 1)]
-  ""
+  "TARGET_SH1"
   "*
 {
   rtx xoperands[1];
 ;; sp_switch attribute.  */
 (define_insn "sp_switch_2"
   [(const_int 2)]
-  ""
+  "TARGET_SH1"
   "mov.l @r15+,r15\;mov.l @r15+,r0"
   [(set_attr "length" "4")])
diff --git a/gcc/config/sh/sh64.h b/gcc/config/sh/sh64.h
new file mode 100644 (file)
index 0000000..ccf7f48
--- /dev/null
@@ -0,0 +1,61 @@
+/* Definitions of target machine for GNU compiler for Hitachi Super-H 5.
+   Copyright 2000, 2001 Free Software Foundation, Inc.
+   Contributed by Alexandre Oliva <aoliva@redhat.com>
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+#undef CPP_DEFAULT_CPU_SPEC
+#define CPP_DEFAULT_CPU_SPEC "-D__SH5__=32 -D__SHMEDIA__"
+
+#undef SUBTARGET_CPP_PTR_SPEC
+#define SUBTARGET_CPP_PTR_SPEC "\
+%{!m1:%{!m2:%{!m3:%{!m3e:%{!m4:%{!m4-single:%{!m4-single-only:%{!m4-nofpu:-D__SIZE_TYPE__=long\\ unsigned\\ int -D__PTRDIFF_TYPE__=long\\ int}}}}}}}} \
+%{m1|m2|m3|m3e|m4|m4-single|m4-single-only|m4-nofpu:-D__SIZE_TYPE__=unsigned\\ int -D__PTRDIFF_TYPE__=int} \
+"
+
+#undef ASM_SPEC
+#define ASM_SPEC  "%{ml:-little} %{mrelax:-relax} \
+%{m5-compact:--isa=SHcompact} %{m5-compact-nofpu:--isa=shcompact} \
+%{m5-32media:--isa=SHmedia --abi=32} %{m5-32media-nofpu:--isa=SHmedia --abi=32} \
+%{m5-64media:--isa=SHmedia --abi=64} %{m5-64media-nofpu:--isa=SHmedia --abi=64} \
+%{!m1:%{!m2:%{!m3:%{!m3e:%{!m4:%{!m4-single:%{!m4-single-only:%{!m4-nofpu:%{!m5-64media:%{!m5-64media-nofpu:%{!m5-32media:%{!m5-32media-nofpu:%{!m5-compact:%{!m5-compact-nofpu:--isa=SHmedia --abi=32}}}}}}}}}}}}}} \
+"
+
+#undef LINK_SPEC
+#define LINK_SPEC " \
+%{m5-compact:%{!ml:-m shelf32} %{ml:-m shlelf32}} \
+%{m5-compact-nofpu:%{!ml:-m shelf32} %{ml:-m shlelf32}} \
+%{m5-32media:%{!ml:-m shelf32} %{ml:-m shlelf32}} \
+%{m5-32media-nofpu:%{!ml:-m shelf32} %{ml:-m shlelf32}} \
+%{m5-64media:%{!ml:-m shelf64} %{ml:-m shlelf64}} \
+%{m5-64media-nofpu:%{!ml:-m shelf64} %{ml:-m shlelf64}} \
+%{!m1:%{!m2:%{!m3:%{!m3e:%{!m4:%{!m4-single:%{!m4-single-only:%{!m4-nofpu:%{!m5-64media:%{!m5-64media-nofpu:%{!m5-32media:%{!m5-32media-nofpu:%{!m5-compact:%{!m5-compact-nofpu:%{!ml:-m shelf32} %{ml:-m shlelf32}}}}}}}}}}}}}}} \
+%{mrelax:-relax}"
+
+#undef TARGET_DEFAULT
+#define TARGET_DEFAULT  (SH5_BIT|SH4_BIT|SH3E_BIT)
+
+/* These have been overridden in svr4.h, included in elf.h.  Restore
+   them.  */
+#undef WCHAR_TYPE
+#define WCHAR_TYPE "short unsigned int"
+
+#undef WCHAR_TYPE_SIZE
+#define WCHAR_TYPE_SIZE 16
+
+#undef MAX_WCHAR_TYPE_SIZE
diff --git a/gcc/config/sh/shmedia.h b/gcc/config/sh/shmedia.h
new file mode 100644 (file)
index 0000000..0ce6624
--- /dev/null
@@ -0,0 +1,33 @@
+/* Copyright (C) 2000 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* As a special exception, if you include this header file into source
+   files compiled by GCC, this header file does not by itself cause
+   the resulting executable to be covered by the GNU General Public
+   License.  This exception does not however invalidate any other
+   reasons why the executable file might be covered by the GNU General
+   Public License.  */
+
+#ifndef _SHMEDIA_H
+#define _SHMEDIA_H
+
+#include <ushmedia.h>
+#include <sshmedia.h>
+
+#endif
diff --git a/gcc/config/sh/sshmedia.h b/gcc/config/sh/sshmedia.h
new file mode 100644 (file)
index 0000000..d7ef456
--- /dev/null
@@ -0,0 +1,74 @@
+/* Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* As a special exception, if you include this header file into source
+   files compiled by GCC, this header file does not by itself cause
+   the resulting executable to be covered by the GNU General Public
+   License.  This exception does not however invalidate any other
+   reasons why the executable file might be covered by the GNU General
+   Public License.  */
+
+/* sshmedia.h: Intrinsics corresponding to SHmedia instructions that
+   may only be executed in privileged mode.  */
+
+#ifndef _SSHMEDIA_H
+#define _SSHMEDIA_H
+
+#if __SHMEDIA__
+__inline__ static
+unsigned long long
+sh_media_GETCON (unsigned int k)
+{
+  unsigned long long res;
+  __asm__ __volatile__ ("getcon        cr%1, %0" : "=r" (res) : "n" (k));
+  return res;
+}
+
+__inline__ static
+void
+sh_media_PUTCON (unsigned long long mm, unsigned int k)
+{
+  __asm__ __volatile__ ("putcon        %0, cr%1" : : "r" (mm), "n" (k));
+}
+
+__inline__ static
+unsigned long long
+sh_media_GETCFG (unsigned long long mm, int s)
+{
+  unsigned long long res;
+  __asm__ __volatile__ ("getcfg        %1, %2, %0" : "=r" (res) : "r" (mm), "n" (s));
+  return res;
+}
+
+__inline__ static
+void
+sh_media_PUTCFG (unsigned long long mm, int s, unsigned long long mw)
+{
+  __asm__ __volatile__ ("putcfg        %0, %1, %2" : : "r" (mm), "n" (s), "r" (mw));
+}
+
+__inline__ static
+void
+sh_media_SLEEP (void)
+{
+  __asm__ __volatile__ ("sleep");
+}
+#endif
+
+#endif
diff --git a/gcc/config/sh/t-sh64 b/gcc/config/sh/t-sh64
new file mode 100644 (file)
index 0000000..c332989
--- /dev/null
@@ -0,0 +1,11 @@
+EXTRA_MULTILIB_PARTS= crt1.o crti.o crtn.o crtbegin.o crtend.o
+
+LIB1ASMFUNCS = \
+  _sdivsi3 _sdivsi3_i4 _udivsi3 _udivsi3_i4 _set_fpscr \
+  _shcompact_call_trampoline _shcompact_return_trampoline \
+  _shcompact_incoming_args _ic_invalidate _nested_trampoline \
+  _push_pop_shmedia_regs
+
+MULTILIB_OPTIONS= ml m5-32media-nofpu/m5-compact/m5-compact-nofpu/m5-64media/m5-64media-nofpu
+MULTILIB_DIRNAMES= ml nofpu compact nofpu/compact media64 nofpu/media64
+MULTILIB_MATCHES=
diff --git a/gcc/config/sh/ushmedia.h b/gcc/config/sh/ushmedia.h
new file mode 100644 (file)
index 0000000..9a402e8
--- /dev/null
@@ -0,0 +1,1147 @@
+/* Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* As a special exception, if you include this header file into source
+   files compiled by GCC, this header file does not by itself cause
+   the resulting executable to be covered by the GNU General Public
+   License.  This exception does not however invalidate any other
+   reasons why the executable file might be covered by the GNU General
+   Public License.  */
+
+/* ushmedia.h: Intrinsics corresponding to SHmedia instructions that
+   may be executed in both user and privileged mode.  */
+
+#ifndef _USHMEDIA_H
+#define _USHMEDIA_H
+
+#if __SHMEDIA__
+#if ! __SH4_NO_FPU
+typedef float __GCC_FV __attribute__ ((mode (V4SF)));
+typedef float __GCC_MTRX __attribute__ ((mode (V16SF)));
+#endif
+
+__inline__ static
+unsigned long long
+sh_media_MABS_L (unsigned long long mm)
+{
+  unsigned long long res;
+  __asm__ ("mabs.l     %1, %0" : "=r" (res) : "r" (mm));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MABS_W (unsigned long long mm)
+{
+  unsigned long long res;
+  __asm__ ("mabs.w     %1, %0" : "=r" (res) : "r" (mm));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MADD_L (unsigned long long mm, unsigned long long mn)
+{
+  unsigned long long res;
+  __asm__ ("madd.l     %1, %2, %0" : "=r" (res) : "r" (mm), "r" (mn));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MADD_W (unsigned long long mm, unsigned long long mn)
+{
+  unsigned long long res;
+  __asm__ ("madd.w     %1, %2, %0" : "=r" (res) : "r" (mm), "r" (mn));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MADDS_L (unsigned long long mm, unsigned long long mn)
+{
+  unsigned long long res;
+  __asm__ ("madds.l    %1, %2, %0" : "=r" (res) : "r" (mm), "r" (mn));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MADDS_UB (unsigned long long mm, unsigned long long mn)
+{
+  unsigned long long res;
+  __asm__ ("madds.ub   %1, %2, %0" : "=r" (res) : "r" (mm), "r" (mn));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MADDS_W (unsigned long long mm, unsigned long long mn)
+{
+  unsigned long long res;
+  __asm__ ("madds.w    %1, %2, %0" : "=r" (res) : "r" (mm), "r" (mn));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MCMPEQ_B (unsigned long long mm, unsigned long long mn)
+{
+  unsigned long long res;
+  __asm__ ("mcmpeq.b   %1, %2, %0" : "=r" (res) : "r" (mm), "r" (mn));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MCMPEQ_L (unsigned long long mm, unsigned long long mn)
+{
+  unsigned long long res;
+  __asm__ ("mcmpeq.l   %1, %2, %0" : "=r" (res) : "r" (mm), "r" (mn));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MCMPEQ_W (unsigned long long mm, unsigned long long mn)
+{
+  unsigned long long res;
+  __asm__ ("mcmpeq.w   %1, %2, %0" : "=r" (res) : "r" (mm), "r" (mn));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MCMPGT_L (unsigned long long mm, unsigned long long mn)
+{
+  unsigned long long res;
+  __asm__ ("mcmpgt.l   %1, %2, %0" : "=r" (res) : "r" (mm), "r" (mn));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MCMPGT_UB (unsigned long long mm, unsigned long long mn)
+{
+  unsigned long long res;
+  __asm__ ("mcmpgt.ub  %1, %2, %0" : "=r" (res) : "r" (mm), "r" (mn));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MCMPGT_W (unsigned long long mm, unsigned long long mn)
+{
+  unsigned long long res;
+  __asm__ ("mcmpgt.w   %1, %2, %0" : "=r" (res) : "r" (mm), "r" (mn));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MCMV (unsigned long long mm, unsigned long long mn, unsigned long long mw)
+{
+  unsigned long long res;
+  __asm__ ("mcmv       %1, %2, %0" : "=r" (res)
+          : "r" (mm), "r" (mn), "0" (mw));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MCNVS_LW (unsigned long long mm, unsigned long long mn)
+{
+  unsigned long long res;
+  __asm__ ("mcnvs.lw   %1, %2, %0" : "=r" (res) : "r" (mm), "r" (mn));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MCNVS_WB (unsigned long long mm, unsigned long long mn)
+{
+  unsigned long long res;
+  __asm__ ("mcnvs.wb   %1, %2, %0" : "=r" (res) : "r" (mm), "r" (mn));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MCNVS_WUB (unsigned long long mm, unsigned long long mn)
+{
+  unsigned long long res;
+  __asm__ ("mcnvs.wub  %1, %2, %0" : "=r" (res) : "r" (mm), "r" (mn));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MEXTR1 (unsigned long long mm, unsigned long long mn)
+{
+  unsigned long long res;
+  __asm__ ("mextr1     %1, %2, %0" : "=r" (res) : "r" (mm), "r" (mn));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MEXTR2 (unsigned long long mm, unsigned long long mn)
+{
+  unsigned long long res;
+  __asm__ ("mextr2     %1, %2, %0" : "=r" (res) : "r" (mm), "r" (mn));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MEXTR3 (unsigned long long mm, unsigned long long mn)
+{
+  unsigned long long res;
+  __asm__ ("mextr3     %1, %2, %0" : "=r" (res) : "r" (mm), "r" (mn));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MEXTR4 (unsigned long long mm, unsigned long long mn)
+{
+  unsigned long long res;
+  __asm__ ("mextr4     %1, %2, %0" : "=r" (res) : "r" (mm), "r" (mn));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MEXTR5 (unsigned long long mm, unsigned long long mn)
+{
+  unsigned long long res;
+  __asm__ ("mextr5     %1, %2, %0" : "=r" (res) : "r" (mm), "r" (mn));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MEXTR6 (unsigned long long mm, unsigned long long mn)
+{
+  unsigned long long res;
+  __asm__ ("mextr6     %1, %2, %0" : "=r" (res) : "r" (mm), "r" (mn));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MEXTR7 (unsigned long long mm, unsigned long long mn)
+{
+  unsigned long long res;
+  __asm__ ("mextr7     %1, %2, %0" : "=r" (res) : "r" (mm), "r" (mn));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MMACFX_WL (unsigned long long mm, unsigned long long mn, unsigned long long mw)
+{
+  unsigned long long res;
+  __asm__ ("mmacfx.wl  %1, %2, %0" : "=r" (res)
+          : "r" (mm), "r" (mn), "0" (mw));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MMACNFX_WL (unsigned long long mm, unsigned long long mn, unsigned long long mw)
+{
+  unsigned long long res;
+  __asm__ ("mmacnfx.wl %1, %2, %0" : "=r" (res)
+          : "r" (mm), "r" (mn), "0" (mw));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MMUL_L (unsigned long long mm, unsigned long long mn)
+{
+  unsigned long long res;
+  __asm__ ("mmul.l     %1, %2, %0" : "=r" (res) : "r" (mm), "r" (mn));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MMUL_W (unsigned long long mm, unsigned long long mn)
+{
+  unsigned long long res;
+  __asm__ ("mmul.w     %1, %2, %0" : "=r" (res) : "r" (mm), "r" (mn));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MMULFX_L (unsigned long long mm, unsigned long long mn)
+{
+  unsigned long long res;
+  __asm__ ("mmulfx.l   %1, %2, %0" : "=r" (res) : "r" (mm), "r" (mn));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MMULFX_W (unsigned long long mm, unsigned long long mn)
+{
+  unsigned long long res;
+  __asm__ ("mmulfx.w   %1, %2, %0" : "=r" (res) : "r" (mm), "r" (mn));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MMULFXRP_W (unsigned long long mm, unsigned long long mn)
+{
+  unsigned long long res;
+  __asm__ ("mmulfxrp.w %1, %2, %0" : "=r" (res) : "r" (mm), "r" (mn));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MMULHI_WL (unsigned long long mm, unsigned long long mn)
+{
+  unsigned long long res;
+  __asm__ ("mmulhi.wl  %1, %2, %0" : "=r" (res) : "r" (mm), "r" (mn));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MMULLO_WL (unsigned long long mm, unsigned long long mn)
+{
+  unsigned long long res;
+  __asm__ ("mmullo.wl  %1, %2, %0" : "=r" (res) : "r" (mm), "r" (mn));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MMULSUM_WQ (unsigned long long mm, unsigned long long mn, unsigned long long mw)
+{
+  unsigned long long res;
+  __asm__ ("mmulsum.wq %1, %2, %0" : "=r" (res)
+          : "r" (mm), "r" (mn), "0" (mw));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MPERM_W (unsigned long long mm, unsigned int mn)
+{
+  unsigned long long res;
+  __asm__ ("mperm.w    %1, %2, %0" : "=r" (res) : "r" (mm), "r" (mn));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MSAD_UBQ (unsigned long long mm, unsigned long long mn, unsigned long long mw)
+{
+  unsigned long long res;
+  __asm__ ("msad.ubq   %1, %2, %0" : "=r" (res)
+          : "r" (mm), "r" (mn), "0" (mw));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MSHALDS_L (unsigned long long mm, unsigned int mn)
+{
+  unsigned long long res;
+  __asm__ ("mshalds.l  %1, %2, %0" : "=r" (res) : "r" (mm), "r" (mn));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MSHALDS_W (unsigned long long mm, unsigned int mn)
+{
+  unsigned long long res;
+  __asm__ ("mshalds.w  %1, %2, %0" : "=r" (res) : "r" (mm), "r" (mn));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MSHARD_L (unsigned long long mm, unsigned int mn)
+{
+  unsigned long long res;
+  __asm__ ("mshard.l   %1, %2, %0" : "=r" (res) : "r" (mm), "r" (mn));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MSHARD_W (unsigned long long mm, unsigned int mn)
+{
+  unsigned long long res;
+  __asm__ ("mshard.w   %1, %2, %0" : "=r" (res) : "r" (mm), "r" (mn));
+  return res;
+}
+
+__inline__ static
+short
+sh_media_MSHARDS_Q (long long mm, unsigned int mn)
+{
+  short res;
+  __asm__ ("mshards.q  %1, %2, %0" : "=r" (res) : "r" (mm), "r" (mn));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MSHFHI_B (unsigned long long mm, unsigned long long mn)
+{
+  unsigned long long res;
+  __asm__ ("mshfhi.b   %1, %2, %0" : "=r" (res) : "r" (mm), "r" (mn));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MSHFHI_L (unsigned long long mm, unsigned long long mn)
+{
+  unsigned long long res;
+  __asm__ ("mshfhi.l   %1, %2, %0" : "=r" (res) : "r" (mm), "r" (mn));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MSHFHI_W (unsigned long long mm, unsigned long long mn)
+{
+  unsigned long long res;
+  __asm__ ("mshfhi.w   %1, %2, %0" : "=r" (res) : "r" (mm), "r" (mn));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MSHFLO_B (unsigned long long mm, unsigned long long mn)
+{
+  unsigned long long res;
+  __asm__ ("mshflo.b   %1, %2, %0" : "=r" (res) : "r" (mm), "r" (mn));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MSHFLO_L (unsigned long long mm, unsigned long long mn)
+{
+  unsigned long long res;
+  __asm__ ("mshflo.l   %1, %2, %0" : "=r" (res) : "r" (mm), "r" (mn));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MSHFLO_W (unsigned long long mm, unsigned long long mn)
+{
+  unsigned long long res;
+  __asm__ ("mshflo.w   %1, %2, %0" : "=r" (res) : "r" (mm), "r" (mn));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MSHLLD_L (unsigned long long mm, unsigned int mn)
+{
+  unsigned long long res;
+  __asm__ ("mshlld.l   %1, %2, %0" : "=r" (res) : "r" (mm), "r" (mn));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MSHLLD_W (unsigned long long mm, unsigned int mn)
+{
+  unsigned long long res;
+  __asm__ ("mshlld.w   %1, %2, %0" : "=r" (res) : "r" (mm), "r" (mn));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MSHLRD_L (unsigned long long mm, unsigned int mn)
+{
+  unsigned long long res;
+  __asm__ ("mshlrd.l   %1, %2, %0" : "=r" (res) : "r" (mm), "r" (mn));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MSHLRD_W (unsigned long long mm, unsigned int mn)
+{
+  unsigned long long res;
+  __asm__ ("mshlrd.w   %1, %2, %0" : "=r" (res) : "r" (mm), "r" (mn));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MSUB_L (unsigned long long mm, unsigned long long mn)
+{
+  unsigned long long res;
+  __asm__ ("msub.l     %1, %2, %0" : "=r" (res) : "r" (mm), "r" (mn));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MSUB_W (unsigned long long mm, unsigned long long mn)
+{
+  unsigned long long res;
+  __asm__ ("msub.w     %1, %2, %0" : "=r" (res) : "r" (mm), "r" (mn));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MSUBS_L (unsigned long long mm, unsigned long long mn)
+{
+  unsigned long long res;
+  __asm__ ("msubs.l    %1, %2, %0" : "=r" (res) : "r" (mm), "r" (mn));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MSUBS_UB (unsigned long long mm, unsigned long long mn)
+{
+  unsigned long long res;
+  __asm__ ("msubs.ub   %1, %2, %0" : "=r" (res) : "r" (mm), "r" (mn));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_MSUBS_W (unsigned long long mm, unsigned long long mn)
+{
+  unsigned long long res;
+  __asm__ ("msubs.w    %1, %2, %0" : "=r" (res) : "r" (mm), "r" (mn));
+  return res;
+}
+
+#if ! __SH4_NOFPU__
+__inline__ static
+double
+sh_media_FABS_D (double dg)
+{
+  double res;
+  __asm__ ("fabs.d     %1, %0" : "=f" (res) : "f" (dg));
+  return res;
+}
+
+__inline__ static
+float 
+sh_media_FABS_S (float fg)
+{
+  float res;
+  __asm__ ("fabs.s     %1, %0" : "=f" (res) : "f" (fg));
+  return res;
+}
+
+__inline__ static
+int   
+sh_media_FCMPUN_D (double dg, double dh)
+{
+  int res;
+  __asm__ ("fcmpun.d   %1, %2, %0" : "=f" (res) : "f" (dg), "f" (dh));
+  return res;
+}
+
+__inline__ static
+int   
+sh_media_FCMPUN_S (float fg, float fh)
+{
+  int res;
+  __asm__ ("fcmpun.s   %1, %2, %0" : "=f" (res) : "f" (fg), "f" (fh));
+  return res;
+}
+
+__inline__ static
+float 
+sh_media_FGETSCR (void)
+{
+  float res;
+  __asm__ ("fgetscr    %0" : "=f" (res));
+  return res;
+}
+
+__inline__ static
+float 
+sh_media_FIPR_S (const void *fvg, const void *fvh)
+{
+  float res;
+  __asm__ ("fipr.s     %1, %2, %0" : "=f" (res)
+          : "f" (*(const __GCC_FV *)fvg), "f" (*(const __GCC_FV *)fvh));
+  return res;
+}
+
+__inline__ static
+float 
+sh_media_FMAC_S (float fg, float fh, float fq)
+{
+  float res;
+  __asm__ ("fmac.s     %1, %2, %0" : "=f" (res)
+          : "f" (fg), "f" (fh), "0" (fq));
+  return res;
+}
+
+__inline__ static
+long long
+sh_media_FMOV_DQ (double dg)
+{
+  long long res;
+  __asm__ ("fmov.dq    %1, %0" : "=r" (res) : "f" (dg));
+  return res;
+}
+
+__inline__ static
+float
+sh_media_FMOV_LS (int mm)
+{
+  float res;
+  __asm__ ("fmov.ls    %1, %0" : "=f" (res) : "r" (mm));
+  return res;
+}
+
+__inline__ static
+double
+sh_media_FMOV_QD (long long mm)
+{
+  double res;
+  __asm__ ("fmov.qd    %1, %0" : "=f" (res) : "r" (mm));
+  return res;
+}
+
+__inline__ static
+int
+sh_media_FMOV_SL (float fg)
+{
+  int res;
+  __asm__ ("fmov.sl    %1, %0" : "=r" (res) : "f" (fg));
+  return res;
+}
+
+__inline__ static
+void  
+sh_media_FPUTSCR (float fg)
+{
+  __asm__ ("fputscr    %0" : : "f" (fg));
+}
+
+__inline__ static
+double
+sh_media_FSQRT_D (double dg)
+{
+  double res;
+  __asm__ ("fsqrt.d    %1, %0" : "=f" (res) : "f" (dg));
+  return res;
+}
+
+__inline__ static
+float 
+sh_media_FSQRT_S (float fg)
+{
+  float res;
+  __asm__ ("fsqrt.s    %1, %0" : "=f" (res) : "f" (fg));
+  return res;
+}
+
+__inline__ static
+void  
+sh_media_FTRV_S (const void *mtrxg, const void *fvh, void *fvf)
+{
+  __asm__ ("ftrv.s     %2, %1, %0" : "=f" (*(__GCC_FV *)fvf)
+          : "f" (*(const __GCC_FV *)fvh), "f" (*(const __GCC_MTRX *)mtrxg));
+}
+#endif /* ! __SH4_NOFPU__ */
+
+__inline__ static
+unsigned long long
+sh_media_LDHI_L (void *p, int s)
+{
+  unsigned long long res;
+  __asm__ ("ldhi.l     %m1, %0" : "=r" (res) : "o" (((char*)p)[s]));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_LDHI_Q (void *p, int s)
+{
+  unsigned long long res;
+  __asm__ ("ldhi.q     %m1, %0" : "=r" (res) : "o" (((char*)p)[s]));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_LDLO_L (void *p, int s)
+{
+  unsigned long long res;
+  __asm__ ("ldlo.l     %m1, %0" : "=r" (res) : "o" (((char*)p)[s]));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_LDLO_Q (void *p, int s)
+{
+  unsigned long long res;
+  __asm__ ("ldlo.q     %m1, %0" : "=r" (res) : "o" (((char*)p)[s]));
+  return res;
+}
+
+__inline__ static
+void     
+sh_media_STHI_L (void *p, int s, unsigned int mw)
+{
+  __asm__ ("sthi.l %m0, %1" : "+o" (((char*)p)[s]) : "r" (mw));
+}
+
+__inline__ static
+void     
+sh_media_STHI_Q (void *p, int s, unsigned long long mw)
+{
+  __asm__ ("sthi.q %m0, %1" : "+o" (((char*)p)[s]) : "r" (mw));
+}
+
+__inline__ static
+void     
+sh_media_STLO_L (void *p, int s, unsigned int mw)
+{
+  __asm__ ("stlo.l %m0, %1" : "+o" (((char*)p)[s]) : "r" (mw));
+}
+
+__inline__ static
+void     
+sh_media_STLO_Q (void *p, int s, unsigned long long mw)
+{
+  __asm__ ("stlo.q %m0, %1" : "+o" (((char*)p)[s]) : "r" (mw));
+}
+
+__inline__ static
+unsigned char
+sh_media_NSB (long long mm)
+{
+  unsigned char res;
+  __asm__ ("nsb        %1, %0" : "=r" (res) : "r" (mm));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_BYTEREV (unsigned long long mm)
+{
+  unsigned long long res;
+  __asm__ ("byterev    %1, %0" : "=r" (res) : "r" (mm));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_CMVEQ (unsigned long long mm, unsigned long long mn, unsigned long long mw)
+{
+  unsigned long long res;
+  __asm__ ("cmveq      %1, %2, %0" : "=r" (res)
+          : "r" (mm), "r" (mn), "0" (mw));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_CMVNE (unsigned long long mm, unsigned long long mn, unsigned long long mw)
+{
+  unsigned long long res;
+  __asm__ ("cmveq      %1, %2, %0" : "=r" (res)
+          : "r" (mm), "r" (mn), "0" (mw));
+  return res;
+}
+
+__inline__ static
+unsigned long long
+sh_media_ADDZ_L (unsigned int mm, unsigned int mn)
+{
+  unsigned long long res;
+  __asm__ ("addz.l     %1, %2, %0" : "=r" (res) : "r" (mm), "r" (mn));
+  return res;
+}
+
+__inline__ static
+void
+sh_media_NOP (void)
+{
+  __asm__ __volatile__ ("nop" : :);
+}
+
+__inline__ static
+unsigned long long
+sh_media_SWAP_Q (void *mm, long long mn, unsigned long long mw)
+{
+  unsigned long long res;
+  unsigned long long *addr = (unsigned long long *)((char *)mm + mn);
+  __asm__ ("swap.q     %m1, %0" : "=r" (res), "+o" (*addr) : "0" (mw));
+  return res;
+}
+
+__inline__ static
+void     
+sh_media_SYNCI (void)
+{
+  __asm__ __volatile__ ("synci");
+}
+
+__inline__ static
+void     
+sh_media_SYNCO (void)
+{
+  __asm__ __volatile__ ("synco");
+}
+
+__inline__ static
+void
+sh_media_ALLOCO (void *mm, int s)
+{
+  __asm__ __volatile__ ("alloco        %m0" : : "o" (((char*)mm)[s]));
+}
+
+__inline__ static
+void
+sh_media_ICBI (void *mm, int s)
+{
+  __asm__ __volatile__ ("icbi  %m0" : : "o" (((char*)mm)[s]));
+}
+
+__inline__ static
+void
+sh_media_OCBI (void *mm, int s)
+{
+  __asm__ __volatile__ ("ocbi  %m0" : : "o" (((char*)mm)[s]));
+}
+
+__inline__ static
+void
+sh_media_OCBP (void *mm, int s)
+{
+  __asm__ __volatile__ ("ocbp  %m0" : : "o" (((char*)mm)[s]));
+}
+
+__inline__ static
+void
+sh_media_OCBWB (void *mm, int s)
+{
+  __asm__ __volatile__ ("ocbwb %m0" : : "o" (((char*)mm)[s]));
+}
+
+__inline__ static
+void
+sh_media_PREFI (void *mm, int s)
+{
+  __asm__ __volatile__ ("prefi %m0" : : "o" (((char*)mm)[s]));
+}
+
+__inline__ static
+void
+sh_media_PREFO (void *mm, int s)
+{
+  __asm__ __volatile__ ("ld.b  %m0, r63" : : "o" (((char*)mm)[s]));
+}
+
+__inline__ static
+void
+sh_media_BRK (void)
+{
+  __asm__ __volatile__ ("brk");
+}
+
+__inline__ static
+void
+sh_media_TRAPA (unsigned long long mm)
+{
+  __asm__ __volatile__ ("trapa %%0" : : "r" (mm));
+}
+
+__inline__ static
+short         
+sh_media_unaligned_LD_W (void *p)
+{
+#if __LITTLE_ENDIAN__
+  return (((unsigned char *)p)[0]
+         | (((short)((__signed__ char *)p)[1]) << 8));
+#else
+  return ((((short)((__signed__ char *)p)[0]) << 8)
+         | ((unsigned char *)p)[1]);
+#endif
+}
+
+__inline__ static
+unsigned short
+sh_media_unaligned_LD_UW (void *p)
+{
+  unsigned char *addr = p;
+#if __LITTLE_ENDIAN__
+  return sh_media_MSHFLO_B (addr[0], addr[1]);
+#else
+  return sh_media_MSHFLO_B (addr[1], addr[0]);
+#endif
+}
+
+__inline__ static
+int           
+sh_media_unaligned_LD_L (void *p)
+{
+#if __LITTLE_ENDIAN__
+  return sh_media_LDHI_L (p, 3) | sh_media_LDLO_L (p, 0);
+#else
+  return sh_media_LDLO_L (p, 3) | sh_media_LDHI_L (p, 0);
+#endif
+}
+
+__inline__ static
+long long     
+sh_media_unaligned_LD_Q (void *p)
+{
+#if __LITTLE_ENDIAN__
+  return sh_media_LDHI_Q (p, 7) | sh_media_LDLO_Q (p, 0);
+#else
+  return sh_media_LDLO_Q (p, 7) | sh_media_LDHI_Q (p, 0);
+#endif
+}
+
+__inline__ static
+void
+sh_media_unaligned_ST_W (void *p, unsigned int k)
+{
+  char *addr = p;
+#if __LITTLE_ENDIAN__
+  addr[0] = k;
+  addr[1] = k >> 8;
+#else
+  addr[1] = k;
+  addr[0] = k >> 8;
+#endif
+}
+
+__inline__ static
+void
+sh_media_unaligned_ST_L (void *p, unsigned int k)
+{
+#if __LITTLE_ENDIAN__
+  sh_media_STHI_L (p, 3, k);
+  sh_media_STLO_L (p, 0, k);
+#else
+  sh_media_STLO_L (p, 3, k);
+  sh_media_STHI_L (p, 0, k);
+#endif
+}
+
+__inline__ static
+void
+sh_media_unaligned_ST_Q (void *p, unsigned long long k)
+{
+#if __LITTLE_ENDIAN__
+  sh_media_STHI_Q (p, 7, k);
+  sh_media_STLO_Q (p, 0, k);
+#else
+  sh_media_STLO_Q (p, 7, k);
+  sh_media_STHI_Q (p, 0, k);
+#endif
+}
+
+#if ! __SH4_NOFPU__
+__inline__ static
+void
+sh_media_FVCOPY_S (const void *fvg, void *fvf)
+{
+  const __GCC_FV *g = fvg;
+  __GCC_FV *f = fvf;
+  *f = *g;
+}
+
+__inline__ static
+void
+sh_media_FVADD_S (const void *fvg, const void *fvh, void *fvf)
+{
+  const float *g = fvg, *h = fvh;
+  float *f = fvf;
+#if 1
+  int i;
+
+  for (i = 0; i < 4; i++)
+    f[i] = g[i] + h[i];
+#else
+  f[0] = g[0] + h[0];
+  f[1] = g[1] + h[1];
+  f[2] = g[2] + h[2];
+  f[3] = g[3] + h[3];
+#endif
+}
+
+__inline__ static
+void
+sh_media_FVSUB_S (const void *fvg, const void *fvh, void *fvf)
+{
+  const float *g = fvg, *h = fvh;
+  float *f = fvf;
+#if 1
+  int i;
+
+  for (i = 0; i < 4; i++)
+    f[i] = g[i] - h[i];
+#else
+  f[0] = g[0] - h[0];
+  f[1] = g[1] - h[1];
+  f[2] = g[2] - h[2];
+  f[3] = g[3] - h[3];
+#endif
+}
+
+__inline__ static
+void
+sh_media_FMTRXCOPY_S (const void *mtrxg, void *mtrxf)
+{
+  const __GCC_MTRX *g = mtrxg;
+  __GCC_MTRX *f = mtrxf;
+  *f = *g;
+}
+
+__inline__ static
+void
+sh_media_FMTRXADD_S (const void *mtrxg, const void *mtrxh, void *mtrxf)
+{
+  const __GCC_FV *g = mtrxg, *h = mtrxh;
+  __GCC_FV *f = mtrxf;
+#if 1
+  int i;
+
+  for (i = 0; i < 4; i++)
+    sh_media_FVADD_S (&g[i], &h[i], &f[i]);
+#else
+  sh_media_FVADD_S (&g[0], &h[0], &f[0]);
+  sh_media_FVADD_S (&g[1], &h[1], &f[1]);
+  sh_media_FVADD_S (&g[2], &h[2], &f[2]);
+  sh_media_FVADD_S (&g[3], &h[3], &f[3]);
+#endif
+}
+
+__inline__ static
+void
+sh_media_FMTRXSUB_S (const void *mtrxg, const void *mtrxh, void *mtrxf)
+{
+  const __GCC_FV *g = mtrxg, *h = mtrxh;
+  __GCC_FV *f = mtrxf;
+#if 1
+  int i;
+
+  for (i = 0; i < 4; i++)
+    sh_media_FVSUB_S (&g[i], &h[i], &f[i]);
+#else
+  sh_media_FVSUB_S (&g[0], &h[0], &f[0]);
+  sh_media_FVSUB_S (&g[1], &h[1], &f[1]);
+  sh_media_FVSUB_S (&g[2], &h[2], &f[2]);
+  sh_media_FVSUB_S (&g[3], &h[3], &f[3]);
+#endif
+}
+
+__inline__ static
+void
+sh_media_FTRVADD_S (const void *mtrxg, const void *fvh, const void *fvi, void *fvf)
+{
+  sh_media_FTRV_S (mtrxg, fvh, fvf);
+  sh_media_FVADD_S (fvf, fvi, fvf);
+}
+
+__inline__ static
+void
+sh_media_FTRVSUB_S (const void *mtrxg, const void *fvh, const void *fvi, void *fvf)
+{
+  sh_media_FTRV_S (mtrxg, fvh, fvf);
+  sh_media_FVSUB_S (fvf, fvi, fvf);
+}
+
+__inline__ static
+void
+sh_media_FMTRXMUL_S (const void *mtrxg, const void *mtrxh, void *mtrxf)
+{
+  const __GCC_FV *g = mtrxg;
+  __GCC_FV *f = mtrxf;
+#if 1
+  int j;
+
+  for (j = 0; j < 4; j++)
+    sh_media_FTRV_S (mtrxh, &g[j], &f[j]);
+#else
+  sh_media_FTRV_S (mtrxh, &g[0], &f[0]);
+  sh_media_FTRV_S (mtrxh, &g[1], &f[1]);
+  sh_media_FTRV_S (mtrxh, &g[2], &f[2]);
+  sh_media_FTRV_S (mtrxh, &g[3], &f[3]);
+#endif
+}
+
+__inline__ static
+void
+sh_media_FMTRXMULADD_S (const void *mtrxg, const void *mtrxh, const void *mtrxi, void *mtrxf)
+{
+  const __GCC_FV *g = mtrxg, *i = mtrxi;
+  __GCC_FV *f = mtrxf;
+#if 1
+  int j;
+
+  for (j = 0; j < 4; j++)
+    sh_media_FTRVADD_S (mtrxh, &g[j], &i[j], &f[j]);
+#else
+  sh_media_FTRVADD_S (mtrxh, &g[0], &i[0], &f[0]);
+  sh_media_FTRVADD_S (mtrxh, &g[1], &i[1], &f[1]);
+  sh_media_FTRVADD_S (mtrxh, &g[2], &i[2], &f[2]);
+  sh_media_FTRVADD_S (mtrxh, &g[3], &i[3], &f[3]);
+#endif
+}
+
+__inline__ static
+void
+sh_media_FMTRXMULSUB_S (const void *mtrxg, const void *mtrxh, const void *mtrxi, void *mtrxf)
+{
+  const __GCC_FV *g = mtrxg, *i = mtrxi;
+  __GCC_FV *f = mtrxf;
+#if 1
+  int j;
+
+  for (j = 0; j < 4; j++)
+    sh_media_FTRVSUB_S (mtrxh, &g[j], &i[j], &f[j]);
+#else
+  sh_media_FTRVSUB_S (mtrxh, &g[0], &i[0], &f[0]);
+  sh_media_FTRVSUB_S (mtrxh, &g[1], &i[1], &f[1]);
+  sh_media_FTRVSUB_S (mtrxh, &g[2], &i[2], &f[2]);
+  sh_media_FTRVSUB_S (mtrxh, &g[3], &i[3], &f[3]);
+#endif
+}
+#endif /* ! __SH4_NOFPU__ */
+
+#endif /* __SHMEDIA__ */
+
+#endif /* _USHMEDIA_H */
index 7c1baf3..620edb7 100644 (file)
@@ -540,6 +540,9 @@ in the following sections.
 @gccoptlist{
 -m1  -m2  -m3  -m3e @gol
 -m4-nofpu  -m4-single-only  -m4-single  -m4 @gol
+-m5-64media -m5-64media-nofpu @gol
+-m5-32media -m5-32media-nofpu @gol
+-m5-compact -m5-compact-nofpu @gol
 -mb  -ml  -mdalign  -mrelax @gol
 -mbigtable  -mfmovd  -mhitachi  -mnomacsave @gol
 -mieee  -misize  -mpadstruct  -mspace @gol
index 3cb5c68..663393e 100644 (file)
@@ -3266,6 +3266,22 @@ arguments pop them but other functions (such as @code{printf}) pop
 nothing (the caller pops all).  When this convention is in use,
 @var{funtype} is examined to determine whether a function takes a fixed
 number of arguments.
+
+@findex CALL_POPS_ARGS
+@item   CALL_POPS_ARGS (@var{cum})
+A C expression that should indicate the number of bytes a call sequence
+pops off the stack.  It is added to the value of @code{RETURN_POPS_ARGS}
+when compiling a function call.
+
+@var{cum} is the variable in which all arguments to the called function
+have been accumulated.
+
+On certain architectures, such as the SH5, a call trampoline is used
+that pops certain registers off the stack, depending on the arguments
+that have been passed to the function.  Since this is a property of the
+call site, not of the called function, @code{RETURN_POPS_ARGS} is not
+appropriate.
+
 @end table
 
 @node Register Arguments
index f218a02..c8b9aee 100644 (file)
@@ -1002,6 +1002,21 @@ UDItype __umulsidi3 (USItype, USItype);
 #define UMUL_TIME 5
 #endif
 
+#if defined (__SH5__) && __SHMEDIA__ && W_TYPE_SIZE == 32
+#define __umulsidi3(u,v) ((UDItype)(USItype)u*(USItype)v)
+#define count_leading_zeros(count, x) \
+  do                                                                   \
+    {                                                                  \
+      UDItype x_ = (USItype)(x);                                       \
+      SItype c_;                                                       \
+                                                                       \
+      __asm__ ("nsb %1, %0" : "=r" (c_) : "r" (x_));                   \
+      (count) = c_ - 31;                                               \
+    }                                                                  \
+  while (0)
+#define COUNT_LEADING_ZEROS_0 32
+#endif
+
 #if defined (__sparc__) && !defined (__arch64__) && !defined (__sparcv9) \
     && W_TYPE_SIZE == 32
 #define add_ssaaaa(sh, sl, ah, al, bh, bl) \
index 580f6ff..5ec6a1e 100644 (file)
@@ -139,6 +139,7 @@ DEF_MACHMODE (V4DFmode, "V4DF", MODE_VECTOR_FLOAT, BITS_PER_UNIT*32, 32, 8, V8DF
 
 DEF_MACHMODE (V8SFmode, "V8SF", MODE_VECTOR_FLOAT, BITS_PER_UNIT*32, 32, 4,V4DFmode)
 DEF_MACHMODE (V8DFmode, "V8DF", MODE_VECTOR_FLOAT, BITS_PER_UNIT*64, 64, 8, VOIDmode)
+DEF_MACHMODE (V16SFmode, "V16SF", MODE_VECTOR_FLOAT, 512, 64, 4, VOIDmode)
 
 /* BLKmode is used for structures, arrays, etc.
    that fit no more specific mode.  */
index 28193e9..d664866 100644 (file)
@@ -4907,6 +4907,7 @@ build_common_tree_nodes_2 (short_double)
   unsigned_V16QI_type_node
     = make_vector (V16QImode, unsigned_intQI_type_node, 1);
 
+  V16SF_type_node = make_vector (V16SFmode, float_type_node, 0);
   V4SF_type_node = make_vector (V4SFmode, float_type_node, 0);
   V4SI_type_node = make_vector (V4SImode, intSI_type_node, 0);
   V2SI_type_node = make_vector (V2SImode, intSI_type_node, 0);
index 6c07f5b..fe4e033 100644 (file)
@@ -1910,6 +1910,7 @@ enum tree_index
   TI_UV16QI_TYPE,
 
   TI_V4SF_TYPE,
+  TI_V16SF_TYPE,
   TI_V4SI_TYPE,
   TI_V8HI_TYPE,
   TI_V8QI_TYPE,
@@ -1992,6 +1993,7 @@ extern tree global_trees[TI_MAX];
 #define V4HI_type_node                 global_trees[TI_V4HI_TYPE]
 #define V2SI_type_node                 global_trees[TI_V2SI_TYPE]
 #define V2SF_type_node                 global_trees[TI_V2SF_TYPE]
+#define V16SF_type_node                        global_trees[TI_V16SF_TYPE]
 
 /* An enumeration of the standard C integer types.  These must be
    ordered so that shorter types appear before longer ones.  */