Commit fa5322fa by Alexandre Oliva Committed by Alexandre Oliva

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.

From-SVN: r49630
parent 7aa00daf
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.
......
......@@ -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:
......
......@@ -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,
......
......@@ -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"
......
/* 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"
......
......@@ -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__ */
......@@ -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__ */
......@@ -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) \
......
......@@ -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 */
......@@ -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));
......
......@@ -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));
/* 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;
/* 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);
}
/* 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;
}
/* 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);
}
/* 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;
}
......@@ -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)
/* ??? 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)
/* 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)
/* 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)))))
/* 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 ()
/* 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)
/* 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)
/* 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 \
......
This source diff could not be displayed because it is too large. You can view the blob instead.
/* 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
/* 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
/* 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
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=
/* 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 */
......@@ -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
......
......@@ -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
......
......@@ -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) \
......
......@@ -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. */
......
......@@ -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);
......
......@@ -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. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment