diff --git a/gcc/ChangeLog b/gcc/ChangeLog index cdf9076f30a..2c62f0142fb 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,34 @@ +2004-02-04 Kazu Hirata + + * config.gcc: Remove obsolete ports and configurations. + * config/linux-aout.h, config/netware.h, + config/t-linux-gnulibc1, config/d30v/abi, + config/d30v/d30v-protos.h, config/d30v/d30v.c, + config/d30v/d30v.h, config/d30v/d30v.md, + config/d30v/libgcc1.asm, config/d30v/t-d30v, + config/dsp16xx/dsp16xx-modes.def, + config/dsp16xx/dsp16xx-protos.h, config/dsp16xx/dsp16xx.c, + config/dsp16xx/dsp16xx.h, config/dsp16xx/dsp16xx.md, + config/i370/README, config/i370/i370-c.c, + config/i370/i370-protos.h, config/i370/i370.c, + config/i370/i370.h, config/i370/i370.md, config/i370/linux.h, + config/i370/mvs.h, config/i370/oe.h, config/i370/t-i370, + config/i386/freebsd-aout.h, config/i386/linux-aout.h, + config/i386/moss.h, config/i386/netware.h, + config/i386/svr3.ifile, config/i386/svr3dbx.h, + config/i386/svr3gas.h, config/i386/svr3z.ifile, + config/i386/t-udk, config/i386/udk.h, config/i386/vsta.h, + config/i960/i960-c.c, config/i960/i960-coff.h, + config/i960/i960-modes.def, config/i960/i960-protos.h, + config/i960/i960.c, config/i960/i960.h, config/i960/i960.md, + config/i960/rtems.h, config/i960/t-960bare, + config/m68k/hp310.h, config/m68k/hp320.h, + config/m68k/hp320base.h, config/m68k/m68kv4.h, + config/m68k/netbsd.h, config/m68k/sgs.h, config/m68k/t-hp320: + Remove. + * doc/extend.texi, doc/install.texi, doc/invoke.texi, + doc/md.texi: Remove mentions of obsolete ports. + 2004-02-04 Jan Hubicka * alias.c (find_base_term, get_addr): Do not dereference NULL diff --git a/gcc/config.gcc b/gcc/config.gcc index db1e010f45e..42aab18f74b 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -58,7 +58,7 @@ # tm_file="${tm_file} dbxelf.h elfos.h svr4.h ${cpu_type.h}/elf.h" # Note that the preferred order is: # - specific target header "${cpu_type}/${cpu_type.h}" -# - generic headers like dbxelf.h elfos.h, netware.h, etc. +# - generic headers like dbxelf.h elfos.h, etc. # - specializing target headers like ${cpu_type.h}/elf.h # This helps to keep OS specific stuff out of the CPU # defining header ${cpu_type}/${cpu_type.h}. @@ -182,23 +182,7 @@ md_file= # Obsolete configurations. case ${target} in - d30v-* | \ - dsp16xx-* | \ - i370-* | \ - i960-* | \ - i?86-moss-msdos | i?86-*-moss* | \ - i?86-ncr-sysv4* | \ - i?86-*-netware | \ - i?86-*-freebsd2* | i?86-*-freebsd*aout* | \ - i?86-*-linux*aout* | \ - i?86-*-linux*libc1* | \ - i?86-*-interix | \ - i?86-*-mach* | \ - i?86-*-udk* | \ - i?86-*-sysv[123]* | \ - i386-*-vsta | \ - m68k-hp-hpux* | m68000-hp-hpux* | \ - m68k-*-sysv4*) + dummy*) if test "x$enable_obsolete" != xyes; then echo "*** Configuration ${target} is obsolete." >&2 echo "*** Specify --enable-obsolete to build it anyway." >&2 @@ -726,12 +710,6 @@ cris-*-linux*) tm_file="dbxelf.h elfos.h svr4.h ${tm_file} linux.h cris/linux.h" tmake_file="cris/t-cris t-slibgcc-elf-ver cris/t-linux" ;; -d30v-*) - tm_file="dbxelf.h elfos.h svr4.h ${tm_file}" - ;; -dsp16xx-*) - use_fixproto=yes - ;; fr30-*-elf) tm_file="dbxelf.h elfos.h svr4.h ${tm_file}" tmake_file=fr30/t-fr30 @@ -900,16 +878,6 @@ i[34567]86-*-elf*) tmake_file="i386/t-i386elf t-svr4" use_fixproto=yes ;; -i[34567]86-ncr-sysv4*) # NCR 3000 - ix86 running system V.4 - xm_defines="SMALL_ARG_MAX" - tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h svr4.h i386/sysv4.h i386/sysv4-cpp.h" - extra_parts="crtbegin.o crtend.o" - tmake_file=i386/t-crtpic - use_fixproto=yes - ;; -i[34567]86-*-netware) # Intel 80386's running netware - tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h svr4.h i386/sysv4.h netware.h i386/netware.h" - ;; i[34567]86-sequent-ptx4* | i[34567]86-sequent-sysv4*) if test x$gas = xyes then @@ -930,10 +898,6 @@ i[34567]86-*-beoself* | i[34567]86-*-beos*) tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h svr4.h i386/beos-elf.h" extra_parts='crtbegin.o crtend.o' ;; -i[34567]86-*-freebsd2 | i[34567]86-*-freebsd2.* | i[34567]86-*-freebsd*aout*) - tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h i386/gstabs.h i386/freebsd-aout.h" - tmake_file=t-freebsd - ;; i[34567]86-*-freebsd*) tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h ${fbsd_tm_file} i386/freebsd.h" ;; @@ -963,23 +927,6 @@ i[34567]86-*-coff*) tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h dbxcoff.h i386/i386-coff.h" use_fixproto=yes ;; -i[34567]86-*-linux*aout*) # Intel 80386's running GNU/Linux - # with a.out format - tmake_file="i386/t-crtstuff" - tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h i386/gstabs.h linux-aout.h i386/linux-aout.h" - gnu_ld=yes - ;; -i[34567]86-*-linux*libc1) # Intel 80386's running GNU/Linux - # with ELF format using the - # GNU/Linux C library 5 - tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h svr4.h linux.h i386/linux.h" - tmake_file="t-slibgcc-elf-ver t-linux t-linux-gnulibc1 i386/t-crtstuff" - extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o" - gnu_ld=yes - if test x$enable_threads = xyes; then - thread_file='single' - fi - ;; i[34567]86-*-linux*) # Intel 80386's running GNU/Linux # with ELF format using glibc 2 # aka GNU/Linux C library 6 @@ -1006,13 +953,6 @@ i[34567]86-pc-msdosdjgpp*) gnu_ld=yes gas=yes ;; -i[34567]86-moss-msdos* | i[34567]86-*-moss*) - tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h svr4.h linux.h i386/linux.h i386/moss.h" - tmake_file=t-libc-ok - gnu_ld=yes - gas=yes - use_fixproto=yes - ;; i[34567]86-*-lynxos*) if test x$gas = xyes then @@ -1022,12 +962,6 @@ i[34567]86-*-lynxos*) fi use_fixproto=yes ;; -i[34567]86-*-mach*) - tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h i386/gstabs.h i386/mach.h" -# tmake_file=t-libc-ok - use_collect2=yes - use_fixproto=yes - ;; i[34567]86-*-nto-qnx*) tm_file="${tm_file} i386/att.h dbxelf.h tm-dwarf2.h elfos.h svr4.h i386/unix.h i386/nto.h" tmake_file=i386/t-nto @@ -1097,38 +1031,6 @@ i[34567]86-*-sysv4*) # Intel 80386's running system V.4 extra_parts="crtbegin.o crtend.o" use_fixproto=yes ;; -i[34567]86-*-udk*) # Intel x86 on SCO UW/OSR5 Dev Kit - tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h svr4.h i386/sysv4.h i386/sysv5.h i386/udk.h" - tmake_file="i386/t-crtpic i386/t-udk t-svr4" - extra_parts="crtbegin.o crtend.o" - use_fixproto=yes - ;; -i[34567]86-*-sysv*) # Intel 80386's running system V - if test x$gas = xyes - then - if test x$stabs = xyes - then - tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h i386/svr3gas.h i386/svr3dbx.h" - tmake_file=i386/t-svr3dbx - extra_parts="svr3.ifile svr3z.ifile" - else - tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h i386/svr3gas.h" - extra_parts="crtbegin.o crtend.o" - tmake_file=i386/t-crtstuff - fi - else - tm_file="${tm_file} svr3.h i386/unix.h i386/att.h i386/sysv3.h" - extra_parts="crtbegin.o crtend.o" - tmake_file=i386/t-crtstuff - fi - tmake_file="$tmake_file i386/t-crtpic" - use_fixproto=yes - ;; -i386-*-vsta) # Intel 80386's running VSTa kernel - xm_file="i386/xm-vsta.h" - tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h i386/vsta.h" - use_fixproto=yes - ;; i[4567]86-wrs-vxworks) tm_file="${tm_file} i386/sysv4.h i386/unix.h i386/vxworks.h" tmake_file="${tmake_file} i386/t-vxworks" @@ -1180,17 +1082,6 @@ i[34567]86-*-interix3*) tm_file="${tm_file} dbxcoff.h" fi ;; -i[34567]86-*-interix*) - tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h i386/i386-interix.h interix.h" - tmake_file="i386/t-interix" - extra_objs=winnt.o - if test x$enable_threads = xyes ; then - thread_file='posix' - fi - if test x$stabs = xyes ; then - tm_file="${tm_file} dbxcoff.h" - fi - ;; i[34567]86-*-kaos*) tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h i386/i386elf.h kaos.h i386/kaos-i386.h" tmake_file="i386/t-i386elf t-svr4" @@ -1201,25 +1092,6 @@ i860-*-sysv4*) extra_parts="crtbegin.o crtend.o" use_fixproto=yes ;; -i960-*-coff*) - tm_file="${tm_file} dbxcoff.h i960/i960-coff.h libgloss.h" - tmake_file=i960/t-960bare - c_target_objs="i960-c.o" - cxx_target_objs="i960-c.o" - ;; -i960-*-rtems) - tmake_file="i960/t-960bare t-rtems" - tm_file="${tm_file} dbxcoff.h i960/i960-coff.h i960/rtems.h rtems.h" - c_target_objs="i960-c.o" - cxx_target_objs="i960-c.o" - ;; -i960-*-*) # Default i960 environment. - use_collect2=yes - tmake_file=i960/t-960bare - c_target_objs="i960-c.o" - cxx_target_objs="i960-c.o" - use_fixproto=yes - ;; ia64*-*-elf*) tm_file="${tm_file} dbxelf.h elfos.h ia64/sysv4.h ia64/elf.h" tmake_file="ia64/t-ia64" @@ -1324,37 +1196,6 @@ m68hc12-*-*|m6812-*-*) tmake_file="m68hc11/t-m68hc11-gas" use_fixproto=yes ;; -m68000-hp-hpux*) # HP 9000 series 300 - tm_file="m68k/hp320base.h m68k/m68k.h m68k/hp320.h m68k/hp310.h" - tm_defines="TARGET_DEFAULT=0" # 68000, no 68881, no bitfield ops - if test x$gas = xyes - then - tm_defines="${tm_defines} DBX_DEBUGGING_INFO=1 USE_GAS" - fi - tmake_file=m68k/t-hp320 - use_collect2=yes - use_fixproto=yes - ;; -m68k-hp-hpux7*) # HP 9000 series 300 running HPUX version 7. - tm_file="m68k/hp320base.h m68k/m68k.h m68k/hp320.h" - if test x$gas = xyes - then - tm_defines="DBX_DEBUGGING_INFO=1 USE_GAS" - else - tm_defines="NO_DOT_IN_LABEL NO_BUGS" - fi - use_collect2=yes - use_fixproto=yes - ;; -m68k-hp-hpux*) # HP 9000 series 300 - tm_file="m68k/hp320base.h m68k/m68k.h m68k/hp320.h" - if test x$gas = xyes - then - tm_defines="DBX_DEBUGGING_INFO=1 USE_GAS" - fi - use_collect2=yes - use_fixproto=yes - ;; m68k-*-aout*) tmake_file=m68k/t-m68kbare tm_file="m68k/m68k.h m68k/m68k-none.h m68k/m68kemb.h m68k/m68k-aout.h libgloss.h" @@ -1384,34 +1225,6 @@ m68010-*-netbsdelf* | m68k*-*-netbsdelf*) ;; esac ;; -m68k*-*-netbsd*) - if test "x$enable_obsolete" != xyes; then - echo "*** Configuration ${target} is obsolete." >&2 - echo "*** Specify --enable-obsolete to build it anyway." >&2 - echo "*** Support will be REMOVED in the next major release of GCC," >&2 - echo "*** unless a maintainer comes forward." >&2 - exit 1 - fi - tm_file="m68k/m68k.h netbsd.h netbsd-aout.h m68k/netbsd.h" - tmake_file=t-netbsd - extra_parts="" - use_collect2=yes - ;; -m68k*-*-openbsd*) - # needed to unconfuse gdb - tm_defines="OBSD_OLD_GAS TARGET_DEFAULT=(MASK_68020|MASK_68881|MASK_BITFIELD)" - tm_file="m68k/m68k.h openbsd.h m68k/openbsd.h" - tmake_file="t-libc-ok t-openbsd m68k/t-openbsd" - # we need collect2 until our bug is fixed... - use_collect2=yes - ;; -m68k-*-sysv4*) # Motorola m68k's running system V.4 - tm_file="m68k/m68k.h m68k/sgs.h dbxelf.h elfos.h svr4.h m68k/m68kv4.h" - tm_defines="MOTOROLA SGS SGS_CMP_ORDER SGS_SWITCH_TABLES" - tmake_file=t-svr4 - extra_parts="crtbegin.o crtend.o" - use_fixproto=yes - ;; m68k-*-uclinux*) # Motorola m68k/ColdFire running uClinux with uClibc tm_file="m68k/m68k.h m68k/m68k-none.h m68k/m68kelf.h dbxelf.h elfos.h m68k/uclinux.h" tm_defines="MOTOROLA USE_GAS" @@ -2214,16 +2027,6 @@ vax-*-ultrix*) # VAXen running ultrix tm_file="${tm_file} vax/ultrix.h" use_fixproto=yes ;; -vax-*-*) # VAX default entry - if test "x$enable_obsolete" != xyes; then - echo "*** Configuration ${target} is obsolete." >&2 - echo "*** Specify --enable-obsolete to build it anyway." >&2 - echo "*** Support will be REMOVED in the next major release of GCC," >&2 - echo "*** unless a maintainer comes forward." >&2 - exit 1 - fi - use_fixproto=yes - ;; xscale-*-elf) tm_file="arm/xscale-elf.h dbxelf.h elfos.h arm/unknown-elf.h arm/elf.h arm/aout.h arm/arm.h" tmake_file=arm/t-xscale-elf diff --git a/gcc/config/d30v/abi b/gcc/config/d30v/abi deleted file mode 100644 index c706e94f63f..00000000000 --- a/gcc/config/d30v/abi +++ /dev/null @@ -1,231 +0,0 @@ --*- Text -*- - -This document describes the proposed ABI for the D30V processor. This is -revision 2 of the document. - -Revision history: - -Revision 1: - Original revision of this document. - -Revision 2: - Done after consultation with Mitsubshi about the calling sequence. - This revision now reduces the number of registers the compiler will not - touch from 18 registers down to 8. - - Register 1 is now a normal temporary register, since mvfacc rx,ay,32 is - legal. - - Arguments greater than 4 bytes must be passed in an even register or at - a double word alignment. - - The va_list type is a structure, not a char *. - - The stack must be aligned to 8 byte boundary. Doubles and long longs - must also be aligned to 8 byte boundaries. - - System calls are specified via trap 31. - -Revision 3: - I added discussion about compiler switches. - -Register usage: -=============== - - Registers Call Status Usage - --------- ----------- ----- - R0 hardware Hardwired to 0 - R1 volatile temp - R2 volatile Arg 1 and main return value. - R3 volatile Arg 2 and low bits of 64 bit returns - R4 - R17 volatile Args 3-16 - R18 volatile Static chain if used - R19 - R25 volatile temps - R26 - R33 saved Reserved for user use - R34 - R60 saved Registers preserved across calls - R61 saved Frame pointer if needed. - R62 saved Return address pointer (hardware) - R63 saved Stack pointer - CR0 - CR3 hardware {normal,backup} {psw,pc} - CR4 - CR6 hardware Reserved for future use - CR7 - CR9 volatile Repeat count, addresses - CR10 - CR11 saved Modulo start/end - CR12 - CR14 hardware Reserved for future use - CR15 - CR17 hardware Interrupt support - F0 - F1 volatile Execution flags - F2 - F3 volatile General flags - F4 - F7 volatile Special purpose flags - A0 volatile Accumulator - A1 saved Accumulator - -Notes on the register usage: -============================ - - 1) R61 will hold the frame pointer if it is needed. Normally the frame - pointer will not be needed, in which case this will become another - saved register. - - 2) Repeat instructions and delayed branches cannot cross call boundaries. - Similarly, all flags are assumed to not be preserved across calls. - - 3) Since so many registers are available, I reserved 8 registers (r26-r33) - for the user to use for any purpose (global variables, interrupt - routines, thread pointer, etc.). These registers will not be used by - the compiler for any purpose. - - 4) One of the two accumulators is saved across calls. - - 5) Doubles and long longs will only be allocated to even/odd register - pairs to allow use of the ld2w/st2w instructions. - -Miscellaneous call information: -=============================== - - 1) Structures are passed in registers, rounding them up to word - boundaries. - - 2) Any argument that is greater than word size (4 bytes) must be aligned - to a double word boundary and/or start in an even register. The - intention here is to be able to use the ld2w/st2w instructions for - moving doubles and long longs. - - 3) Variable argument functions are called with the same calling sequence - as non-variable argument functions. When called, a variable argument - function first saves the 16 registers (R2 - R17) used for passing - arguments. The va_list type is a structure. The first element of the - structure is a pointer to the first word saved on the stack, and the - second element is a number that gives which argument number is being - processed. - - 4) Word and double word sized structures/unions are returned in registers, - other functions returning structures expect a temporary area address to - be passed as the first argument. - - -The stack frame when a function is called looks like: - -high | .... | - +-------------------------------+ - | Argument word #20 | - +-------------------------------+ - | Argument word #19 | - +-------------------------------+ - | Argument word #18 | - +-------------------------------+ - | Argument word #17 | -low SP----> +-------------------------------+ - -After the prologue is executed, the stack frame will look like: - -high | .... | - +-------------------------------+ - | Argument word #20 | - +-------------------------------+ - | Argument word #19 | - +-------------------------------+ - | Argument word #18 | - +-------------------------------+ - | Argument word #17 | - Prev sp +-------------------------------+ - | | - | Save for arguments 1..16 if | - | the func. uses stdarg/varargs | - | | - +-------------------------------+ - | | - | Save area for preserved regs | - | | - +-------------------------------+ - | | - | Local variables | - | | - +-------------------------------+ - | | - | alloca space if used | - | | - +-------------------------------+ - | | - | Space for outgoing arguments | - | | -low SP----> +-------------------------------+ - -System Calls -============ - -System calls will be done using "TRAP 31". Input arguments will be in R2 - R5, -and the system call number will be in R6. Return values from the system call -will be in R2. Negative values of the return indicate the system call failed, -and the value is the negative of the error code. Here are the assigned system -call numbers (value in R6): - - exit 1 - open 2 - close 3 - read 4 - write 5 - lseek 6 - unlink 7 - getpid 8 - kill 9 - fstat 10 - (11 is reserved for sbrk) - argvlen 12 - argv 13 - chdir 14 - stat 15 - chmod 16 - utime 17 - time 18 - -Compiler Switches -================= - -The following d30v specific compiler switches are currently supported: - - -mextmem Link .text/.data/.bss/etc in external memory. - - -mextmemory Same as -mextmem. - - -monchip Link .text/.data/.bss/etc in the onchip data/text - memory. - - -mno-asm-optimize Do not pass -O to the assembler when optimizing (the -O - switch will mark two short instructions that don't - interfere with each other as being done parallel - instead of sequentially). - - -masm-optimize [default] If optimizing, pass -O to the assembler. - - -mbranch-cost=n Increase the internal costs of branches to n. Higher - costs means that the compiler will issue more - instructions to avoid doing a branch. The default is - 2. - - -mcond-exec=n Replace branches around n insns with conditional - execution if we can. Default is 4. - - -Sections -======== - -You can override the effect of the -mextmem/-monchip options by putting -functions into either the ".stext" or ".etext" sections. If you put them into -the ".stext" section, the linker will always link the function into the onchip -memory area. Similarly, if you put the function in the ".etext" section, the -linker will always link the function into the external memory area. - -Data can be controlled as well. If you put the data in the ".sdata" section, -the linker will put the data into the onchip data area. Similarly, if you put -the data in the ".edata" section, the linker will put the data into the -external memory. - - -Stack pointer -============= - -The crt0.o that we ship loads up the stack pointer with the value of the label -__stack. If you do not define a value for __stack, the linker will choose the -top of the onchip data area (0x20008000) for the stack pointer. You can set a -new value via the options: - - -Wl,-defsym,__stack=0x20008000 diff --git a/gcc/config/d30v/d30v-protos.h b/gcc/config/d30v/d30v-protos.h deleted file mode 100644 index 1f93f3b38b8..00000000000 --- a/gcc/config/d30v/d30v-protos.h +++ /dev/null @@ -1,142 +0,0 @@ -/* d30v prototypes. - Copyright (C) 1999, 2000 Free Software Foundation, Inc. - Contributed by Cygnus Solutions. - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GCC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/* External functions called. */ - -extern void override_options (void); -#ifdef RTX_CODE -extern int short_memory_operand (rtx, enum machine_mode); -extern int long_memory_operand (rtx, enum machine_mode); -extern int d30v_memory_operand (rtx, enum machine_mode); -extern int single_reg_memory_operand (rtx, enum machine_mode); -extern int const_addr_memory_operand (rtx, enum machine_mode); -extern int call_operand (rtx, enum machine_mode); -extern int gpr_operand (rtx, enum machine_mode); -extern int accum_operand (rtx, enum machine_mode); -extern int gpr_or_accum_operand (rtx, enum machine_mode); -extern int cr_operand (rtx, enum machine_mode); -extern int repeat_operand (rtx, enum machine_mode); -extern int flag_operand (rtx, enum machine_mode); -extern int br_flag_operand (rtx, enum machine_mode); -extern int br_flag_or_constant_operand (rtx, enum machine_mode); -extern int gpr_br_flag_operand (rtx, enum machine_mode); -extern int f0_operand (rtx, enum machine_mode); -extern int f1_operand (rtx, enum machine_mode); -extern int carry_operand (rtx, enum machine_mode); -extern int reg_or_0_operand (rtx, enum machine_mode); -extern int gpr_or_signed6_operand (rtx, enum machine_mode); -extern int gpr_or_unsigned5_operand (rtx, enum machine_mode); -extern int gpr_or_unsigned6_operand (rtx, enum machine_mode); -extern int gpr_or_constant_operand (rtx, enum machine_mode); -extern int gpr_or_dbl_const_operand (rtx, enum machine_mode); -extern int gpr_or_memory_operand (rtx, enum machine_mode); -extern int move_input_operand (rtx, enum machine_mode); -extern int move_output_operand (rtx, enum machine_mode); -extern int signed6_operand (rtx, enum machine_mode); -extern int unsigned5_operand (rtx, enum machine_mode); -extern int unsigned6_operand (rtx, enum machine_mode); -extern int bitset_operand (rtx, enum machine_mode); -extern int condexec_test_operator (rtx, enum machine_mode); -extern int condexec_branch_operator (rtx, enum machine_mode); -extern int condexec_unary_operator (rtx, enum machine_mode); -extern int condexec_addsub_operator (rtx, enum machine_mode); -extern int condexec_binary_operator (rtx, enum machine_mode); -extern int condexec_shiftl_operator (rtx, enum machine_mode); -extern int condexec_extend_operator (rtx, enum machine_mode); -extern int branch_zero_operator (rtx, enum machine_mode); -extern int cond_move_dest_operand (rtx, enum machine_mode); -extern int cond_move_operand (rtx, enum machine_mode); -extern int cond_exec_operand (rtx, enum machine_mode); -extern int srelational_si_operator (rtx, enum machine_mode); -extern int urelational_si_operator (rtx, enum machine_mode); -extern int relational_di_operator (rtx, enum machine_mode); -#endif -extern d30v_stack_t *d30v_stack_info (void); -extern int direct_return (void); - -#ifdef TREE_CODE -#ifdef RTX_CODE -extern void d30v_init_cumulative_args (CUMULATIVE_ARGS *, tree, - rtx, tree, int); -#endif -extern int d30v_function_arg_boundary (enum machine_mode, tree); -#ifdef RTX_CODE -extern rtx d30v_function_arg (CUMULATIVE_ARGS *, - enum machine_mode, tree, int, int); -#endif -extern int d30v_function_arg_partial_nregs (CUMULATIVE_ARGS *, - enum machine_mode, tree, int); - -extern int d30v_function_arg_pass_by_reference (CUMULATIVE_ARGS *, - enum machine_mode, tree, int); - -extern void d30v_function_arg_advance (CUMULATIVE_ARGS *, - enum machine_mode, tree, int); -#endif - -#ifdef RTX_CODE -extern rtx d30v_expand_builtin_saveregs (void); -#endif -#ifdef TREE_CODE -extern void d30v_setup_incoming_varargs (CUMULATIVE_ARGS *, - enum machine_mode, tree, int *, int); -#ifdef RTX_CODE -extern void d30v_expand_builtin_va_start (tree, rtx); -extern rtx d30v_expand_builtin_va_arg (tree, tree); -#endif /* RTX_CODE */ -#endif /* TREE_CODE */ - -extern void d30v_expand_prologue (void); -extern void d30v_expand_epilogue (void); -extern void d30v_function_profiler (FILE *, int); -#ifdef RTX_CODE -extern void d30v_split_double (rtx, rtx *, rtx *); -extern void d30v_print_operand (FILE *, rtx, int); -extern void d30v_print_operand_address (FILE *, rtx); -#endif -extern int d30v_trampoline_size (void); -#ifdef RTX_CODE -extern void d30v_initialize_trampoline (rtx, rtx, rtx); -extern int d30v_legitimate_address_p (enum machine_mode, rtx, int); -extern rtx d30v_legitimize_address (rtx, rtx, enum machine_mode, int); -extern int d30v_mode_dependent_address_p (rtx); -extern rtx d30v_emit_comparison (int, rtx, rtx, rtx); -extern const char *d30v_move_2words (rtx *, rtx); -extern int d30v_emit_cond_move (rtx, rtx, rtx, rtx); -extern rtx d30v_return_addr (void); -#endif -extern void d30v_init_expanders (void); -extern void debug_stack_info (d30v_stack_t *); - - -/* External variables referenced */ - -/* Define the information needed to generate branch and scc insns. This is - stored from the compare operation. */ - -extern GTY(()) rtx d30v_compare_op0; -extern GTY(()) rtx d30v_compare_op1; - -/* Define the information needed to modify the epilogue for EH. */ - -#ifdef RTX_CODE -extern rtx d30v_eh_epilogue_sp_ofs; -#endif diff --git a/gcc/config/d30v/d30v.c b/gcc/config/d30v/d30v.c deleted file mode 100644 index 5794d0bb64f..00000000000 --- a/gcc/config/d30v/d30v.c +++ /dev/null @@ -1,3525 +0,0 @@ -/* Definitions of target machine for Mitsubishi D30V. - Copyright (C) 1997, 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc. - Contributed by Cygnus Solutions. - - This file is part of GCC. - - GCC is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - GCC is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GCC; see the file COPYING. If not, write to - the Free Software Foundation, 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include "config.h" -#include "system.h" -#include "coretypes.h" -#include "tm.h" -#include "rtl.h" -#include "tree.h" -#include "regs.h" -#include "hard-reg-set.h" -#include "real.h" -#include "insn-config.h" -#include "conditions.h" -#include "output.h" -#include "insn-attr.h" -#include "flags.h" -#include "recog.h" -#include "expr.h" -#include "obstack.h" -#include "tm_p.h" -#include "except.h" -#include "function.h" -#include "toplev.h" -#include "integrate.h" -#include "ggc.h" -#include "target.h" -#include "target-def.h" -#include "langhooks.h" - -static void d30v_print_operand_memory_reference (FILE *, rtx); -static void d30v_build_long_insn (HOST_WIDE_INT, HOST_WIDE_INT, rtx, rtx); -static struct machine_function * d30v_init_machine_status (void); -static void d30v_output_function_prologue (FILE *, HOST_WIDE_INT); -static void d30v_output_function_epilogue (FILE *, HOST_WIDE_INT); -static int d30v_adjust_cost (rtx, rtx, rtx, int); -static int d30v_issue_rate (void); -static bool d30v_rtx_costs (rtx, int, int, int *); -static tree d30v_build_builtin_va_list (void); - -/* Define the information needed to generate branch and scc insns. This is - stored from the compare operation. */ - -struct rtx_def *d30v_compare_op0; -struct rtx_def *d30v_compare_op1; - -/* Cached value of d30v_stack_info */ -static d30v_stack_t *d30v_stack_cache = (d30v_stack_t *)0; - -/* Values of the -mbranch-cost=n string. */ -int d30v_branch_cost = D30V_DEFAULT_BRANCH_COST; -const char *d30v_branch_cost_string = (const char *)0; - -/* Values of the -mcond-exec=n string. */ -int d30v_cond_exec = D30V_DEFAULT_MAX_CONDITIONAL_EXECUTE; -const char *d30v_cond_exec_string = (const char *)0; - -/* Whether or not a hard register can accept a register */ -unsigned char hard_regno_mode_ok[ (int)MAX_MACHINE_MODE ][FIRST_PSEUDO_REGISTER]; - -/* Whether to try and avoid moves between two different modes */ -unsigned char modes_tieable_p[ (NUM_MACHINE_MODES) * (NUM_MACHINE_MODES) ]; - -/* Map register number to smallest register class. */ -enum reg_class regno_reg_class[FIRST_PSEUDO_REGISTER]; - -/* Map class letter into register class */ -enum reg_class reg_class_from_letter[256]; - -/* Initialize the GCC target structure. */ -#undef TARGET_ASM_ALIGNED_HI_OP -#define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t" -#undef TARGET_ASM_ALIGNED_SI_OP -#define TARGET_ASM_ALIGNED_SI_OP "\t.word\t" - -#undef TARGET_ASM_FUNCTION_PROLOGUE -#define TARGET_ASM_FUNCTION_PROLOGUE d30v_output_function_prologue -#undef TARGET_ASM_FUNCTION_EPILOGUE -#define TARGET_ASM_FUNCTION_EPILOGUE d30v_output_function_epilogue -#undef TARGET_SCHED_ADJUST_COST -#define TARGET_SCHED_ADJUST_COST d30v_adjust_cost -#undef TARGET_SCHED_ISSUE_RATE -#define TARGET_SCHED_ISSUE_RATE d30v_issue_rate - -#undef TARGET_RTX_COSTS -#define TARGET_RTX_COSTS d30v_rtx_costs -#undef TARGET_ADDRESS_COST -#define TARGET_ADDRESS_COST hook_int_rtx_0 - -#undef TARGET_BUILD_BUILTIN_VA_LIST -#define TARGET_BUILD_BUILTIN_VA_LIST d30v_build_builtin_va_list - -struct gcc_target targetm = TARGET_INITIALIZER; - -/* Sometimes certain combinations of command options do not make - sense on a particular target machine. You can define a macro - `OVERRIDE_OPTIONS' to take account of this. This macro, if - defined, is executed once just after all the command options have - been parsed. - - Don't use this macro to turn on various extra optimizations for - `-O'. That is what `OPTIMIZATION_OPTIONS' is for. */ - -void -override_options () -{ - int regno, i, ok_p; - enum machine_mode mode1, mode2; - - /* Set up the branch cost information */ - if (d30v_branch_cost_string) - d30v_branch_cost = atoi (d30v_branch_cost_string); - - /* Set up max # instructions to use with conditional execution */ - if (d30v_cond_exec_string) - d30v_cond_exec = atoi (d30v_cond_exec_string); - - /* Setup hard_regno_mode_ok/modes_tieable_p */ - for (mode1 = VOIDmode; - (int)mode1 < NUM_MACHINE_MODES; - mode1 = (enum machine_mode)((int)mode1 + 1)) - { - int size = GET_MODE_SIZE (mode1); - int large_p = size > UNITS_PER_WORD; - int int_p = GET_MODE_CLASS (mode1) == MODE_INT; - - for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) - { - if (mode1 == VOIDmode) - ok_p = FALSE; - - else if (GPR_P (regno)) - { - if (!large_p) - ok_p = TRUE; - else - ok_p = (((regno - GPR_FIRST) & 1) == 0); - } - - else if (FLAG_P (regno)) - ok_p = (mode1 == CCmode); - - else if (CR_P (regno)) - ok_p = int_p && !large_p; - - else if (ACCUM_P (regno)) - ok_p = (mode1 == DImode); - - else if (SPECIAL_REG_P (regno)) - ok_p = (mode1 == SImode); - - else - ok_p = FALSE; - - hard_regno_mode_ok[ (int)mode1 ][ regno ] = ok_p; - } - - /* A C expression that is nonzero if it is desirable to choose - register allocation so as to avoid move instructions between a - value of mode MODE1 and a value of mode MODE2. - - If `HARD_REGNO_MODE_OK (R, MODE1)' and `HARD_REGNO_MODE_OK (R, - MODE2)' are ever different for any R, then `MODES_TIEABLE_P (MODE1, - MODE2)' must be zero. */ - for (mode2 = VOIDmode; - (int)mode2 <= NUM_MACHINE_MODES; - mode2 = (enum machine_mode)((int)mode2 + 1)) - { - if (mode1 == mode2) - ok_p = TRUE; - -#if 0 - else if (GET_MODE_CLASS (mode1) == MODE_INT - && GET_MODE_SIZE (mode1) <= UNITS_PER_WORD - && GET_MODE_CLASS (mode2) == MODE_INT - && GET_MODE_SIZE (mode2) <= UNITS_PER_WORD) - ok_p = TRUE; -#endif - - else - ok_p = FALSE; - - modes_tieable_p[ ((int)mode1 * (NUM_MACHINE_MODES)) + (int)mode2 ] = ok_p; - } - } - -#if 0 - for (mode1 = VOIDmode; - (int)mode1 < NUM_MACHINE_MODES; - mode1 = (enum machine_mode)((int)mode1 + 1)) - { - for (mode2 = VOIDmode; - (int)mode2 <= NUM_MACHINE_MODES; - mode2 = (enum machine_mode)((int)mode2 + 1)) - { - for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) - if (ok_p - && (hard_regno_mode_ok[(int)mode1][regno] - != hard_regno_mode_ok[(int)mode2][regno])) - error ("bad modes_tieable_p for register %s, mode1 %s, mode2 %s", - reg_names[regno], GET_MODE_NAME (mode1), - GET_MODE_NAME (mode2)); - } - } -#endif - - /* A C expression whose value is a register class containing hard - register REGNO. In general there is more than one such class; - choose a class which is "minimal", meaning that no smaller class - also contains the register. */ - for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) - { - enum reg_class class; - - if (GPR_P (regno)) - class = (IN_RANGE_P (regno, GPR_FIRST+2, GPR_FIRST+62) - && ((regno - GPR_FIRST) & 1) == 0) ? EVEN_REGS : GPR_REGS; - - else if (regno == FLAG_F0) - class = F0_REGS; - - else if (regno == FLAG_F1) - class = F1_REGS; - - else if (FLAG_P (regno)) - class = OTHER_FLAG_REGS; - - else if (ACCUM_P (regno)) - class = ACCUM_REGS; - - else if (regno == CR_RPT_C) - class = REPEAT_REGS; - - else if (CR_P (regno)) - class = CR_REGS; - - else if (SPECIAL_REG_P (regno)) - class = GPR_REGS; - - else - class = NO_REGS; - - regno_reg_class[regno] = class; - -#if 0 - { - static const char *const names[] = REG_CLASS_NAMES; - fprintf (stderr, "Register %s class is %s, can hold modes", reg_names[regno], names[class]); - for (mode1 = VOIDmode; - (int)mode1 < NUM_MACHINE_MODES; - mode1 = (enum machine_mode)((int)mode1 + 1)) - { - if (hard_regno_mode_ok[ (int)mode1 ][ regno ]) - fprintf (stderr, " %s", GET_MODE_NAME (mode1)); - } - fprintf (stderr, "\n"); - } -#endif - } - - /* A C expression which defines the machine-dependent operand - constraint letters for register classes. If CHAR is such a - letter, the value should be the register class corresponding to - it. Otherwise, the value should be `NO_REGS'. The register - letter `r', corresponding to class `GENERAL_REGS', will not be - passed to this macro; you do not need to handle it. - - The following letters are unavailable, due to being used as - constraints: - '0'..'9' - '<', '>' - 'E', 'F', 'G', 'H' - 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P' - 'Q', 'R', 'S', 'T', 'U' - 'V', 'X' - 'g', 'i', 'm', 'n', 'o', 'p', 'r', 's' */ - - for (i = 0; i < 256; i++) - reg_class_from_letter[i] = NO_REGS; - - reg_class_from_letter['a'] = ACCUM_REGS; - reg_class_from_letter['b'] = BR_FLAG_REGS; - reg_class_from_letter['c'] = CR_REGS; - reg_class_from_letter['d'] = GPR_REGS; - reg_class_from_letter['e'] = EVEN_REGS; - reg_class_from_letter['f'] = FLAG_REGS; - reg_class_from_letter['l'] = REPEAT_REGS; - reg_class_from_letter['x'] = F0_REGS; - reg_class_from_letter['y'] = F1_REGS; - reg_class_from_letter['z'] = OTHER_FLAG_REGS; -} - - -/* Return true if a memory operand is a short memory operand. */ - -int -short_memory_operand (op, mode) - register rtx op; - enum machine_mode mode; -{ - if (GET_CODE (op) != MEM) - return FALSE; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - return (d30v_legitimate_address_p (mode, XEXP (op, 0), reload_completed) - == 1); -} - -/* Return true if a memory operand is a long operand. */ - -int -long_memory_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (GET_CODE (op) != MEM) - return FALSE; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - return (d30v_legitimate_address_p (mode, XEXP (op, 0), reload_completed) - == 2); -} - -/* Return true if a memory operand is valid for the D30V. */ - -int -d30v_memory_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (GET_CODE (op) != MEM) - return FALSE; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - return (d30v_legitimate_address_p (mode, XEXP (op, 0), reload_completed) - != 0); -} - -/* Return true if a memory operand uses a single register for the - address. */ - -int -single_reg_memory_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - rtx addr; - - if (GET_CODE (op) != MEM) - return FALSE; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - addr = XEXP (op, 0); - if (! d30v_legitimate_address_p (mode, addr, reload_completed)) - return FALSE; - - if (GET_CODE (addr) == SUBREG) - addr = SUBREG_REG (addr); - - return (GET_CODE (addr) == REG); -} - -/* Return true if a memory operand uses a constant address. */ - -int -const_addr_memory_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (GET_CODE (op) != MEM) - return FALSE; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (! d30v_legitimate_address_p (mode, XEXP (op, 0), reload_completed)) - return FALSE; - - switch (GET_CODE (XEXP (op, 0))) - { - default: - break; - - case SYMBOL_REF: - case LABEL_REF: - case CONST_INT: - case CONST: - return TRUE; - } - - return FALSE; -} - -/* Return true if operand is a memory reference suitable for a call. */ - -int -call_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (GET_CODE (op) != MEM) - return FALSE; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (! d30v_legitimate_address_p (mode, XEXP (op, 0), reload_completed)) - return FALSE; - - switch (GET_CODE (XEXP (op, 0))) - { - default: - break; - - case SUBREG: - op = SUBREG_REG (op); - if (GET_CODE (op) != REG) - return FALSE; - - /* fall through */ - - case REG: - return (GPR_OR_PSEUDO_P (REGNO (XEXP (op, 0)))); - - case SYMBOL_REF: - case LABEL_REF: - case CONST_INT: - case CONST: - return TRUE; - } - - return FALSE; -} - -/* Return true if operand is a GPR register. */ - -int -gpr_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) == SUBREG) - { - if (GET_CODE (SUBREG_REG (op)) != REG) - return register_operand (op, mode); - - op = SUBREG_REG (op); - } - - if (GET_CODE (op) != REG) - return FALSE; - - return GPR_OR_PSEUDO_P (REGNO (op)); -} - -/* Return true if operand is an accumulator register. */ - -int -accum_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) == SUBREG) - { - if (GET_CODE (SUBREG_REG (op)) != REG) - return register_operand (op, mode); - - op = SUBREG_REG (op); - } - - if (GET_CODE (op) != REG) - return FALSE; - - return ACCUM_OR_PSEUDO_P (REGNO (op)); -} - -/* Return true if operand is a GPR or an accumulator register. */ - -int -gpr_or_accum_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) == SUBREG) - { - if (GET_CODE (SUBREG_REG (op)) != REG) - return register_operand (op, mode); - - op = SUBREG_REG (op); - } - - if (GET_CODE (op) != REG) - return FALSE; - - if (ACCUM_P (REGNO (op))) - return TRUE; - - return GPR_OR_PSEUDO_P (REGNO (op)); -} - -/* Return true if operand is a CR register. */ - -int -cr_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) == SUBREG) - { - if (GET_CODE (SUBREG_REG (op)) != REG) - return register_operand (op, mode); - - op = SUBREG_REG (op); - } - - if (GET_CODE (op) != REG) - return FALSE; - - return CR_OR_PSEUDO_P (REGNO (op)); -} - -/* Return true if operand is the repeat count register. */ - -int -repeat_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) == SUBREG) - { - if (GET_CODE (SUBREG_REG (op)) != REG) - return register_operand (op, mode); - - op = SUBREG_REG (op); - } - - if (GET_CODE (op) != REG) - return FALSE; - - return (REGNO (op) == CR_RPT_C || REGNO (op) >= FIRST_PSEUDO_REGISTER); -} - -/* Return true if operand is a FLAG register. */ - -int -flag_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) == SUBREG) - { - if (GET_CODE (SUBREG_REG (op)) != REG) - return register_operand (op, mode); - - op = SUBREG_REG (op); - } - - if (GET_CODE (op) != REG) - return FALSE; - - return FLAG_OR_PSEUDO_P (REGNO (op)); -} - -/* Return true if operand is either F0 or F1. */ - -int -br_flag_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) == SUBREG) - { - if (GET_CODE (SUBREG_REG (op)) != REG) - return register_operand (op, mode); - - op = SUBREG_REG (op); - } - - if (GET_CODE (op) != REG) - return FALSE; - - return BR_FLAG_OR_PSEUDO_P (REGNO (op)); -} - -/* Return true if operand is either F0/F1 or the constants 0/1. */ - -int -br_flag_or_constant_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) == SUBREG) - { - if (GET_CODE (SUBREG_REG (op)) != REG) - return register_operand (op, mode); - - op = SUBREG_REG (op); - } - - if (GET_CODE (op) == CONST_INT) - return (INTVAL (op) == 0 || INTVAL (op) == 1); - - if (GET_CODE (op) != REG) - return FALSE; - - return BR_FLAG_OR_PSEUDO_P (REGNO (op)); -} - -/* Return true if operand is either F0 or F1, or a GPR register. */ - -int -gpr_or_br_flag_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) == SUBREG) - { - if (GET_CODE (SUBREG_REG (op)) != REG) - return register_operand (op, mode); - - op = SUBREG_REG (op); - } - - if (GET_CODE (op) != REG) - return FALSE; - - return GPR_OR_PSEUDO_P (REGNO (op)) || BR_FLAG_P (REGNO (op)); -} - -/* Return true if operand is the F0 register. */ - -int -f0_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) == SUBREG) - { - if (GET_CODE (SUBREG_REG (op)) != REG) - return register_operand (op, mode); - - op = SUBREG_REG (op); - } - - if (GET_CODE (op) != REG) - return FALSE; - - return (REGNO (op) == FLAG_F0 || REGNO (op) >= FIRST_PSEUDO_REGISTER); -} - -/* Return true if operand is the F1 register. */ - -int -f1_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) == SUBREG) - { - if (GET_CODE (SUBREG_REG (op)) != REG) - return register_operand (op, mode); - - op = SUBREG_REG (op); - } - - if (GET_CODE (op) != REG) - return FALSE; - - return (REGNO (op) == FLAG_F1 || REGNO (op) >= FIRST_PSEUDO_REGISTER); -} - -/* Return true if operand is the F1 register. */ - -int -carry_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) == SUBREG) - { - if (GET_CODE (SUBREG_REG (op)) != REG) - return register_operand (op, mode); - - op = SUBREG_REG (op); - } - - if (GET_CODE (op) != REG) - return FALSE; - - return (REGNO (op) == FLAG_CARRY || REGNO (op) >= FIRST_PSEUDO_REGISTER); -} - -/* Return true if operand is a register of any flavor or a 0 of the - appropriate type. */ - -int -reg_or_0_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - switch (GET_CODE (op)) - { - default: - break; - - case REG: - case SUBREG: - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - return register_operand (op, mode); - - case CONST_INT: - return INTVAL (op) == 0; - - case CONST_DOUBLE: - return CONST_DOUBLE_HIGH (op) == 0 && CONST_DOUBLE_LOW (op) == 0; - } - - return FALSE; -} - -/* Return true if operand is a GPR register or a signed 6 bit immediate. */ - -int -gpr_or_signed6_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (GET_CODE (op) == SUBREG) - { - if (GET_CODE (SUBREG_REG (op)) != REG) - return register_operand (op, mode); - - op = SUBREG_REG (op); - } - - if (GET_CODE (op) == CONST_INT) - return IN_RANGE_P (INTVAL (op), -32, 31); - - if (GET_CODE (op) != REG) - return FALSE; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - return GPR_OR_PSEUDO_P (REGNO (op)); -} - -/* Return true if operand is a GPR register or an unsigned 5 bit immediate. */ - -int -gpr_or_unsigned5_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (GET_CODE (op) == SUBREG) - { - if (GET_CODE (SUBREG_REG (op)) != REG) - return register_operand (op, mode); - - op = SUBREG_REG (op); - } - - if (GET_CODE (op) == CONST_INT) - return IN_RANGE_P (INTVAL (op), 0, 31); - - if (GET_CODE (op) != REG) - return FALSE; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - return GPR_OR_PSEUDO_P (REGNO (op)); -} - -/* Return true if operand is a GPR register or an unsigned 6 bit immediate. */ - -int -gpr_or_unsigned6_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (GET_CODE (op) == SUBREG) - { - if (GET_CODE (SUBREG_REG (op)) != REG) - return register_operand (op, mode); - - op = SUBREG_REG (op); - } - - if (GET_CODE (op) == CONST_INT) - return IN_RANGE_P (INTVAL (op), 0, 63); - - if (GET_CODE (op) != REG) - return FALSE; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - return GPR_OR_PSEUDO_P (REGNO (op)); -} - -/* Return true if operand is a GPR register or a constant of some form. */ - -int -gpr_or_constant_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - switch (GET_CODE (op)) - { - default: - break; - - case CONST_INT: - case SYMBOL_REF: - case LABEL_REF: - case CONST: - return TRUE; - - case SUBREG: - if (GET_CODE (SUBREG_REG (op)) != REG) - return register_operand (op, mode); - - op = SUBREG_REG (op); - /* fall through */ - - case REG: - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - return GPR_OR_PSEUDO_P (REGNO (op)); - } - - return FALSE; -} - -/* Return true if operand is a GPR register or a constant of some form, - including a CONST_DOUBLE, which gpr_or_constant_operand doesn't recognize. */ - -int -gpr_or_dbl_const_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - switch (GET_CODE (op)) - { - default: - break; - - case CONST_INT: - case CONST_DOUBLE: - case SYMBOL_REF: - case LABEL_REF: - case CONST: - return TRUE; - - case SUBREG: - if (GET_CODE (SUBREG_REG (op)) != REG) - return register_operand (op, mode); - - op = SUBREG_REG (op); - /* fall through */ - - case REG: - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - return GPR_OR_PSEUDO_P (REGNO (op)); - } - - return FALSE; -} - -/* Return true if operand is a gpr register or a valid memory operation. */ - -int -gpr_or_memory_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - switch (GET_CODE (op)) - { - default: - break; - - case SUBREG: - if (GET_CODE (SUBREG_REG (op)) != REG) - return register_operand (op, mode); - - op = SUBREG_REG (op); - /* fall through */ - - case REG: - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - return GPR_OR_PSEUDO_P (REGNO (op)); - - case MEM: - return d30v_legitimate_address_p (mode, XEXP (op, 0), reload_completed); - } - - return FALSE; -} - -/* Return true if operand is something that can be an input for a move - operation. */ - -int -move_input_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - rtx subreg; - enum rtx_code code; - - switch (GET_CODE (op)) - { - default: - break; - - case CONST_INT: - case CONST_DOUBLE: - case SYMBOL_REF: - case LABEL_REF: - case CONST: - return TRUE; - - case SUBREG: - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - subreg = SUBREG_REG (op); - code = GET_CODE (subreg); - if (code == MEM) - return d30v_legitimate_address_p ((int)mode, XEXP (subreg, 0), - reload_completed); - - return (code == REG); - - case REG: - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - return TRUE; - - case MEM: - if (GET_CODE (XEXP (op, 0)) == ADDRESSOF) - return TRUE; - return d30v_legitimate_address_p (mode, XEXP (op, 0), - reload_completed); - } - - return FALSE; -} - -/* Return true if operand is something that can be an output for a move - operation. */ - -int -move_output_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - rtx subreg; - enum rtx_code code; - - switch (GET_CODE (op)) - { - default: - break; - - case SUBREG: - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - subreg = SUBREG_REG (op); - code = GET_CODE (subreg); - if (code == MEM) - return d30v_legitimate_address_p ((int)mode, XEXP (subreg, 0), - reload_completed); - - return (code == REG); - - case REG: - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - return TRUE; - - case MEM: - if (GET_CODE (XEXP (op, 0)) == ADDRESSOF) - return TRUE; - return d30v_legitimate_address_p (mode, XEXP (op, 0), - reload_completed); - } - - return FALSE; -} - -/* Return true if operand is a signed 6 bit immediate. */ - -int -signed6_operand (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - if (GET_CODE (op) == CONST_INT) - return IN_RANGE_P (INTVAL (op), -32, 31); - - return FALSE; -} - -/* Return true if operand is an unsigned 5 bit immediate. */ - -int -unsigned5_operand (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - if (GET_CODE (op) == CONST_INT) - return IN_RANGE_P (INTVAL (op), 0, 31); - - return FALSE; -} - -/* Return true if operand is an unsigned 6 bit immediate. */ - -int -unsigned6_operand (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - if (GET_CODE (op) == CONST_INT) - return IN_RANGE_P (INTVAL (op), 0, 63); - - return FALSE; -} - -/* Return true if operand is a constant with a single bit set. */ - -int -bitset_operand (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - if (GET_CODE (op) == CONST_INT) - return IN_RANGE_P (exact_log2 (INTVAL (op)), 0, 31); - - return FALSE; -} - -/* Return true if the operator is a ==/!= test against f0 or f1 that can be - used in conditional execution. */ - -int -condexec_test_operator (op, mode) - rtx op; - enum machine_mode mode; -{ - rtx x0, x1; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) != EQ && GET_CODE (op) != NE) - return FALSE; - - x0 = XEXP (op, 0); - if (GET_CODE (x0) != REG || !BR_FLAG_OR_PSEUDO_P (REGNO (x0))) - return FALSE; - - x1 = XEXP (op, 1); - if (GET_CODE (x1) != CONST_INT || INTVAL (x1) != 0) - return FALSE; - - return TRUE; -} - -/* Return true if the operator is a ==/!= test against f0, f1, or a general - register that can be used in a branch instruction. */ - -int -condexec_branch_operator (op, mode) - rtx op; - enum machine_mode mode; -{ - rtx x0, x1; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) != EQ && GET_CODE (op) != NE) - return FALSE; - - x0 = XEXP (op, 0); - if (GET_CODE (x0) == REG) - { - int regno = REGNO (x0); - if (!GPR_OR_PSEUDO_P (regno) && !BR_FLAG_P (regno)) - return FALSE; - } - /* Allow the optimizer to generate things like: - (if_then_else (ne (const_int 1) (const_int 0))) */ - else if (GET_CODE (x0) != CONST_INT) - return FALSE; - - x1 = XEXP (op, 1); - if (GET_CODE (x1) != CONST_INT || INTVAL (x1) != 0) - return FALSE; - - return TRUE; -} - -/* Return true if the unary operator can be executed with conditional - execution. */ - -int -condexec_unary_operator (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - rtx op0; - - /* Only do this after register allocation, so that we can look at the register # */ - if (!reload_completed) - return FALSE; - - if (GET_RTX_CLASS (GET_CODE (op)) != '1') - return FALSE; - - op0 = XEXP (op, 0); - if (GET_CODE (op0) == SUBREG) - op0 = SUBREG_REG (op0); - - switch (GET_CODE (op)) - { - default: - break; - - case ABS: - case NOT: - if (GET_MODE (op) == SImode && GET_CODE (op0) == REG && GPR_P (REGNO (op0))) - return TRUE; - - break; - } - - return FALSE; -} - -/* Return true if the add or subtraction can be executed with conditional - execution. */ - -int -condexec_addsub_operator (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - rtx op0, op1; - - /* Only do this after register allocation, so that we can look at the register # */ - if (!reload_completed) - return FALSE; - - if (GET_RTX_CLASS (GET_CODE (op)) != '2' && GET_RTX_CLASS (GET_CODE (op)) != 'c') - return FALSE; - - op0 = XEXP (op, 0); - op1 = XEXP (op, 1); - - if (GET_CODE (op0) == SUBREG) - op0 = SUBREG_REG (op0); - - if (GET_CODE (op1) == SUBREG) - op1 = SUBREG_REG (op1); - - if (GET_CODE (op0) != REG) - return FALSE; - - switch (GET_CODE (op)) - { - default: - break; - - case PLUS: - case MINUS: - return (GET_MODE (op) == SImode && GPR_P (REGNO (op0)) - && gpr_or_constant_operand (op1, SImode)); - } - - return FALSE; -} - -/* Return true if the binary operator can be executed with conditional - execution. We don't include add/sub here, since they have extra - clobbers for the flags registers. */ - -int -condexec_binary_operator (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - rtx op0, op1; - - /* Only do this after register allocation, so that we can look at the register # */ - if (!reload_completed) - return FALSE; - - if (GET_RTX_CLASS (GET_CODE (op)) != '2' && GET_RTX_CLASS (GET_CODE (op)) != 'c') - return FALSE; - - op0 = XEXP (op, 0); - op1 = XEXP (op, 1); - - if (GET_CODE (op0) == SUBREG) - op0 = SUBREG_REG (op0); - - if (GET_CODE (op1) == SUBREG) - op1 = SUBREG_REG (op1); - - if (GET_CODE (op0) != REG) - return FALSE; - - /* MULT is not included here, because it is an IU only instruction. */ - switch (GET_CODE (op)) - { - default: - break; - - case AND: - case IOR: - case XOR: - case ASHIFTRT: - case LSHIFTRT: - case ROTATERT: - return (GET_MODE (op) == SImode && GPR_P (REGNO (op0)) - && gpr_or_constant_operand (op1, SImode)); - - case ASHIFT: - case ROTATE: - return (GET_MODE (op) == SImode && GPR_P (REGNO (op0)) - && GET_CODE (op1) == CONST_INT); - } - - return FALSE; -} - -/* Return true if the shift/rotate left operator can be executed with - conditional execution. */ - -int -condexec_shiftl_operator (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - rtx op0, op1; - - /* Only do this after register allocation, so that we can look at the register # */ - if (!reload_completed) - return FALSE; - - if (GET_RTX_CLASS (GET_CODE (op)) != '2' && GET_RTX_CLASS (GET_CODE (op)) != 'c') - return FALSE; - - op0 = XEXP (op, 0); - op1 = XEXP (op, 1); - - if (GET_CODE (op0) == SUBREG) - op0 = SUBREG_REG (op0); - - if (GET_CODE (op1) == SUBREG) - op1 = SUBREG_REG (op1); - - if (GET_CODE (op0) != REG) - return FALSE; - - switch (GET_CODE (op)) - { - default: - break; - - case ASHIFT: - case ROTATE: - return (GET_MODE (op) == SImode && GPR_P (REGNO (op0)) - && GET_CODE (op1) == NEG - && GET_CODE (XEXP (op1, 0)) == REG - && GPR_P (REGNO (XEXP (op1, 0)))); - } - - return FALSE; -} - -/* Return true if the {sign,zero} extend operator from memory can be - conditionally executed. */ - -int -condexec_extend_operator (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - /* Only do this after register allocation, so that we can look at the register # */ - if (!reload_completed) - return FALSE; - - if (GET_RTX_CLASS (GET_CODE (op)) != '1') - return FALSE; - - switch (GET_CODE (op)) - { - default: - break; - - case SIGN_EXTEND: - case ZERO_EXTEND: - if ((GET_MODE (op) == SImode && GET_MODE (XEXP (op, 0)) == QImode) - || (GET_MODE (op) == SImode && GET_MODE (XEXP (op, 0)) == HImode) - || (GET_MODE (op) == HImode && GET_MODE (XEXP (op, 0)) == QImode)) - return TRUE; - - break; - } - - return FALSE; -} - -/* Return true for comparisons against 0 that can be turned into a - bratnz/bratzr instruction. */ - -int -branch_zero_operator (op, mode) - rtx op; - enum machine_mode mode; -{ - rtx x0, x1; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_CODE (op) != EQ && GET_CODE (op) != NE) - return FALSE; - - x0 = XEXP (op, 0); - if (GET_CODE (x0) != REG || !GPR_OR_PSEUDO_P (REGNO (x0))) - return FALSE; - - x1 = XEXP (op, 1); - if (GET_CODE (x1) != CONST_INT || INTVAL (x1) != 0) - return FALSE; - - return TRUE; -} - -/* Return true if an operand is simple, suitable for use as the destination of - a conditional move */ - -int -cond_move_dest_operand (op, mode) - register rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - rtx addr; - - if (mode != QImode && mode != HImode && mode != SImode && mode != SFmode) - return FALSE; - - switch (GET_CODE (op)) - { - default: - break; - - case REG: - case SUBREG: - return gpr_operand (op, mode); - - /* Don't allow post dec/inc, since we might not get the side effects correct. */ - case MEM: - addr = XEXP (op, 0); - return (GET_CODE (addr) != POST_DEC - && GET_CODE (addr) != POST_INC - && d30v_legitimate_address_p (mode, addr, reload_completed)); - } - - return FALSE; -} - -/* Return true if an operand is simple, suitable for use in a conditional move */ - -int -cond_move_operand (op, mode) - register rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - rtx addr; - - if (mode != QImode && mode != HImode && mode != SImode && mode != SFmode) - return FALSE; - - switch (GET_CODE (op)) - { - default: - break; - - case REG: - case SUBREG: - return gpr_operand (op, mode); - - case CONST_DOUBLE: - return GET_MODE (op) == SFmode; - - case CONST_INT: - case SYMBOL_REF: - case LABEL_REF: - case CONST: - return TRUE; - - /* Don't allow post dec/inc, since we might not get the side effects correct. */ - case MEM: - addr = XEXP (op, 0); - return (GET_CODE (addr) != POST_DEC - && GET_CODE (addr) != POST_INC - && d30v_legitimate_address_p (mode, addr, reload_completed)); - } - - return FALSE; -} - -/* Return true if an operand is simple, suitable for use in conditional execution. - Unlike cond_move, we can allow auto inc/dec. */ - -int -cond_exec_operand (op, mode) - register rtx op; - enum machine_mode mode; -{ - if (mode != QImode && mode != HImode && mode != SImode && mode != SFmode) - return FALSE; - - switch (GET_CODE (op)) - { - default: - break; - - case REG: - case SUBREG: - return gpr_operand (op, mode); - - case CONST_DOUBLE: - return GET_MODE (op) == SFmode; - - case CONST_INT: - case SYMBOL_REF: - case LABEL_REF: - case CONST: - return TRUE; - - case MEM: - return memory_operand (op, mode); - } - - return FALSE; -} - -/* Return true if operand is a SI mode signed relational test. */ - -int -srelational_si_operator (op, mode) - register rtx op; - enum machine_mode mode; -{ - rtx x0, x1; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - switch (GET_CODE (op)) - { - default: - return FALSE; - - case EQ: - case NE: - case LT: - case LE: - case GT: - case GE: - break; - } - - x0 = XEXP (op, 0); - if (GET_CODE (x0) != REG && GET_CODE (x0) != SUBREG) - return FALSE; - - if (GET_MODE (x0) != SImode) - return FALSE; - - x1 = XEXP (op, 1); - switch (GET_CODE (x1)) - { - default: - return FALSE; - - case REG: - case SUBREG: - case CONST_INT: - case LABEL_REF: - case SYMBOL_REF: - case CONST: - break; - } - - return TRUE; -} - -/* Return true if operand is a SI mode unsigned relational test. */ - -int -urelational_si_operator (op, mode) - register rtx op; - enum machine_mode mode; -{ - rtx x0, x1; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - switch (GET_CODE (op)) - { - default: - return FALSE; - - case LTU: - case LEU: - case GTU: - case GEU: - break; - } - - x0 = XEXP (op, 0); - if (GET_CODE (x0) != REG && GET_CODE (x0) != SUBREG) - return FALSE; - - if (GET_MODE (x0) != SImode) - return FALSE; - - x1 = XEXP (op, 1); - switch (GET_CODE (x1)) - { - default: - return FALSE; - - case REG: - case SUBREG: - case CONST_INT: - case LABEL_REF: - case SYMBOL_REF: - case CONST: - break; - } - - return TRUE; -} - -/* Return true if operand is a DI mode relational test. */ - -int -relational_di_operator (op, mode) - register rtx op; - enum machine_mode mode; -{ - rtx x0, x1; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return FALSE; - - if (GET_RTX_CLASS (GET_CODE (op)) != '<') - return FALSE; - - x0 = XEXP (op, 0); - if (GET_CODE (x0) != REG && GET_CODE (x0) != SUBREG) - return FALSE; - - if (GET_MODE (x0) != DImode) - return FALSE; - - x1 = XEXP (op, 1); - if (GET_CODE (x1) != REG && GET_CODE (x1) != SUBREG - && GET_CODE (x1) != CONST_INT && GET_CODE (x1) != CONST_DOUBLE) - return FALSE; - - return TRUE; -} - - -/* Calculate the stack information for the current function. - - D30V stack frames look like: - - high | .... | - +-------------------------------+ - | Argument word #19 | - +-------------------------------+ - | Argument word #18 | - +-------------------------------+ - | Argument word #17 | - +-------------------------------+ - | Argument word #16 | - Prev sp +-------------------------------+ - | | - | Save for arguments 1..16 if | - | the func. uses stdarg/varargs | - | | - +-------------------------------+ - | | - | Save area for GPR registers | - | | - +-------------------------------+ - | | - | Save area for accumulators | - | | - +-------------------------------+ - | | - | Local variables | - | | - +-------------------------------+ - | | - | alloca space if used | - | | - +-------------------------------+ - | | - | Space for outgoing arguments | - | | - low SP----> +-------------------------------+ -*/ - -d30v_stack_t * -d30v_stack_info () -{ - static d30v_stack_t info, zero_info; - d30v_stack_t *info_ptr = &info; - tree fndecl = current_function_decl; - tree fntype = TREE_TYPE (fndecl); - int varargs_p = 0; - tree cur_arg; - tree next_arg; - int saved_gprs; - int saved_accs; - int memrefs_2words; - int memrefs_1word; - unsigned char save_gpr_p[GPR_LAST]; - int i; - - /* If we've already calculated the values and reload is complete, just return now */ - if (d30v_stack_cache) - return d30v_stack_cache; - - /* Zero all fields */ - info = zero_info; - - if (current_function_profile) - regs_ever_live[GPR_LINK] = 1; - - /* Determine if this is a stdarg function */ - if (TYPE_ARG_TYPES (fntype) != 0 - && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype))) != void_type_node)) - varargs_p = 1; - else - { - /* Find the last argument, and see if it is __builtin_va_alist. */ - for (cur_arg = DECL_ARGUMENTS (fndecl); cur_arg != (tree)0; cur_arg = next_arg) - { - next_arg = TREE_CHAIN (cur_arg); - if (next_arg == (tree)0) - { - if (DECL_NAME (cur_arg) - && !strcmp (IDENTIFIER_POINTER (DECL_NAME (cur_arg)), "__builtin_va_alist")) - varargs_p = 1; - - break; - } - } - } - - /* Calculate which registers need to be saved & save area size */ - saved_accs = 0; - memrefs_2words = 0; - memrefs_1word = 0; - for (i = ACCUM_FIRST; i <= ACCUM_LAST; i++) - { - if (regs_ever_live[i] && !call_used_regs[i]) - { - info_ptr->save_p[i] = 2; - saved_accs++; - memrefs_2words++; - } - } - - saved_gprs = 0; - for (i = GPR_FIRST; i <= GPR_LAST; i++) - { - if (regs_ever_live[i] && (!call_used_regs[i] || i == GPR_LINK)) - { - save_gpr_p[i] = 1; - saved_gprs++; - } - else - save_gpr_p[i] = 0; - } - - /* Determine which register pairs can be saved together with ld2w/st2w */ - for (i = GPR_FIRST; i <= GPR_LAST; i++) - { - if (((i - GPR_FIRST) & 1) == 0 && save_gpr_p[i] && save_gpr_p[i+1]) - { - memrefs_2words++; - info_ptr->save_p[i++] = 2; - } - else if (save_gpr_p[i]) - { - memrefs_1word++; - info_ptr->save_p[i] = 1; - } - } - - /* Determine various sizes */ - info_ptr->varargs_p = varargs_p; - info_ptr->varargs_size = ((varargs_p) - ? (GPR_ARG_LAST + 1 - GPR_ARG_FIRST) * UNITS_PER_WORD - : 0); - - info_ptr->accum_size = 2 * UNITS_PER_WORD * saved_accs; - info_ptr->gpr_size = D30V_ALIGN (UNITS_PER_WORD * saved_gprs, - 2 * UNITS_PER_WORD); - info_ptr->vars_size = D30V_ALIGN (get_frame_size (), 2 * UNITS_PER_WORD); - info_ptr->parm_size = D30V_ALIGN (current_function_outgoing_args_size, - 2 * UNITS_PER_WORD); - - info_ptr->total_size = D30V_ALIGN ((info_ptr->gpr_size - + info_ptr->accum_size - + info_ptr->vars_size - + info_ptr->parm_size - + info_ptr->varargs_size - + current_function_pretend_args_size), - (STACK_BOUNDARY / BITS_PER_UNIT)); - - info_ptr->save_offset = (info_ptr->total_size - - (current_function_pretend_args_size - + info_ptr->varargs_size - + info_ptr->gpr_size - + info_ptr->accum_size)); - - /* The link register is the last GPR saved, but there might be some padding - bytes after it, so account for that. */ - info_ptr->link_offset = (info_ptr->total_size - - (current_function_pretend_args_size - + info_ptr->varargs_size - + (info_ptr->gpr_size - - UNITS_PER_WORD * saved_gprs) - + UNITS_PER_WORD)); - - info_ptr->memrefs_varargs = info_ptr->varargs_size / (2 * UNITS_PER_WORD); - info_ptr->memrefs_2words = memrefs_2words; - info_ptr->memrefs_1word = memrefs_1word; - - if (reload_completed) - d30v_stack_cache = info_ptr; - - return info_ptr; -} - - -/* Internal function to print all of the information about the stack */ - -void -debug_stack_info (info) - d30v_stack_t *info; -{ - int i; - - if (!info) - info = d30v_stack_info (); - - fprintf (stderr, "\nStack information for function %s:\n", - ((current_function_decl && DECL_NAME (current_function_decl)) - ? IDENTIFIER_POINTER (DECL_NAME (current_function_decl)) - : "")); - - fprintf (stderr, "\tsave_offset = %d\n", info->save_offset); - fprintf (stderr, "\tmemrefs_varargs = %d\n", info->memrefs_varargs); - fprintf (stderr, "\tmemrefs_2words = %d\n", info->memrefs_2words); - fprintf (stderr, "\tmemrefs_1word = %d\n", info->memrefs_1word); - fprintf (stderr, "\tvarargs_p = %d\n", info->varargs_p); - fprintf (stderr, "\tvarargs_size = %d\n", info->varargs_size); - fprintf (stderr, "\tvars_size = %d\n", info->vars_size); - fprintf (stderr, "\tparm_size = %d\n", info->parm_size); - fprintf (stderr, "\tgpr_size = %d\n", info->gpr_size); - fprintf (stderr, "\taccum_size = %d\n", info->accum_size); - fprintf (stderr, "\ttotal_size = %d\n", info->total_size); - fprintf (stderr, "\tsaved registers ="); - - for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) - { - if (info->save_p[i] == 2) - { - fprintf (stderr, " %s-%s", reg_names[i], reg_names[i+1]); - i++; - } - else if (info->save_p[i]) - fprintf (stderr, " %s", reg_names[i]); - } - - putc ('\n', stderr); - fflush (stderr); -} - - -/* Return nonzero if this function is known to have a null or 1 instruction epilogue. */ - -int -direct_return () -{ - if (reload_completed) - { - d30v_stack_t *info = d30v_stack_info (); - - /* If no epilogue code is needed, can use just a simple jump */ - if (info->total_size == 0) - return 1; - -#if 0 - /* If just a small amount of local stack was allocated and no registers - saved, skip forward branch */ - if (info->total_size == info->vars_size - && IN_RANGE_P (info->total_size, 1, 31)) - return 1; -#endif - } - - return 0; -} - - -/* A C statement (sans semicolon) for initializing the variable CUM for the - state at the beginning of the argument list. The variable has type - `CUMULATIVE_ARGS'. The value of FNTYPE is the tree node for the data type - of the function which will receive the args, or 0 if the args are to a - compiler support library function. - - The value of FNDECL is NULL for indirect calls (eg via a function pointer) - and library calls. For direct calls, and when INIT_CUMULATIVE_ARGS is - being used to find arguments for the function being compiled it contains - the declaration node of FNTYPE. - - When processing a call to a compiler support library function, LIBNAME - identifies which one. It is a `symbol_ref' rtx which contains the name of - the function, as a string. LIBNAME is 0 when an ordinary C function call - is being processed. Thus, each time this macro is called, either LIBNAME - or FNTYPE is nonzero, but never both of them at once. */ - -void -d30v_init_cumulative_args (cum, fntype, libname, fndecl, incoming) - CUMULATIVE_ARGS *cum; - tree fntype; - rtx libname; - tree fndecl; - int incoming; -{ - *cum = GPR_ARG_FIRST; - - if (TARGET_DEBUG_ARG) - { - fprintf (stderr, "\ninit_cumulative_args:"); - if (!fndecl && fntype) - fputs (" indirect", stderr); - - if (incoming) - fputs (" incoming", stderr); - - if (fntype) - { - tree ret_type = TREE_TYPE (fntype); - fprintf (stderr, " return=%s,", - tree_code_name[ (int)TREE_CODE (ret_type) ]); - } - - if (libname && GET_CODE (libname) == SYMBOL_REF) - fprintf (stderr, " libname=%s", XSTR (libname, 0)); - - putc ('\n', stderr); - } -} - - -/* If defined, a C expression that gives the alignment boundary, in bits, of an - argument with the specified mode and type. If it is not defined, - `PARM_BOUNDARY' is used for all arguments. */ - -int -d30v_function_arg_boundary (mode, type) - enum machine_mode mode; - tree type; -{ - int size = ((mode == BLKmode && type) - ? int_size_in_bytes (type) - : (int) GET_MODE_SIZE (mode)); - - return (size > UNITS_PER_WORD) ? 2*UNITS_PER_WORD : UNITS_PER_WORD; -} - - -/* A C expression that controls whether a function argument is passed in a - register, and which register. - - The arguments are CUM, which summarizes all the previous arguments; MODE, - the machine mode of the argument; TYPE, the data type of the argument as a - tree node or 0 if that is not known (which happens for C support library - functions); and NAMED, which is 1 for an ordinary argument and 0 for - nameless arguments that correspond to `...' in the called function's - prototype. - - The value of the expression should either be a `reg' RTX for the hard - register in which to pass the argument, or zero to pass the argument on the - stack. - - For machines like the VAX and 68000, where normally all arguments are - pushed, zero suffices as a definition. - - The usual way to make the ANSI library `stdarg.h' work on a machine where - some arguments are usually passed in registers, is to cause nameless - arguments to be passed on the stack instead. This is done by making - `FUNCTION_ARG' return 0 whenever NAMED is 0. - - You may use the macro `MUST_PASS_IN_STACK (MODE, TYPE)' in the definition of - this macro to determine if this argument is of a type that must be passed in - the stack. If `REG_PARM_STACK_SPACE' is not defined and `FUNCTION_ARG' - returns nonzero for such an argument, the compiler will abort. If - `REG_PARM_STACK_SPACE' is defined, the argument will be computed in the - stack and then loaded into a register. */ - -rtx -d30v_function_arg (cum, mode, type, named, incoming) - CUMULATIVE_ARGS *cum; - enum machine_mode mode; - tree type; - int named; - int incoming ATTRIBUTE_UNUSED; -{ - int size = ((mode == BLKmode && type) - ? int_size_in_bytes (type) - : (int) GET_MODE_SIZE (mode)); - int adjust = (size > UNITS_PER_WORD && (*cum & 1) != 0); - rtx ret; - - /* Return a marker for use in the call instruction. */ - if (mode == VOIDmode) - ret = const0_rtx; - - else if (*cum + adjust <= GPR_ARG_LAST) - ret = gen_rtx (REG, mode, *cum + adjust); - - else - ret = NULL_RTX; - - if (TARGET_DEBUG_ARG) - fprintf (stderr, - "function_arg: words = %2d, mode = %4s, named = %d, size = %3d, adjust = %1d, arg = %s\n", - *cum, GET_MODE_NAME (mode), named, size, adjust, - (ret) ? ((ret == const0_rtx) ? "<0>" : reg_names[ REGNO (ret) ]) : "memory"); - - return ret; -} - - -/* A C expression for the number of words, at the beginning of an argument, - must be put in registers. The value must be zero for arguments that are - passed entirely in registers or that are entirely pushed on the stack. - - On some machines, certain arguments must be passed partially in registers - and partially in memory. On these machines, typically the first N words of - arguments are passed in registers, and the rest on the stack. If a - multi-word argument (a `double' or a structure) crosses that boundary, its - first few words must be passed in registers and the rest must be pushed. - This macro tells the compiler when this occurs, and how many of the words - should go in registers. - - `FUNCTION_ARG' for these arguments should return the first register to be - used by the caller for this argument; likewise `FUNCTION_INCOMING_ARG', for - the called function. */ - -int -d30v_function_arg_partial_nregs (cum, mode, type, named) - CUMULATIVE_ARGS *cum; - enum machine_mode mode; - tree type; - int named ATTRIBUTE_UNUSED; -{ - int bytes = ((mode == BLKmode) - ? int_size_in_bytes (type) - : (int) GET_MODE_SIZE (mode)); - int words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD; - int adjust = (bytes > UNITS_PER_WORD && (*cum & 1) != 0); - int arg_num = *cum + adjust; - int ret; - - ret = ((arg_num <= GPR_ARG_LAST && arg_num + words > GPR_ARG_LAST+1) - ? GPR_ARG_LAST - arg_num + 1 - : 0); - - if (TARGET_DEBUG_ARG && ret) - fprintf (stderr, "function_arg_partial_nregs: %d\n", ret); - - return ret; -} - - -/* A C expression that indicates when an argument must be passed by reference. - If nonzero for an argument, a copy of that argument is made in memory and a - pointer to the argument is passed instead of the argument itself. The - pointer is passed in whatever way is appropriate for passing a pointer to - that type. - - On machines where `REG_PARM_STACK_SPACE' is not defined, a suitable - definition of this macro might be - #define FUNCTION_ARG_PASS_BY_REFERENCE\ - (CUM, MODE, TYPE, NAMED) \ - MUST_PASS_IN_STACK (MODE, TYPE) */ - -int -d30v_function_arg_pass_by_reference (cum, mode, type, named) - CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED; - enum machine_mode mode; - tree type; - int named ATTRIBUTE_UNUSED; -{ - int ret = MUST_PASS_IN_STACK (mode, type); - - if (TARGET_DEBUG_ARG && ret) - fprintf (stderr, "function_arg_pass_by_reference: %d\n", ret); - - return ret; -} - - -/* A C statement (sans semicolon) to update the summarizer variable CUM to - advance past an argument in the argument list. The values MODE, TYPE and - NAMED describe that argument. Once this is done, the variable CUM is - suitable for analyzing the *following* argument with `FUNCTION_ARG', etc. - - This macro need not do anything if the argument in question was passed on - the stack. The compiler knows how to track the amount of stack space used - for arguments without any special help. */ - -void -d30v_function_arg_advance (cum, mode, type, named) - CUMULATIVE_ARGS *cum; - enum machine_mode mode; - tree type; - int named; -{ - int bytes = ((mode == BLKmode) - ? int_size_in_bytes (type) - : (int) GET_MODE_SIZE (mode)); - int words = D30V_ALIGN (bytes, UNITS_PER_WORD) / UNITS_PER_WORD; - int adjust = (bytes > UNITS_PER_WORD && (*cum & 1) != 0); - - *cum += words + adjust; - - if (TARGET_DEBUG_ARG) - fprintf (stderr, - "function_adv: words = %2d, mode = %4s, named = %d, size = %3d, adjust = %1d\n", - *cum, GET_MODE_NAME (mode), named, words * UNITS_PER_WORD, adjust); -} - - -/* If defined, is a C expression that produces the machine-specific code for a - call to `__builtin_saveregs'. This code will be moved to the very beginning - of the function, before any parameter access are made. The return value of - this function should be an RTX that contains the value to use as the return - of `__builtin_saveregs'. - - If this macro is not defined, the compiler will output an ordinary call to - the library function `__builtin_saveregs'. */ - -rtx -d30v_expand_builtin_saveregs () -{ - int offset = UNITS_PER_WORD * (GPR_ARG_LAST + 1 - GPR_ARG_FIRST); - - if (TARGET_DEBUG_ARG) - fprintf (stderr, "expand_builtin_saveregs: offset from ap = %d\n", - offset); - - return gen_rtx (PLUS, Pmode, virtual_incoming_args_rtx, GEN_INT (- offset)); -} - - -/* This macro offers an alternative to using `__builtin_saveregs' and defining - the macro `EXPAND_BUILTIN_SAVEREGS'. Use it to store the anonymous register - arguments into the stack so that all the arguments appear to have been - passed consecutively on the stack. Once this is done, you can use the - standard implementation of varargs that works for machines that pass all - their arguments on the stack. - - The argument ARGS_SO_FAR is the `CUMULATIVE_ARGS' data structure, containing - the values that obtain after processing of the named arguments. The - arguments MODE and TYPE describe the last named argument--its machine mode - and its data type as a tree node. - - The macro implementation should do two things: first, push onto the stack - all the argument registers *not* used for the named arguments, and second, - store the size of the data thus pushed into the `int'-valued variable whose - name is supplied as the argument PRETEND_ARGS_SIZE. The value that you - store here will serve as additional offset for setting up the stack frame. - - Because you must generate code to push the anonymous arguments at compile - time without knowing their data types, `SETUP_INCOMING_VARARGS' is only - useful on machines that have just a single category of argument register and - use it uniformly for all data types. - - If the argument SECOND_TIME is nonzero, it means that the arguments of the - function are being analyzed for the second time. This happens for an inline - function, which is not actually compiled until the end of the source file. - The macro `SETUP_INCOMING_VARARGS' should not generate any instructions in - this case. */ - -void -d30v_setup_incoming_varargs (cum, mode, type, pretend_size, second_time) - CUMULATIVE_ARGS *cum; - enum machine_mode mode; - tree type ATTRIBUTE_UNUSED; - int *pretend_size ATTRIBUTE_UNUSED; - int second_time; -{ - if (TARGET_DEBUG_ARG) - fprintf (stderr, - "setup_vararg: words = %2d, mode = %4s, second_time = %d\n", - *cum, GET_MODE_NAME (mode), second_time); -} - - -/* Create the va_list data type. */ - -static tree -d30v_build_builtin_va_list () -{ - tree f_arg_ptr, f_arg_num, record, type_decl; - tree int_type_node; - - record = (*lang_hooks.types.make_type) (RECORD_TYPE); - type_decl = build_decl (TYPE_DECL, get_identifier ("__va_list_tag"), record); - int_type_node = make_signed_type (INT_TYPE_SIZE); - - f_arg_ptr = build_decl (FIELD_DECL, get_identifier ("__va_arg_ptr"), - ptr_type_node); - f_arg_num = build_decl (FIELD_DECL, get_identifier ("__va_arg_num"), - int_type_node); - - DECL_FIELD_CONTEXT (f_arg_ptr) = record; - DECL_FIELD_CONTEXT (f_arg_num) = record; - - TREE_CHAIN (record) = type_decl; - TYPE_NAME (record) = type_decl; - TYPE_FIELDS (record) = f_arg_ptr; - TREE_CHAIN (f_arg_ptr) = f_arg_num; - - layout_type (record); - - /* The correct type is an array type of one element. */ - return build_array_type (record, build_index_type (size_zero_node)); -} - - -/* Expand __builtin_va_start to do the va_start macro. */ - -void -d30v_expand_builtin_va_start (valist, nextarg) - tree valist; - rtx nextarg ATTRIBUTE_UNUSED; -{ - HOST_WIDE_INT words; - tree f_arg_ptr, f_arg_num; - tree arg_ptr, arg_num, saveregs, t; - - f_arg_ptr = TYPE_FIELDS (TREE_TYPE (va_list_type_node)); - f_arg_num = TREE_CHAIN (f_arg_ptr); - - valist = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (valist)), valist); - arg_ptr = build (COMPONENT_REF, TREE_TYPE (f_arg_ptr), valist, f_arg_ptr); - arg_num = build (COMPONENT_REF, TREE_TYPE (f_arg_num), valist, f_arg_num); - - words = current_function_args_info; /* __builtin_args_info (0) */ - - /* (AP)->__va_arg_ptr = (int *) __builtin_saveregs (); */ - saveregs = make_tree (TREE_TYPE (arg_ptr), d30v_expand_builtin_saveregs ()); - t = build (MODIFY_EXPR, TREE_TYPE (arg_ptr), arg_ptr, saveregs); - TREE_SIDE_EFFECTS (t) = 1; - expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); - - /* (AP)->__va_arg_num = __builtin_args_info (0) - 2; */ - t = build (PLUS_EXPR, TREE_TYPE (arg_num), build_int_2 (words, 0), - build_int_2 (-GPR_ARG_FIRST, 0)); - t = build (MODIFY_EXPR, TREE_TYPE (arg_num), arg_num, t); - TREE_SIDE_EFFECTS (t) = 1; - expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); -} - - -/* Expand __builtin_va_arg to do the va_arg macro. */ - -rtx -d30v_expand_builtin_va_arg(valist, type) - tree valist; - tree type; -{ - tree f_arg_ptr, f_arg_num; - tree arg_ptr, arg_num, t, ptr; - int num, size; - rtx lab_false, ptr_rtx, r; - - f_arg_ptr = TYPE_FIELDS (TREE_TYPE (va_list_type_node)); - f_arg_num = TREE_CHAIN (f_arg_ptr); - - valist = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (valist)), valist); - arg_ptr = build (COMPONENT_REF, TREE_TYPE (f_arg_ptr), valist, f_arg_ptr); - arg_num = build (COMPONENT_REF, TREE_TYPE (f_arg_num), valist, f_arg_num); - - size = int_size_in_bytes (type); - - lab_false = gen_label_rtx (); - ptr_rtx = gen_reg_rtx (Pmode); - - /* if (sizeof (TYPE) > 4 && ((AP)->__va_arg_num & 1) != 0) - (AP)->__va_arg_num++; */ - - if (size > UNITS_PER_WORD) - { - t = build (BIT_AND_EXPR, TREE_TYPE (arg_num), arg_num, - build_int_2 (1, 0)); - - emit_cmp_and_jump_insns (expand_expr (t, NULL_RTX, QImode, EXPAND_NORMAL), - GEN_INT (0), EQ, const1_rtx, QImode, 1, - lab_false); - - t = build (POSTINCREMENT_EXPR, TREE_TYPE (arg_num), arg_num, - build_int_2 (1, 0)); - TREE_SIDE_EFFECTS (t) = 1; - expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); - - emit_label (lab_false); - } - - - /* __ptr = (TYPE *)(((char *)(void *)((AP)->__va_arg_ptr - + (AP)->__va_arg_num))); */ - - t = build (MULT_EXPR, TREE_TYPE (arg_num), arg_num, build_int_2 (4, 0)); - t = build (PLUS_EXPR, ptr_type_node, arg_ptr, t); - - /* if (sizeof (TYPE) < 4) - __ptr = (void *)__ptr + 4 - sizeof (TYPE); */ - - if (size < UNITS_PER_WORD) - t = build (PLUS_EXPR, ptr_type_node, t, - build_int_2 (UNITS_PER_WORD - size, 0)); - - TREE_SIDE_EFFECTS (t) = 1; - - ptr = build1 (NOP_EXPR, build_pointer_type (type), t); - t = build (MODIFY_EXPR, type, ptr, t); - - r = expand_expr (t, ptr_rtx, Pmode, EXPAND_NORMAL); - if (r != ptr_rtx) - emit_move_insn (ptr_rtx, r); - - - /* (AP)->__va_arg_num += (sizeof (TYPE) + 3) / 4; */ - num = (size + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD; - t = build (POSTINCREMENT_EXPR, TREE_TYPE (arg_num), arg_num, - build_int_2 (num, 0)); - expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); - - return ptr_rtx; -} - -/* Generate the assembly code for function entry. FILE is a stdio - stream to output the code to. SIZE is an int: how many units of - temporary storage to allocate. - - Refer to the array `regs_ever_live' to determine which registers to - save; `regs_ever_live[I]' is nonzero if register number I is ever - used in the function. This function is responsible for knowing - which registers should not be saved even if used. */ - -static void -d30v_output_function_prologue (stream, size) - FILE *stream ATTRIBUTE_UNUSED; - HOST_WIDE_INT size ATTRIBUTE_UNUSED; -{ - /* For the d30v, move all of the prologue processing into separate - insns. */ -} - - -/* Called after register allocation to add any instructions needed for - the prologue. Using a prologue insn is favored compared to putting - all of the instructions in output_function_prologue (), since it - allows the scheduler to intermix instructions with the saves of the - caller saved registers. In some cases, it might be necessary to - emit a barrier instruction as the last insn to prevent such - scheduling. */ - -void -d30v_expand_prologue () -{ - rtx sp = stack_pointer_rtx; - d30v_stack_t *info = d30v_stack_info (); - int i; - rtx mem_di = NULL_RTX; - rtx mem_si = NULL_RTX; - int num_memrefs = (info->memrefs_2words - + info->memrefs_1word - + info->memrefs_varargs); - - if (TARGET_DEBUG_STACK) - debug_stack_info (info); - - /* Grow the stack. */ - if (info->total_size) - emit_insn (gen_addsi3 (sp, sp, GEN_INT (- info->total_size))); - - /* If there is more than one save, use post-increment addressing which will - result in smaller code, than would the normal references. If there is - only one save, just do the store as normal. */ - - if (num_memrefs > 1) - { - rtx save_tmp = gen_rtx (REG, Pmode, GPR_STACK_TMP); - rtx post_inc = gen_rtx (POST_INC, Pmode, save_tmp); - mem_di = gen_rtx (MEM, DImode, post_inc); - mem_si = gen_rtx (MEM, SImode, post_inc); - emit_insn (gen_addsi3 (save_tmp, sp, GEN_INT (info->save_offset))); - } - else if (num_memrefs == 1) - { - rtx addr = plus_constant (sp, info->save_offset); - mem_di = gen_rtx (MEM, DImode, addr); - mem_si = gen_rtx (MEM, SImode, addr); - } - - /* Save the accumulators. */ - for (i = ACCUM_FIRST; i <= ACCUM_LAST; i++) - if (info->save_p[i]) - { - rtx acc_tmp = gen_rtx (REG, DImode, GPR_ATMP_FIRST); - emit_insn (gen_movdi (acc_tmp, gen_rtx (REG, DImode, i))); - emit_insn (gen_movdi (mem_di, acc_tmp)); - } - - /* Save the GPR registers that are adjacent to each other with st2w. */ - for (i = GPR_FIRST; i <= GPR_LAST; i += 2) - if (info->save_p[i] == 2) - emit_insn (gen_movdi (mem_di, gen_rtx (REG, DImode, i))); - - /* Save the GPR registers that need to be saved with a single word store. */ - for (i = GPR_FIRST; i <= GPR_LAST; i++) - if (info->save_p[i] == 1) - emit_insn (gen_movsi (mem_si, gen_rtx (REG, SImode, i))); - - /* Save the argument registers if this function accepts variable args. */ - if (info->varargs_p) - { - /* Realign r22 if an odd # of GPRs were saved. */ - if ((info->memrefs_1word & 1) != 0) - { - rtx save_tmp = XEXP (XEXP (mem_si, 0), 0); - emit_insn (gen_addsi3 (save_tmp, save_tmp, GEN_INT (UNITS_PER_WORD))); - } - - for (i = GPR_ARG_FIRST; i <= GPR_ARG_LAST; i += 2) - emit_insn (gen_movdi (mem_di, gen_rtx (REG, DImode, i))); - } - - /* Update the frame pointer. */ - if (frame_pointer_needed) - emit_move_insn (frame_pointer_rtx, sp); - - /* Hack for now, to prevent scheduler from being too cleaver */ - emit_insn (gen_blockage ()); -} - - -/* This function generates the assembly code for function exit. - Args are as for output_function_prologue (). - - The function epilogue should not depend on the current stack - pointer! It should use the frame pointer only. This is mandatory - because of alloca; we also take advantage of it to omit stack - adjustments before returning. */ - -static void -d30v_output_function_epilogue (stream, size) - FILE *stream ATTRIBUTE_UNUSED; - HOST_WIDE_INT size ATTRIBUTE_UNUSED; -{ - /* For the d30v, move all processing to be as insns, but do any - cleanup here, since it is done after handling all of the insns. */ - d30v_stack_cache = (d30v_stack_t *)0; /* reset stack cache */ -} - - - -/* Called after register allocation to add any instructions needed for - the epilogue. Using an epilogue insn is favored compared to putting - all of the instructions in output_function_prologue(), since it - allows the scheduler to intermix instructions with the saves of the - caller saved registers. In some cases, it might be necessary to - emit a barrier instruction as the last insn to prevent such - scheduling. */ - -void -d30v_expand_epilogue () -{ - rtx sp = stack_pointer_rtx; - d30v_stack_t *info = d30v_stack_info (); - int i; - rtx mem_di = NULL_RTX; - rtx mem_si = NULL_RTX; - rtx post_inc; - int extra_stack; - - /* Hack for now, to prevent scheduler from being too cleaver */ - emit_insn (gen_blockage ()); - - /* Restore sp from fp. */ - if (frame_pointer_needed) - emit_move_insn (sp, frame_pointer_rtx); - - /* For the epilogue, use post-increment addressing all of the time. First - adjust the sp, to eliminate all of the stack, except for the save area. */ - - if (info->save_offset) - emit_insn (gen_addsi3 (sp, sp, GEN_INT (info->save_offset))); - - post_inc = gen_rtx (POST_INC, Pmode, sp); - mem_di = gen_rtx (MEM, DImode, post_inc); - mem_si = gen_rtx (MEM, SImode, post_inc); - - /* Restore the accumulators. */ - for (i = ACCUM_FIRST; i <= ACCUM_LAST; i++) - if (info->save_p[i]) - { - rtx acc_tmp = gen_rtx (REG, DImode, GPR_ATMP_FIRST); - emit_insn (gen_movdi (acc_tmp, mem_di)); - emit_insn (gen_movdi (gen_rtx (REG, DImode, i), acc_tmp)); - } - - /* Restore the GPR registers that are adjacent to each other with ld2w. */ - for (i = GPR_FIRST; i <= GPR_LAST; i += 2) - if (info->save_p[i] == 2) - emit_insn (gen_movdi (gen_rtx (REG, DImode, i), mem_di)); - - /* Save the GPR registers that need to be saved with a single word store. */ - extra_stack = 0; - for (i = GPR_FIRST; i <= GPR_LAST; i++) - if (info->save_p[i] == 1) - { - if (cfun->machine->eh_epilogue_sp_ofs && i == GPR_LINK) - extra_stack = 4; - else - { - if (extra_stack) - { - emit_insn (gen_addsi3 (sp, sp, GEN_INT (extra_stack))); - extra_stack = 0; - } - emit_insn (gen_movsi (gen_rtx (REG, SImode, i), mem_si)); - } - } - - /* Release any remaining stack that was allocated for saving the - varargs registers or because an odd # of registers were stored. */ - if ((info->memrefs_1word & 1) != 0) - extra_stack += UNITS_PER_WORD; - extra_stack += current_function_pretend_args_size + info->varargs_size; - - if (extra_stack) - { - if (cfun->machine->eh_epilogue_sp_ofs) - emit_insn (gen_addsi3 (cfun->machine->eh_epilogue_sp_ofs, - cfun->machine->eh_epilogue_sp_ofs, - GEN_INT (extra_stack))); - else - emit_insn (gen_addsi3 (sp, sp, GEN_INT (extra_stack))); - } - if (cfun->machine->eh_epilogue_sp_ofs) - emit_insn (gen_addsi3 (sp, sp, cfun->machine->eh_epilogue_sp_ofs)); - - /* Now emit the return instruction. */ - emit_jump_insn (gen_rtx_RETURN (VOIDmode)); -} - - -/* A C statement or compound statement to output to FILE some assembler code to - call the profiling subroutine `mcount'. Before calling, the assembler code - must load the address of a counter variable into a register where `mcount' - expects to find the address. The name of this variable is `LP' followed by - the number LABELNO, so you would generate the name using `LP%d' in a - `fprintf'. - - The details of how the address should be passed to `mcount' are determined - by your operating system environment, not by GCC. To figure them out, - compile a small program for profiling using the system's installed C - compiler and look at the assembler code that results. */ - -void -d30v_function_profiler (stream, labelno) - FILE *stream; - int labelno ATTRIBUTE_UNUSED; -{ - fprintf (stream, "# profile\n"); -} - - -/* Split a 64 bit item into an upper and a lower part. We specifically do not - want to call gen_highpart/gen_lowpart on CONST_DOUBLEs since it will give us - the wrong part for floating point in cross compilers, and split_double does - not handle registers. Also abort if the register is not a general purpose - register. */ - -void -d30v_split_double (value, p_high, p_low) - rtx value; - rtx *p_high; - rtx *p_low; -{ - int offset = 0; - int regno; - - if (!reload_completed) - abort (); - - switch (GET_CODE (value)) - { - case SUBREG: - if (GET_CODE (SUBREG_REG (value)) != REG) - abort (); - offset = subreg_regno_offset (REGNO (SUBREG_REG (value)), - GET_MODE (SUBREG_REG (value)), - SUBREG_BYTE (value), - GET_MODE (value)); - value = SUBREG_REG (value); - - /* fall through */ - - case REG: - regno = REGNO (value) + offset; - if (!GPR_P (regno)) - abort (); - - *p_high = gen_rtx (REG, SImode, regno); - *p_low = gen_rtx (REG, SImode, regno+1); - break; - - case CONST_INT: - case CONST_DOUBLE: - split_double (value, p_high, p_low); - break; - - default: - abort (); - } -} - - -/* A C compound statement to output to stdio stream STREAM the assembler syntax - for an instruction operand that is a memory reference whose address is X. X - is an RTL expression. */ - -void -d30v_print_operand_address (stream, x) - FILE *stream; - rtx x; -{ - if (GET_CODE (x) == MEM) - x = XEXP (x, 0); - - switch (GET_CODE (x)) - { - default: - break; - - case REG: - fputs (reg_names[ REGNO (x) ], stream); - return; - - case CONST_INT: - fprintf (stream, "%ld", (long) INTVAL (x)); - return; - - /* We wrap simple symbol refs inside a parenthesis, so that a name - like `r2' is not taken for a register name. */ - case SYMBOL_REF: - fputs ("(", stream); - assemble_name (stream, XSTR (x, 0)); - fputs (")", stream); - return; - - case LABEL_REF: - case CONST: - output_addr_const (stream, x); - return; - } - - fatal_insn ("bad insn to d30v_print_operand_address:", x); -} - - -/* Print a memory reference suitable for the ld/st instructions. */ - -static void -d30v_print_operand_memory_reference (stream, x) - FILE *stream; - rtx x; -{ - rtx x0 = NULL_RTX; - rtx x1 = NULL_RTX; - - switch (GET_CODE (x)) - { - default: - fatal_insn ("bad insn to d30v_print_operand_memory_reference:", x); - break; - - case SUBREG: - case REG: - case POST_DEC: - case POST_INC: - x0 = x; - break; - - case CONST_INT: - case SYMBOL_REF: - case LABEL_REF: - case CONST: - x1 = x; - break; - - case PLUS: - x0 = XEXP (x, 0); - x1 = XEXP (x, 1); - if (GET_CODE (x0) == CONST_INT || GET_CODE (x0) == SYMBOL_REF - || GET_CODE (x0) == CONST || GET_CODE (x0) == LABEL_REF) - { - x0 = XEXP (x, 1); - x1 = XEXP (x, 0); - } - break; - } - - fputs ("@(", stream); - if (!x0) - fputs (reg_names[GPR_R0], stream); - - else - { - const char *suffix = ""; - int offset0 = 0; - - if (GET_CODE (x0) == SUBREG) - { - offset0 = subreg_regno_offset (REGNO (SUBREG_REG (x0)), - GET_MODE (SUBREG_REG (x0)), - SUBREG_BYTE (x0), - GET_MODE (x0)); - x0 = SUBREG_REG (x0); - } - - if (GET_CODE (x0) == POST_INC) - { - x0 = XEXP (x0, 0); - suffix = "+"; - } - else if (GET_CODE (x0) == POST_DEC) - { - x0 = XEXP (x0, 0); - suffix = "-"; - } - - if (GET_CODE (x0) == REG && GPR_P (REGNO (x0))) - fprintf (stream, "%s%s", reg_names[REGNO (x0) + offset0], suffix); - else - fatal_insn ("bad insn to d30v_print_operand_memory_reference:", x); - } - - fputs (",", stream); - - if (!x1) - fputs (reg_names[GPR_R0], stream); - - else - { - int offset1 = 0; - - switch (GET_CODE (x1)) - { - case SUBREG: - offset1 = subreg_regno_offset (REGNO (SUBREG_REG (x1)), - GET_MODE (SUBREG_REG (x1)), - SUBREG_BYTE (x1), - GET_MODE (x1)); - x1 = SUBREG_REG (x1); - if (GET_CODE (x1) != REG) - fatal_insn ("bad insn to d30v_print_operand_memory_reference:", x); - - /* fall through */ - case REG: - fputs (reg_names[REGNO (x1) + offset1], stream); - break; - - case CONST_INT: - fprintf (stream, "%ld", (long) INTVAL (x1)); - break; - - case SYMBOL_REF: - case LABEL_REF: - case CONST: - d30v_print_operand_address (stream, x1); - break; - - default: - fatal_insn ("bad insn to d30v_print_operand_memory_reference:", x); - } - } - - fputs (")", stream); -} - - -/* A C compound statement to output to stdio stream STREAM the assembler syntax - for an instruction operand X. X is an RTL expression. - - LETTER is a value that can be used to specify one of several ways of - printing the operand. It is used when identical operands must be printed - differently depending on the context. LETTER comes from the `%' - specification that was used to request printing of the operand. If the - specification was just `%DIGIT' then LETTER is 0; if the specification was - `%LTR DIGIT' then LETTER is the ASCII code for LTR. - - If X is a register, this macro should print the register's name. The names - can be found in an array `reg_names' whose type is `char *[]'. `reg_names' - is initialized from `REGISTER_NAMES'. - - When the machine description has a specification `%PUNCT' (a `%' followed by - a punctuation character), this macro is called with a null pointer for X and - the punctuation character for LETTER. - - Standard operand flags that are handled elsewhere: - `=' Output a number unique to each instruction in the compilation. - `a' Substitute an operand as if it were a memory reference. - `c' Omit the syntax that indicates an immediate operand. - `l' Substitute a LABEL_REF into a jump instruction. - `n' Like %cDIGIT, except negate the value before printing. - - The d30v specific operand flags are: - `.' Print r0. - `f' Print a SF constant as an int. - `s' Subtract 32 and negate. - `A' Print accumulator number without an `a' in front of it. - `B' Print bit offset for BSET, etc. instructions. - `E' Print u if this is zero extend, nothing if this is sign extend. - `F' Emit /{f,t,x}{f,t,x} for executing a false condition. - `L' Print the lower half of a 64 bit item. - `M' Print a memory reference for ld/st instructions. - `R' Return appropriate cmp instruction for relational test. - `S' Subtract 32. - `T' Emit /{f,t,x}{f,t,x} for executing a true condition. - `U' Print the upper half of a 64 bit item. */ - -void -d30v_print_operand (stream, x, letter) - FILE *stream; - rtx x; - int letter; -{ - enum rtx_code code = (x) ? GET_CODE (x) : NIL; - rtx split_values[2]; - REAL_VALUE_TYPE rv; - long num; - int log; - - switch (letter) - { - case '.': /* Output r0 */ - fputs (reg_names[GPR_R0], stream); - break; - - case 'f': /* Print a SF floating constant as an int */ - if (GET_CODE (x) != CONST_DOUBLE) - fatal_insn ("bad insn to d30v_print_operand, 'f' modifier:", x); - - REAL_VALUE_FROM_CONST_DOUBLE (rv, x); - REAL_VALUE_TO_TARGET_SINGLE (rv, num); - fprintf (stream, "%ld", num); - break; - - case 'A': /* Print accumulator number without an `a' in front of it. */ - if (GET_CODE (x) != REG || !ACCUM_P (REGNO (x))) - fatal_insn ("bad insn to d30v_print_operand, 'A' modifier:", x); - - putc ('0' + REGNO (x) - ACCUM_FIRST, stream); - break; - - case 'M': /* Print a memory reference for ld/st */ - if (GET_CODE (x) != MEM) - fatal_insn ("bad insn to d30v_print_operand, 'M' modifier:", x); - - d30v_print_operand_memory_reference (stream, XEXP (x, 0)); - break; - - case 'L': /* print lower part of 64 bit item. */ - case 'U': /* print upper part of 64 bit item. */ - d30v_split_double (x, &split_values[0], &split_values[1]); - d30v_print_operand (stream, split_values[ letter == 'L' ], '\0'); - break; - - case ':': /* Output the condition for the current insn. */ - x = current_insn_predicate; - if (x == NULL_RTX) - break; - letter = 'T'; - /* FALLTHRU */ - - case 'F': /* Print an appropriate suffix for a false comparison. */ - case 'T': /* Print an appropriate suffix for a true comparison. */ - /* Note that the sense of appropriate suffix is for conditional execution - and opposite of what branches want. Branches just use the inverse - operation. */ - if ((GET_CODE (x) == NE || GET_CODE (x) == EQ) - && GET_MODE (x) == CCmode - && GET_CODE (XEXP (x, 0)) == REG - && (GPR_P (REGNO (XEXP (x, 0))) || BR_FLAG_P (REGNO (XEXP (x, 0)))) - && GET_CODE (XEXP (x, 1)) == CONST_INT && INTVAL (XEXP (x, 1)) == 0) - { - int true_false = (letter == 'T'); - - if (GET_CODE (x) == EQ) - true_false = !true_false; - - if (REGNO (XEXP (x, 0)) == FLAG_F0) - fprintf (stream, "/%cx", (true_false) ? 'f' : 't'); - - else if (REGNO (XEXP (x, 0)) == FLAG_F1) - fprintf (stream, "/x%c", (true_false) ? 'f' : 't'); - - else - fputs ((true_false) ? "tnz" : "tzr", stream); - } - - else if (GET_CODE (x) == REG && REGNO (x) == FLAG_F0) - fprintf (stream, "/%cx", (letter == 'T') ? 't' : 'f'); - - else if (GET_CODE (x) == REG && REGNO (x) == FLAG_F1) - fprintf (stream, "/x%c", (letter == 'T') ? 't' : 'f'); - - else if (GET_CODE (x) == REG && GPR_P (REGNO (x))) - fputs ((letter == 'T') ? "tnz" : "tzr", stream); - - else - fatal_insn ("bad insn to print_operand, 'F' or 'T' modifier:", x); - break; - - case 'B': /* emit offset single bit to change */ - if (GET_CODE (x) == CONST_INT && (log = exact_log2 (INTVAL (x))) >= 0) - fprintf (stream, "%d", 31 - log); - - else if (GET_CODE (x) == CONST_INT && (log = exact_log2 (~ INTVAL (x))) >= 0) - fprintf (stream, "%d", 31 - log); - - else - fatal_insn ("bad insn to print_operand, 'B' modifier:", x); - break; - - case 'E': /* Print u if this is zero extend, nothing if sign extend. */ - if (GET_CODE (x) == ZERO_EXTEND) - putc ('u', stream); - else if (GET_CODE (x) != SIGN_EXTEND) - fatal_insn ("bad insn to print_operand, 'E' modifier:", x); - break; - - case 'R': /* Return appropriate cmp instruction for relational test. */ - switch (GET_CODE (x)) - { - case EQ: fputs ("cmpeq", stream); break; - case NE: fputs ("cmpne", stream); break; - case LT: fputs ("cmplt", stream); break; - case LE: fputs ("cmple", stream); break; - case GT: fputs ("cmpgt", stream); break; - case GE: fputs ("cmpge", stream); break; - case LTU: fputs ("cmpult", stream); break; - case LEU: fputs ("cmpule", stream); break; - case GTU: fputs ("cmpugt", stream); break; - case GEU: fputs ("cmpuge", stream); break; - - default: - fatal_insn ("bad insn to print_operand, 'R' modifier:", x); - } - break; - - case 's': /* Subtract 32 and negate (for 64 bit shifts). */ - if (GET_CODE (x) == CONST_INT) - fprintf (stream, "%d", (int) (32 - INTVAL (x))); - - else - fatal_insn ("bad insn to print_operand, 's' modifier:", x); - break; - - case 'S': /* Subtract 32. */ - if (GET_CODE (x) == CONST_INT) - fprintf (stream, "%d", (int)(INTVAL (x) - 32)); - - else - fatal_insn ("bad insn to print_operand, 's' modifier:", x); - break; - - - case 'z': /* If arg is 0 or 0.0, print r0, otherwise print as normal */ - if ((GET_CODE (x) == CONST_INT && INTVAL (x) == 0) - || (GET_CODE (x) == CONST_DOUBLE && CONST_DOUBLE_LOW (x) == 0 - && CONST_DOUBLE_HIGH (x) == 0)) - { - fputs (reg_names[GPR_FIRST], stream); - return; - } - - /* fall through */ - - case '\0': - if (code == REG) - fputs (reg_names[ REGNO (x) ], stream); - - else if (code == CONST_INT) - fprintf (stream, "%d", (int)INTVAL (x)); - - else if (code == MEM) - d30v_print_operand_address (stream, XEXP (x, 0)); - - else if (CONSTANT_ADDRESS_P (x)) - d30v_print_operand_address (stream, x); - - else - fatal_insn ("bad insn in d30v_print_operand, 0 case", x); - - return; - - default: - { - char buf[80]; - - sprintf (buf, "invalid asm template character '%%%c'", letter); - fatal_insn (buf, x); - } - } -} - - -/* A C expression for the size in bytes of the trampoline, as an integer. */ - -int -d30v_trampoline_size () -{ - return 16; -} - - -/* Create a long instruction for building up a trampoline. */ - -static void -d30v_build_long_insn (high_bits, low_bits, imm, mem) - HOST_WIDE_INT high_bits; - HOST_WIDE_INT low_bits; - rtx imm; - rtx mem; -{ - rtx reg = gen_reg_rtx (DImode); - rtx high_word = gen_highpart (SImode, reg); - rtx low_word = gen_lowpart (SImode, reg); - rtx tmp1 = gen_reg_rtx (SImode); - rtx tmp2 = gen_reg_rtx (SImode); - rtx tmp3 = gen_reg_rtx (SImode); - rtx tmp4 = gen_reg_rtx (SImode); - rtx tmp5 = gen_reg_rtx (SImode); - rtx tmp6 = gen_reg_rtx (SImode); - - imm = force_reg (SImode, imm); - - /* Stuff top 6 bits of immediate value into high word */ - emit_insn (gen_lshrsi3 (tmp1, imm, GEN_INT (26))); - emit_insn (gen_andsi3 (tmp2, tmp1, GEN_INT (0x3F))); - emit_insn (gen_iorsi3 (high_word, tmp2, GEN_INT (high_bits))); - - /* Now get the next 8 bits for building the low word */ - emit_insn (gen_andsi3 (tmp3, imm, GEN_INT (0x03FC0000))); - emit_insn (gen_ashlsi3 (tmp4, tmp3, GEN_INT (2))); - - /* And the bottom 18 bits */ - emit_insn (gen_andsi3 (tmp5, imm, GEN_INT (0x0003FFFF))); - emit_insn (gen_iorsi3 (tmp6, tmp4, tmp5)); - emit_insn (gen_iorsi3 (low_word, tmp6, GEN_INT (low_bits))); - - /* Store the instruction */ - emit_insn (gen_movdi (mem, reg)); -} - - -/* A C statement to initialize the variable parts of a trampoline. ADDR is an - RTX for the address of the trampoline; FNADDR is an RTX for the address of - the nested function; STATIC_CHAIN is an RTX for the static chain value that - should be passed to the function when it is called. */ - -void -d30v_initialize_trampoline (addr, fnaddr, static_chain) - rtx addr; - rtx fnaddr; - rtx static_chain; -{ - /* The instruction space can only be accessed by ld2w/st2w. - Generate on the fly: - or r18,r0, - jmp */ - d30v_build_long_insn (0x83A80000 | ((STATIC_CHAIN_REGNUM - GPR_FIRST) << 12), - 0x80000000, static_chain, - gen_rtx (MEM, DImode, addr)); - - d30v_build_long_insn (0x80180000, 0x80000000, fnaddr, - gen_rtx (MEM, DImode, plus_constant (addr, 8))); -} - - -/* A C compound statement with a conditional `goto LABEL;' executed if X (an - RTX) is a legitimate memory address on the target machine for a memory - operand of mode MODE. */ - -#define XREGNO_OK_FOR_BASE_P(REGNO, STRICT_P) \ -((STRICT_P) \ - ? REGNO_OK_FOR_BASE_P (REGNO) \ - : GPR_OR_PSEUDO_P (REGNO)) - -int -d30v_legitimate_address_p (mode, x, strict_p) - enum machine_mode mode; - rtx x; - int strict_p; -{ - rtx x0, x1; - int ret = 0; - - switch (GET_CODE (x)) - { - default: - break; - - case SUBREG: - x = SUBREG_REG (x); - if (GET_CODE (x) != REG) - break; - - /* fall through */ - - case REG: - ret = XREGNO_OK_FOR_BASE_P (REGNO (x), strict_p); - break; - - case PLUS: - x0 = XEXP (x, 0); - x1 = XEXP (x, 1); - - if (GET_CODE (x0) == SUBREG) - x0 = SUBREG_REG (x0); - - if (GET_CODE (x0) == POST_INC || GET_CODE (x0) == POST_DEC) - x0 = XEXP (x0, 0); - - if (GET_CODE (x0) != REG || !XREGNO_OK_FOR_BASE_P (REGNO (x0), strict_p)) - break; - - switch (GET_CODE (x1)) - { - default: - break; - - case SUBREG: - x1 = SUBREG_REG (x1); - if (GET_CODE (x1) != REG) - break; - - /* fall through */ - - case REG: - ret = XREGNO_OK_FOR_BASE_P (REGNO (x1), strict_p); - break; - - case CONST_INT: - ret = (IN_RANGE_P (INTVAL (x1), -32, 31)) ? 1 : 2; - break; - - case SYMBOL_REF: - case LABEL_REF: - case CONST: - ret = 2; - break; - } - break; - - case CONST_INT: - ret = (IN_RANGE_P (INTVAL (x), -32, 31)) ? 1 : 2; - break; - - case SYMBOL_REF: - case LABEL_REF: - case CONST: - ret = 2; - break; - - case POST_INC: - case POST_DEC: - x0 = XEXP (x, 0); - if (GET_CODE (x0) == REG && XREGNO_OK_FOR_BASE_P (REGNO (x0), strict_p)) - ret = 1; - break; - } - - if (TARGET_DEBUG_ADDR) - { - fprintf (stderr, "\n========== GO_IF_LEGITIMATE_ADDRESS, mode = %s, result = %d, addresses are %sstrict\n", - GET_MODE_NAME (mode), ret, (strict_p) ? "" : "not "); - debug_rtx (x); - } - - return ret; -} - - -/* A C compound statement that attempts to replace X with a valid memory - address for an operand of mode MODE. WIN will be a C statement label - elsewhere in the code; the macro definition may use - - GO_IF_LEGITIMATE_ADDRESS (MODE, X, WIN); - - to avoid further processing if the address has become legitimate. - - X will always be the result of a call to `break_out_memory_refs', and OLDX - will be the operand that was given to that function to produce X. - - The code generated by this macro should not alter the substructure of X. If - it transforms X into a more legitimate form, it should assign X (which will - always be a C variable) a new value. - - It is not necessary for this macro to come up with a legitimate address. - The compiler has standard ways of doing so in all cases. In fact, it is - safe for this macro to do nothing. But often a machine-dependent strategy - can generate better code. */ - -rtx -d30v_legitimize_address (x, oldx, mode, strict_p) - rtx x; - rtx oldx ATTRIBUTE_UNUSED; - enum machine_mode mode ATTRIBUTE_UNUSED; - int strict_p ATTRIBUTE_UNUSED; -{ - rtx ret = NULL_RTX; - - if (TARGET_DEBUG_ADDR) - { - if (ret) - { - fprintf (stderr, "\n========== LEGITIMIZE_ADDRESS, transformed:\n"); - debug_rtx (x); - fprintf (stderr, "\ninto:\n"); - debug_rtx (ret); - } - else - { - fprintf (stderr, "\n========== LEGITIMIZE_ADDRESS, did nothing with:\n"); - debug_rtx (x); - } - } - - return ret; -} - - -/* A C statement or compound statement with a conditional `goto LABEL;' - executed if memory address X (an RTX) can have different meanings depending - on the machine mode of the memory reference it is used for or if the address - is valid for some modes but not others. - - Autoincrement and autodecrement addresses typically have mode-dependent - effects because the amount of the increment or decrement is the size of the - operand being addressed. Some machines have other mode-dependent addresses. - Many RISC machines have no mode-dependent addresses. - - You may assume that ADDR is a valid address for the machine. */ - -int -d30v_mode_dependent_address_p (addr) - rtx addr; -{ - switch (GET_CODE (addr)) - { - default: - break; - - case POST_INC: - case POST_DEC: - return TRUE; - } - - return FALSE; -} - - -/* Generate the appropriate comparison code for a test. */ - -rtx -d30v_emit_comparison (test_int, result, arg1, arg2) - int test_int; - rtx result; - rtx arg1; - rtx arg2; -{ - enum rtx_code test = (enum rtx_code) test_int; - enum machine_mode mode = GET_MODE (arg1); - rtx rtx_test = gen_rtx (SET, VOIDmode, result, gen_rtx (test, CCmode, arg1, arg2)); - - if (mode == SImode - || (mode == DImode && (test == EQ || test == NE)) - || (mode == DImode && (test == LT || test == GE) - && GET_CODE (arg2) == CONST_INT && INTVAL (arg2) == 0)) - return rtx_test; - - else if (mode == DImode) - return gen_rtx (PARALLEL, VOIDmode, - gen_rtvec (2, - rtx_test, - gen_rtx (CLOBBER, VOIDmode, - gen_reg_rtx (CCmode)))); - - else - fatal_insn ("d30v_emit_comparison", rtx_test); -} - - -/* Return appropriate code to move 2 words. Since DImode registers must start - on even register numbers, there is no possibility of overlap. */ - -const char * -d30v_move_2words (operands, insn) - rtx operands[]; - rtx insn; -{ - if (GET_CODE (operands[0]) == REG && GPR_P (REGNO (operands[0]))) - { - if (GET_CODE (operands[1]) == REG && GPR_P (REGNO (operands[1]))) - return "or %U0,%.,%U1\n\tor %L0,%.,%L1"; - - else if (GET_CODE (operands[1]) == REG && ACCUM_P (REGNO (operands[1]))) - return "mvfacc %L0,%1,%.\n\tmvfacc %U0,%1,32"; - - else if (GET_CODE (operands[1]) == MEM) - return "ld2w %0,%M1"; - - else if (GET_CODE (operands[1]) == CONST_INT - || GET_CODE (operands[1]) == CONST_DOUBLE) - return "or %U0,%.,%U1\n\tor %L0,%.,%L1"; - } - - else if (GET_CODE (operands[0]) == REG && ACCUM_P (REGNO (operands[0]))) - { - if (GET_CODE (operands[1]) == REG - && GPR_P (REGNO (operands[1]))) - return "mvtacc %0,%U1,%L1"; - - if (GET_CODE (operands[1]) == CONST_INT - && INTVAL (operands[1]) == 0) - return "mvtacc %0,%.,%."; - } - - else if (GET_CODE (operands[0]) == MEM - && GET_CODE (operands[1]) == REG - && GPR_P (REGNO (operands[1]))) - return "st2w %1,%M0"; - - fatal_insn ("bad call to d30v_move_2words", insn); -} - - -/* Emit the code to do a conditional move instruction. Return FALSE - if the conditional move could not be executed. */ - -int -d30v_emit_cond_move (dest, test, true_value, false_value) - rtx dest; - rtx test; - rtx true_value; - rtx false_value; -{ - rtx br_reg; - enum machine_mode mode = GET_MODE (dest); - int two_mem_moves_p = FALSE; - - if (GET_CODE (dest) == MEM) - { - if (!reg_or_0_operand (true_value, mode)) - return FALSE; - - if (rtx_equal_p (dest, false_value)) - two_mem_moves_p = TRUE; - - else if (!reg_or_0_operand (false_value, mode)) - return FALSE; - } - - /* We used to try to optimize setting 0/1 by using mvfsys, but that turns out - to be slower than just doing the conditional execution. */ - - br_reg = gen_reg_rtx (CCmode); - emit_insn (d30v_emit_comparison (GET_CODE (test), br_reg, - d30v_compare_op0, d30v_compare_op1)); - - if (!two_mem_moves_p) - emit_insn (gen_rtx_SET (VOIDmode, - dest, - gen_rtx_IF_THEN_ELSE (mode, - gen_rtx_NE (CCmode, br_reg, - const0_rtx), - true_value, - false_value))); - else - { - /* Emit conditional stores as two separate stores. This avoids a problem - where you have a conditional store, and one of the arms of the - conditional store is spilled to memory. */ - emit_insn (gen_rtx_SET (VOIDmode, - dest, - gen_rtx_IF_THEN_ELSE (mode, - gen_rtx_NE (CCmode, br_reg, - const0_rtx), - true_value, - dest))); - - emit_insn (gen_rtx_SET (VOIDmode, - dest, - gen_rtx_IF_THEN_ELSE (mode, - gen_rtx_EQ (CCmode, br_reg, - const0_rtx), - false_value, - dest))); - - } - - return TRUE; -} - - -/* A C statement (sans semicolon) to update the integer variable COST based on - the relationship between INSN that is dependent on DEP_INSN through the - dependence LINK. The default is to make no adjustment to COST. This can be - used for example to specify to the scheduler that an output- or - anti-dependence does not incur the same cost as a data-dependence. */ - -/* For the d30v, try to insure that the source operands for a load/store are - set 2 cycles before the memory reference. */ - -static int -d30v_adjust_cost (insn, link, dep_insn, cost) - rtx insn; - rtx link ATTRIBUTE_UNUSED; - rtx dep_insn; - int cost; -{ - rtx set_dep = single_set (dep_insn); - rtx set_insn = single_set (insn); - - if (set_dep != NULL_RTX && set_insn != NULL_RTX - && GET_CODE (SET_DEST (set_dep)) == REG) - { - rtx reg = SET_DEST (set_dep); - rtx mem; - - if ((GET_CODE (mem = SET_SRC (set_insn)) == MEM - && reg_mentioned_p (reg, XEXP (mem, 0))) - || (GET_CODE (mem = SET_DEST (set_insn)) == MEM - && reg_mentioned_p (reg, XEXP (mem, 0)))) - { - return cost + 2; - } - } - - return cost; -} - -/* Function which returns the number of insns that can be - scheduled in the same machine cycle. This must be constant - over an entire compilation. The default is 1. */ -static int -d30v_issue_rate () -{ - return 2; -} - - -/* Routine to allocate, mark and free a per-function, - machine specific structure. */ - -static struct machine_function * -d30v_init_machine_status () -{ - return ggc_alloc_cleared (sizeof (machine_function)); -} - -/* Do anything needed before RTL is emitted for each function. */ - -void -d30v_init_expanders () -{ - /* Arrange to save and restore machine status around nested functions. */ - init_machine_status = d30v_init_machine_status; -} - -/* Find the current function's return address. - - ??? It would be better to arrange things such that if we would ordinarily - have been a leaf function and we didn't spill the hard reg that we - wouldn't have to save the register in the prolog. But it's not clear - how to get the right information at the right time. */ - -rtx -d30v_return_addr () -{ - return get_hard_reg_initial_val (Pmode, GPR_LINK); -} - -static bool -d30v_rtx_costs (x, code, outer_code, total) - rtx x; - int code; - int outer_code ATTRIBUTE_UNUSED; - int *total; -{ - switch (code) - { - case MULT: - *total = COSTS_N_INSNS ((GET_CODE (XEXP (x, 1)) == CONST_INT - && exact_log2 (INTVAL (XEXP (x, 1))) >= 0) - ? 1 : 2); - return true; - - default: - return false; - } -} diff --git a/gcc/config/d30v/d30v.h b/gcc/config/d30v/d30v.h deleted file mode 100644 index f63292ecaa3..00000000000 --- a/gcc/config/d30v/d30v.h +++ /dev/null @@ -1,2069 +0,0 @@ -/* Definitions of target machine for Mitsubishi D30V. - Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 - Free Software Foundation, Inc. - Contributed by Cygnus Solutions. - - This file is part of GCC. - - GCC is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - GCC is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GCC; see the file COPYING. If not, write to - the Free Software Foundation, 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#ifndef GCC_D30V_H - -/* D30V specific macros */ - -/* Align an address */ -#define D30V_ALIGN(addr,align) (((addr) + (align) - 1) & ~((align) - 1)) - - -/* Driver configuration */ - -/* Defined in svr4.h. */ -/* #define SWITCH_TAKES_ARG(CHAR) */ - -/* Defined in svr4.h. */ -/* #define WORD_SWITCH_TAKES_ARG(NAME) */ - -/* Defined in svr4.h. */ -#undef ASM_SPEC -#define ASM_SPEC "\ -%{!mno-asm-optimize: %{O*: %{!O0: -O} %{O0: %{masm-optimize: -O}}}} \ -%{v} %{n} %{T} %{Ym,*} %{Yd,*} %{Wa,*:%*}" - -/* Defined in svr4.h. */ -#undef LINK_SPEC -#define LINK_SPEC "\ -%{h*} %{v:-V} \ -%{b} %{Wl,*:%*} \ -%{static:-dn -Bstatic} \ -%{shared:-G -dy -z text} \ -%{symbolic:-Bsymbolic -G -dy -z text} \ -%{G:-G} \ -%{YP,*} \ -%{Qy:} %{!Qn:-Qy} \ -%{mextmem: -m d30v_e} %{mextmemory: -m d30v_e} %{monchip: -m d30v_o}" - -/* Defined in svr4.h. */ -#undef LIB_SPEC -#define LIB_SPEC "--start-group -lsim -lc --end-group" - -/* Defined in svr4.h. */ -#undef STARTFILE_SPEC -#define STARTFILE_SPEC "crt0%O%s crtbegin%O%s" - -/* Defined in svr4.h. */ -#undef ENDFILE_SPEC -#define ENDFILE_SPEC "crtend%O%s" - -/* Defined in svr4.h for host compilers. */ -/* #define MD_EXEC_PREFIX "" */ - -/* Defined in svr4.h for host compilers. */ -/* #define MD_STARTFILE_PREFIX "" */ - - -/* Run-time target specifications */ - -#define TARGET_CPU_CPP_BUILTINS() \ - do \ - { \ - builtin_define ("__D30V__"); \ - builtin_assert ("machine=d30v"); \ - } \ - while (0) - -/* This declaration should be present. */ -extern int target_flags; - -#define MASK_NO_COND_MOVE 0x00000001 /* disable conditional moves */ - -#define MASK_DEBUG_ARG 0x10000000 /* debug argument handling */ -#define MASK_DEBUG_STACK 0x20000000 /* debug stack allocations */ -#define MASK_DEBUG_ADDR 0x40000000 /* debug GO_IF_LEGITIMATE_ADDRESS */ - -#define TARGET_NO_COND_MOVE (target_flags & MASK_NO_COND_MOVE) -#define TARGET_DEBUG_ARG (target_flags & MASK_DEBUG_ARG) -#define TARGET_DEBUG_STACK (target_flags & MASK_DEBUG_STACK) -#define TARGET_DEBUG_ADDR (target_flags & MASK_DEBUG_ADDR) - -#define TARGET_COND_MOVE (! TARGET_NO_COND_MOVE) - -/* Default switches used. */ -#ifndef TARGET_DEFAULT -#define TARGET_DEFAULT 0 -#endif - -#define TARGET_SWITCHES \ -{ \ - { "cond-move", -MASK_NO_COND_MOVE, \ - N_("Enable use of conditional move instructions") }, \ - \ - { "no-cond-move", MASK_NO_COND_MOVE, \ - N_("Disable use of conditional move instructions") }, \ - \ - { "debug-arg", MASK_DEBUG_ARG, \ - N_("Debug argument support in compiler") }, \ - \ - { "debug-stack", MASK_DEBUG_STACK, \ - N_("Debug stack support in compiler") }, \ - \ - { "debug-addr", MASK_DEBUG_ADDR, \ - N_("Debug memory address support in compiler") }, \ - \ - { "asm-optimize", 0, \ - N_("Make adjacent short instructions parallel if possible") }, \ - \ - { "no-asm-optimize", 0, \ - N_("Do not make adjacent short instructions parallel") }, \ - \ - { "extmem", 0, \ - N_("Link programs/data to be in external memory by default") }, \ - \ - { "extmemory", 0, \ - N_("Link programs/data to be in external memory by default") }, \ - \ - { "onchip", 0, \ - N_("Link programs/data to be in onchip memory by default") }, \ - \ - { "", TARGET_DEFAULT, "" }, \ -} - -#define TARGET_OPTIONS \ -{ \ - {"branch-cost=", &d30v_branch_cost_string, \ - N_("Change the branch costs within the compiler"), 0}, \ - \ - {"cond-exec=", &d30v_cond_exec_string, \ - N_("Change the threshold for conversion to conditional execution"), 0}, \ -} - -#define TARGET_VERSION fprintf (stderr, " d30v") - -#define OVERRIDE_OPTIONS override_options () - -#define CAN_DEBUG_WITHOUT_FP - - -/* Storage Layout */ - -#define BITS_BIG_ENDIAN 1 - -#define BYTES_BIG_ENDIAN 1 - -#define WORDS_BIG_ENDIAN 1 - -#define UNITS_PER_WORD 4 - -#define PROMOTE_MODE(MODE,UNSIGNEDP,TYPE) \ -do { \ - if (GET_MODE_CLASS (MODE) == MODE_INT \ - && GET_MODE_SIZE (MODE) < 4) \ - (MODE) = SImode; \ -} while (0) - -#define PARM_BOUNDARY 32 - -#define STACK_BOUNDARY 64 - -#define FUNCTION_BOUNDARY 64 - -#define BIGGEST_ALIGNMENT 64 - -/* Defined in svr4.h. */ -/* #define MAX_OFILE_ALIGNMENT */ - -#define DATA_ALIGNMENT(TYPE, ALIGN) \ - (TREE_CODE (TYPE) == ARRAY_TYPE \ - && TYPE_MODE (TREE_TYPE (TYPE)) == QImode \ - && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN)) - -#define CONSTANT_ALIGNMENT(EXP, ALIGN) \ - (TREE_CODE (EXP) == STRING_CST \ - && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN)) - -#define STRICT_ALIGNMENT 1 - -/* Defined in svr4.h. */ - -#define PCC_BITFIELD_TYPE_MATTERS 1 - -/* Layout of Source Language Data Types */ - -#define INT_TYPE_SIZE 32 - -#define SHORT_TYPE_SIZE 16 - -#define LONG_TYPE_SIZE 32 - -#define LONG_LONG_TYPE_SIZE 64 - -#define FLOAT_TYPE_SIZE 32 - -#define DOUBLE_TYPE_SIZE 64 - -#define LONG_DOUBLE_TYPE_SIZE 64 - -#define DEFAULT_SIGNED_CHAR 1 - -/* Defined in svr4.h. */ -/* #define SIZE_TYPE */ - -/* Defined in svr4.h. */ -/* #define PTRDIFF_TYPE */ - -/* Defined in svr4.h. */ -/* #define WCHAR_TYPE */ - -/* Defined in svr4.h. */ -/* #define WCHAR_TYPE_SIZE */ - - -/* D30V register layout. */ - -/* Return true if a value is inside a range */ -#define IN_RANGE_P(VALUE, LOW, HIGH) \ - (((unsigned)((VALUE) - (LOW))) <= ((unsigned)((HIGH) - (LOW)))) - -/* General purpose registers. */ -#define GPR_FIRST 0 /* First gpr */ -#define GPR_LAST (GPR_FIRST + 63) /* Last gpr */ -#define GPR_R0 GPR_FIRST /* R0, constant 0 */ -#define GPR_ARG_FIRST (GPR_FIRST + 2) /* R2, first argument reg */ -#define GPR_ARG_LAST (GPR_FIRST + 17) /* R17, last argument reg */ -#define GPR_RET_VALUE GPR_ARG_FIRST /* R2, function return reg */ -#define GPR_ATMP_FIRST (GPR_FIRST + 20) /* R20, tmp to save accs */ -#define GPR_ATMP_LAST (GPR_FIRST + 21) /* R21, tmp to save accs */ -#define GPR_STACK_TMP (GPR_FIRST + 22) /* R22, tmp for saving stack */ -#define GPR_RES_FIRST (GPR_FIRST + 32) /* R32, first reserved reg */ -#define GPR_RES_LAST (GPR_FIRST + 35) /* R35, last reserved reg */ -#define GPR_FP (GPR_FIRST + 61) /* Frame pointer */ -#define GPR_LINK (GPR_FIRST + 62) /* Return address register */ -#define GPR_SP (GPR_FIRST + 63) /* Stack pointer */ - -/* Argument register that is eliminated in favor of the frame and/or stack - pointer. Also add register to point to where the return address is - stored. */ -#define SPECIAL_REG_FIRST (GPR_LAST + 1) -#define SPECIAL_REG_LAST (SPECIAL_REG_FIRST) -#define ARG_POINTER_REGNUM (SPECIAL_REG_FIRST + 0) -#define SPECIAL_REG_P(R) ((R) == SPECIAL_REG_FIRST) - -#define GPR_OR_SPECIAL_REG_P(R) IN_RANGE_P (R, GPR_FIRST, SPECIAL_REG_LAST) -#define GPR_P(R) IN_RANGE_P (R, GPR_FIRST, GPR_LAST) -#define GPR_OR_PSEUDO_P(R) (GPR_OR_SPECIAL_REG_P (R) \ - || (R) >= FIRST_PSEUDO_REGISTER) - -/* Flag bits. */ -#define FLAG_FIRST (SPECIAL_REG_LAST + 1) /* First flag */ -#define FLAG_LAST (FLAG_FIRST + 7) /* Last flag */ -#define FLAG_F0 (FLAG_FIRST) /* F0, used in prediction */ -#define FLAG_F1 (FLAG_FIRST + 1) /* F1, used in prediction */ -#define FLAG_F2 (FLAG_FIRST + 2) /* F2, general flag */ -#define FLAG_F3 (FLAG_FIRST + 3) /* F3, general flag */ -#define FLAG_SAT (FLAG_FIRST + 4) /* F4, saturation flag */ -#define FLAG_OVERFLOW (FLAG_FIRST + 5) /* F5, overflow flag */ -#define FLAG_ACC_OVER (FLAG_FIRST + 6) /* F6, accumulated overflow */ -#define FLAG_CARRY (FLAG_FIRST + 7) /* F7, carry/borrow flag */ -#define FLAG_BORROW FLAG_CARRY - -#define FLAG_P(R) IN_RANGE_P (R, FLAG_FIRST, FLAG_LAST) -#define FLAG_OR_PSEUDO_P(R) (FLAG_P (R) || (R) >= FIRST_PSEUDO_REGISTER) - -#define BR_FLAG_P(R) IN_RANGE_P (R, FLAG_F0, FLAG_F1) -#define BR_FLAG_OR_PSEUDO_P(R) (BR_FLAG_P (R) || (R) >= FIRST_PSEUDO_REGISTER) - -/* Accumulators */ -#define ACCUM_FIRST (FLAG_LAST + 1) /* First accumulator */ -#define ACCUM_A0 ACCUM_FIRST /* Register A0 */ -#define ACCUM_A1 (ACCUM_FIRST + 1) /* Register A1 */ -#define ACCUM_LAST (ACCUM_FIRST + 1) /* Last accumulator */ - -#define ACCUM_P(R) IN_RANGE_P (R, ACCUM_FIRST, ACCUM_LAST) -#define ACCUM_OR_PSEUDO_P(R) (ACCUM_P (R) || (R) >= FIRST_PSEUDO_REGISTER) - -/* Special registers. Note, we only define the registers that can actually - be used. */ -#define CR_FIRST (ACCUM_LAST + 1) /* First CR */ -#define CR_LAST (CR_FIRST + 14) /* Last CR */ -#define CR_PSW (CR_FIRST + 0) /* CR0, Program status word */ -#define CR_BPSW (CR_FIRST + 1) /* CR1, Backup PSW */ -#define CR_PC (CR_FIRST + 2) /* CR2, Program counter */ -#define CR_BPC (CR_FIRST + 3) /* CR3, Backup PC */ -#define CR_DPSW (CR_FIRST + 4) /* CR4, Debug PSW */ -#define CR_DPC (CR_FIRST + 5) /* CR5, Debug PC */ -#define CR_RPT_C (CR_FIRST + 6) /* CR7, loop count register */ -#define CR_RPT_S (CR_FIRST + 7) /* CR8, loop start address */ -#define CR_RPT_E (CR_FIRST + 8) /* CR9, loop end address */ -#define CR_MOD_S (CR_FIRST + 9) /* CR10, modulo address start*/ -#define CR_MOD_E (CR_FIRST + 10) /* CR11, modulo address */ -#define CR_IBA (CR_FIRST + 11) /* CR14, Interrupt break addr */ -#define CR_EIT_VB (CR_FIRST + 12) /* CR15, EIT vector address */ -#define CR_INT_S (CR_FIRST + 13) /* CR16, Interrupt status */ -#define CR_INT_M (CR_FIRST + 14) /* CR17, Interrupt mask */ - -#define CR_P(R) IN_RANGE_P (R, CR_FIRST, CR_LAST) -#define CR_OR_PSEUDO_P(R) (CR_P (R) || (R) >= FIRST_PSEUDO_REGISTER) - - -/* Register Basics */ - -/* Number of hardware registers known to the compiler. They receive numbers 0 - through `FIRST_PSEUDO_REGISTER-1'; thus, the first pseudo register's number - really is assigned the number `FIRST_PSEUDO_REGISTER'. */ -#define FIRST_PSEUDO_REGISTER (CR_LAST + 1) - -/* An initializer that says which registers are used for fixed purposes all - throughout the compiled code and are therefore not available for general - allocation. These would include the stack pointer, the frame pointer - (except on machines where that can be used as a general register when no - frame pointer is needed), the program counter on machines where that is - considered one of the addressable registers, and any other numbered register - with a standard use. - - This information is expressed as a sequence of numbers, separated by commas - and surrounded by braces. The Nth number is 1 if register N is fixed, 0 - otherwise. - - The table initialized from this macro, and the table initialized by the - following one, may be overridden at run time either automatically, by the - actions of the macro `CONDITIONAL_REGISTER_USAGE', or by the user with the - command options `-ffixed-REG', `-fcall-used-REG' and `-fcall-saved-REG'. */ -#define FIXED_REGISTERS \ -{ \ - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* R0 - R15 */ \ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, /* R16 - R31 */ \ - 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* R32 - R47 */ \ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* R48 - R63 */ \ - 1, /* ARG ptr */ \ - 0, 0, 0, 0, 1, 1, 1, 1, /* F0 - F7 */ \ - 0, 0, /* A0 - A1 */ \ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* CRs */ \ -} - -/* Like `FIXED_REGISTERS' but has 1 for each register that is clobbered (in - general) by function calls as well as for fixed registers. This macro - therefore identifies the registers that are not available for general - allocation of values that must live across function calls. - - If a register has 0 in `CALL_USED_REGISTERS', the compiler automatically - saves it on function entry and restores it on function exit, if the register - is used within the function. */ -#define CALL_USED_REGISTERS \ -{ \ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* R0 - R15 */ \ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* R16 - R31 */ \ - 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* R32 - R47 */ \ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* R48 - R63 */ \ - 1, /* ARG ptr */ \ - 1, 1, 1, 1, 1, 1, 1, 1, /* F0 - F7 */ \ - 1, 0, /* A0 - A1 */ \ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* CRs */ \ -} - - -/* Order of allocation of registers */ - -/* If defined, an initializer for a vector of integers, containing the numbers - of hard registers in the order in which GCC should prefer to use them - (from most preferred to least). - - If this macro is not defined, registers are used lowest numbered first (all - else being equal). - - One use of this macro is on machines where the highest numbered registers - must always be saved and the save-multiple-registers instruction supports - only sequences of consecutive registers. On such machines, define - `REG_ALLOC_ORDER' to be an initializer that lists the highest numbered - allocatable register first. */ - -#define REG_ALLOC_ORDER \ -{ \ - /* volatile registers */ \ - GPR_FIRST + 2, GPR_FIRST + 3, GPR_FIRST + 4, GPR_FIRST + 5, \ - GPR_FIRST + 6, GPR_FIRST + 7, GPR_FIRST + 8, GPR_FIRST + 9, \ - GPR_FIRST + 10, GPR_FIRST + 11, GPR_FIRST + 12, GPR_FIRST + 13, \ - GPR_FIRST + 14, GPR_FIRST + 15, GPR_FIRST + 16, GPR_FIRST + 17, \ - GPR_FIRST + 18, GPR_FIRST + 19, GPR_FIRST + 20, GPR_FIRST + 21, \ - GPR_FIRST + 22, GPR_FIRST + 23, GPR_FIRST + 24, GPR_FIRST + 25, \ - GPR_FIRST + 1, \ - \ - /* saved registers */ \ - GPR_FIRST + 34, GPR_FIRST + 35, GPR_FIRST + 36, GPR_FIRST + 37, \ - GPR_FIRST + 38, GPR_FIRST + 39, GPR_FIRST + 40, GPR_FIRST + 41, \ - GPR_FIRST + 42, GPR_FIRST + 43, GPR_FIRST + 44, GPR_FIRST + 45, \ - GPR_FIRST + 46, GPR_FIRST + 47, GPR_FIRST + 48, GPR_FIRST + 49, \ - GPR_FIRST + 50, GPR_FIRST + 51, GPR_FIRST + 52, GPR_FIRST + 53, \ - GPR_FIRST + 54, GPR_FIRST + 55, GPR_FIRST + 56, GPR_FIRST + 57, \ - GPR_FIRST + 58, GPR_FIRST + 59, GPR_FIRST + 60, GPR_FIRST + 61, \ - GPR_FIRST + 62, \ - \ - /* flags */ \ - FLAG_F2, FLAG_F3, FLAG_F0, FLAG_F1, \ - FLAG_SAT, FLAG_OVERFLOW, FLAG_ACC_OVER, FLAG_CARRY, \ - \ - /* accumultors */ \ - ACCUM_FIRST + 0, ACCUM_FIRST + 1, \ - \ - /* fixed registers */ \ - GPR_FIRST + 0, GPR_FIRST + 26, GPR_FIRST + 27, GPR_FIRST + 28, \ - GPR_FIRST + 29, GPR_FIRST + 30, GPR_FIRST + 31, GPR_FIRST + 32, \ - GPR_FIRST + 33, GPR_FIRST + 63, \ - CR_PSW, CR_BPSW, CR_PC, CR_BPC, \ - CR_DPSW, CR_DPC, CR_RPT_C, CR_RPT_S, \ - CR_RPT_E, CR_MOD_S, CR_MOD_E, CR_IBA, \ - CR_EIT_VB, CR_INT_S, CR_INT_M, \ - ARG_POINTER_REGNUM, \ -} - - -/* How Values Fit in Registers */ - -/* A C expression for the number of consecutive hard registers, starting at - register number REGNO, required to hold a value of mode MODE. - - On a machine where all registers are exactly one word, a suitable definition - of this macro is - - #define HARD_REGNO_NREGS(REGNO, MODE) \ - ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) \ - / UNITS_PER_WORD)) */ - -#define HARD_REGNO_NREGS(REGNO, MODE) \ -(ACCUM_P (REGNO) ? ((GET_MODE_SIZE (MODE) + 2*UNITS_PER_WORD - 1) \ - / (2*UNITS_PER_WORD)) \ - : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) \ - / UNITS_PER_WORD)) - -/* A C expression that is nonzero if it is permissible to store a value of mode - MODE in hard register number REGNO (or in several registers starting with - that one). For a machine where all registers are equivalent, a suitable - definition is - - #define HARD_REGNO_MODE_OK(REGNO, MODE) 1 - - It is not necessary for this macro to check for the numbers of fixed - registers, because the allocation mechanism considers them to be always - occupied. - - On some machines, double-precision values must be kept in even/odd register - pairs. The way to implement that is to define this macro to reject odd - register numbers for such modes. - - The minimum requirement for a mode to be OK in a register is that the - `movMODE' instruction pattern support moves between the register and any - other hard register for which the mode is OK; and that moving a value into - the register and back out not alter it. - - Since the same instruction used to move `SImode' will work for all narrower - integer modes, it is not necessary on any machine for `HARD_REGNO_MODE_OK' - to distinguish between these modes, provided you define patterns `movhi', - etc., to take advantage of this. This is useful because of the interaction - between `HARD_REGNO_MODE_OK' and `MODES_TIEABLE_P'; it is very desirable for - all integer modes to be tieable. - - Many machines have special registers for floating point arithmetic. Often - people assume that floating point machine modes are allowed only in floating - point registers. This is not true. Any registers that can hold integers - can safely *hold* a floating point machine mode, whether or not floating - arithmetic can be done on it in those registers. Integer move instructions - can be used to move the values. - - On some machines, though, the converse is true: fixed-point machine modes - may not go in floating registers. This is true if the floating registers - normalize any value stored in them, because storing a non-floating value - there would garble it. In this case, `HARD_REGNO_MODE_OK' should reject - fixed-point machine modes in floating registers. But if the floating - registers do not automatically normalize, if you can store any bit pattern - in one and retrieve it unchanged without a trap, then any machine mode may - go in a floating register, so you can define this macro to say so. - - The primary significance of special floating registers is rather that they - are the registers acceptable in floating point arithmetic instructions. - However, this is of no concern to `HARD_REGNO_MODE_OK'. You handle it by - writing the proper constraints for those instructions. - - On some machines, the floating registers are especially slow to access, so - that it is better to store a value in a stack frame than in such a register - if floating point arithmetic is not being done. As long as the floating - registers are not in class `GENERAL_REGS', they will not be used unless some - pattern's constraint asks for one. */ - -extern unsigned char hard_regno_mode_ok[][FIRST_PSEUDO_REGISTER]; -#define HARD_REGNO_MODE_OK(REGNO, MODE) hard_regno_mode_ok[ (int)MODE ][ REGNO ] - -/* A C expression that is nonzero if it is desirable to choose register - allocation so as to avoid move instructions between a value of mode MODE1 - and a value of mode MODE2. - - If `HARD_REGNO_MODE_OK (R, MODE1)' and `HARD_REGNO_MODE_OK (R, MODE2)' are - ever different for any R, then `MODES_TIEABLE_P (MODE1, MODE2)' must be - zero. */ - -extern unsigned char modes_tieable_p[]; -#define MODES_TIEABLE_P(MODE1, MODE2) \ - modes_tieable_p[ (((int)(MODE1)) * (NUM_MACHINE_MODES)) + (int)(MODE2) ] - -/* Define this macro if the compiler should avoid copies to/from CCmode - registers. You should only define this macro if support fo copying to/from - CCmode is incomplete. */ - -/* On the D30V, copying to/from CCmode is complete, but since there are only - two CC registers usable for conditional tests, this helps gcse not compound - the reload problem. */ -#define AVOID_CCMODE_COPIES - - -/* Register Classes */ - -/* An enumeral type that must be defined with all the register class names as - enumeral values. `NO_REGS' must be first. `ALL_REGS' must be the last - register class, followed by one more enumeral value, `LIM_REG_CLASSES', - which is not a register class but rather tells how many classes there are. - - Each register class has a number, which is the value of casting the class - name to type `int'. The number serves as an index in many of the tables - described below. */ -enum reg_class -{ - NO_REGS, - REPEAT_REGS, - CR_REGS, - ACCUM_REGS, - OTHER_FLAG_REGS, - F0_REGS, - F1_REGS, - BR_FLAG_REGS, - FLAG_REGS, - EVEN_REGS, - GPR_REGS, - ALL_REGS, - LIM_REG_CLASSES -}; - -#define GENERAL_REGS GPR_REGS - -/* The number of distinct register classes, defined as follows: - - #define N_REG_CLASSES (int) LIM_REG_CLASSES */ -#define N_REG_CLASSES ((int) LIM_REG_CLASSES) - -/* An initializer containing the names of the register classes as C string - constants. These names are used in writing some of the debugging dumps. */ -#define REG_CLASS_NAMES \ -{ \ - "NO_REGS", \ - "REPEAT_REGS", \ - "CR_REGS", \ - "ACCUM_REGS", \ - "OTHER_FLAG_REGS", \ - "F0_REGS", \ - "F1_REGS", \ - "BR_FLAG_REGS", \ - "FLAG_REGS", \ - "EVEN_REGS", \ - "GPR_REGS", \ - "ALL_REGS", \ -} - -/* Create mask bits for 3rd word of REG_CLASS_CONTENTS */ -#define MASK_WORD3(REG) ((long)1 << ((REG) - 64)) - -#define NO_MASK 0 -#define REPEAT_MASK MASK_WORD3 (CR_RPT_C) -#define CR_MASK (MASK_WORD3 (CR_PSW) | MASK_WORD3 (CR_BPSW) \ - | MASK_WORD3 (CR_PC) | MASK_WORD3 (CR_BPC) \ - | MASK_WORD3 (CR_DPSW) | MASK_WORD3 (CR_DPC) \ - | MASK_WORD3 (CR_RPT_C) | MASK_WORD3 (CR_RPT_S) \ - | MASK_WORD3 (CR_RPT_E) | MASK_WORD3 (CR_MOD_S) \ - | MASK_WORD3 (CR_MOD_E) | MASK_WORD3 (CR_IBA) \ - | MASK_WORD3 (CR_EIT_VB) | MASK_WORD3 (CR_INT_S) \ - | MASK_WORD3 (CR_INT_M)) - -#define ACCUM_MASK (MASK_WORD3 (ACCUM_A0) | MASK_WORD3 (ACCUM_A1)) -#define OTHER_FLAG_MASK (MASK_WORD3 (FLAG_F2) | MASK_WORD3 (FLAG_F3) \ - | MASK_WORD3 (FLAG_SAT) | MASK_WORD3 (FLAG_OVERFLOW) \ - | MASK_WORD3 (FLAG_ACC_OVER) | MASK_WORD3 (FLAG_CARRY)) - -#define F0_MASK MASK_WORD3 (FLAG_F0) -#define F1_MASK MASK_WORD3 (FLAG_F1) -#define BR_FLAG_MASK (F0_MASK | F1_MASK) -#define FLAG_MASK (BR_FLAG_MASK | OTHER_FLAG_MASK) -#define SPECIAL_MASK MASK_WORD3 (ARG_POINTER_REGNUM) - -#define ALL_MASK (CR_MASK | ACCUM_MASK | FLAG_MASK | SPECIAL_MASK) - -/* An initializer containing the contents of the register classes, as integers - which are bit masks. The Nth integer specifies the contents of class N. - The way the integer MASK is interpreted is that register R is in the class - if `MASK & (1 << R)' is 1. - - When the machine has more than 32 registers, an integer does not suffice. - Then the integers are replaced by sub-initializers, braced groupings - containing several integers. Each sub-initializer must be suitable as an - initializer for the type `HARD_REG_SET' which is defined in - `hard-reg-set.h'. */ -#define REG_CLASS_CONTENTS \ -{ \ - { 0x00000000, 0x00000000, NO_MASK }, /* NO_REGS */ \ - { 0x00000000, 0x00000000, REPEAT_MASK }, /* REPEAT_REGS */ \ - { 0x00000000, 0x00000000, CR_MASK }, /* CR_REGS */ \ - { 0x00000000, 0x00000000, ACCUM_MASK }, /* ACCUM_REGS */ \ - { 0x00000000, 0x00000000, OTHER_FLAG_MASK }, /* OTHER_FLAG_REGS */ \ - { 0x00000000, 0x00000000, F0_MASK }, /* F0_REGS */ \ - { 0x00000000, 0x00000000, F1_MASK }, /* F1_REGS */ \ - { 0x00000000, 0x00000000, BR_FLAG_MASK }, /* BR_FLAG_REGS */ \ - { 0x00000000, 0x00000000, FLAG_MASK }, /* FLAG_REGS */ \ - { 0xfffffffc, 0x3fffffff, NO_MASK }, /* EVEN_REGS */ \ - { 0xffffffff, 0xffffffff, SPECIAL_MASK }, /* GPR_REGS */ \ - { 0xffffffff, 0xffffffff, ALL_MASK }, /* ALL_REGS */ \ -} - -/* A C expression whose value is a register class containing hard register - REGNO. In general there is more than one such class; choose a class which - is "minimal", meaning that no smaller class also contains the register. */ - -extern enum reg_class regno_reg_class[FIRST_PSEUDO_REGISTER]; -#define REGNO_REG_CLASS(REGNO) regno_reg_class[ (REGNO) ] - -/* A macro whose definition is the name of the class to which a valid base - register must belong. A base register is one used in an address which is - the register value plus a displacement. */ -#define BASE_REG_CLASS GPR_REGS - -/* A macro whose definition is the name of the class to which a valid index - register must belong. An index register is one used in an address where its - value is either multiplied by a scale factor or added to another register - (as well as added to a displacement). */ -#define INDEX_REG_CLASS GPR_REGS - -/* A C expression which defines the machine-dependent operand constraint - letters for register classes. If CHAR is such a letter, the value should be - the register class corresponding to it. Otherwise, the value should be - `NO_REGS'. The register letter `r', corresponding to class `GENERAL_REGS', - will not be passed to this macro; you do not need to handle it. - - The following letters are unavailable, due to being used as - constraints: - '0'..'9' - '<', '>' - 'E', 'F', 'G', 'H' - 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P' - 'Q', 'R', 'S', 'T', 'U' - 'V', 'X' - 'g', 'i', 'm', 'n', 'o', 'p', 'r', 's' */ - -extern enum reg_class reg_class_from_letter[256]; -#define REG_CLASS_FROM_LETTER(CHAR) reg_class_from_letter[(unsigned char)(CHAR)] - -/* A C expression which is nonzero if register number NUM is suitable for use - as a base register in operand addresses. It may be either a suitable hard - register or a pseudo register that has been allocated such a hard register. */ - -#define REGNO_OK_FOR_BASE_P(NUM) \ -((NUM) < FIRST_PSEUDO_REGISTER \ - ? GPR_P (NUM) \ - : (reg_renumber[NUM] >= 0 && GPR_P (reg_renumber[NUM]))) - - -/* A C expression which is nonzero if register number NUM is suitable for use - as an index register in operand addresses. It may be either a suitable hard - register or a pseudo register that has been allocated such a hard register. - - The difference between an index register and a base register is that the - index register may be scaled. If an address involves the sum of two - registers, neither one of them scaled, then either one may be labeled the - "base" and the other the "index"; but whichever labeling is used must fit - the machine's constraints of which registers may serve in each capacity. - The compiler will try both labelings, looking for one that is valid, and - will reload one or both registers only if neither labeling works. */ - -#define REGNO_OK_FOR_INDEX_P(NUM) \ -((NUM) < FIRST_PSEUDO_REGISTER \ - ? GPR_P (NUM) \ - : (reg_renumber[NUM] >= 0 && GPR_P (reg_renumber[NUM]))) - -/* A C expression that places additional restrictions on the register class to - use when it is necessary to copy value X into a register in class CLASS. - The value is a register class; perhaps CLASS, or perhaps another, smaller - class. On many machines, the following definition is safe: - - #define PREFERRED_RELOAD_CLASS(X,CLASS) CLASS - - Sometimes returning a more restrictive class makes better code. For - example, on the 68000, when X is an integer constant that is in range for a - `moveq' instruction, the value of this macro is always `DATA_REGS' as long - as CLASS includes the data registers. Requiring a data register guarantees - that a `moveq' will be used. - - If X is a `const_double', by returning `NO_REGS' you can force X into a - memory constant. This is useful on certain machines where immediate - floating values cannot be loaded into certain kinds of registers. */ -#define PREFERRED_RELOAD_CLASS(X, CLASS) CLASS - -/* Many machines have some registers that cannot be copied directly to or from - memory or even from other types of registers. An example is the `MQ' - register, which on most machines, can only be copied to or from general - registers, but not memory. Some machines allow copying all registers to and - from memory, but require a scratch register for stores to some memory - locations (e.g., those with symbolic address on the RT, and those with - certain symbolic address on the SPARC when compiling PIC). In some cases, - both an intermediate and a scratch register are required. - - You should define these macros to indicate to the reload phase that it may - need to allocate at least one register for a reload in addition to the - register to contain the data. Specifically, if copying X to a register - CLASS in MODE requires an intermediate register, you should define - `SECONDARY_INPUT_RELOAD_CLASS' to return the largest register class all of - whose registers can be used as intermediate registers or scratch registers. - - If copying a register CLASS in MODE to X requires an intermediate or scratch - register, `SECONDARY_OUTPUT_RELOAD_CLASS' should be defined to return the - largest register class required. If the requirements for input and output - reloads are the same, the macro `SECONDARY_RELOAD_CLASS' should be used - instead of defining both macros identically. - - The values returned by these macros are often `GENERAL_REGS'. Return - `NO_REGS' if no spare register is needed; i.e., if X can be directly copied - to or from a register of CLASS in MODE without requiring a scratch register. - Do not define this macro if it would always return `NO_REGS'. - - If a scratch register is required (either with or without an intermediate - register), you should define patterns for `reload_inM' or `reload_outM', as - required (*note Standard Names::.. These patterns, which will normally be - implemented with a `define_expand', should be similar to the `movM' - patterns, except that operand 2 is the scratch register. - - Define constraints for the reload register and scratch register that contain - a single register class. If the original reload register (whose class is - CLASS) can meet the constraint given in the pattern, the value returned by - these macros is used for the class of the scratch register. Otherwise, two - additional reload registers are required. Their classes are obtained from - the constraints in the insn pattern. - - X might be a pseudo-register or a `subreg' of a pseudo-register, which could - either be in a hard register or in memory. Use `true_regnum' to find out; - it will return -1 if the pseudo is in memory and the hard register number if - it is in a register. - - These macros should not be used in the case where a particular class of - registers can only be copied to memory and not to another class of - registers. In that case, secondary reload registers are not needed and - would not be helpful. Instead, a stack location must be used to perform the - copy and the `movM' pattern should use memory as an intermediate storage. - This case often occurs between floating-point and general registers. */ - -#define SECONDARY_RELOAD_CLASS(CLASS, MODE, X) \ -((CLASS) == GPR_REGS ? NO_REGS \ - : (CLASS) == EVEN_REGS ? NO_REGS \ - : (CLASS) == ACCUM_REGS ? EVEN_REGS \ - : GPR_REGS) - -/* A C expression whose value is nonzero if pseudos that have been assigned to - registers of class CLASS would likely be spilled because registers of CLASS - are needed for spill registers. - - The default value of this macro returns 1 if CLASS has exactly one register - and zero otherwise. On most machines, this default should be used. Only - define this macro to some other expression if pseudo allocated by - `local-alloc.c' end up in memory because their hard registers were needed - for spill registers. If this macro returns nonzero for those classes, those - pseudos will only be allocated by `global.c', which knows how to reallocate - the pseudo to another register. If there would not be another register - available for reallocation, you should not change the definition of this - macro since the only effect of such a definition would be to slow down - register allocation. */ -#define CLASS_LIKELY_SPILLED_P(CLASS) \ - ((CLASS) != GPR_REGS && (CLASS) != EVEN_REGS) - -/* A C expression for the maximum number of consecutive registers of - class CLASS needed to hold a value of mode MODE. - - This is closely related to the macro `HARD_REGNO_NREGS'. In fact, the value - of the macro `CLASS_MAX_NREGS (CLASS, MODE)' should be the maximum value of - `HARD_REGNO_NREGS (REGNO, MODE)' for all REGNO values in the class CLASS. - - This macro helps control the handling of multiple-word values in - the reload pass. */ - -#define CLASS_MAX_NREGS(CLASS, MODE) \ -(((CLASS) == ACCUM_REGS) \ - ? ((GET_MODE_SIZE (MODE) + 8 - 1) / 8) \ - : ((GET_MODE_SIZE (MODE) + 4 - 1) / 4)) - -/* A C expression that defines the machine-dependent operand constraint letters - (`I', `J', `K', .. 'P') that specify particular ranges of integer values. - If C is one of those letters, the expression should check that VALUE, an - integer, is in the appropriate range and return 1 if so, 0 otherwise. If C - is not one of those letters, the value should be 0 regardless of VALUE. */ -#define CONST_OK_FOR_LETTER_P(VALUE, C) \ -((C) == 'I' ? IN_RANGE_P (VALUE, -32, 31) \ - : (C) == 'J' ? IN_RANGE_P (VALUE, 0, 31) \ - : (C) == 'K' ? IN_RANGE_P (exact_log2 (VALUE), 0, 31) \ - : (C) == 'L' ? IN_RANGE_P (exact_log2 (~ (VALUE)), 0, 31) \ - : (C) == 'M' ? ((VALUE) == 32) \ - : (C) == 'N' ? ((VALUE) == 1) \ - : (C) == 'O' ? ((VALUE) == 0) \ - : (C) == 'P' ? IN_RANGE_P (VALUE, 32, 63) \ - : FALSE) - -/* A C expression that defines the machine-dependent operand constraint letters - (`G', `H') that specify particular ranges of `const_double' values. - - If C is one of those letters, the expression should check that VALUE, an RTX - of code `const_double', is in the appropriate range and return 1 if so, 0 - otherwise. If C is not one of those letters, the value should be 0 - regardless of VALUE. - - `const_double' is used for all floating-point constants and for `DImode' - fixed-point constants. A given letter can accept either or both kinds of - values. It can use `GET_MODE' to distinguish between these kinds. */ -#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \ -((C) == 'G' ? (CONST_DOUBLE_LOW (VALUE) == 0 \ - && CONST_DOUBLE_HIGH (VALUE) == 0) \ - : (C) == 'H' ? FALSE \ - : FALSE) - -/* A C expression that defines the optional machine-dependent constraint - letters (`Q', `R', `S', `T', `U') that can be used to segregate specific - types of operands, usually memory references, for the target machine. - Normally this macro will not be defined. If it is required for a particular - target machine, it should return 1 if VALUE corresponds to the operand type - represented by the constraint letter C. If C is not defined as an extra - constraint, the value returned should be 0 regardless of VALUE. - - For example, on the ROMP, load instructions cannot have their output in r0 - if the memory reference contains a symbolic address. Constraint letter `Q' - is defined as representing a memory address that does *not* contain a - symbolic address. An alternative is specified with a `Q' constraint on the - input and `r' on the output. The next alternative specifies `m' on the - input and a register class that does not include r0 on the output. */ - -#define EXTRA_CONSTRAINT(VALUE, C) \ -(((C) == 'Q') ? short_memory_operand ((VALUE), GET_MODE (VALUE)) \ - : ((C) == 'R') ? single_reg_memory_operand ((VALUE), GET_MODE (VALUE)) \ - : ((C) == 'S') ? const_addr_memory_operand ((VALUE), GET_MODE (VALUE)) \ - : ((C) == 'T') ? long_memory_operand ((VALUE), GET_MODE (VALUE)) \ - : ((C) == 'U') ? FALSE \ - : FALSE) - - -/* Basic Stack Layout */ - -/* Stack layout */ - -/* Structure used to define the d30v stack */ -typedef struct d30v_stack { - int varargs_p; /* whether this is a varargs function */ - int varargs_size; /* size to hold varargs args passed in regs */ - int vars_size; /* variable save area size */ - int parm_size; /* outgoing parameter size */ - int gpr_size; /* size of saved GPR registers */ - int accum_size; /* size of saved ACCUM registers */ - int total_size; /* total bytes allocated for stack */ - /* which registers are to be saved */ - int save_offset; /* offset from new sp to start saving vars at */ - int link_offset; /* offset r62 is saved at */ - int memrefs_varargs; /* # of 2 word memory references for varargs */ - int memrefs_2words; /* # of 2 word memory references */ - int memrefs_1word; /* # of 1 word memory references */ - /* 1 for ldw/stw ops; 2 for ld2w/st2w ops */ - unsigned char save_p[FIRST_PSEUDO_REGISTER]; -} d30v_stack_t; - -/* Define this macro if pushing a word onto the stack moves the stack pointer - to a smaller address. - - When we say, "define this macro if ...," it means that the compiler checks - this macro only with `#ifdef' so the precise definition used does not - matter. */ -#define STACK_GROWS_DOWNWARD 1 - -/* Offset from the frame pointer to the first local variable slot to be - allocated. - - If `FRAME_GROWS_DOWNWARD', find the next slot's offset by subtracting the - first slot's length from `STARTING_FRAME_OFFSET'. Otherwise, it is found by - adding the length of the first slot to the value `STARTING_FRAME_OFFSET'. */ - -#define STARTING_FRAME_OFFSET \ - (D30V_ALIGN (current_function_outgoing_args_size, \ - (STACK_BOUNDARY / BITS_PER_UNIT))) - -/* Offset from the argument pointer register to the first argument's address. - On some machines it may depend on the data type of the function. - - If `ARGS_GROW_DOWNWARD', this is the offset to the location above the first - argument's address. */ -#define FIRST_PARM_OFFSET(FUNDECL) 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, after the - prologue. FRAMEADDR is the frame pointer of the COUNT frame, or the frame - pointer of the COUNT - 1 frame if `RETURN_ADDR_IN_PREVIOUS_FRAME' is - defined. - - The value of the expression must always be the correct address when COUNT is - zero, but may be `NULL_RTX' if there is not way to determine the return - address of other frames. */ - -/* ??? This definition fails for leaf functions. There is currently no - general solution for this problem. */ - -/* ??? There appears to be no way to get the return address of any previous - frame except by disassembling instructions in the prologue/epilogue. - So currently we support only the current frame. */ - -#define RETURN_ADDR_RTX(COUNT, FRAME) \ - ((COUNT) == 0 ? d30v_return_addr() : const0_rtx) - -/* A C expression whose value is RTL representing the location of the incoming - return address at the beginning of any function, before the prologue. This - RTL is either a `REG', indicating that the return value is saved in `REG', - or a `MEM' representing a location in the stack. - - You only need to define this macro if you want to support call frame - debugging information like that provided by DWARF 2. */ - -/* Before the prologue, RA lives in r62. */ -#define INCOMING_RETURN_ADDR_RTX gen_rtx (REG, Pmode, GPR_LINK) - -/* A C expression whose value is an integer giving the offset, in bytes, from - the value of the stack pointer register to the top of the stack frame at the - beginning of any function, before the prologue. The top of the frame is - defined to be the value of the stack pointer in the previous frame, just - before the call instruction. - - You only need to define this macro if you want to support call frame - debugging information like that provided by DWARF 2. */ -#define INCOMING_FRAME_SP_OFFSET 0 - -/* Initialize data used by insn expanders. This is called from insn_emit, - once for every function before code is generated. */ - -#define INIT_EXPANDERS d30v_init_expanders () - - -/* Register That Address the Stack Frame. */ - -/* The register number of the stack pointer register, which must also be a - fixed register according to `FIXED_REGISTERS'. On most machines, the - hardware determines which register this is. */ -#define STACK_POINTER_REGNUM GPR_SP - -/* The register number of the frame pointer register, which is used to access - automatic variables in the stack frame. On some machines, the hardware - determines which register this is. On other machines, you can choose any - register you wish for this purpose. */ -#define FRAME_POINTER_REGNUM GPR_FP - -/* Register numbers used for passing a function's static chain pointer. If - register windows are used, the register number as seen by the called - function is `STATIC_CHAIN_INCOMING_REGNUM', while the register number as - seen by the calling function is `STATIC_CHAIN_REGNUM'. If these registers - are the same, `STATIC_CHAIN_INCOMING_REGNUM' need not be defined. - - The static chain register need not be a fixed register. - - If the static chain is passed in memory, these macros should not be defined; - instead, the next two macros should be defined. */ - -#define STATIC_CHAIN_REGNUM (GPR_FIRST + 18) - - -/* Eliminating the Frame Pointer and the Arg Pointer */ - -/* A C expression which is nonzero if a function must have and use a frame - pointer. This expression is evaluated in the reload pass. If its value is - nonzero the function will have a frame pointer. - - The expression can in principle examine the current function and decide - according to the facts, but on most machines the constant 0 or the constant - 1 suffices. Use 0 when the machine allows code to be generated with no - frame pointer, and doing so saves some time or space. Use 1 when there is - no possible advantage to avoiding a frame pointer. - - In certain cases, the compiler does not know how to produce valid code - without a frame pointer. The compiler recognizes those cases and - automatically gives the function a frame pointer regardless of what - `FRAME_POINTER_REQUIRED' says. You don't need to worry about them. - - In a function that does not require a frame pointer, the frame pointer - register can be allocated for ordinary usage, unless you mark it as a fixed - register. See `FIXED_REGISTERS' for more information. */ -#define FRAME_POINTER_REQUIRED 0 - -/* If defined, this macro specifies a table of register pairs used to eliminate - unneeded registers that point into the stack frame. If it is not defined, - the only elimination attempted by the compiler is to replace references to - the frame pointer with references to the stack pointer. - - The definition of this macro is a list of structure initializations, each of - which specifies an original and replacement register. - - On some machines, the position of the argument pointer is not known until - the compilation is completed. In such a case, a separate hard register must - be used for the argument pointer. This register can be eliminated by - replacing it with either the frame pointer or the argument pointer, - depending on whether or not the frame pointer has been eliminated. - - In this case, you might specify: - #define ELIMINABLE_REGS \ - {{ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ - {ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \ - {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}} - - Note that the elimination of the argument pointer with the stack pointer is - specified first since that is the preferred elimination. */ -#define ELIMINABLE_REGS \ -{ \ - { ARG_POINTER_REGNUM, STACK_POINTER_REGNUM }, \ - { ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM }, \ - { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM } \ -} - -/* A C expression that returns nonzero if the compiler is allowed to try to - replace register number FROM-REG with register number TO-REG. This macro - need only be defined if `ELIMINABLE_REGS' is defined, and will usually be - the constant 1, since most of the cases preventing register elimination are - things that the compiler already knows about. */ - -#define CAN_ELIMINATE(FROM, TO) \ - ((FROM) == ARG_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM \ - ? ! frame_pointer_needed \ - : 1) - -/* This macro is similar to `INITIAL_FRAME_POINTER_OFFSET'. It specifies the - initial difference between the specified pair of registers. This macro must - be defined if `ELIMINABLE_REGS' is defined. */ - -#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \ -{ \ - d30v_stack_t *info = d30v_stack_info (); \ - \ - if ((FROM) == FRAME_POINTER_REGNUM) \ - (OFFSET) = 0; \ - else if ((FROM) == ARG_POINTER_REGNUM) \ - (OFFSET) = info->total_size - current_function_pretend_args_size; \ - else \ - abort (); \ -} - - -/* Passing Function Arguments on the Stack */ - -/* If defined, the maximum amount of space required for outgoing arguments will - be computed and placed into the variable - `current_function_outgoing_args_size'. No space will be pushed onto the - stack for each call; instead, the function prologue should increase the - stack frame size by this amount. - - Defining both `PUSH_ROUNDING' and `ACCUMULATE_OUTGOING_ARGS' is not - proper. */ -#define ACCUMULATE_OUTGOING_ARGS 1 - -/* A C expression that should indicate the number of bytes of its own arguments - that a function pops on returning, or 0 if the function pops no arguments - and the caller must therefore pop them all after the function returns. - - FUNDECL is a C variable whose value is a tree node that describes the - function in question. Normally it is a node of type `FUNCTION_DECL' that - describes the declaration of the function. From this it is possible to - obtain the DECL_ATTRIBUTES of the function. - - FUNTYPE is a C variable whose value is a tree node that describes the - function in question. Normally it is a node of type `FUNCTION_TYPE' that - describes the data type of the function. From this it is possible to obtain - the data types of the value and arguments (if known). - - When a call to a library function is being considered, FUNTYPE will contain - an identifier node for the library function. Thus, if you need to - distinguish among various library functions, you can do so by their names. - Note that "library function" in this context means a function used to - perform arithmetic, whose name is known specially in the compiler and was - not mentioned in the C code being compiled. - - STACK-SIZE is the number of bytes of arguments passed on the stack. If a - variable number of bytes is passed, it is zero, and argument popping will - always be the responsibility of the calling function. - - On the VAX, all functions always pop their arguments, so the definition of - this macro is STACK-SIZE. On the 68000, using the standard calling - convention, no functions pop their arguments, so the value of the macro is - always 0 in this case. But an alternative calling convention is available - in which functions that take a fixed number of arguments pop them but other - functions (such as `printf') pop nothing (the caller pops all). When this - convention is in use, FUNTYPE is examined to determine whether a function - takes a fixed number of arguments. */ -#define RETURN_POPS_ARGS(FUNDECL, FUNTYPE, STACK_SIZE) 0 - - -/* Function Arguments in Registers */ - -/* A C expression that controls whether a function argument is passed in a - register, and which register. - - The arguments are CUM, which summarizes all the previous arguments; MODE, - the machine mode of the argument; TYPE, the data type of the argument as a - tree node or 0 if that is not known (which happens for C support library - functions); and NAMED, which is 1 for an ordinary argument and 0 for - nameless arguments that correspond to `...' in the called function's - prototype. - - The value of the expression should either be a `reg' RTX for the hard - register in which to pass the argument, or zero to pass the argument on the - stack. - - For machines like the VAX and 68000, where normally all arguments are - pushed, zero suffices as a definition. - - The usual way to make the ANSI library `stdarg.h' work on a machine where - some arguments are usually passed in registers, is to cause nameless - arguments to be passed on the stack instead. This is done by making - `FUNCTION_ARG' return 0 whenever NAMED is 0. - - You may use the macro `MUST_PASS_IN_STACK (MODE, TYPE)' in the definition of - this macro to determine if this argument is of a type that must be passed in - the stack. If `REG_PARM_STACK_SPACE' is not defined and `FUNCTION_ARG' - returns nonzero for such an argument, the compiler will abort. If - `REG_PARM_STACK_SPACE' is defined, the argument will be computed in the - stack and then loaded into a register. */ - -#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ - d30v_function_arg (&CUM, (int)MODE, TYPE, NAMED, FALSE) - -/* Define this macro if the target machine has "register windows", so that the - register in which a function sees an arguments is not necessarily the same - as the one in which the caller passed the argument. - - For such machines, `FUNCTION_ARG' computes the register in which the caller - passes the value, and `FUNCTION_INCOMING_ARG' should be defined in a similar - fashion to tell the function being called where the arguments will arrive. - - If `FUNCTION_INCOMING_ARG' is not defined, `FUNCTION_ARG' serves both - purposes. */ - -#define FUNCTION_INCOMING_ARG(CUM, MODE, TYPE, NAMED) \ - d30v_function_arg (&CUM, (int)MODE, TYPE, NAMED, TRUE) - -/* A C expression for the number of words, at the beginning of an argument, - must be put in registers. The value must be zero for arguments that are - passed entirely in registers or that are entirely pushed on the stack. - - On some machines, certain arguments must be passed partially in registers - and partially in memory. On these machines, typically the first N words of - arguments are passed in registers, and the rest on the stack. If a - multi-word argument (a `double' or a structure) crosses that boundary, its - first few words must be passed in registers and the rest must be pushed. - This macro tells the compiler when this occurs, and how many of the words - should go in registers. - - `FUNCTION_ARG' for these arguments should return the first register to be - used by the caller for this argument; likewise `FUNCTION_INCOMING_ARG', for - the called function. */ -#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \ - d30v_function_arg_partial_nregs (&CUM, (int)MODE, TYPE, NAMED) - -/* A C expression that indicates when an argument must be passed by reference. - If nonzero for an argument, a copy of that argument is made in memory and a - pointer to the argument is passed instead of the argument itself. The - pointer is passed in whatever way is appropriate for passing a pointer to - that type. - - On machines where `REG_PARM_STACK_SPACE' is not defined, a suitable - definition of this macro might be - #define FUNCTION_ARG_PASS_BY_REFERENCE\ - (CUM, MODE, TYPE, NAMED) \ - MUST_PASS_IN_STACK (MODE, TYPE) */ -#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) 0 - -/* A C type for declaring a variable that is used as the first argument of - `FUNCTION_ARG' and other related values. For some target machines, the type - `int' suffices and can hold the number of bytes of argument so far. - - There is no need to record in `CUMULATIVE_ARGS' anything about the arguments - that have been passed on the stack. The compiler has other variables to - keep track of that. For target machines on which all arguments are passed - on the stack, there is no need to store anything in `CUMULATIVE_ARGS'; - however, the data structure must exist and should not be empty, so use - `int'. */ -#define CUMULATIVE_ARGS int - -/* A C statement (sans semicolon) for initializing the variable CUM for the - state at the beginning of the argument list. The variable has type - `CUMULATIVE_ARGS'. The value of FNTYPE is the tree node for the data type - of the function which will receive the args, or 0 if the args are to a - compiler support library function. The value of INDIRECT is nonzero when - processing an indirect call, for example a call through a function pointer. - The value of INDIRECT is zero for a call to an explicitly named function, a - library function call, or when `INIT_CUMULATIVE_ARGS' is used to find - arguments for the function being compiled. - - When processing a call to a compiler support library function, LIBNAME - identifies which one. It is a `symbol_ref' rtx which contains the name of - the function, as a string. LIBNAME is 0 when an ordinary C function call is - being processed. Thus, each time this macro is called, either LIBNAME or - FNTYPE is nonzero, but never both of them at once. */ - -#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, FNDECL) \ - d30v_init_cumulative_args (&CUM, FNTYPE, LIBNAME, FNDECL, FALSE) - -/* Like `INIT_CUMULATIVE_ARGS' but overrides it for the purposes of finding the - arguments for the function being compiled. If this macro is undefined, - `INIT_CUMULATIVE_ARGS' is used instead. - - The value passed for LIBNAME is always 0, since library routines with - special calling conventions are never compiled with GCC. The argument - LIBNAME exists for symmetry with `INIT_CUMULATIVE_ARGS'. */ - -#define INIT_CUMULATIVE_INCOMING_ARGS(CUM, FNTYPE, LIBNAME) \ - d30v_init_cumulative_args (&CUM, FNTYPE, LIBNAME, NULL, TRUE) - -/* A C statement (sans semicolon) to update the summarizer variable CUM to - advance past an argument in the argument list. The values MODE, TYPE and - NAMED describe that argument. Once this is done, the variable CUM is - suitable for analyzing the *following* argument with `FUNCTION_ARG', etc. - - This macro need not do anything if the argument in question was passed on - the stack. The compiler knows how to track the amount of stack space used - for arguments without any special help. */ - -#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ - d30v_function_arg_advance (&CUM, (int) MODE, TYPE, NAMED) - -/* If defined, a C expression that gives the alignment boundary, in bits, of an - argument with the specified mode and type. If it is not defined, - `PARM_BOUNDARY' is used for all arguments. */ - -#define FUNCTION_ARG_BOUNDARY(MODE, TYPE) \ - d30v_function_arg_boundary ((int) MODE, TYPE) - -/* A C expression that is nonzero if REGNO is the number of a hard register in - which function arguments are sometimes passed. This does *not* include - implicit arguments such as the static chain and the structure-value address. - On many machines, no registers can be used for this purpose since all - function arguments are pushed on the stack. */ - -#define FUNCTION_ARG_REGNO_P(REGNO) \ - IN_RANGE_P (REGNO, GPR_ARG_FIRST, GPR_ARG_LAST) - - -/* How Scalar Function Values are Returned */ - -/* A C expression to create an RTX representing the place where a function - returns a value of data type VALTYPE. VALTYPE is a tree node representing a - data type. Write `TYPE_MODE (VALTYPE)' to get the machine mode used to - represent that type. On many machines, only the mode is relevant. - (Actually, on most machines, scalar values are returned in the same place - regardless of mode). - - If `PROMOTE_FUNCTION_RETURN' is defined, you must apply the same promotion - rules specified in `PROMOTE_MODE' if VALTYPE is a scalar type. - - If the precise function being called is known, FUNC is a tree node - (`FUNCTION_DECL') for it; otherwise, FUNC is a null pointer. This makes it - possible to use a different value-returning convention for specific - functions when all their calls are known. - - `FUNCTION_VALUE' is not used for return vales with aggregate data types, - because these are returned in another way. See `STRUCT_VALUE_REGNUM' and - related macros, below. */ - -#define FUNCTION_VALUE(VALTYPE, FUNC) \ - gen_rtx (REG, TYPE_MODE (VALTYPE), GPR_RET_VALUE) - -/* A C expression to create an RTX representing the place where a library - function returns a value of mode MODE. If the precise function being called - is known, FUNC is a tree node (`FUNCTION_DECL') for it; otherwise, FUNC is a - null pointer. This makes it possible to use a different value-returning - convention for specific functions when all their calls are known. - - Note that "library function" in this context means a compiler support - routine, used to perform arithmetic, whose name is known specially by the - compiler and was not mentioned in the C code being compiled. - - The definition of `LIBRARY_VALUE' need not be concerned aggregate data - types, because none of the library functions returns such types. */ - -#define LIBCALL_VALUE(MODE) gen_rtx (REG, MODE, GPR_RET_VALUE) - -/* A C expression that is nonzero if REGNO is the number of a hard register in - which the values of called function may come back. - - A register whose use for returning values is limited to serving as the - second of a pair (for a value of type `double', say) need not be recognized - by this macro. So for most machines, this definition suffices: - - #define FUNCTION_VALUE_REGNO_P(N) ((N) == 0) - - If the machine has register windows, so that the caller and the called - function use different registers for the return value, this macro should - recognize only the caller's register numbers. */ - -#define FUNCTION_VALUE_REGNO_P(REGNO) ((REGNO) == GPR_RET_VALUE) - - -/* How Large Values are Returned */ - -/* If the structure value address is passed in a register, then - `STRUCT_VALUE_REGNUM' should be the number of that register. */ - -#define STRUCT_VALUE_REGNUM GPR_ARG_FIRST - -/* If the structure value address is not passed in a register, define - `STRUCT_VALUE' as an expression returning an RTX for the place where the - address is passed. If it returns 0, the address is passed as an "invisible" - first argument. */ - -#define STRUCT_VALUE 0 - - -/* Define this macro as a C expression that is nonzero for registers - are used by the epilogue or the `return' pattern. The stack and - frame pointer registers are already be assumed to be used as - needed. */ -#define EPILOGUE_USES(REGNO) ((REGNO) == GPR_LINK) - -/* A C structure for machine-specific, per-function data. - This is added to the cfun structure. */ -typedef struct machine_function GTY(()) -{ - /* Additionsl stack adjustment in __builtin_eh_throw. */ - rtx eh_epilogue_sp_ofs; -} machine_function; - - -/* Generating Code for Profiling. */ - -/* A C statement or compound statement to output to FILE some assembler code to - call the profiling subroutine `mcount'. Before calling, the assembler code - must load the address of a counter variable into a register where `mcount' - expects to find the address. The name of this variable is `LP' followed by - the number LABELNO, so you would generate the name using `LP%d' in a - `fprintf'. - - The details of how the address should be passed to `mcount' are determined - by your operating system environment, not by GCC. To figure them out, - compile a small program for profiling using the system's installed C - compiler and look at the assembler code that results. */ - -#define FUNCTION_PROFILER(FILE, LABELNO) d30v_function_profiler (FILE, LABELNO) - - -/* Implementing the Varargs Macros. */ - -/* If defined, is a C expression that produces the machine-specific code for a - call to `__builtin_saveregs'. This code will be moved to the very beginning - of the function, before any parameter access are made. The return value of - this function should be an RTX that contains the value to use as the return - of `__builtin_saveregs'. - - If this macro is not defined, the compiler will output an ordinary call to - the library function `__builtin_saveregs'. */ - -#define EXPAND_BUILTIN_SAVEREGS() d30v_expand_builtin_saveregs () - -/* This macro offers an alternative to using `__builtin_saveregs' and defining - the macro `EXPAND_BUILTIN_SAVEREGS'. Use it to store the anonymous register - arguments into the stack so that all the arguments appear to have been - passed consecutively on the stack. Once this is done, you can use the - standard implementation of varargs that works for machines that pass all - their arguments on the stack. - - The argument ARGS_SO_FAR is the `CUMULATIVE_ARGS' data structure, containing - the values that obtain after processing of the named arguments. The - arguments MODE and TYPE describe the last named argument--its machine mode - and its data type as a tree node. - - The macro implementation should do two things: first, push onto the stack - all the argument registers *not* used for the named arguments, and second, - store the size of the data thus pushed into the `int'-valued variable whose - name is supplied as the argument PRETEND_ARGS_SIZE. The value that you - store here will serve as additional offset for setting up the stack frame. - - Because you must generate code to push the anonymous arguments at compile - time without knowing their data types, `SETUP_INCOMING_VARARGS' is only - useful on machines that have just a single category of argument register and - use it uniformly for all data types. - - If the argument SECOND_TIME is nonzero, it means that the arguments of the - function are being analyzed for the second time. This happens for an inline - function, which is not actually compiled until the end of the source file. - The macro `SETUP_INCOMING_VARARGS' should not generate any instructions in - this case. */ - -#define SETUP_INCOMING_VARARGS(ARGS_SO_FAR, MODE, TYPE, PRETEND_ARGS_SIZE, SECOND_TIME) \ - d30v_setup_incoming_varargs (&ARGS_SO_FAR, (int) MODE, TYPE, \ - &PRETEND_ARGS_SIZE, SECOND_TIME) - -/* Implement the stdarg/varargs va_start macro. STDARG_P is nonzero if this - is stdarg.h instead of varargs.h. VALIST is the tree of the va_list - variable to initialize. NEXTARG is the machine independent notion of the - 'next' argument after the variable arguments. If not defined, a standard - implementation will be defined that works for arguments passed on the stack. */ - -#define EXPAND_BUILTIN_VA_START(VALIST, NEXTARG) \ - d30v_expand_builtin_va_start(VALIST, NEXTARG) - -/* Implement the stdarg/varargs va_arg macro. VALIST is the variable of type - va_list as a tree, TYPE is the type passed to va_arg. */ - -#define EXPAND_BUILTIN_VA_ARG(VALIST, TYPE) \ -(d30v_expand_builtin_va_arg (VALIST, TYPE)) - -/* Trampolines for Nested Functions. */ - -/* A C expression for the size in bytes of the trampoline, as an integer. */ -#define TRAMPOLINE_SIZE (d30v_trampoline_size ()) - -/* Alignment required for trampolines, in bits. - - If you don't define this macro, the value of `BIGGEST_ALIGNMENT' is used for - aligning trampolines. */ -#define TRAMPOLINE_ALIGNMENT 64 - -/* A C statement to initialize the variable parts of a trampoline. ADDR is an - RTX for the address of the trampoline; FNADDR is an RTX for the address of - the nested function; STATIC_CHAIN is an RTX for the static chain value that - should be passed to the function when it is called. */ -#define INITIALIZE_TRAMPOLINE(ADDR, FNADDR, STATIC_CHAIN) \ - d30v_initialize_trampoline (ADDR, FNADDR, STATIC_CHAIN) - - -/* Addressing Modes */ - -/* Define this macro if the machine supports post-increment addressing. */ -#define HAVE_POST_INCREMENT 1 - -/* Similar for other kinds of addressing. */ -#define HAVE_POST_DECREMENT 1 - -/* A C expression that is 1 if the RTX X is a constant which is a valid - address. On most machines, this can be defined as `CONSTANT_P (X)', but a - few machines are more restrictive in which constant addresses are supported. - - `CONSTANT_P' accepts integer-values expressions whose values are not - explicitly known, such as `symbol_ref', `label_ref', and `high' expressions - and `const' arithmetic expressions, in addition to `const_int' and - `const_double' expressions. */ -#define CONSTANT_ADDRESS_P(X) CONSTANT_P (X) - -/* A number, the maximum number of registers that can appear in a valid memory - address. Note that it is up to you to specify a value equal to the maximum - number that `GO_IF_LEGITIMATE_ADDRESS' would ever accept. */ -#define MAX_REGS_PER_ADDRESS 2 - -/* A C compound statement with a conditional `goto LABEL;' executed if X (an - RTX) is a legitimate memory address on the target machine for a memory - operand of mode MODE. */ - -#ifdef REG_OK_STRICT -#define REG_OK_STRICT_P 1 -#else -#define REG_OK_STRICT_P 0 -#endif - -#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ -do { \ - if (d30v_legitimate_address_p ((int)MODE, X, REG_OK_STRICT_P)) \ - goto ADDR; \ -} while (0) - -/* A C expression that is nonzero if X (assumed to be a `reg' RTX) is valid for - use as a base register. For hard registers, it should always accept those - which the hardware permits and reject the others. Whether the macro accepts - or rejects pseudo registers must be controlled by `REG_OK_STRICT' as - described above. This usually requires two variant definitions, of which - `REG_OK_STRICT' controls the one actually used. */ - -#ifdef REG_OK_STRICT -#define REG_OK_FOR_BASE_P(X) (GPR_P (REGNO (X))) -#else -#define REG_OK_FOR_BASE_P(X) (GPR_OR_PSEUDO_P (REGNO (X))) -#endif - -/* A C expression that is nonzero if X (assumed to be a `reg' RTX) is valid for - use as an index register. - - The difference between an index register and a base register is that the - index register may be scaled. If an address involves the sum of two - registers, neither one of them scaled, then either one may be labeled the - "base" and the other the "index"; but whichever labeling is used must fit - the machine's constraints of which registers may serve in each capacity. - The compiler will try both labelings, looking for one that is valid, and - will reload one or both registers only if neither labeling works. */ - -#define REG_OK_FOR_INDEX_P(X) REG_OK_FOR_BASE_P (X) - -/* A C compound statement that attempts to replace X with a valid memory - address for an operand of mode MODE. WIN will be a C statement label - elsewhere in the code; the macro definition may use - - GO_IF_LEGITIMATE_ADDRESS (MODE, X, WIN); - - to avoid further processing if the address has become legitimate. - - X will always be the result of a call to `break_out_memory_refs', and OLDX - will be the operand that was given to that function to produce X. - - The code generated by this macro should not alter the substructure of X. If - it transforms X into a more legitimate form, it should assign X (which will - always be a C variable) a new value. - - It is not necessary for this macro to come up with a legitimate address. - The compiler has standard ways of doing so in all cases. In fact, it is - safe for this macro to do nothing. But often a machine-dependent strategy - can generate better code. */ - -#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \ -do { \ - rtx y = d30v_legitimize_address (X, OLDX, (int)MODE, REG_OK_STRICT_P); \ - if (y) \ - { \ - X = y; \ - GO_IF_LEGITIMATE_ADDRESS (MODE, X, WIN); \ - } \ -} while (0) - -/* A C statement or compound statement with a conditional `goto LABEL;' - executed if memory address X (an RTX) can have different meanings depending - on the machine mode of the memory reference it is used for or if the address - is valid for some modes but not others. - - Autoincrement and autodecrement addresses typically have mode-dependent - effects because the amount of the increment or decrement is the size of the - operand being addressed. Some machines have other mode-dependent addresses. - Many RISC machines have no mode-dependent addresses. - - You may assume that ADDR is a valid address for the machine. */ - -#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL) \ -do { \ - if (d30v_mode_dependent_address_p (ADDR)) \ - goto LABEL; \ -} while (0) \ - -/* A C expression that is nonzero if X is a legitimate constant for an - immediate operand on the target machine. You can assume that X satisfies - `CONSTANT_P', so you need not check this. In fact, `1' is a suitable - definition for this macro on machines where anything `CONSTANT_P' is valid. */ -#define LEGITIMATE_CONSTANT_P(X) 1 - - -/* Describing Relative Costs of Operations */ - -/* A C expression for the cost of moving data from a register in class FROM to - one in class TO. The classes are expressed using the enumeration values - such as `GENERAL_REGS'. A value of 4 is the default; other values are - interpreted relative to that. - - It is not required that the cost always equal 2 when FROM is the same as TO; - on some machines it is expensive to move between registers if they are not - general registers. - - If reload sees an insn consisting of a single `set' between two hard - registers, and if `REGISTER_MOVE_COST' applied to their classes returns a - value of 2, reload does not check to ensure that the constraints of the insn - are met. Setting a cost of other than 2 will allow reload to verify that - the constraints are met. You should do this if the `movM' pattern's - constraints do not allow such copying. */ - -#define REGISTER_MOVE_COST(MODE, FROM, TO) \ - (((FROM) != GPR_REGS && (FROM) != EVEN_REGS \ - && (TO) != GPR_REGS && (TO) != EVEN_REGS) ? 4 : 2) - -/* A C expression for the cost of moving data of mode M between a register and - memory. A value of 2 is the default; this cost is relative to those in - `REGISTER_MOVE_COST'. - - If moving between registers and memory is more expensive than between two - registers, you should define this macro to express the relative cost. */ -#define MEMORY_MOVE_COST(M,C,I) 4 - -/* A C expression for the cost of a branch instruction. A value of 1 is the - default; other values are interpreted relative to that. */ - -#define BRANCH_COST d30v_branch_cost - -#define D30V_DEFAULT_BRANCH_COST 2 - -/* Values of the -mbranch-cost=n string. */ -extern int d30v_branch_cost; -extern const char *d30v_branch_cost_string; - -/* Here are additional macros which do not specify precise relative costs, but - only that certain actions are more expensive than GCC would ordinarily - expect. */ - -/* Define this macro as a C expression which is nonzero if accessing less than - a word of memory (i.e. a `char' or a `short') is no faster than accessing a - word of memory, i.e., if such access require more than one instruction or if - there is no difference in cost between byte and (aligned) word loads. - - When this macro is not defined, the compiler will access a field by finding - the smallest containing object; when it is defined, a fullword load will be - used if alignment permits. Unless bytes accesses are faster than word - accesses, using word accesses is preferable since it may eliminate - subsequent memory access if subsequent accesses occur to other fields in the - same word of the structure, but to different bytes. */ -#define SLOW_BYTE_ACCESS 1 - -/* Define this macro if it is as good or better to call a constant function - address than to call an address kept in a register. */ -#define NO_FUNCTION_CSE - - -/* Dividing the output into sections. */ - -/* A C expression whose value is a string containing the assembler operation - that should precede instructions and read-only data. Normally `".text"' is - right. */ -#define TEXT_SECTION_ASM_OP "\t.text" - -/* A C expression whose value is a string containing the assembler operation to - identify the following data as writable initialized data. Normally - `".data"' is right. */ -#define DATA_SECTION_ASM_OP "\t.data" - -/* 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 - `ASM_OUTPUT_BSS' nor `ASM_OUTPUT_ALIGNED_BSS' are defined, - uninitialized global data will be output in the data section if - `-fno-common' is passed, otherwise `ASM_OUTPUT_COMMON' will be - used. */ -#define BSS_SECTION_ASM_OP "\t.section .bss" - - -/* The Overall Framework of an Assembler File. */ - -/* A C string constant describing how to begin a comment in the target - assembler language. The compiler assumes that the comment will end at the - end of the line. */ -#define ASM_COMMENT_START ";" - -/* A C string constant for text to be output before each `asm' statement or - group of consecutive ones. Normally this is `"#APP"', which is a comment - that has no effect on most assemblers but tells the GNU assembler that it - must check the lines that follow for all valid assembler constructs. */ -#define ASM_APP_ON "#APP\n" - -/* A C string constant for text to be output after each `asm' statement or - group of consecutive ones. Normally this is `"#NO_APP"', which tells the - GNU assembler to resume making the time-saving assumptions that are valid - for ordinary compiler output. */ -#define ASM_APP_OFF "#NO_APP\n" - - -/* Output and Generation of Labels. */ - -/* Globalizing directive for a label. */ -#define GLOBAL_ASM_OP "\t.globl " - - -/* Macros Controlling Initialization Routines. */ - -/* If defined, `main' will call `__main' despite the presence of - `INIT_SECTION_ASM_OP'. This macro should be defined for systems where the - init section is not actually run automatically, but is still useful for - collecting the lists of constructors and destructors. */ -#define INVOKE__main - - -/* Output of Assembler Instructions. */ - -/* A C initializer containing the assembler's names for the machine registers, - each one as a C string constant. This is what translates register numbers - in the compiler into assembler language. */ -#define REGISTER_NAMES \ -{ \ - "r0", "r1", "r2", "r3", \ - "r4", "r5", "r6", "r7", \ - "r8", "r9", "r10", "r11", \ - "r12", "r13", "r14", "r15", \ - "r16", "r17", "r18", "r19", \ - "r20", "r21", "r22", "r23", \ - "r24", "r25", "r26", "r27", \ - "r28", "r29", "r30", "r31", \ - "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", "link", "sp", \ - "ap", \ - "f0", "f1", "f2", "f3", \ - "s", "v", "va", "c", \ - "a0", "a1", \ - "psw", "bpsw", "pc", "bpc", \ - "dpsw", "dpc", "rpt_c", "rpt_s", \ - "rpt_e", "mod_s", "mod_e", "iba", \ - "eit_vb", "int_s", "int_m", \ -} - -/* If defined, a C initializer for an array of structures containing a name and - a register number. This macro defines additional names for hard registers, - thus allowing the `asm' option in declarations to refer to registers using - alternate names. */ -#define ADDITIONAL_REGISTER_NAMES \ -{ \ - {"r62", GPR_LINK}, \ - {"r63", GPR_SP}, \ - {"f4", FLAG_SAT}, \ - {"f5", FLAG_OVERFLOW}, \ - {"f6", FLAG_ACC_OVER}, \ - {"f7", FLAG_CARRY}, \ - {"carry", FLAG_CARRY}, \ - {"borrow", FLAG_BORROW}, \ - {"b", FLAG_BORROW}, \ - {"cr0", CR_PSW}, \ - {"cr1", CR_BPSW}, \ - {"cr2", CR_PC}, \ - {"cr3", CR_BPC}, \ - {"cr4", CR_DPSW}, \ - {"cr5", CR_DPC}, \ - {"cr7", CR_RPT_C}, \ - {"cr8", CR_RPT_S}, \ - {"cr9", CR_RPT_E}, \ - {"cr10", CR_MOD_S}, \ - {"cr11", CR_MOD_E}, \ - {"cr14", CR_IBA}, \ - {"cr15", CR_EIT_VB}, \ - {"cr16", CR_INT_S}, \ - {"cr17", CR_INT_M} \ -} - -/* A C compound statement to output to stdio stream STREAM the assembler syntax - for an instruction operand X. X is an RTL expression. - - CODE is a value that can be used to specify one of several ways of printing - the operand. It is used when identical operands must be printed differently - depending on the context. CODE comes from the `%' specification that was - used to request printing of the operand. If the specification was just - `%DIGIT' then CODE is 0; if the specification was `%LTR DIGIT' then CODE is - the ASCII code for LTR. - - If X is a register, this macro should print the register's name. The names - can be found in an array `reg_names' whose type is `char *[]'. `reg_names' - is initialized from `REGISTER_NAMES'. - - When the machine description has a specification `%PUNCT' (a `%' followed by - a punctuation character), this macro is called with a null pointer for X and - the punctuation character for CODE. - - Standard operand flags that are handled elsewhere: - `=' Output a number unique to each instruction in the compilation. - `a' Substitute an operand as if it were a memory reference. - `c' Omit the syntax that indicates an immediate operand. - `l' Substitute a LABEL_REF into a jump instruction. - `n' Like %cDIGIT, except negate the value before printing. - - The d30v specific operand flags are: - `.' Print r0. - `f' Print a SF constant as an int. - `s' Subtract 32 and negate. - `A' Print accumulator number without an `a' in front of it. - `B' Print bit offset for BSET, etc. instructions. - `E' Print u if this is zero extend, nothing if this is sign extend. - `F' Emit /{f,t,x}{f,t,x} for executing a false condition. - `L' Print the lower half of a 64 bit item. - `M' Print a memory reference for ld/st instructions. - `R' Return appropriate cmp instruction for relational test. - `S' Subtract 32. - `T' Emit /{f,t,x}{f,t,x} for executing a true condition. - `U' Print the upper half of a 64 bit item. */ - -#define PRINT_OPERAND(STREAM, X, CODE) d30v_print_operand (STREAM, X, CODE) - -/* A C expression which evaluates to true if CODE is a valid punctuation - character for use in the `PRINT_OPERAND' macro. If - `PRINT_OPERAND_PUNCT_VALID_P' is not defined, it means that no punctuation - characters (except for the standard one, `%') are used in this way. */ - -#define PRINT_OPERAND_PUNCT_VALID_P(CODE) ((CODE) == '.' || (CODE) == ':') - -/* A C compound statement to output to stdio stream STREAM the assembler syntax - for an instruction operand that is a memory reference whose address is X. X - is an RTL expression. */ - -#define PRINT_OPERAND_ADDRESS(STREAM, X) d30v_print_operand_address (STREAM, X) - -/* If defined, C string expressions to be used for the `%R', `%L', `%U', and - `%I' options of `asm_fprintf' (see `final.c'). These are useful when a - single `md' file must support multiple assembler formats. In that case, the - various `tm.h' files can define these macros differently. - - USER_LABEL_PREFIX is defined in svr4.h. */ - -#define REGISTER_PREFIX "%" -#define LOCAL_LABEL_PREFIX "." -#define USER_LABEL_PREFIX "" -#define IMMEDIATE_PREFIX "" - - -/* Output of dispatch tables. */ - -/* This macro should be provided on machines where the addresses in a dispatch - table are relative to the table's own address. - - The definition should be a C statement to output to the stdio stream STREAM - an assembler pseudo-instruction to generate a difference between two labels. - VALUE and REL are the numbers of two internal labels. The definitions of - these labels are output using `(*targetm.asm_out.internal_label)', and they must be - printed in the same way here. For example, - - fprintf (STREAM, "\t.word L%d-L%d\n", VALUE, REL) */ - -#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM, BODY, VALUE, REL) \ -fprintf (STREAM, "\t.word .L%d-.L%d\n", VALUE, REL) - -/* This macro should be provided on machines where the addresses in a dispatch - table are absolute. - - The definition should be a C statement to output to the stdio stream STREAM - an assembler pseudo-instruction to generate a reference to a label. VALUE - is the number of an internal label whose definition is output using - `(*targetm.asm_out.internal_label)'. For example, - - fprintf (STREAM, "\t.word L%d\n", VALUE) */ - -#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM, VALUE) \ -fprintf (STREAM, "\t.word .L%d\n", VALUE) - - -/* Assembler Commands for Alignment. */ - -/* A C statement to output to the stdio stream STREAM an assembler command to - advance the location counter to a multiple of 2 to the POWER bytes. POWER - will be a C expression of type `int'. */ -#define ASM_OUTPUT_ALIGN(STREAM, POWER) \ - fprintf ((STREAM), "\t.p2align %d\n", (POWER)) - - -/* Macros Affecting all Debug Formats. */ - -/* A C expression that returns the DBX register number for the compiler - register number REGNO. In simple cases, the value of this expression may be - REGNO itself. But sometimes there are some registers that the compiler - knows about and DBX does not, or vice versa. In such cases, some register - may need to have one number in the compiler and another for DBX. - - If two registers have consecutive numbers inside GCC, and they can be - used as a pair to hold a multiword value, then they *must* have consecutive - numbers after renumbering with `DBX_REGISTER_NUMBER'. Otherwise, debuggers - will be unable to access such a pair, because they expect register pairs to - be consecutive in their own numbering scheme. - - If you find yourself defining `DBX_REGISTER_NUMBER' in way that does not - preserve register pairs, then what you must do instead is redefine the - actual register numbering scheme. */ -#define DBX_REGISTER_NUMBER(REGNO) \ -(GPR_P (REGNO) ? ((REGNO) - GPR_FIRST) \ - : ACCUM_P (REGNO) ? ((REGNO) - ACCUM_FIRST + 84) \ - : FLAG_P (REGNO) ? 66 /* return psw for all flags */ \ - : (REGNO) == ARG_POINTER_REGNUM ? (GPR_SP - GPR_FIRST) \ - : (REGNO) == CR_PSW ? (66 + 0) \ - : (REGNO) == CR_BPSW ? (66 + 1) \ - : (REGNO) == CR_PC ? (66 + 2) \ - : (REGNO) == CR_BPC ? (66 + 3) \ - : (REGNO) == CR_DPSW ? (66 + 4) \ - : (REGNO) == CR_DPC ? (66 + 5) \ - : (REGNO) == CR_RPT_C ? (66 + 7) \ - : (REGNO) == CR_RPT_S ? (66 + 8) \ - : (REGNO) == CR_RPT_E ? (66 + 9) \ - : (REGNO) == CR_MOD_S ? (66 + 10) \ - : (REGNO) == CR_MOD_E ? (66 + 11) \ - : (REGNO) == CR_IBA ? (66 + 14) \ - : (REGNO) == CR_EIT_VB ? (66 + 15) \ - : (REGNO) == CR_INT_S ? (66 + 16) \ - : (REGNO) == CR_INT_M ? (66 + 17) \ - : -1) - -/* A C expression that returns the type of debugging output GCC produces - when the user specifies `-g' or `-ggdb'. Define this if you have arranged - for GCC to support more than one format of debugging output. Currently, - the allowable values are `DBX_DEBUG', `SDB_DEBUG', `DWARF_DEBUG', - `DWARF2_DEBUG', and `XCOFF_DEBUG'. - - The value of this macro only affects the default debugging output; the user - can always get a specific type of output by using `-gstabs', `-gcoff', - `-gdwarf-1', `-gdwarf-2', or `-gxcoff'. - - Defined in svr4.h. */ - -#undef PREFERRED_DEBUGGING_TYPE -#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG - - -/* Miscellaneous Parameters. */ - -/* Define this if you have defined special-purpose predicates in the file - `MACHINE.c'. This macro is called within an initializer of an array of - structures. The first field in the structure is the name of a predicate and - the second field is an array of rtl codes. For each predicate, list all rtl - codes that can be in expressions matched by the predicate. The list should - have a trailing comma. Here is an example of two entries in the list for a - typical RISC machine: - - #define PREDICATE_CODES \ - {"gen_reg_rtx_operand", {SUBREG, REG}}, \ - {"reg_or_short_cint_operand", {SUBREG, REG, CONST_INT}}, - - Defining this macro does not affect the generated code (however, incorrect - definitions that omit an rtl code that may be matched by the predicate can - cause the compiler to malfunction). Instead, it allows the table built by - `genrecog' to be more compact and efficient, thus speeding up the compiler. - The most important predicates to include in the list specified by this macro - are thoses used in the most insn patterns. */ - -#define PREDICATE_CODES \ - { "short_memory_operand", { MEM }}, \ - { "long_memory_operand", { MEM }}, \ - { "d30v_memory_operand", { MEM }}, \ - { "single_reg_memory_operand", { MEM }}, \ - { "const_addr_memory_operand", { MEM }}, \ - { "call_operand", { MEM }}, \ - { "gpr_operand", { REG, SUBREG }}, \ - { "accum_operand", { REG, SUBREG }}, \ - { "gpr_or_accum_operand", { REG, SUBREG }}, \ - { "cr_operand", { REG, SUBREG }}, \ - { "repeat_operand", { REG, SUBREG }}, \ - { "flag_operand", { REG, SUBREG }}, \ - { "br_flag_operand", { REG, SUBREG }}, \ - { "br_flag_or_constant_operand", { REG, SUBREG, CONST_INT }}, \ - { "gpr_or_br_flag_operand", { REG, SUBREG }}, \ - { "f0_operand", { REG, SUBREG }}, \ - { "f1_operand", { REG, SUBREG }}, \ - { "carry_operand", { REG, SUBREG }}, \ - { "reg_or_0_operand", { REG, SUBREG, CONST_INT, \ - CONST_DOUBLE }}, \ - { "gpr_or_signed6_operand", { REG, SUBREG, CONST_INT }}, \ - { "gpr_or_unsigned5_operand", { REG, SUBREG, CONST_INT }}, \ - { "gpr_or_unsigned6_operand", { REG, SUBREG, CONST_INT }}, \ - { "gpr_or_constant_operand", { REG, SUBREG, CONST_INT, \ - CONST, SYMBOL_REF, \ - LABEL_REF }}, \ - { "gpr_or_dbl_const_operand", { REG, SUBREG, CONST_INT, \ - CONST, SYMBOL_REF, \ - LABEL_REF, CONST_DOUBLE }}, \ - { "gpr_or_memory_operand", { REG, SUBREG, MEM }}, \ - { "move_input_operand", { REG, SUBREG, MEM, CONST_INT, \ - CONST, SYMBOL_REF, \ - LABEL_REF, CONST_DOUBLE }}, \ - { "move_output_operand", { REG, SUBREG, MEM }}, \ - { "signed6_operand", { CONST_INT }}, \ - { "unsigned5_operand", { CONST_INT }}, \ - { "unsigned6_operand", { CONST_INT }}, \ - { "bitset_operand", { CONST_INT }}, \ - { "condexec_test_operator", { EQ, NE }}, \ - { "condexec_branch_operator", { EQ, NE }}, \ - { "condexec_unary_operator", { ABS, NEG, NOT, ZERO_EXTEND }}, \ - { "condexec_addsub_operator", { PLUS, MINUS }}, \ - { "condexec_binary_operator", { MULT, AND, IOR, XOR, \ - ASHIFT, ASHIFTRT, LSHIFTRT, \ - ROTATE, ROTATERT }}, \ - { "condexec_shiftl_operator", { ASHIFT, ROTATE }}, \ - { "condexec_extend_operator", { SIGN_EXTEND, ZERO_EXTEND }}, \ - { "branch_zero_operator", { EQ, NE }}, \ - { "cond_move_dest_operand", { REG, SUBREG, MEM }}, \ - { "cond_move_operand", { REG, SUBREG, CONST_INT, \ - CONST, SYMBOL_REF, \ - LABEL_REF, MEM }}, \ - { "cond_exec_operand", { REG, SUBREG, CONST_INT, \ - CONST, SYMBOL_REF, \ - LABEL_REF, MEM }}, \ - { "srelational_si_operator", { EQ, NE, LT, LE, GT, GE }}, \ - { "urelational_si_operator", { LTU, LEU, GTU, GEU }}, \ - { "relational_di_operator", { EQ, NE, LT, LE, GT, GE, \ - LTU, LEU, GTU, GEU }}, - -/* An alias for a machine mode name. This is the machine mode that elements of - a jump-table should have. */ -#define CASE_VECTOR_MODE SImode - -/* Define this macro if operations between registers with integral mode smaller - than a word are always performed on the entire register. Most RISC machines - have this property and most CISC machines do not. */ -#define WORD_REGISTER_OPERATIONS 1 - -/* Define this macro to be a C expression indicating when insns that read - memory in MODE, an integral mode narrower than a word, set the bits outside - of MODE to be either the sign-extension or the zero-extension of the data - read. Return `SIGN_EXTEND' for values of MODE for which the insn - sign-extends, `ZERO_EXTEND' for which it zero-extends, and `NIL' for other - modes. - - This macro is not called with MODE non-integral or with a width greater than - or equal to `BITS_PER_WORD', so you may return any value in this case. Do - not define this macro if it would always return `NIL'. On machines where - this macro is defined, you will normally define it as the constant - `SIGN_EXTEND' or `ZERO_EXTEND'. */ - -#define LOAD_EXTEND_OP(MODE) SIGN_EXTEND - -/* Define if loading short immediate values into registers sign extends. */ -#define SHORT_IMMEDIATES_SIGN_EXTEND - -/* The maximum number of bytes that a single instruction can move quickly from - memory to memory. */ -#define MOVE_MAX 8 - -/* A C expression which is nonzero if on this machine it is safe to "convert" - an integer of INPREC bits to one of OUTPREC bits (where OUTPREC is smaller - than INPREC) by merely operating on it as if it had only OUTPREC bits. - - On many machines, this expression can be 1. - - When `TRULY_NOOP_TRUNCATION' returns 1 for a pair of sizes for modes for - which `MODES_TIEABLE_P' is 0, suboptimal code can result. If this is the - case, making `TRULY_NOOP_TRUNCATION' return 0 in such cases may improve - things. */ -#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1 - -/* An alias for the machine mode for pointers. On most machines, define this - to be the integer mode corresponding to the width of a hardware pointer; - `SImode' on 32-bit machine or `DImode' on 64-bit machines. On some machines - you must define this to be one of the partial integer modes, such as - `PSImode'. - - The width of `Pmode' must be at least as large as the value of - `POINTER_SIZE'. If it is not equal, you must define the macro - `POINTERS_EXTEND_UNSIGNED' to specify how pointers are extended to `Pmode'. */ -#define Pmode SImode - -/* An alias for the machine mode used for memory references to functions being - called, in `call' RTL expressions. On most machines this should be - `QImode'. */ -#define FUNCTION_MODE QImode - -/* Define this macro to handle System V style pragmas (particularly #pack). - - Defined in svr4.h. */ -#define HANDLE_SYSV_PRAGMA 1 - -/* A C expression for the maximum number of instructions to execute via - conditional execution instructions instead of a branch. A value of - BRANCH_COST+1 is the default if the machine does not use cc0, and 1 if it - does use cc0. */ -#define MAX_CONDITIONAL_EXECUTE d30v_cond_exec - -#define D30V_DEFAULT_MAX_CONDITIONAL_EXECUTE 4 - -/* Values of the -mcond-exec=n string. */ -extern int d30v_cond_exec; -extern const char *d30v_cond_exec_string; - -#endif /* GCC_D30V_H */ diff --git a/gcc/config/d30v/d30v.md b/gcc/config/d30v/d30v.md deleted file mode 100644 index 7846074261d..00000000000 --- a/gcc/config/d30v/d30v.md +++ /dev/null @@ -1,3361 +0,0 @@ -;; Mitsubishi D30V Machine description template -;; Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc. -;; Contributed by Cygnus Solutions. -;; -;; This file is part of GCC. -;; -;; GCC is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. -;; -;; GCC is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. -;; -;; You should have received a copy of the GNU General Public License -;; along with GCC; see the file COPYING. If not, write to -;; the Free Software Foundation, 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - -;;- See file "rtl.def" for documentation on define_insn, match_*, et. al. - - -;; :::::::::::::::::::: -;; :: -;; :: Constraints -;; :: -;; :::::::::::::::::::: - -;; Standard Constraints -;; -;; `m' A memory operand is allowed, with any kind of address that the -;; machine supports in general. -;; -;; `o' A memory operand is allowed, but only if the address is -;; "offsettable". This means that adding a small integer (actually, the -;; width in bytes of the operand, as determined by its machine mode) may be -;; added to the address and the result is also a valid memory address. -;; -;; `V' A memory operand that is not offsettable. In other words, -;; anything that would fit the `m' constraint but not the `o' constraint. -;; -;; `<' A memory operand with autodecrement addressing (either -;; predecrement or postdecrement) is allowed. -;; -;; `>' A memory operand with autoincrement addressing (either -;; preincrement or postincrement) is allowed. -;; -;; `r' A register operand is allowed provided that it is in a general -;; register. -;; -;; `d', `a', `f', ... -;; Other letters can be defined in machine-dependent fashion to stand for -;; particular classes of registers. `d', `a' and `f' are defined on the -;; 68000/68020 to stand for data, address and floating point registers. -;; -;; `i' An immediate integer operand (one with constant value) is allowed. -;; This includes symbolic constants whose values will be known only at -;; assembly time. -;; -;; `n' An immediate integer operand with a known numeric value is allowed. -;; Many systems cannot support assembly-time constants for operands less -;; than a word wide. Constraints for these operands should use `n' rather -;; than `i'. -;; -;; 'I' First machine-dependent integer constant. -;; 'J' Second machine-dependent integer constant. -;; 'K' Third machine-dependent integer constant. -;; 'L' Fourth machine-dependent integer constant. -;; 'M' Fifth machine-dependent integer constant. -;; 'N' Sixth machine-dependent integer constant. -;; 'O' Seventh machine-dependent integer constant. -;; 'P' Eighth machine-dependent integer constant. -;; -;; Other letters in the range `I' through `P' may be defined in a -;; machine-dependent fashion to permit immediate integer operands with -;; explicit integer values in specified ranges. For example, on the 68000, -;; `I' is defined to stand for the range of values 1 to 8. This is the -;; range permitted as a shift count in the shift instructions. -;; -;; `E' An immediate floating operand (expression code `const_double') is -;; allowed, but only if the target floating point format is the same as -;; that of the host machine (on which the compiler is running). -;; -;; `F' An immediate floating operand (expression code `const_double') is -;; allowed. -;; -;; 'G' First machine-dependent const_double. -;; 'H' Second machine-dependent const_double. -;; -;; `s' An immediate integer operand whose value is not an explicit -;; integer is allowed. -;; -;; This might appear strange; if an insn allows a constant operand with a -;; value not known at compile time, it certainly must allow any known -;; value. So why use `s' instead of `i'? Sometimes it allows better code -;; to be generated. -;; -;; For example, on the 68000 in a fullword instruction it is possible to -;; use an immediate operand; but if the immediate value is between -128 and -;; 127, better code results from loading the value into a register and -;; using the register. This is because the load into the register can be -;; done with a `moveq' instruction. We arrange for this to happen by -;; defining the letter `K' to mean "any integer outside the range -128 to -;; 127", and then specifying `Ks' in the operand constraints. -;; -;; `g' Any register, memory or immediate integer operand is allowed, -;; except for registers that are not general registers. -;; -;; `X' Any operand whatsoever is allowed, even if it does not satisfy -;; `general_operand'. This is normally used in the constraint of a -;; `match_scratch' when certain alternatives will not actually require a -;; scratch register. -;; -;; `0' Match operand 0. -;; `1' Match operand 1. -;; `2' Match operand 2. -;; `3' Match operand 3. -;; `4' Match operand 4. -;; `5' Match operand 5. -;; `6' Match operand 6. -;; `7' Match operand 7. -;; `8' Match operand 8. -;; `9' Match operand 9. -;; -;; An operand that matches the specified operand number is allowed. If a -;; digit is used together with letters within the same alternative, the -;; digit should come last. -;; -;; This is called a "matching constraint" and what it really means is that -;; the assembler has only a single operand that fills two roles considered -;; separate in the RTL insn. For example, an add insn has two input -;; operands and one output operand in the RTL, but on most CISC machines an -;; add instruction really has only two operands, one of them an -;; input-output operand: -;; -;; addl #35,r12 -;; -;; Matching constraints are used in these circumstances. More precisely, -;; the two operands that match must include one input-only operand and one -;; output-only operand. Moreover, the digit must be a smaller number than -;; the number of the operand that uses it in the constraint. -;; -;; For operands to match in a particular case usually means that they are -;; identical-looking RTL expressions. But in a few special cases specific -;; kinds of dissimilarity are allowed. For example, `*x' as an input -;; operand will match `*x++' as an output operand. For proper results in -;; such cases, the output template should always use the output-operand's -;; number when printing the operand. -;; -;; `p' An operand that is a valid memory address is allowed. This is for -;; "load address" and "push address" instructions. -;; -;; `p' in the constraint must be accompanied by `address_operand' as the -;; predicate in the `match_operand'. This predicate interprets the mode -;; specified in the `match_operand' as the mode of the memory reference for -;; which the address would be valid. -;; -;; `Q` First non constant, non register machine-dependent insns -;; `R` Second non constant, non register machine-dependent insns -;; `S` Third non constant, non register machine-dependent insns -;; `T` Fourth non constant, non register machine-dependent insns -;; `U` Fifth non constant, non register machine-dependent insns -;; -;; Letters in the range `Q' through `U' may be defined in a -;; machine-dependent fashion to stand for arbitrary operand types. The -;; machine description macro `EXTRA_CONSTRAINT' is passed the operand as -;; its first argument and the constraint letter as its second operand. -;; -;; A typical use for this would be to distinguish certain types of memory -;; references that affect other insn operands. -;; -;; Do not define these constraint letters to accept register references -;; (`reg'); the reload pass does not expect this and would not handle it -;; properly. - -;; Multiple Alternative Constraints -;; `?' Disparage slightly the alternative that the `?' appears in, as a -;; choice when no alternative applies exactly. The compiler regards this -;; alternative as one unit more costly for each `?' that appears in it. -;; -;; `!' Disparage severely the alternative that the `!' appears in. This -;; alternative can still be used if it fits without reloading, but if -;; reloading is needed, some other alternative will be used. - -;; Constraint modifiers -;; `=' Means that this operand is write-only for this instruction: the -;; previous value is discarded and replaced by output data. -;; -;; `+' Means that this operand is both read and written by the -;; instruction. -;; -;; When the compiler fixes up the operands to satisfy the constraints, it -;; needs to know which operands are inputs to the instruction and which are -;; outputs from it. `=' identifies an output; `+' identifies an operand -;; that is both input and output; all other operands are assumed to be -;; input only. -;; -;; `&' Means (in a particular alternative) that this operand is written -;; before the instruction is finished using the input operands. Therefore, -;; this operand may not lie in a register that is used as an input operand -;; or as part of any memory address. -;; -;; `&' applies only to the alternative in which it is written. In -;; constraints with multiple alternatives, sometimes one alternative -;; requires `&' while others do not. -;; -;; `&' does not obviate the need to write `='. -;; -;; `%' Declares the instruction to be commutative for this operand and the -;; following operand. This means that the compiler may interchange the two -;; operands if that is the cheapest way to make all operands fit the -;; constraints. This is often used in patterns for addition instructions -;; that really have only two operands: the result must go in one of the -;; arguments. -;; -;; `#' Says that all following characters, up to the next comma, are to be -;; ignored as a constraint. They are significant only for choosing -;; register preferences. -;; -;; `*' Says that the following character should be ignored when choosing -;; register preferences. `*' has no effect on the meaning of the -;; constraint as a constraint, and no effect on reloading. - -;; :::::::::::::::::::: -;; :: -;; :: D30V register classes -;; :: -;; :::::::::::::::::::: - -;; `a' Accumulator registers (a0, a1) -;; `b' Flag registers for speculative execution (f0, f1) -;; `c' CR registers -;; `d' GPR registers -;; `e' Even GPR registers -;; `f' Any flag registers (f0, f1, ..., c) -;; `l' CR7, the repeat count -;; `x' F0 -;; `y' F1 -;; `z' Flag registers other than F0 and F1. - -;; :::::::::::::::::::: -;; :: -;; :: D30V special constraints -;; :: -;; :::::::::::::::::::: - -;; `G' Const double with 0 in both low & high part. -;; `H' Unused. -;; `I' Signed 6 bit integer constant (>= -32 && <= 31). -;; `J' Unsigned 5 bit integer constant (>= 0 && <= 31). -;; `K' Integer constant with 1 bit set (for bset). -;; `L' Integer constant with 1 bit clear (for bclr). -;; `M' Integer constant 32. -;; `N' Integer constant 1. -;; `O' Integer constant 0. -;; `P' Integer constant >= 32 && <= 63. -;; `Q' Short memory operand (can be done in small insn). -;; `R' Memory operand using a single register for address. -;; `S' Memory operand to constant address. -;; `T' Unused. -;; `U' Unused. - -;; :::::::::::::::::::: -;; :: -;; :: Standard operand flags -;; :: -;; :::::::::::::::::::: - -;; `=' Output a number unique to each instruction in the compilation. -;; `a' Substitute an operand as if it were a memory reference. -;; `c' Omit the syntax that indicates an immediate operand. -;; `l' Substitute a LABEL_REF into a jump instruction. -;; `n' Like %cDIGIT, except negate the value before printing. - -;; :::::::::::::::::::: -;; :: -;; :: D30V print_operand flags -;; :: -;; :::::::::::::::::::: - -;; `.' Print r0 -;; `f' Print a SF constant as an int. -;; `s' Subtract 32 and negate. -;; `A' Print accumulator number without an `a' in front of it. -;; `B' Print bit offset for BSET, etc. instructions. -;; `E' Print u if this is zero extend, nothing if this is sign extend. -;; `F' Emit /{f,t,x}{f,t,x} for executing a false condition. -;; `L' Print the lower half of a 64 bit item. -;; `M' Print a memory reference for ld/st instructions. -;; `R' Return appropriate cmp instruction for relational test. -;; `S' Subtract 32. -;; `T' Emit /{f,t,x}{f,t,x} for executing a true condition. -;; `U' Print the upper half of a 64 bit item. - - -;; :::::::::::::::::::: -;; :: -;; :: Attributes -;; :: -;; :::::::::::::::::::: - -;; The `define_attr' expression is used to define each attribute required by -;; the target machine. It looks like: -;; -;; (define_attr NAME LIST-OF-VALUES DEFAULT) - -;; NAME is a string specifying the name of the attribute being defined. - -;; LIST-OF-VALUES is either a string that specifies a comma-separated list of -;; values that can be assigned to the attribute, or a null string to indicate -;; that the attribute takes numeric values. - -;; DEFAULT is an attribute expression that gives the value of this attribute -;; for insns that match patterns whose definition does not include an explicit -;; value for this attribute. - -;; For each defined attribute, a number of definitions are written to the -;; `insn-attr.h' file. For cases where an explicit set of values is specified -;; for an attribute, the following are defined: - -;; * A `#define' is written for the symbol `HAVE_ATTR_NAME'. -;; -;; * An enumeral class is defined for `attr_NAME' with elements of the -;; form `UPPER-NAME_UPPER-VALUE' where the attribute name and value are first -;; converted to upper case. -;; -;; * A function `get_attr_NAME' is defined that is passed an insn and -;; returns the attribute value for that insn. - -;; For example, if the following is present in the `md' file: -;; -;; (define_attr "type" "branch,fp,load,store,arith" ...) -;; -;; the following lines will be written to the file `insn-attr.h'. -;; -;; #define HAVE_ATTR_type -;; enum attr_type {TYPE_BRANCH, TYPE_FP, TYPE_LOAD, TYPE_STORE, TYPE_ARITH}; -;; extern enum attr_type get_attr_type (); - -;; If the attribute takes numeric values, no `enum' type will be defined and -;; the function to obtain the attribute's value will return `int'. - -;; Note, we lie a little bit here to make it simpler to optimize. We pretend there -;; is a separate long functional unit for long instructions that uses both the IU & MU. - -(define_attr "type" "iu,mu,br,br2,either,scarry,lcarry,scmp,lcmp,sload,lload,mul,long,multi,unknown" - (const_string "unknown")) - -;; Length in word units -(define_attr "length" "" - (cond [(eq_attr "type" "iu,mu,either,scmp,sload,mul,scarry,") - (const_int 4) - (eq_attr "type" "long,lcmp,lload,lcarry") - (const_int 8) - (eq_attr "type" "multi,unknown") - (const_int 64) ;; set higher to give a fudge factor - (eq_attr "type" "br") - (if_then_else (and (ge (minus (pc) (match_dup 0)) - (const_int -1048576)) - (lt (minus (pc) (match_dup 0)) - (const_int 1048575))) - (const_int 4) - (const_int 8)) - (eq_attr "type" "br2") - (if_then_else (and (ge (minus (pc) (match_dup 0)) - (const_int -16384)) - (lt (minus (pc) (match_dup 0)) - (const_int 16383))) - (const_int 4) - (const_int 8)) - ] - (const_int 8))) - -(define_attr "predicable" "no,yes" - (const_string "yes")) - -;; :::::::::::::::::::: -;; :: -;; :: Function Units -;; :: -;; :::::::::::::::::::: - -;; On most RISC machines, there are instructions whose results are not -;; available for a specific number of cycles. Common cases are instructions -;; that load data from memory. On many machines, a pipeline stall will result -;; if the data is referenced too soon after the load instruction. - -;; In addition, many newer microprocessors have multiple function units, -;; usually one for integer and one for floating point, and often will incur -;; pipeline stalls when a result that is needed is not yet ready. - -;; The descriptions in this section allow the specification of how much time -;; must elapse between the execution of an instruction and the time when its -;; result is used. It also allows specification of when the execution of an -;; instruction will delay execution of similar instructions due to function -;; unit conflicts. - -;; For the purposes of the specifications in this section, a machine is divided -;; into "function units", each of which execute a specific class of -;; instructions in first-in-first-out order. Function units that accept one -;; instruction each cycle and allow a result to be used in the succeeding -;; instruction (usually via forwarding) need not be specified. Classic RISC -;; microprocessors will normally have a single function unit, which we can call -;; `memory'. The newer "superscalar" processors will often have function units -;; for floating point operations, usually at least a floating point adder and -;; multiplier. - -;; Each usage of a function units by a class of insns is specified with a -;; `define_function_unit' expression, which looks like this: - -;; (define_function_unit NAME MULTIPLICITY SIMULTANEITY TEST READY-DELAY -;; ISSUE-DELAY [CONFLICT-LIST]) - -;; NAME is a string giving the name of the function unit. - -;; MULTIPLICITY is an integer specifying the number of identical units in the -;; processor. If more than one unit is specified, they will be scheduled -;; independently. Only truly independent units should be counted; a pipelined -;; unit should be specified as a single unit. (The only common example of a -;; machine that has multiple function units for a single instruction class that -;; are truly independent and not pipelined are the two multiply and two -;; increment units of the CDC 6600.) - -;; SIMULTANEITY specifies the maximum number of insns that can be executing in -;; each instance of the function unit simultaneously or zero if the unit is -;; pipelined and has no limit. - -;; All `define_function_unit' definitions referring to function unit NAME must -;; have the same name and values for MULTIPLICITY and SIMULTANEITY. - -;; TEST is an attribute test that selects the insns we are describing in this -;; definition. Note that an insn may use more than one function unit and a -;; function unit may be specified in more than one `define_function_unit'. - -;; READY-DELAY is an integer that specifies the number of cycles after which -;; the result of the instruction can be used without introducing any stalls. - -;; ISSUE-DELAY is an integer that specifies the number of cycles after the -;; instruction matching the TEST expression begins using this unit until a -;; subsequent instruction can begin. A cost of N indicates an N-1 cycle delay. -;; A subsequent instruction may also be delayed if an earlier instruction has a -;; longer READY-DELAY value. This blocking effect is computed using the -;; SIMULTANEITY, READY-DELAY, ISSUE-DELAY, and CONFLICT-LIST terms. For a -;; normal non-pipelined function unit, SIMULTANEITY is one, the unit is taken -;; to block for the READY-DELAY cycles of the executing insn, and smaller -;; values of ISSUE-DELAY are ignored. - -;; CONFLICT-LIST is an optional list giving detailed conflict costs for this -;; unit. If specified, it is a list of condition test expressions to be -;; applied to insns chosen to execute in NAME following the particular insn -;; matching TEST that is already executing in NAME. For each insn in the list, -;; ISSUE-DELAY specifies the conflict cost; for insns not in the list, the cost -;; is zero. If not specified, CONFLICT-LIST defaults to all instructions that -;; use the function unit. - -;; Typical uses of this vector are where a floating point function unit can -;; pipeline either single- or double-precision operations, but not both, or -;; where a memory unit can pipeline loads, but not stores, etc. - -;; As an example, consider a classic RISC machine where the result of a load -;; instruction is not available for two cycles (a single "delay" instruction is -;; required) and where only one load instruction can be executed -;; simultaneously. This would be specified as: - -;; (define_function_unit "memory" 1 1 (eq_attr "type" "load") 2 0) - -;; For the case of a floating point function unit that can pipeline -;; either single or double precision, but not both, the following could be -;; specified: -;; -;; (define_function_unit "fp" 1 0 -;; (eq_attr "type" "sp_fp") 4 4 -;; [(eq_attr "type" "dp_fp")]) -;; -;; (define_function_unit "fp" 1 0 -;; (eq_attr "type" "dp_fp") 4 4 -;; [(eq_attr "type" "sp_fp")]) - -;; Note: The scheduler attempts to avoid function unit conflicts and uses all -;; the specifications in the `define_function_unit' expression. It has -;; recently come to our attention that these specifications may not allow -;; modeling of some of the newer "superscalar" processors that have insns using -;; multiple pipelined units. These insns will cause a potential conflict for -;; the second unit used during their execution and there is no way of -;; representing that conflict. We welcome any examples of how function unit -;; conflicts work in such processors and suggestions for their representation. - -(define_function_unit "iu" 1 0 - (eq_attr "type" "iu,either") - 1 1 - [(eq_attr "type" "long,lcmp,lload,multi,unknown")]) - -(define_function_unit "iu" 1 0 - (eq_attr "type" "scmp,mul,scarry") - 2 1 - [(eq_attr "type" "long,lcmp,lload,multi,unknown")]) - -(define_function_unit "mu" 1 0 - (eq_attr "type" "mu,br,br2,either") - 1 1 - [(eq_attr "type" "long,lcmp,lload,multi,unknown")]) - -(define_function_unit "mu" 1 0 - (eq_attr "type" "scarry,scmp,sload") - 2 1 - [(eq_attr "type" "long,lcmp,lload,multi,unknown")]) - -(define_function_unit "long" 1 0 - (eq_attr "type" "long,multi,unknown") - 1 1 - [(eq_attr "type" "iu,mu,scarry,scmp,sload,mul,br,br2,either")]) - -(define_function_unit "long" 1 0 - (eq_attr "type" "lcmp,lload,lcarry") - 2 1 - [(eq_attr "type" "iu,mu,scarry,scmp,sload,mul,br,br2,either")]) - - -;; :::::::::::::::::::: -;; :: -;; :: Delay Slots -;; :: -;; :::::::::::::::::::: - -;; The insn attribute mechanism can be used to specify the requirements for -;; delay slots, if any, on a target machine. An instruction is said to require -;; a "delay slot" if some instructions that are physically after the -;; instruction are executed as if they were located before it. Classic -;; examples are branch and call instructions, which often execute the following -;; instruction before the branch or call is performed. - -;; On some machines, conditional branch instructions can optionally "annul" -;; instructions in the delay slot. This means that the instruction will not be -;; executed for certain branch outcomes. Both instructions that annul if the -;; branch is true and instructions that annul if the branch is false are -;; supported. - -;; Delay slot scheduling differs from instruction scheduling in that -;; determining whether an instruction needs a delay slot is dependent only -;; on the type of instruction being generated, not on data flow between the -;; instructions. See the next section for a discussion of data-dependent -;; instruction scheduling. - -;; The requirement of an insn needing one or more delay slots is indicated via -;; the `define_delay' expression. It has the following form: -;; -;; (define_delay TEST -;; [DELAY-1 ANNUL-TRUE-1 ANNUL-FALSE-1 -;; DELAY-2 ANNUL-TRUE-2 ANNUL-FALSE-2 -;; ...]) - -;; TEST is an attribute test that indicates whether this `define_delay' applies -;; to a particular insn. If so, the number of required delay slots is -;; determined by the length of the vector specified as the second argument. An -;; insn placed in delay slot N must satisfy attribute test DELAY-N. -;; ANNUL-TRUE-N is an attribute test that specifies which insns may be annulled -;; if the branch is true. Similarly, ANNUL-FALSE-N specifies which insns in -;; the delay slot may be annulled if the branch is false. If annulling is not -;; supported for that delay slot, `(nil)' should be coded. - -;; For example, in the common case where branch and call insns require a single -;; delay slot, which may contain any insn other than a branch or call, the -;; following would be placed in the `md' file: - -;; (define_delay (eq_attr "type" "branch,call") -;; [(eq_attr "type" "!branch,call") (nil) (nil)]) - -;; Multiple `define_delay' expressions may be specified. In this case, each -;; such expression specifies different delay slot requirements and there must -;; be no insn for which tests in two `define_delay' expressions are both true. - -;; For example, if we have a machine that requires one delay slot for branches -;; but two for calls, no delay slot can contain a branch or call insn, and any -;; valid insn in the delay slot for the branch can be annulled if the branch is -;; true, we might represent this as follows: - -;; (define_delay (eq_attr "type" "branch") -;; [(eq_attr "type" "!branch,call") -;; (eq_attr "type" "!branch,call") -;; (nil)]) -;; -;; (define_delay (eq_attr "type" "call") -;; [(eq_attr "type" "!branch,call") (nil) (nil) -;; (eq_attr "type" "!branch,call") (nil) (nil)]) - - -;; :::::::::::::::::::: -;; :: -;; :: Moves -;; :: -;; :::::::::::::::::::: - -;; Wrap moves in define_expand to prevent memory->memory moves from being -;; generated at the RTL level, which generates better code for most machines -;; which can't do mem->mem moves. - -;; If operand 0 is a `subreg' with mode M of a register whose own mode is wider -;; than M, the effect of this instruction is to store the specified value in -;; the part of the register that corresponds to mode M. The effect on the rest -;; of the register is undefined. - -;; This class of patterns is special in several ways. First of all, each of -;; these names *must* be defined, because there is no other way to copy a datum -;; from one place to another. - -;; Second, these patterns are not used solely in the RTL generation pass. Even -;; the reload pass can generate move insns to copy values from stack slots into -;; temporary registers. When it does so, one of the operands is a hard -;; register and the other is an operand that can need to be reloaded into a -;; register. - -;; Therefore, when given such a pair of operands, the pattern must -;; generate RTL which needs no reloading and needs no temporary -;; registers--no registers other than the operands. For example, if -;; you support the pattern with a `define_expand', then in such a -;; case the `define_expand' mustn't call `force_reg' or any other such -;; function which might generate new pseudo registers. - -;; This requirement exists even for subword modes on a RISC machine -;; where fetching those modes from memory normally requires several -;; insns and some temporary registers. Look in `spur.md' to see how -;; the requirement can be satisfied. - -;; During reload a memory reference with an invalid address may be passed as an -;; operand. Such an address will be replaced with a valid address later in the -;; reload pass. In this case, nothing may be done with the address except to -;; use it as it stands. If it is copied, it will not be replaced with a valid -;; address. No attempt should be made to make such an address into a valid -;; address and no routine (such as `change_address') that will do so may be -;; called. Note that `general_operand' will fail when applied to such an -;; address. -;; -;; The global variable `reload_in_progress' (which must be explicitly declared -;; if required) can be used to determine whether such special handling is -;; required. -;; -;; The variety of operands that have reloads depends on the rest of -;; the machine description, but typically on a RISC machine these can -;; only be pseudo registers that did not get hard registers, while on -;; other machines explicit memory references will get optional -;; reloads. -;; -;; If a scratch register is required to move an object to or from memory, it -;; can be allocated using `gen_reg_rtx' prior to reload. But this is -;; impossible during and after reload. If there are cases needing scratch -;; registers after reload, you must define `SECONDARY_INPUT_RELOAD_CLASS' and -;; perhaps also `SECONDARY_OUTPUT_RELOAD_CLASS' to detect them, and provide -;; patterns `reload_inM' or `reload_outM' to handle them. *Note Register -;; Classes::. - -;; The constraints on a `moveM' must permit moving any hard register to any -;; other hard register provided that `HARD_REGNO_MODE_OK' permits mode M in -;; both registers and `REGISTER_MOVE_COST' applied to their classes returns a -;; value of 2. - -;; It is obligatory to support floating point `moveM' instructions -;; into and out of any registers that can hold fixed point values, -;; because unions and structures (which have modes `SImode' or -;; `DImode') can be in those registers and they may have floating -;; point members. - -;; There may also be a need to support fixed point `moveM' instructions in and -;; out of floating point registers. Unfortunately, I have forgotten why this -;; was so, and I don't know whether it is still true. If `HARD_REGNO_MODE_OK' -;; rejects fixed point values in floating point registers, then the constraints -;; of the fixed point `moveM' instructions must be designed to avoid ever -;; trying to reload into a floating point register. - -(define_expand "movqi" - [(set (match_operand:QI 0 "general_operand" "") - (match_operand:QI 1 "general_operand" ""))] - "" - " -{ - if (!reload_in_progress && !reload_completed - && !register_operand (operands[0], QImode) - && !reg_or_0_operand (operands[1], QImode)) - operands[1] = copy_to_mode_reg (QImode, operands[1]); -}") - -(define_insn "*movqi_internal" - [(set (match_operand:QI 0 "move_output_operand" "=d,d,d,d,Q,m,Q,m,d,c") - (match_operand:QI 1 "move_input_operand" "dI,i,Q,m,d,d,O,O,c,d"))] - "register_operand (operands[0], QImode) || reg_or_0_operand (operands[1], QImode)" - "@ - or%: %0,%.,%1 - or%: %0,%.,%1 - ldb%: %0,%M1 - ldb%: %0,%M1 - stb%: %1,%M0 - stb%: %1,%M0 - stb%: %.,%M0 - stb%: %.,%M0 - mvfsys%: %0,%1 - mvtsys%: %0,%1" - [(set_attr "length" "4,8,4,8,4,8,4,8,4,4") - (set_attr "type" "either,long,sload,lload,mu,long,mu,long,mu,mu")]) - -(define_expand "movhi" - [(set (match_operand:HI 0 "general_operand" "") - (match_operand:HI 1 "general_operand" ""))] - "" - " -{ - if (!reload_in_progress && !reload_completed - && !register_operand (operands[0], HImode) - && !reg_or_0_operand (operands[1], HImode)) - operands[1] = copy_to_mode_reg (HImode, operands[1]); -}") - -(define_insn "*movhi_internal" - [(set (match_operand:HI 0 "move_output_operand" "=d,d,d,d,Q,m,Q,m,d,c") - (match_operand:HI 1 "move_input_operand" "dI,i,Q,m,d,d,O,O,c,d"))] - "register_operand (operands[0], HImode) || reg_or_0_operand (operands[1], HImode)" - "@ - or%: %0,%.,%1 - or%: %0,%.,%1 - ldh%: %0,%M1 - ldh%: %0,%M1 - sth%: %1,%M0 - sth%: %1,%M0 - sth%: %.,%M0 - sth%: %.,%M0 - mvfsys%: %0,%1 - mvtsys%: %0,%1" - [(set_attr "length" "4,8,4,8,4,8,4,8,4,4") - (set_attr "type" "either,long,sload,lload,mu,long,mu,long,mu,mu")]) - -(define_expand "movsi" - [(set (match_operand:SI 0 "general_operand" "") - (match_operand:SI 1 "general_operand" ""))] - "" - " -{ - if (!reload_in_progress && !reload_completed - && !register_operand (operands[0], SImode) - && !reg_or_0_operand (operands[1], SImode)) - operands[1] = copy_to_mode_reg (SImode, operands[1]); - - /* Convert addressing modes into the appropriate add/sub with the clobbers - needed. This is generated by builtin_setjmp in the exception handling. */ - if (GET_CODE (operands[1]) == PLUS) - { - emit_insn (gen_addsi3 (operands[0], XEXP (operands[1], 0), - XEXP (operands[1], 1))); - DONE; - } - - else if (GET_CODE (operands[1]) == MINUS) - { - emit_insn (gen_subsi3 (operands[0], XEXP (operands[1], 0), - XEXP (operands[1], 1))); - DONE; - } -}") - -(define_insn "*movsi_internal" - [(set (match_operand:SI 0 "move_output_operand" "=d,d,d,d,d,Q,m,Q,m,d,c") - (match_operand:SI 1 "move_input_operand" "dI,F,i,Q,m,d,d,O,O,c,d"))] - "register_operand (operands[0], SImode) || reg_or_0_operand (operands[1], SImode)" - "@ - or%: %0,%.,%1 - or%: %0,%.,%L1 - or%: %0,%.,%1 - ldw%: %0,%M1 - ldw%: %0,%M1 - stw%: %1,%M0 - stw%: %1,%M0 - stw%: %.,%M0 - stw%: %.,%M0 - mvfsys%: %0,%1 - mvtsys%: %0,%1" - [(set_attr "length" "4,8,8,4,8,4,8,4,8,4,4") - (set_attr "type" "either,long,long,sload,lload,mu,long,mu,long,mu,mu")]) - -(define_expand "movdi" - [(set (match_operand:DI 0 "general_operand" "") - (match_operand:DI 1 "general_operand" ""))] - "" - " -{ - if (!reload_in_progress && !reload_completed - && !register_operand (operands[0], DImode) - && !register_operand (operands[1], DImode)) - operands[1] = copy_to_mode_reg (DImode, operands[1]); -}") - -(define_insn "*movdi_internal" - [(set (match_operand:DI 0 "move_output_operand" "=e,e,e,e,Q,m,e,a,a") - (match_operand:DI 1 "move_input_operand" "eI,iF,Q,m,e,e,a,e,O"))] - "register_operand (operands[0], DImode) || register_operand (operands[1], DImode)" - "* return d30v_move_2words (operands, insn);" - [(set_attr "length" "8,16,4,8,4,8,8,4,4") - (set_attr "type" "multi,multi,sload,lload,mu,long,multi,iu,iu")]) - -(define_split - [(set (match_operand:DI 0 "gpr_operand" "") - (match_operand:DI 1 "gpr_or_dbl_const_operand" ""))] - "reload_completed" - [(set (match_dup 2) (match_dup 3)) - (set (match_dup 4) (match_dup 5))] - " -{ - d30v_split_double (operands[0], &operands[2], &operands[4]); - d30v_split_double (operands[1], &operands[3], &operands[5]); -}") - -(define_expand "movsf" - [(set (match_operand:SF 0 "general_operand" "") - (match_operand:SF 1 "general_operand" ""))] - "" - " -{ - if (!reload_in_progress && !reload_completed - && !register_operand (operands[0], SFmode) - && !reg_or_0_operand (operands[1], SFmode)) - operands[1] = copy_to_mode_reg (SFmode, operands[1]); -}") - -(define_insn "*movsf_internal" - [(set (match_operand:SF 0 "move_output_operand" "=d,d,d,d,d,Q,m,Q,m") - (match_operand:SF 1 "move_input_operand" "d,G,F,Q,m,d,d,G,G"))] - "register_operand (operands[0], SFmode) || reg_or_0_operand (operands[1], SFmode)" - "@ - or%: %0,%.,%1 - or%: %0,%.,0 - or%: %0,%.,%f1 - ldw%: %0,%M1 - ldw%: %0,%M1 - stw%: %1,%M0 - stw%: %1,%M0 - stw%: %.,%M0 - stw%: %.,%M0" - [(set_attr "length" "4,4,8,4,8,4,8,4,8") - (set_attr "type" "either,either,long,sload,lload,mu,long,mu,long")]) - -(define_expand "movdf" - [(set (match_operand:DF 0 "general_operand" "") - (match_operand:DF 1 "general_operand" ""))] - "" - " -{ - if (!reload_in_progress && !reload_completed - && !register_operand (operands[0], DFmode) - && !register_operand (operands[1], DFmode)) - operands[1] = copy_to_mode_reg (DFmode, operands[1]); -}") - -(define_insn "*movdf_internal" - [(set (match_operand:DF 0 "move_output_operand" "=e,e,e,e,Q,m,!*e,!*a") - (match_operand:DF 1 "move_input_operand" "eG,F,Q,m,e,e,!*a,!*e"))] - "register_operand (operands[0], DFmode) || register_operand (operands[1], DFmode)" - "* return d30v_move_2words (operands, insn);" - [(set_attr "length" "8,16,4,8,4,8,8,4") - (set_attr "type" "multi,multi,sload,lload,mu,long,multi,iu")]) - -(define_split - [(set (match_operand:DF 0 "gpr_operand" "") - (match_operand:DF 1 "gpr_or_dbl_const_operand" ""))] - "reload_completed" - [(set (match_dup 2) (match_dup 3)) - (set (match_dup 4) (match_dup 5))] - " -{ - d30v_split_double (operands[0], &operands[2], &operands[4]); - d30v_split_double (operands[1], &operands[3], &operands[5]); -}") - -(define_expand "movcc" - [(set (match_operand:CC 0 "general_operand" "") - (match_operand:CC 1 "general_operand" ""))] - "" - " -{ - if (!reload_in_progress && !reload_completed - && GET_CODE (operands[0]) == MEM - && GET_CODE (operands[1]) == MEM) - operands[1] = copy_to_mode_reg (CCmode, operands[1]); -}") - -(define_insn "*movcc_internal" - [(set (match_operand:CC 0 "move_output_operand" "=f,f,f,d,?d,f,d,*d,*d,*Q,*m") - (match_operand:CC 1 "move_input_operand" "f,O,N,b,f,d,dON,*Q,*m,*d,*d"))] - "!memory_operand (operands[0], CCmode) || !memory_operand (operands[1], CCmode)" - "@ - orfg%: %0,%1,%1 - andfg%: %0,%0,0 - orfg%: %0,%0,1 - # - mvfsys%: %0,%1 - cmpne%: %0,%1,0 - or%: %0,%.,%1 - ldb%: %0,%M1 - ldb%: %0,%M1 - stb%: %1,%M0 - stb%: %1,%M0" - [(set_attr "length" "4,4,4,8,4,4,4,4,8,4,8") - (set_attr "type" "either,either,either,multi,mu,mu,either,sload,lload,mu,long")]) - -(define_split - [(set (match_operand:CC 0 "gpr_operand" "") - (match_operand:CC 1 "br_flag_operand" ""))] - "reload_completed" - [(set (match_dup 2) - (const_int 0)) - (set (match_dup 2) - (if_then_else:SI (ne:CC (match_dup 1) - (const_int 0)) - (const_int 1) - (match_dup 2)))] - " -{ - operands[2] = gen_lowpart (SImode, operands[0]); -}") - - -;; :::::::::::::::::::: -;; :: -;; :: Conversions -;; :: -;; :::::::::::::::::::: - -;; Signed conversions from a smaller integer to a larger integer -(define_insn "extendqihi2" - [(set (match_operand:HI 0 "gpr_operand" "=d,d,d") - (sign_extend:HI (match_operand:QI 1 "gpr_or_memory_operand" "d,Q,m")))] - "" - "@ - # - ldb%: %0,%M1 - ldb%: %0,%M1" - [(set_attr "type" "multi,sload,lload") - (set_attr "length" "16,4,8")]) - -(define_split - [(set (match_operand:HI 0 "gpr_operand" "") - (sign_extend:HI (match_operand:QI 1 "gpr_operand" "")))] - "reload_completed" - [(match_dup 2) - (match_dup 3)] - " -{ - rtx op0 = gen_lowpart (SImode, operands[0]); - rtx op1 = gen_lowpart (SImode, operands[1]); - rtx shift = gen_rtx (CONST_INT, VOIDmode, 24); - - operands[2] = gen_ashlsi3 (op0, op1, shift); - operands[3] = gen_ashrsi3 (op0, op0, shift); -}") - -(define_insn "extendqisi2" - [(set (match_operand:SI 0 "gpr_operand" "=d,d,d") - (sign_extend:SI (match_operand:QI 1 "gpr_or_memory_operand" "d,Q,m")))] - "" - "@ - # - ldb%: %0,%M1 - ldb%: %0,%M1" - [(set_attr "type" "multi,sload,lload") - (set_attr "length" "16,4,8")]) - -(define_split - [(set (match_operand:SI 0 "gpr_operand" "") - (sign_extend:SI (match_operand:QI 1 "gpr_operand" "")))] - "reload_completed" - [(match_dup 2) - (match_dup 3)] - " -{ - rtx op0 = gen_lowpart (SImode, operands[0]); - rtx op1 = gen_lowpart (SImode, operands[1]); - rtx shift = gen_rtx (CONST_INT, VOIDmode, 24); - - operands[2] = gen_ashlsi3 (op0, op1, shift); - operands[3] = gen_ashrsi3 (op0, op0, shift); -}") - -(define_insn "extendhisi2" - [(set (match_operand:SI 0 "gpr_operand" "=d,d,d") - (sign_extend:SI (match_operand:HI 1 "gpr_or_memory_operand" "d,Q,m")))] - "" - "@ - # - ldh%: %0,%M1 - ldh%: %0,%M1" - [(set_attr "type" "multi,sload,lload") - (set_attr "length" "16,4,8")]) - -(define_split - [(set (match_operand:SI 0 "gpr_operand" "") - (sign_extend:SI (match_operand:HI 1 "gpr_operand" "")))] - "reload_completed" - [(match_dup 2) - (match_dup 3)] - " -{ - rtx op0 = gen_lowpart (SImode, operands[0]); - rtx op1 = gen_lowpart (SImode, operands[1]); - rtx shift = gen_rtx (CONST_INT, VOIDmode, 16); - - operands[2] = gen_ashlsi3 (op0, op1, shift); - operands[3] = gen_ashrsi3 (op0, op0, shift); -}") - -(define_insn "extendqidi2" - [(set (match_operand:DI 0 "gpr_operand" "=e,e,e") - (sign_extend:DI (match_operand:QI 1 "gpr_or_memory_operand" "d,Q,m")))] - "" - "#" - [(set_attr "length" "12,8,12") - (set_attr "type" "multi")]) - -(define_split - [(set (match_operand:DI 0 "gpr_operand" "") - (sign_extend:DI (match_operand:QI 1 "gpr_or_memory_operand" "")))] - "reload_completed" - [(set (match_dup 2) (sign_extend:SI (match_dup 1))) - (set (match_dup 3) (ashiftrt:SI (match_dup 2) (const_int 31)))] - " -{ - d30v_split_double (operands[0], &operands[3], &operands[2]); -}") - -(define_insn "extendhidi2" - [(set (match_operand:DI 0 "gpr_operand" "=e,e,e") - (sign_extend:DI (match_operand:HI 1 "gpr_or_memory_operand" "d,Q,m")))] - "" - "#" - [(set_attr "length" "12,8,12") - (set_attr "type" "multi")]) - -(define_split - [(set (match_operand:DI 0 "gpr_operand" "") - (sign_extend:DI (match_operand:HI 1 "gpr_or_memory_operand" "")))] - "reload_completed" - [(set (match_dup 2) (sign_extend:SI (match_dup 1))) - (set (match_dup 3) (ashiftrt:SI (match_dup 2) (const_int 31)))] - " -{ - d30v_split_double (operands[0], &operands[3], &operands[2]); -}") - -(define_insn "extendsidi2" - [(set (match_operand:DI 0 "gpr_operand" "=e,e,e") - (sign_extend:DI (match_operand:SI 1 "gpr_or_memory_operand" "d,Q,m")))] - "" - "#" - [(set_attr "length" "8,8,12") - (set_attr "type" "multi")]) - -(define_split - [(set (match_operand:DI 0 "gpr_operand" "") - (sign_extend:DI (match_operand:SI 1 "gpr_or_memory_operand" "")))] - "reload_completed" - [(set (match_dup 2) (match_dup 1)) - (set (match_dup 3) (ashiftrt:SI (match_dup 2) (const_int 31)))] - " -{ - d30v_split_double (operands[0], &operands[3], &operands[2]); -}") - -;; Unsigned conversions from a smaller integer to a larger integer - -(define_insn "zero_extendqihi2" - [(set (match_operand:HI 0 "gpr_operand" "=d,d,d") - (zero_extend:HI (match_operand:QI 1 "gpr_or_memory_operand" "d,Q,m")))] - "" - "@ - and%: %0,%1,0xff - ldbu%: %0,%M1 - ldbu%: %0,%M1" - [(set_attr "length" "8,4,8") - (set_attr "type" "long,sload,lload")]) - -(define_insn "zero_extendqisi2" - [(set (match_operand:SI 0 "gpr_operand" "=d,d,d") - (zero_extend:SI (match_operand:QI 1 "gpr_or_memory_operand" "d,Q,m")))] - "" - "@ - and%: %0,%1,0xff - ldbu%: %0,%M1 - ldbu%: %0,%M1" - [(set_attr "length" "8,4,8") - (set_attr "type" "long,sload,lload")]) - -(define_insn "zero_extendhisi2" - [(set (match_operand:SI 0 "gpr_operand" "=d,d,d") - (zero_extend:SI (match_operand:HI 1 "gpr_or_memory_operand" "d,Q,m")))] - "" - "@ - and%: %0,%1,0xffff - ldhu%: %0,%M1 - ldhu%: %0,%M1" - [(set_attr "length" "8,4,8") - (set_attr "type" "long,sload,lload")]) - -(define_insn "zero_extendqidi2" - [(set (match_operand:DI 0 "gpr_operand" "=e,e,e") - (zero_extend:DI (match_operand:QI 1 "gpr_or_memory_operand" "d,Q,m")))] - "" - "#" - [(set_attr "length" "12,8,12") - (set_attr "type" "multi")]) - -(define_split - [(set (match_operand:DI 0 "gpr_operand" "") - (zero_extend:DI (match_operand:QI 1 "gpr_or_memory_operand" "")))] - "reload_completed" - [(set (match_dup 2) (zero_extend:SI (match_dup 1))) - (set (match_dup 3) (const_int 0))] - " -{ - d30v_split_double (operands[0], &operands[3], &operands[2]); -}") - -(define_insn "zero_extendhidi2" - [(set (match_operand:DI 0 "gpr_operand" "=e,e,e") - (zero_extend:DI (match_operand:HI 1 "gpr_or_memory_operand" "d,Q,m")))] - "" - "#" - [(set_attr "length" "8,8,12") - (set_attr "type" "multi")]) - -(define_split - [(set (match_operand:DI 0 "gpr_operand" "") - (zero_extend:DI (match_operand:HI 1 "gpr_or_memory_operand" "")))] - "reload_completed" - [(set (match_dup 2) (zero_extend:SI (match_dup 1))) - (set (match_dup 3) (const_int 0))] - " -{ - d30v_split_double (operands[0], &operands[3], &operands[2]); -}") - -(define_insn "zero_extendsidi2" - [(set (match_operand:DI 0 "gpr_operand" "=e,e,e") - (zero_extend:DI (match_operand:SI 1 "gpr_or_memory_operand" "d,Q,m")))] - "" - "#" - [(set_attr "length" "8,8,12") - (set_attr "type" "multi")]) - -(define_split - [(set (match_operand:DI 0 "gpr_operand" "") - (zero_extend:DI (match_operand:SI 1 "gpr_or_memory_operand" "")))] - "reload_completed" - [(set (match_dup 2) (match_dup 1)) - (set (match_dup 3) (const_int 0))] - " -{ - d30v_split_double (operands[0], &operands[3], &operands[2]); -}") - - -;; :::::::::::::::::::: -;; :: -;; :: 32 bit Integer arithmetic -;; :: -;; :::::::::::::::::::: - -;; Addition -(define_expand "addsi3" - [(parallel [(set (match_operand:SI 0 "gpr_operand" "") - (plus:SI (match_operand:SI 1 "gpr_operand" "") - (match_operand:SI 2 "gpr_or_constant_operand" ""))) - (clobber (match_dup 3)) - (clobber (match_dup 4)) - (clobber (match_dup 5))])] - "" - " -{ - operands[3] = gen_rtx (REG, CCmode, FLAG_CARRY); - operands[4] = gen_rtx (REG, CCmode, FLAG_OVERFLOW); - operands[5] = gen_rtx (REG, CCmode, FLAG_ACC_OVER); -}") - -(define_insn "*addsi3_internal" - [(set (match_operand:SI 0 "gpr_operand" "=d,d") - (plus:SI (match_operand:SI 1 "gpr_operand" "%d,d") - (match_operand:SI 2 "gpr_or_constant_operand" "dI,i"))) - (clobber (match_operand:CC 3 "flag_operand" "=f,f")) - (clobber (match_operand:CC 4 "flag_operand" "=f,f")) - (clobber (match_operand:CC 5 "flag_operand" "=f,f"))] - "" - "add%: %0,%1,%2" - [(set_attr "length" "4,8") - (set_attr "type" "either,long")]) - -;; Subtraction -(define_expand "subsi3" - [(parallel [(set (match_operand:SI 0 "gpr_operand" "") - (minus:SI (match_operand:SI 1 "reg_or_0_operand" "") - (match_operand:SI 2 "gpr_or_constant_operand" ""))) - (clobber (match_dup 3)) - (clobber (match_dup 4)) - (clobber (match_dup 5))])] - "" - " -{ - operands[3] = gen_rtx (REG, CCmode, FLAG_CARRY); - operands[4] = gen_rtx (REG, CCmode, FLAG_OVERFLOW); - operands[5] = gen_rtx (REG, CCmode, FLAG_ACC_OVER); -}") - -(define_insn "*subsi3_internal" - [(set (match_operand:SI 0 "gpr_operand" "=d,d,d,d") - (minus:SI (match_operand:SI 1 "reg_or_0_operand" "d,d,O,O") - (match_operand:SI 2 "gpr_or_constant_operand" "dI,i,dI,i"))) - (clobber (match_operand:CC 3 "flag_operand" "=f,f,f,f")) - (clobber (match_operand:CC 4 "flag_operand" "=f,f,f,f")) - (clobber (match_operand:CC 5 "flag_operand" "=f,f,f,f"))] - "" - "@ - sub%: %0,%1,%2 - sub%: %0,%1,%2 - sub%: %0,%.,%2 - sub%: %0,%.,%2" - [(set_attr "length" "4,8,4,8") - (set_attr "type" "either,long,either,long")]) - -;; Multiplication (same size) -(define_insn "mulsi3" - [(set (match_operand:SI 0 "gpr_operand" "=d") - (mult:SI (match_operand:SI 1 "gpr_operand" "%d") - (match_operand:SI 2 "gpr_or_signed6_operand" "dI")))] - "" - "mul%: %0,%1,%2" - [(set_attr "length" "4") - (set_attr "type" "mul")]) - -;; Signed multiplication producing 64 bit results from 32 bit inputs -(define_insn "mulsidi3" - [(set (match_operand:DI 0 "accum_operand" "=a") - (mult:DI (sign_extend:DI (match_operand:SI 1 "gpr_operand" "d")) - (sign_extend:DI (match_operand:SI 2 "gpr_operand" "d"))))] - "" - "mulx%: %0,%1,%2" - [(set_attr "length" "4") - (set_attr "type" "mul")]) - -(define_insn "*mulsidi3_const" - [(set (match_operand:DI 0 "accum_operand" "=a") - (mult:DI (sign_extend:DI (match_operand:SI 1 "gpr_operand" "%d")) - (match_operand:DI 2 "signed6_operand" "I")))] - "" - "mulx%: %0,%1,%2" - [(set_attr "length" "4") - (set_attr "type" "mul")]) - -;; Signed multiplication producing just the upper 32 bits from a 32x32->64 -;; bit multiply. We specifically allow any integer constant here so -;; allow division by constants to be done by multiplying by a large constant. - -(define_expand "smulsi3_highpart" - [(set (match_dup 3) - (mult:DI (sign_extend:DI (match_operand:SI 1 "gpr_operand" "")) - (match_operand:SI 2 "gpr_or_constant_operand" ""))) - (set (match_operand:SI 0 "gpr_operand" "") - (truncate:SI (lshiftrt:DI (match_dup 3) - (const_int 32))))] - "" - " -{ - operands[3] = gen_reg_rtx (DImode); - - if (GET_CODE (operands[2]) == CONST_INT && - !IN_RANGE_P (INTVAL (operands[2]), -32, 31)) - operands[2] = force_reg (SImode, operands[2]); - - if (GET_CODE (operands[2]) == REG || GET_CODE (operands[2]) == SUBREG) - operands[2] = gen_rtx (SIGN_EXTEND, DImode, operands[2]); -}") - -(define_insn "*di_highpart" - [(set (match_operand:SI 0 "gpr_operand" "=d,d") - (truncate:SI (lshiftrt:DI (match_operand:DI 1 "gpr_or_accum_operand" "e,a") - (const_int 32))))] - "" - "@ - or%: %0,%.,%U1 - mvfacc%: %0,%1,32" - [(set_attr "length" "4") - (set_attr "type" "either,iu")]) - -;; Negation -(define_expand "negsi2" - [(parallel [(set (match_operand:SI 0 "gpr_operand" "") - (neg:SI (match_operand:SI 1 "gpr_operand" ""))) - (clobber (match_dup 2)) - (clobber (match_dup 3)) - (clobber (match_dup 4))])] - "" - " -{ - operands[2] = gen_rtx (REG, CCmode, FLAG_CARRY); - operands[3] = gen_rtx (REG, CCmode, FLAG_OVERFLOW); - operands[4] = gen_rtx (REG, CCmode, FLAG_ACC_OVER); -}") - -(define_insn "*negsi2_internal" - [(set (match_operand:SI 0 "gpr_operand" "=d") - (neg:SI (match_operand:SI 1 "gpr_operand" "d"))) - (clobber (match_operand:CC 2 "flag_operand" "=f")) - (clobber (match_operand:CC 3 "flag_operand" "=f")) - (clobber (match_operand:CC 4 "flag_operand" "=f"))] - "" - "sub%: %0,%.,%1" - [(set_attr "length" "4") - (set_attr "type" "either")]) - -;; Absolute value -(define_insn "abssi2" - [(set (match_operand:SI 0 "gpr_operand" "=d") - (abs:SI (match_operand:SI 1 "gpr_operand" "d")))] - "" - "abs%: %0,%1" - [(set_attr "length" "4") - (set_attr "type" "either")]) - - -;; :::::::::::::::::::: -;; :: -;; :: 64 bit Integer arithmetic -;; :: -;; :::::::::::::::::::: - -;; Addition -(define_expand "adddi3" - [(parallel [(set (match_operand:DI 0 "gpr_operand" "") - (plus:DI (match_operand:DI 1 "gpr_operand" "") - (match_operand:DI 2 "gpr_or_constant_operand" ""))) - (clobber (match_dup 3)) - (clobber (match_dup 4)) - (clobber (match_dup 5))])] - "" - " -{ - operands[3] = gen_rtx (REG, CCmode, FLAG_CARRY); - operands[4] = gen_rtx (REG, CCmode, FLAG_OVERFLOW); - operands[5] = gen_rtx (REG, CCmode, FLAG_ACC_OVER); -}") - -(define_insn "*adddi3_internal" - [(set (match_operand:DI 0 "gpr_operand" "=e,e,e,e") - (plus:DI (match_operand:DI 1 "gpr_operand" "%e,e,e,e") - (match_operand:DI 2 "gpr_or_constant_operand" "I,i,e,F"))) - (clobber (match_operand:CC 3 "flag_operand" "=f,f,f,f")) - (clobber (match_operand:CC 4 "flag_operand" "=f,f,f,f")) - (clobber (match_operand:CC 5 "flag_operand" "=f,f,f,f"))] - "" - "#" - [(set_attr "length" "8,12,8,16") - (set_attr "type" "multi")]) - -(define_insn "addsi3_set_carry" - [(set (match_operand:SI 0 "gpr_operand" "=d,d") - (plus:SI (match_operand:SI 1 "gpr_operand" "%d,d") - (match_operand:SI 2 "gpr_or_constant_operand" "dI,i"))) - (set (match_operand:CC 3 "carry_operand" "=f,f") - (unspec:CC [(match_dup 1) - (match_dup 2)] 1)) - (clobber (match_operand:CC 4 "flag_operand" "=f,f")) - (clobber (match_operand:CC 5 "flag_operand" "=f,f"))] - "" - "add%: %0,%1,%2" - [(set_attr "length" "4,8") - (set_attr "type" "scarry,lcarry")]) - -(define_insn "addsi3_use_carry" - [(set (match_operand:SI 0 "gpr_operand" "=d,d") - (unspec:SI [(match_operand:SI 1 "gpr_operand" "%d,d") - (match_operand:SI 2 "gpr_or_constant_operand" "dI,i") - (match_operand:CC 3 "carry_operand" "+f,f")] 2)) - (clobber (match_operand:CC 4 "flag_operand" "=f,f")) - (clobber (match_operand:CC 5 "flag_operand" "=f,f"))] - "" - "addc%: %0,%1,%2" - [(set_attr "length" "4,8") - (set_attr "type" "scarry,lcarry")]) - -(define_split - [(set (match_operand:DI 0 "gpr_operand" "") - (plus:DI (match_operand:DI 1 "gpr_operand" "") - (match_operand:DI 2 "gpr_or_constant_operand" ""))) - (clobber (match_operand:CC 3 "flag_operand" "")) - (clobber (match_operand:CC 4 "flag_operand" "")) - (clobber (match_operand:CC 5 "flag_operand" ""))] - "reload_completed" - [(match_dup 6) - (match_dup 7)] - " -{ - rtx high[3]; - rtx low[3]; - - d30v_split_double (operands[0], &high[0], &low[0]); - d30v_split_double (operands[1], &high[1], &low[1]); - d30v_split_double (operands[2], &high[2], &low[2]); - - operands[6] = gen_addsi3_set_carry (low[0], low[1], low[2], operands[3], - operands[4], operands[5]); - - operands[7] = gen_addsi3_use_carry (high[0], high[1], high[2], operands[3], - operands[4], operands[5]); -}") - -;; Subtraction -(define_expand "subdi3" - [(parallel [(set (match_operand:DI 0 "gpr_operand" "") - (minus:DI (match_operand:DI 1 "gpr_operand" "") - (match_operand:DI 2 "gpr_or_constant_operand" ""))) - (clobber (match_dup 3)) - (clobber (match_dup 4)) - (clobber (match_dup 5))])] - "" - " -{ - operands[3] = gen_rtx (REG, CCmode, FLAG_CARRY); - operands[4] = gen_rtx (REG, CCmode, FLAG_OVERFLOW); - operands[5] = gen_rtx (REG, CCmode, FLAG_ACC_OVER); -}") - -(define_insn "*subdi3_internal" - [(set (match_operand:DI 0 "gpr_operand" "=e,e,e,e") - (minus:DI (match_operand:DI 1 "gpr_operand" "e,e,e,e") - (match_operand:DI 2 "gpr_or_constant_operand" "I,i,e,F"))) - (clobber (match_operand:CC 3 "flag_operand" "=f,f,f,f")) - (clobber (match_operand:CC 4 "flag_operand" "=f,f,f,f")) - (clobber (match_operand:CC 5 "flag_operand" "=f,f,f,f"))] - "" - "#" - [(set_attr "length" "8,12,8,16") - (set_attr "type" "multi")]) - -(define_insn "subsi3_set_carry" - [(set (match_operand:SI 0 "gpr_operand" "=d,d,d,d") - (minus:SI (match_operand:SI 1 "reg_or_0_operand" "d,d,O,O") - (match_operand:SI 2 "gpr_or_constant_operand" "dI,i,dI,i"))) - (set (match_operand:CC 3 "carry_operand" "=f,f,f,f") - (unspec:CC [(match_dup 1) - (match_dup 2)] 3)) - (clobber (match_operand:CC 4 "flag_operand" "=f,f,f,f")) - (clobber (match_operand:CC 5 "flag_operand" "=f,f,f,f"))] - "" - "@ - sub%: %0,%1,%2 - sub%: %0,%1,%2 - sub%: %0,%.,%2 - sub%: %0,%.,%2" - [(set_attr "length" "4,8,4,8") - (set_attr "type" "scarry,lcarry,scarry,lcarry")]) - -(define_insn "subsi3_use_carry" - [(set (match_operand:SI 0 "gpr_operand" "=d,d,d,d") - (unspec:SI [(match_operand:SI 1 "reg_or_0_operand" "d,d,O,O") - (match_operand:SI 2 "gpr_operand" "dI,i,dI,i") - (match_operand:CC 3 "carry_operand" "+f,f,f,f")] 4)) - (clobber (match_operand:CC 4 "flag_operand" "=f,f,f,f")) - (clobber (match_operand:CC 5 "flag_operand" "=f,f,f,f"))] - "" - "@ - subb%: %0,%1,%2 - subb%: %0,%1,%2 - subb%: %0,%.,%2 - subb%: %0,%.,%2" - [(set_attr "length" "4,8,4,8") - (set_attr "type" "scarry,lcarry,scarry,lcarry")]) - -(define_split - [(set (match_operand:DI 0 "gpr_operand" "") - (minus:DI (match_operand:DI 1 "gpr_operand" "") - (match_operand:DI 2 "gpr_or_constant_operand" ""))) - (clobber (match_operand:CC 3 "flag_operand" "")) - (clobber (match_operand:CC 4 "flag_operand" "")) - (clobber (match_operand:CC 5 "flag_operand" ""))] - "reload_completed" - [(match_dup 6) - (match_dup 7)] - " -{ - rtx high[3]; - rtx low[3]; - - d30v_split_double (operands[0], &high[0], &low[0]); - d30v_split_double (operands[1], &high[1], &low[1]); - d30v_split_double (operands[2], &high[2], &low[2]); - - operands[6] = gen_subsi3_set_carry (low[0], low[1], low[2], operands[3], - operands[4], operands[5]); - - operands[7] = gen_subsi3_use_carry (high[0], high[1], high[2], operands[3], - operands[4], operands[5]); -}") - -;; Negation -(define_expand "negdi2" - [(parallel [(set (match_operand:DI 0 "gpr_operand" "") - (neg:DI (match_operand:DI 1 "gpr_operand" ""))) - (clobber (match_dup 2)) - (clobber (match_dup 3)) - (clobber (match_dup 4))])] - "" - " -{ - operands[2] = gen_rtx (REG, CCmode, FLAG_CARRY); - operands[3] = gen_rtx (REG, CCmode, FLAG_OVERFLOW); - operands[4] = gen_rtx (REG, CCmode, FLAG_ACC_OVER); -}") - -(define_insn "*negdi2_internal" - [(set (match_operand:DI 0 "gpr_operand" "=e") - (neg:DI (match_operand:DI 1 "gpr_operand" "e"))) - (clobber (match_operand:CC 2 "flag_operand" "=f")) - (clobber (match_operand:CC 3 "flag_operand" "=f")) - (clobber (match_operand:CC 4 "flag_operand" "=f"))] - "" - "#" - [(set_attr "length" "8") - (set_attr "type" "multi")]) - -(define_split - [(set (match_operand:DI 0 "gpr_operand" "=e") - (neg:DI (match_operand:DI 1 "gpr_operand" "e"))) - (clobber (match_operand:CC 2 "flag_operand" "=f")) - (clobber (match_operand:CC 3 "flag_operand" "=f")) - (clobber (match_operand:CC 4 "flag_operand" "=f"))] - "reload_completed" - [(match_dup 5) - (match_dup 6)] - " -{ - rtx high[2]; - rtx low[2]; - rtx r0 = const0_rtx; - - d30v_split_double (operands[0], &high[0], &low[0]); - d30v_split_double (operands[1], &high[1], &low[1]); - - operands[5] = gen_subsi3_set_carry (low[0], r0, low[1], operands[2], - operands[3], operands[4]); - - operands[6] = gen_subsi3_use_carry (high[0], r0, high[1], operands[2], - operands[3], operands[4]); -}") - - -;; :::::::::::::::::::: -;; :: -;; :: 32 bit Integer Shifts and Rotates -;; :: -;; :::::::::::::::::::: - -;; Arithmetic Shift Left (negate the shift value and use shift right) -(define_expand "ashlsi3" - [(set (match_operand:SI 0 "gpr_operand" "") - (ashift:SI (match_operand:SI 1 "gpr_operand" "") - (match_operand:SI 2 "gpr_or_unsigned5_operand" "")))] - "" - " -{ - if (GET_CODE (operands[2]) != CONST_INT) - operands[2] = gen_rtx (NEG, SImode, negate_rtx (SImode, operands[2])); -}") - -(define_insn "*ashlsi3_constant" - [(set (match_operand:SI 0 "gpr_operand" "=d") - (ashift:SI (match_operand:SI 1 "gpr_operand" "d") - (match_operand:SI 2 "unsigned5_operand" "J")))] - "" - "sra%: %0,%1,%n2" - [(set_attr "length" "4") - (set_attr "type" "either")]) - -(define_insn "*ashlsi3_register" - [(set (match_operand:SI 0 "gpr_operand" "=d") - (ashift:SI (match_operand:SI 1 "gpr_operand" "d") - (neg:SI (match_operand:SI 2 "gpr_operand" "d"))))] - "" - "sra%: %0,%1,%2" - [(set_attr "length" "4") - (set_attr "type" "either")]) - -;; Arithmetic Shift Right -(define_insn "ashrsi3" - [(set (match_operand:SI 0 "gpr_operand" "=d") - (ashiftrt:SI (match_operand:SI 1 "gpr_operand" "d") - (match_operand:SI 2 "gpr_or_unsigned5_operand" "dJ")))] - "" - "sra%: %0,%1,%2" - [(set_attr "length" "4")]) - -;; Logical Shift Right -(define_insn "lshrsi3" - [(set (match_operand:SI 0 "gpr_operand" "=d") - (lshiftrt:SI (match_operand:SI 1 "gpr_operand" "d") - (match_operand:SI 2 "gpr_or_unsigned5_operand" "dJ")))] - "" - "srl%: %0,%1,%2" - [(set_attr "length" "4") - (set_attr "type" "either")]) - -;; Rotate Left (negate the shift value and use rotate right) -(define_expand "rotlsi3" - [(set (match_operand:SI 0 "gpr_operand" "") - (rotate:SI (match_operand:SI 1 "gpr_operand" "") - (match_operand:SI 2 "gpr_or_unsigned5_operand" "")))] - "" - " -{ - if (GET_CODE (operands[2]) != CONST_INT) - operands[2] = gen_rtx (NEG, SImode, negate_rtx (SImode, operands[2])); -}") - -(define_insn "*rotlsi3_constant" - [(set (match_operand:SI 0 "gpr_operand" "=d") - (rotate:SI (match_operand:SI 1 "gpr_operand" "d") - (match_operand:SI 2 "unsigned5_operand" "J")))] - "" - "rot%: %0,%1,%n2" - [(set_attr "length" "4") - (set_attr "type" "either")]) - -(define_insn "*rotlsi3_register" - [(set (match_operand:SI 0 "gpr_operand" "=d") - (rotate:SI (match_operand:SI 1 "gpr_operand" "d") - (neg:SI (match_operand:SI 2 "gpr_operand" "d"))))] - "" - "rot%: %0,%1,%2" - [(set_attr "length" "4") - (set_attr "type" "either")]) - -;; Rotate Right -(define_insn "rotrsi3" - [(set (match_operand:SI 0 "gpr_operand" "=d") - (rotatert:SI (match_operand:SI 1 "gpr_operand" "d") - (match_operand:SI 2 "gpr_or_unsigned5_operand" "dJ")))] - "" - "rot%: %0,%1,%2" - [(set_attr "length" "4") - (set_attr "type" "either")]) - - -;; :::::::::::::::::::: -;; :: -;; :: 64 bit Integer Shifts and Rotates -;; :: -;; :::::::::::::::::::: - -;; Arithmetic Shift Left -(define_expand "ashldi3" - [(parallel [(set (match_operand:DI 0 "gpr_operand" "") - (ashift:DI (match_operand:DI 1 "gpr_operand" "") - (match_operand:SI 2 "gpr_or_unsigned6_operand" ""))) - (clobber (match_scratch:CC 3 ""))])] - "" - " -{ - if (GET_CODE (operands[2]) == CONST_INT) - { - if (IN_RANGE_P (INTVAL (operands[2]), 0, 63)) - { - emit_insn (gen_ashldi3_constant (operands[0], operands[1], operands[2])); - DONE; - } - else - operands[2] = copy_to_mode_reg (SImode, operands[2]); - } - - operands[2] = gen_rtx (NEG, SImode, negate_rtx (SImode, operands[2])); -}") - -(define_insn "ashldi3_constant" - [(set (match_operand:DI 0 "gpr_operand" "=e,e") - (ashift:DI (match_operand:DI 1 "gpr_operand" "0,e") - (match_operand:SI 2 "unsigned6_operand" "J,P")))] - "" - "@ - src%: %U0,%L0,%n2\;sra%: %L0,%L0,%n2 - sra%: %U0,%L1,%s2\;or%: %L0,%.,0" - [(set_attr "length" "8") - (set_attr "type" "multi")]) - -(define_insn "*ashldi3_register" - [(set (match_operand:DI 0 "gpr_operand" "=e") - (ashift:DI (match_operand:DI 1 "gpr_operand" "0") - (neg:SI (match_operand:SI 2 "gpr_operand" "d")))) - (clobber (match_scratch:CC 3 "=b"))] - "" - "cmpge %3,%2,-31\;src%T3 %U0,%L0,%2\;sra%T3 %L0,%L0,%2\;sub%F3 %U0,%2,-32\;sra%F3 %U0,%L0,%U0\;or%F3 %L0,%.,0" - [(set_attr "length" "32") - (set_attr "type" "multi") - ;; Not strictly true, since we ought to be able to combine conditions, - (set_attr "predicable" "no")]) - -;; Arithmetic Shift Right -(define_insn "ashrdi3" - [(set (match_operand:DI 0 "gpr_operand" "=e,e,e") - (ashiftrt:DI (match_operand:DI 1 "gpr_operand" "0,e,0") - (match_operand:SI 2 "gpr_or_unsigned6_operand" "J,P,d"))) - (clobber (match_scratch:CC 3 "=X,X,b"))] - "" - "@ - src %L0,%U0,%2\;sra %U0,%U0,%2 - sra %L0,%U1,%S2\;sra %U0,%L0,31 - cmple %3,%2,31\;src%T3 %L0,%U0,%2\;sra%T3 %U0,%U0,%2\;add%F3 %L0,%2,-32\;sra%F3 %L0,%U0,%L0\;sra%F3 %U0,%U0,31" - [(set_attr "length" "8,8,28") - (set_attr "type" "multi") - ;; Not strictly true, since we ought to be able to combine conditions, - (set_attr "predicable" "no")]) - -;; Logical Shift Right - -(define_insn "lshrdi3" - [(set (match_operand:DI 0 "gpr_operand" "=e,e,e") - (lshiftrt:DI (match_operand:DI 1 "gpr_operand" "0,e,0") - (match_operand:SI 2 "gpr_or_unsigned6_operand" "J,P,d"))) - (clobber (match_scratch:CC 3 "=X,X,b"))] - "" - "@ - src %L0,%U0,%2\;srl %U0,%U0,%2 - srl %L0,%U1,%S2\;or %U0,%.,0 - cmple %3,%2,31\;src%T3 %L0,%U0,%2\;srl%T3 %U0,%U0,%2\;add%F3 %L0,%2,-32\;srl%F3 %L0,%U0,%L0\;or%F3 %U0,%.,0" - [(set_attr "length" "8,8,28") - (set_attr "type" "multi") - ;; Not strictly true, since we ought to be able to combine conditions, - (set_attr "predicable" "no")]) - - -;; :::::::::::::::::::: -;; :: -;; :: 32 Bit Integer Logical operations -;; :: -;; :::::::::::::::::::: - -;; Logical AND, 32 bit integers - -(define_insn "andsi3" - [(set (match_operand:SI 0 "gpr_operand" "=d,d,d,d") - (and:SI (match_operand:SI 1 "gpr_operand" "%d,d,d,d") - (match_operand:SI 2 "gpr_or_constant_operand" "L,I,i,d")))] - "" - "@ - bclr%: %0,%1,%B2 - and%: %0,%1,%2 - and%: %0,%1,%2 - and%: %0,%1,%2" - [(set_attr "length" "4,4,8,4") - (set_attr "type" "either,either,long,either")]) - -;; Inclusive OR, 32 bit integers - -(define_insn "iorsi3" - [(set (match_operand:SI 0 "gpr_operand" "=d,d,d,d") - (ior:SI (match_operand:SI 1 "gpr_operand" "%d,d,d,d") - (match_operand:SI 2 "gpr_or_constant_operand" "K,I,i,d")))] - "" - "@ - bset%: %0,%1,%B2 - or%: %0,%1,%2 - or%: %0,%1,%2 - or%: %0,%1,%2" - [(set_attr "length" "4,4,8,4") - (set_attr "type" "either,either,long,either")]) - -;; Exclusive OR, 32 bit integers - -(define_insn "*xorsi3_constant" - [(set (match_operand:SI 0 "gpr_operand" "=d,d,d,d") - (xor:SI (match_operand:SI 1 "gpr_operand" "%d,d,d,d") - (match_operand:SI 2 "gpr_or_constant_operand" "K,I,i,d")))] - "" - "@ - bnot%: %0,%1,%B2 - xor%: %0,%1,%2 - xor%: %0,%1,%2 - xor%: %0,%1,%2" - [(set_attr "length" "4,4,8,4") - (set_attr "type" "either,either,long,either")]) - -;; One's complement, 32 bit integers -(define_insn "one_cmplsi2" - [(set (match_operand:SI 0 "gpr_operand" "=d") - (not:SI (match_operand:SI 1 "gpr_operand" "d")))] - "" - "not%: %0,%1" - [(set_attr "length" "4") - (set_attr "type" "either")]) - - -;; :::::::::::::::::::: -;; :: -;; :: 64 Bit Integer Logical operations -;; :: -;; :::::::::::::::::::: - -;; Logical AND, 64 bit integers -(define_insn "anddi3" - [(set (match_operand:DI 0 "gpr_operand" "=e,e,&e,e,e,e") - (and:DI (match_operand:DI 1 "gpr_operand" "%e,0,e,e,e,e") - (match_operand:DI 2 "gpr_or_dbl_const_operand" "0,e,e,I,i,F")))] - "" - "#" - [(set_attr "length" "8,8,8,8,12,16") - (set_attr "type" "multi")]) - -(define_split - [(set (match_operand:DI 0 "gpr_operand" "") - (and:DI (match_operand:DI 1 "gpr_operand" "") - (match_operand:DI 2 "gpr_or_dbl_const_operand" "")))] - "reload_completed" - [(set (match_dup 3) (and:SI (match_dup 4) (match_dup 5))) - (set (match_dup 6) (and:SI (match_dup 7) (match_dup 8)))] - " -{ - d30v_split_double (operands[0], &operands[3], &operands[6]); - d30v_split_double (operands[1], &operands[4], &operands[7]); - d30v_split_double (operands[2], &operands[5], &operands[8]); -}") - -;; Includive OR, 64 bit integers -(define_insn "iordi3" - [(set (match_operand:DI 0 "gpr_operand" "=e,e,&e,e,e,e") - (ior:DI (match_operand:DI 1 "gpr_operand" "%e,0,e,e,e,e") - (match_operand:DI 2 "gpr_or_dbl_const_operand" "0,e,e,I,i,F")))] - "" - "#" - [(set_attr "length" "8,8,8,8,12,16") - (set_attr "type" "multi")]) - -(define_split - [(set (match_operand:DI 0 "gpr_operand" "") - (ior:DI (match_operand:DI 1 "gpr_operand" "") - (match_operand:DI 2 "gpr_or_dbl_const_operand" "")))] - "reload_completed" - [(set (match_dup 3) (ior:SI (match_dup 4) (match_dup 5))) - (set (match_dup 6) (ior:SI (match_dup 7) (match_dup 8)))] - " -{ - d30v_split_double (operands[0], &operands[3], &operands[6]); - d30v_split_double (operands[1], &operands[4], &operands[7]); - d30v_split_double (operands[2], &operands[5], &operands[8]); -}") - -;; Excludive OR, 64 bit integers -(define_insn "xordi3" - [(set (match_operand:DI 0 "gpr_operand" "=e,e,&e,e,e,e") - (xor:DI (match_operand:DI 1 "gpr_operand" "%e,0,e,e,e,e") - (match_operand:DI 2 "gpr_or_dbl_const_operand" "0,e,e,I,i,F")))] - "" - "#" - [(set_attr "length" "8,8,8,8,12,16") - (set_attr "type" "multi")]) - -(define_split - [(set (match_operand:DI 0 "gpr_operand" "") - (xor:DI (match_operand:DI 1 "gpr_operand" "") - (match_operand:DI 2 "gpr_or_dbl_const_operand" "")))] - "reload_completed" - [(set (match_dup 3) (xor:SI (match_dup 4) (match_dup 5))) - (set (match_dup 6) (xor:SI (match_dup 7) (match_dup 8)))] - " -{ - d30v_split_double (operands[0], &operands[3], &operands[6]); - d30v_split_double (operands[1], &operands[4], &operands[7]); - d30v_split_double (operands[2], &operands[5], &operands[8]); -}") - -;; One's complement, 64 bit integers -(define_insn "one_cmpldi2" - [(set (match_operand:DI 0 "gpr_operand" "=e,&e") - (not:DI (match_operand:DI 1 "gpr_operand" "0,e")))] - "" - "#" - [(set_attr "length" "8") - (set_attr "type" "multi")]) - -(define_split - [(set (match_operand:DI 0 "gpr_operand" "") - (not:DI (match_operand:DI 1 "gpr_operand" "")))] - "reload_completed" - [(set (match_dup 3) (not:SI (match_dup 4))) - (set (match_dup 5) (not:SI (match_dup 6)))] - " -{ - d30v_split_double (operands[0], &operands[3], &operands[5]); - d30v_split_double (operands[1], &operands[4], &operands[6]); -}") - - -;; :::::::::::::::::::: -;; :: -;; :: Multiply and accumulate instructions -;; :: -;; :::::::::::::::::::: - -(define_insn "*mac_reg" - [(set (match_operand:DI 0 "accum_operand" "+a") - (plus:DI (match_dup 0) - (mult:DI (sign_extend:DI (match_operand:SI 1 "gpr_operand" "%d")) - (sign_extend:DI (match_operand:SI 2 "gpr_operand" "d")))))] - "" - "mac%A0%: %.,%1,%2" - [(set_attr "length" "4") - (set_attr "type" "mul")]) - -(define_insn "*mac_const" - [(set (match_operand:DI 0 "accum_operand" "+a") - (plus:DI (match_dup 0) - (mult:DI (sign_extend:DI (match_operand:SI 1 "gpr_operand" "%d")) - (match_operand:DI 2 "signed6_operand" "I"))))] - "" - "mac%A0%: %.,%1,%2" - [(set_attr "length" "4") - (set_attr "type" "mul")]) - -(define_insn "*macs_reg" - [(set (match_operand:DI 0 "accum_operand" "+a") - (plus:DI (match_dup 0) - (ashift:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "gpr_operand" "%d")) - (sign_extend:DI (match_operand:SI 2 "gpr_operand" "d"))) - (const_int 1))))] - "" - "macs%A0%: %.,%1,%2" - [(set_attr "length" "4") - (set_attr "type" "mul")]) - -(define_insn "*macs_const" - [(set (match_operand:DI 0 "accum_operand" "+a") - (plus:DI (match_dup 0) - (ashift:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "gpr_operand" "%d")) - (match_operand:DI 2 "signed6_operand" "I")) - (const_int 1))))] - "" - "macs%A0%: %.,%1,%2" - [(set_attr "length" "4") - (set_attr "type" "mul")]) - -(define_insn "*msub_reg" - [(set (match_operand:DI 0 "accum_operand" "+a") - (minus:DI (match_dup 0) - (mult:DI (sign_extend:DI (match_operand:SI 1 "gpr_operand" "d")) - (sign_extend:DI (match_operand:SI 2 "gpr_operand" "d")))))] - "" - "msub%A0%: %.,%1,%2" - [(set_attr "length" "4") - (set_attr "type" "mul")]) - -(define_insn "*msub_const" - [(set (match_operand:DI 0 "accum_operand" "+a") - (minus:DI (match_dup 0) - (mult:DI (sign_extend:DI (match_operand:SI 1 "gpr_operand" "d")) - (match_operand:DI 2 "signed6_operand" "I"))))] - "" - "msub%A0%: %.,%1,%2" - [(set_attr "length" "4") - (set_attr "type" "mul")]) - -(define_insn "*msubs_reg" - [(set (match_operand:DI 0 "accum_operand" "+a") - (minus:DI (match_dup 0) - (ashift:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "gpr_operand" "d")) - (sign_extend:DI (match_operand:SI 2 "gpr_operand" "d"))) - (const_int 1))))] - "" - "msubs%A0%: %.,%1,%2" - [(set_attr "length" "4") - (set_attr "type" "mul")]) - -(define_insn "*msubs_const" - [(set (match_operand:DI 0 "accum_operand" "+a") - (minus:DI (match_dup 0) - (ashift:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "gpr_operand" "d")) - (match_operand:DI 2 "signed6_operand" "I")) - (const_int 1))))] - "" - "msubs%A0%: %.,%1,%2" - [(set_attr "length" "4") - (set_attr "type" "mul")]) - - -;; :::::::::::::::::::: -;; :: -;; :: Comparisons -;; :: -;; :::::::::::::::::::: - -;; Note, we store the operands in the comparison insns, and use them later -;; when generating the branch or scc operation. - -;; First the routines called by the machine independent part of the compiler -(define_expand "cmpsi" - [(set (cc0) - (compare (match_operand:SI 0 "gpr_operand" "") - (match_operand:SI 1 "gpr_or_constant_operand" "")))] - "" - " -{ - d30v_compare_op0 = operands[0]; - d30v_compare_op1 = operands[1]; - DONE; -}") - -(define_expand "cmpdi" - [(set (cc0) - (compare (match_operand:DI 0 "gpr_operand" "") - (match_operand:DI 1 "nonmemory_operand" "")))] - "" - " -{ - d30v_compare_op0 = operands[0]; - d30v_compare_op1 = operands[1]; - DONE; -}") - -;; Now, the actual comparisons, generated by the branch and/or scc operations - -;; 32 bit integer tests -(define_insn "*srelational" - [(set (match_operand:CC 0 "flag_operand" "=f,f") - (match_operator:CC 1 "srelational_si_operator" - [(match_operand:SI 2 "gpr_operand" "d,d") - (match_operand:SI 3 "gpr_or_constant_operand" "dI,i")]))] - "" - "%R1%: %0,%2,%3" - [(set_attr "length" "4,8") - (set_attr "type" "scmp,lcmp")]) - -(define_insn "*urelational" - [(set (match_operand:CC 0 "flag_operand" "=f,f") - (match_operator:CC 1 "urelational_si_operator" - [(match_operand:SI 2 "gpr_operand" "d,d") - (match_operand:SI 3 "gpr_or_constant_operand" "dJP,i")]))] - "" - "%R1%: %0,%2,%3" - [(set_attr "length" "4,8") - (set_attr "type" "scmp,lcmp")]) - -;; 64 bit integer tests -(define_insn "*eqdi_internal" - [(set (match_operand:CC 0 "br_flag_operand" "=b,b,b") - (eq:CC (match_operand:DI 1 "gpr_operand" "e,e,e") - (match_operand:DI 2 "gpr_or_dbl_const_operand" "eI,i,F")))] - "" - "#" - [(set_attr "length" "8,12,16") - (set_attr "type" "multi")]) - -(define_split - [(set (match_operand:CC 0 "br_flag_operand" "") - (eq:CC (match_operand:DI 1 "gpr_operand" "") - (match_operand:DI 2 "gpr_or_dbl_const_operand" "")))] - "reload_completed" - [(set (match_dup 0) - (eq:CC (match_dup 3) - (match_dup 4))) - (cond_exec - (eq:CC (match_dup 0) - (const_int 0)) - (set (match_dup 0) - (eq:CC (match_dup 5) - (match_dup 6))))] - " -{ - d30v_split_double (operands[1], &operands[3], &operands[5]); - d30v_split_double (operands[2], &operands[4], &operands[6]); -}") - -(define_insn "*nedi_internal" - [(set (match_operand:CC 0 "br_flag_operand" "=b,b,b") - (ne:CC (match_operand:DI 1 "gpr_operand" "e,e,e") - (match_operand:DI 2 "gpr_or_dbl_const_operand" "eI,i,F")))] - "" - "#" - [(set_attr "length" "8,12,16") - (set_attr "type" "multi")]) - -(define_split - [(set (match_operand:CC 0 "br_flag_operand" "") - (ne:CC (match_operand:DI 1 "gpr_operand" "") - (match_operand:DI 2 "gpr_or_dbl_const_operand" "")))] - "reload_completed" - [(set (match_dup 0) - (ne:CC (match_dup 3) - (match_dup 4))) - (cond_exec - (ne:CC (match_dup 0) - (const_int 0)) - (set (match_dup 0) - (ne:CC (match_dup 5) - (match_dup 6))))] - " -{ - d30v_split_double (operands[1], &operands[3], &operands[5]); - d30v_split_double (operands[2], &operands[4], &operands[6]); -}") - -(define_insn "*ltdi_zero" - [(set (match_operand:CC 0 "flag_operand" "=f") - (lt:CC (match_operand:DI 1 "gpr_operand" "e") - (const_int 0)))] - "" - "cmplt%: %0,%U1,0" - [(set_attr "length" "4") - (set_attr "type" "scmp")]) - -(define_insn "*ltdi_internal" - [(set (match_operand:CC 0 "flag_operand" "=&f,&f,&f") - (lt:CC (match_operand:DI 1 "gpr_operand" "e,e,e") - (match_operand:DI 2 "gpr_or_dbl_const_operand" "eJP,i,F"))) - (clobber (match_operand:CC 3 "br_flag_operand" "=&b,&b,&b"))] - "" - "#" - [(set_attr "length" "12,16,24") - (set_attr "type" "multi")]) - -(define_insn "*ledi_internal" - [(set (match_operand:CC 0 "flag_operand" "=&f,&f,&f") - (le:CC (match_operand:DI 1 "gpr_operand" "e,e,e") - (match_operand:DI 2 "gpr_or_dbl_const_operand" "eJP,i,F"))) - (clobber (match_operand:CC 3 "br_flag_operand" "=&b,&b,&b"))] - "" - "#" - [(set_attr "length" "12,16,24") - (set_attr "type" "multi")]) - -(define_insn "*gtdi_internal" - [(set (match_operand:CC 0 "flag_operand" "=&f,&f,&f") - (gt:CC (match_operand:DI 1 "gpr_operand" "e,e,e") - (match_operand:DI 2 "gpr_or_dbl_const_operand" "eJP,i,F"))) - (clobber (match_operand:CC 3 "br_flag_operand" "=&b,&b,&b"))] - "" - "#" - [(set_attr "length" "12,16,24") - (set_attr "type" "multi")]) - -(define_insn "*gedi_zero" - [(set (match_operand:CC 0 "flag_operand" "=f") - (ge:CC (match_operand:DI 1 "gpr_operand" "e") - (const_int 0)))] - "" - "cmpge%: %0,%U1,0" - [(set_attr "length" "4") - (set_attr "type" "scmp")]) - -(define_insn "*gedi_internal" - [(set (match_operand:CC 0 "flag_operand" "=&f,&f,&f") - (ge:CC (match_operand:DI 1 "gpr_operand" "e,e,e") - (match_operand:DI 2 "gpr_or_dbl_const_operand" "eJP,i,F"))) - (clobber (match_operand:CC 3 "br_flag_operand" "=&b,&b,&b"))] - "" - "#" - [(set_attr "length" "12,16,24") - (set_attr "type" "multi")]) - -(define_insn "*ltudi_internal" - [(set (match_operand:CC 0 "flag_operand" "=&f,&f,&f") - (ltu:CC (match_operand:DI 1 "gpr_operand" "e,e,e") - (match_operand:DI 2 "gpr_or_dbl_const_operand" "eJP,i,F"))) - (clobber (match_operand:CC 3 "br_flag_operand" "=&b,&b,&b"))] - "" - "#" - [(set_attr "length" "12,16,24") - (set_attr "type" "multi")]) - -(define_insn "*leudi_internal" - [(set (match_operand:CC 0 "flag_operand" "=&f,&f,&f") - (leu:CC (match_operand:DI 1 "gpr_operand" "e,e,e") - (match_operand:DI 2 "gpr_or_dbl_const_operand" "eJP,i,F"))) - (clobber (match_operand:CC 3 "br_flag_operand" "=&b,&b,&b"))] - "" - "#" - [(set_attr "length" "12,16,24") - (set_attr "type" "multi")]) - -(define_insn "*gtudi_internal" - [(set (match_operand:CC 0 "flag_operand" "=&f,&f,&f") - (gtu:CC (match_operand:DI 1 "gpr_operand" "e,e,e") - (match_operand:DI 2 "gpr_or_dbl_const_operand" "eJP,i,F"))) - (clobber (match_operand:CC 3 "br_flag_operand" "=&b,&b,&b"))] - "" - "#" - [(set_attr "length" "12,16,24") - (set_attr "type" "multi")]) - -(define_insn "*geudi_internal" - [(set (match_operand:CC 0 "flag_operand" "=&f,&f,&f") - (geu:CC (match_operand:DI 1 "gpr_operand" "e,e,e") - (match_operand:DI 2 "gpr_or_dbl_const_operand" "eJP,i,F"))) - (clobber (match_operand:CC 3 "br_flag_operand" "=&b,&b,&b"))] - "" - "#" - [(set_attr "length" "12,16,24") - (set_attr "type" "multi")]) - -(define_split - [(set (match_operand:CC 0 "flag_operand" "") - (match_operator:CC 1 "relational_di_operator" - [(match_operand:DI 2 "gpr_operand" "") - (match_operand:DI 3 "gpr_or_dbl_const_operand" "")])) - (clobber (match_operand:CC 4 "br_flag_operand" ""))] - "reload_completed" - [(match_dup 5) - (match_dup 6) - (match_dup 7)] - " -{ - enum rtx_code cond = GET_CODE (operands[1]); - enum rtx_code ucond = unsigned_condition (cond); - rtx tmpflag = operands[4]; - rtx outflag = operands[0]; - rtx high[2]; - rtx low[2]; - - d30v_split_double (operands[2], &high[0], &low[0]); - d30v_split_double (operands[3], &high[1], &low[1]); - - operands[5] = gen_rtx_SET (VOIDmode, - tmpflag, - gen_rtx_EQ (CCmode, high[0], high[1])); - - operands[6] = gen_rtx_COND_EXEC (VOIDmode, - gen_rtx_NE (CCmode, tmpflag, const0_rtx), - gen_rtx_SET (VOIDmode, outflag, - gen_rtx_fmt_ee (cond, CCmode, - high[0], - high[1]))); - - operands[7] = gen_rtx_COND_EXEC (VOIDmode, - gen_rtx_EQ (CCmode, tmpflag, const0_rtx), - gen_rtx_SET (VOIDmode, outflag, - gen_rtx_fmt_ee (ucond, CCmode, - low[0], - low[1]))); -}") - - -;; :::::::::::::::::::: -;; :: -;; :: Branches -;; :: -;; :::::::::::::::::::: - -;; Define_expands called by the machine independent part of the compiler -;; to allocate a new comparison register - -(define_expand "beq" - [(match_dup 2) - (set (pc) - (if_then_else (ne:CC (match_dup 1) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_reg_rtx (CCmode); - operands[2] = d30v_emit_comparison (EQ, operands[1], - d30v_compare_op0, - d30v_compare_op1); -}") - -(define_expand "bne" - [(match_dup 2) - (set (pc) - (if_then_else (ne:CC (match_dup 1) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_reg_rtx (CCmode); - operands[2] = d30v_emit_comparison (NE, operands[1], - d30v_compare_op0, - d30v_compare_op1); -}") - -(define_expand "bgt" - [(match_dup 2) - (set (pc) - (if_then_else (ne:CC (match_dup 1) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_reg_rtx (CCmode); - operands[2] = d30v_emit_comparison (GT, operands[1], - d30v_compare_op0, - d30v_compare_op1); -}") - -(define_expand "bge" - [(match_dup 2) - (set (pc) - (if_then_else (ne:CC (match_dup 1) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_reg_rtx (CCmode); - operands[2] = d30v_emit_comparison (GE, operands[1], - d30v_compare_op0, - d30v_compare_op1); -}") - -(define_expand "blt" - [(match_dup 2) - (set (pc) - (if_then_else (ne:CC (match_dup 1) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_reg_rtx (CCmode); - operands[2] = d30v_emit_comparison (LT, operands[1], - d30v_compare_op0, - d30v_compare_op1); -}") - -(define_expand "ble" - [(match_dup 2) - (set (pc) - (if_then_else (ne:CC (match_dup 1) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_reg_rtx (CCmode); - operands[2] = d30v_emit_comparison (LE, operands[1], - d30v_compare_op0, - d30v_compare_op1); -}") - -(define_expand "bgtu" - [(match_dup 2) - (set (pc) - (if_then_else (ne:CC (match_dup 1) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_reg_rtx (CCmode); - operands[2] = d30v_emit_comparison (GTU, operands[1], - d30v_compare_op0, - d30v_compare_op1); -}") - -(define_expand "bgeu" - [(match_dup 2) - (set (pc) - (if_then_else (ne:CC (match_dup 1) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_reg_rtx (CCmode); - operands[2] = d30v_emit_comparison (GEU, operands[1], - d30v_compare_op0, - d30v_compare_op1); -}") - -(define_expand "bltu" - [(match_dup 2) - (set (pc) - (if_then_else (ne:CC (match_dup 1) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_reg_rtx (CCmode); - operands[2] = d30v_emit_comparison (LTU, operands[1], - d30v_compare_op0, - d30v_compare_op1); -}") - -(define_expand "bleu" - [(match_dup 2) - (set (pc) - (if_then_else (ne:CC (match_dup 1) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - operands[1] = gen_reg_rtx (CCmode); - operands[2] = d30v_emit_comparison (LEU, operands[1], - d30v_compare_op0, - d30v_compare_op1); -}") - -;; Actual branches. We must allow for the (label_ref) and the (pc) to be -;; swapped. If they are swapped, it reverses the sense of the branch. -;; Also handle changing the ne to eq. -;; In order for the length calculations to be correct, the label must be -;; operand 0. - -;; We used to handle branches against 0 to be folded directly into -;; bratnz/bratzr instruction, but this dimisses the possibility of doing -;; conditional execution. Instead handle these via peepholes. - -;; Branches based off of the flag bits -(define_insn "*bra_true" - [(set (pc) - (if_then_else (match_operator:CC 1 "condexec_branch_operator" - [(match_operand:CC 2 "br_flag_or_constant_operand" "b,I,N") - (const_int 0)]) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* -{ - if (GET_CODE (operands[2]) == REG || GET_CODE (operands[2]) == SUBREG) - return \"bra%F1 %l0\"; - - if (GET_CODE (operands[2]) != CONST_INT) - fatal_insn (\"bad jump\", insn); - - if ((GET_CODE (operands[1]) == EQ && INTVAL (operands[2]) == 0) - || (GET_CODE (operands[1]) == NE && INTVAL (operands[2]) != 0)) - return \"bra %l0\"; - - return \"; jump to %l0 optimized away\"; -}" - [(set_attr "type" "br") - (set_attr "predicable" "no")]) - -(define_insn "*bra_false" - [(set (pc) - (if_then_else (match_operator:CC 1 "condexec_branch_operator" - [(match_operand:CC 2 "br_flag_or_constant_operand" "b,I,N") - (const_int 0)]) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* -{ - if (GET_CODE (operands[2]) == REG || GET_CODE (operands[2]) == SUBREG) - return \"bra%T1 %l0\"; - - if (GET_CODE (operands[2]) != CONST_INT) - fatal_insn (\"bad jump\", insn); - - if ((GET_CODE (operands[1]) == EQ && INTVAL (operands[2]) != 0) - || (GET_CODE (operands[1]) == NE && INTVAL (operands[2]) == 0)) - return \"bra %l0\"; - - return \"; jump to %l0 optimized away\"; -}" - [(set_attr "type" "br") - (set_attr "predicable" "no")]) - -;; Peephole to turn set flag, cond. jumps into branch if register ==/!= 0. - -(define_peephole2 - [(set (match_operand:CC 0 "br_flag_operand" "=b") - (match_operator:CC 1 "branch_zero_operator" - [(match_operand:SI 2 "gpr_operand" "d") - (const_int 0)])) - (set (pc) - (if_then_else (match_operator:CC 3 "condexec_test_operator" - [(match_dup 0) - (const_int 0)]) - (match_operand 4 "" "") - (match_operand 5 "" "")))] - "peep2_reg_dead_p (2, operands[0]) - && GET_CODE (operands[4]) != RETURN - && GET_CODE (operands[5]) != RETURN" - [(set (pc) - (if_then_else (match_dup 6) - (match_dup 4) - (match_dup 5)))] - " -{ - int true_false = 1; - if (GET_CODE (operands[1]) == EQ) - true_false = !true_false; - if (GET_CODE (operands[3]) == EQ) - true_false = !true_false; - operands[6] = gen_rtx_fmt_ee ((true_false ? NE : EQ), CCmode, - operands[2], const0_rtx); -}") - -(define_insn "*bra_reg_true" - [(set (pc) (if_then_else (match_operator:CC 1 "branch_zero_operator" - [(match_operand:SI 2 "gpr_operand" "d") - (const_int 0)]) - (label_ref (match_operand 0 "" "")) - (pc)))] - "reload_completed" - "* -{ - return GET_CODE (operands[1]) == NE ? \"bratnz %2,%l0\" : \"bratzr %2,%l0\"; -}" - [(set_attr "type" "br2") - (set_attr "predicable" "no")]) - -(define_insn "*bra_reg_false" - [(set (pc) (if_then_else (match_operator:CC 1 "branch_zero_operator" - [(match_operand:SI 2 "gpr_operand" "d") - (const_int 0)]) - (pc) - (label_ref (match_operand 0 "" ""))))] - "reload_completed" - "* -{ - return GET_CODE (operands[1]) == EQ ? \"bratnz %2,%l0\" : \"bratzr %2,%l0\"; -}" - [(set_attr "type" "br2") - (set_attr "predicable" "no")]) - -;; :::::::::::::::::::: -;; :: -;; :: Set flag operations -;; :: -;; :::::::::::::::::::: - -;; Define_expands called by the machine independent part of the compiler -;; to allocate a new comparison register - -;; ??? These patterns should all probably use (ne:SI ... (const_int 0)) instead -;; of (eq:SI ... (const_int 1)), because the former is the canonical form. -;; The non-canonical form was used here because I was just trying to get the -;; port working again after it broke, and the non-canonical form was the -;; safer faster way to fix this. - - -(define_expand "seq" - [(match_dup 2) - (set (match_operand:SI 0 "gpr_operand" "") - (ne:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_reg_rtx (CCmode); - operands[2] = d30v_emit_comparison (EQ, operands[1], - d30v_compare_op0, - d30v_compare_op1); -}") - -(define_expand "sne" - [(match_dup 2) - (set (match_operand:SI 0 "gpr_operand" "") - (ne:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_reg_rtx (CCmode); - operands[2] = d30v_emit_comparison (NE, operands[1], - d30v_compare_op0, - d30v_compare_op1); -}") - -(define_expand "sgt" - [(match_dup 2) - (set (match_operand:SI 0 "gpr_operand" "") - (ne:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_reg_rtx (CCmode); - operands[2] = d30v_emit_comparison (GT, operands[1], - d30v_compare_op0, - d30v_compare_op1); -}") - -(define_expand "sge" - [(match_dup 2) - (set (match_operand:SI 0 "gpr_operand" "") - (ne:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_reg_rtx (CCmode); - operands[2] = d30v_emit_comparison (GE, operands[1], - d30v_compare_op0, - d30v_compare_op1); -}") - -(define_expand "slt" - [(match_dup 2) - (set (match_operand:SI 0 "gpr_operand" "") - (ne:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_reg_rtx (CCmode); - operands[2] = d30v_emit_comparison (LT, operands[1], - d30v_compare_op0, - d30v_compare_op1); -}") - -(define_expand "sle" - [(match_dup 2) - (set (match_operand:SI 0 "gpr_operand" "") - (ne:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_reg_rtx (CCmode); - operands[2] = d30v_emit_comparison (LE, operands[1], - d30v_compare_op0, - d30v_compare_op1); -}") - -(define_expand "sgtu" - [(match_dup 2) - (set (match_operand:SI 0 "gpr_operand" "") - (ne:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_reg_rtx (CCmode); - operands[2] = d30v_emit_comparison (GTU, operands[1], - d30v_compare_op0, - d30v_compare_op1); -}") - -(define_expand "sgeu" - [(match_dup 2) - (set (match_operand:SI 0 "gpr_operand" "") - (ne:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_reg_rtx (CCmode); - operands[2] = d30v_emit_comparison (GEU, operands[1], - d30v_compare_op0, - d30v_compare_op1); -}") - -(define_expand "sltu" - [(match_dup 2) - (set (match_operand:SI 0 "gpr_operand" "") - (ne:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_reg_rtx (CCmode); - operands[2] = d30v_emit_comparison (LTU, operands[1], - d30v_compare_op0, - d30v_compare_op1); -}") - -(define_expand "sleu" - [(match_dup 2) - (set (match_operand:SI 0 "gpr_operand" "") - (ne:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_reg_rtx (CCmode); - operands[2] = d30v_emit_comparison (LEU, operands[1], - d30v_compare_op0, - d30v_compare_op1); -}") - -;; Set flag operations. We prefer to use conditional execution instead of -;; mvfsys, since it is faster, but allow the use of mvfsys to offload some -;; register pressure. -(define_insn "*setcc_internal" - [(set (match_operand:SI 0 "gpr_operand" "=d,?d,?*d") - (ne:SI (match_operand:CC 1 "flag_operand" "b,z,*d") - (const_int 0)))] - "" - "@ - # - mvfsys%: %0,%1 - or%: %0,%.,%1" - [(set_attr "length" "8,4,4") - (set_attr "type" "multi,either,either")]) - -(define_split - [(set (match_operand:SI 0 "gpr_operand" "") - (ne:SI (match_operand:CC 1 "br_flag_operand" "") - (const_int 0)))] - "reload_completed" - [(set (match_dup 0) - (const_int 0)) - (set (match_dup 0) - (if_then_else:SI (ne:CC (match_dup 1) - (const_int 0)) - (const_int 1) - (match_dup 0)))] - "") - - -;; :::::::::::::::::::: -;; :: -;; :: Operations on flags -;; :: -;; :::::::::::::::::::: - -(define_insn "andcc3" - [(set (match_operand:CC 0 "flag_operand" "=f") - (and:CC (match_operand:CC 1 "flag_operand" "f") - (match_operand:CC 2 "flag_operand" "f")))] - "" - "andfg%: %0,%1,%2" - [(set_attr "length" "4") - (set_attr "type" "either")]) - -(define_insn "iorcc3" - [(set (match_operand:CC 0 "flag_operand" "=f") - (ior:CC (match_operand:CC 1 "flag_operand" "f") - (match_operand:CC 2 "flag_operand" "f")))] - "" - "orfg%: %0,%1,%2" - [(set_attr "length" "4") - (set_attr "type" "either")]) - -(define_insn "xorcc3" - [(set (match_operand:CC 0 "flag_operand" "=f") - (xor:CC (match_operand:CC 1 "flag_operand" "f") - (match_operand:CC 2 "flag_operand" "f")))] - "" - "xorfg%: %0,%1,%2" - [(set_attr "length" "4") - (set_attr "type" "either")]) - -;; This is the canonical form produced by combine. - -(define_insn "incscc" - [(set (match_operand:SI 0 "gpr_operand" "=d") - (plus:SI (eq:SI (match_operand:CC 1 "br_flag_operand" "b") - (const_int 1)) - (match_operand:SI 2 "gpr_operand" "0")))] - "" - "add%T1 %0,%2,1" - [(set_attr "length" "4") - (set_attr "type" "either") - ;; Not strictly true -- we could combine conditions. - (set_attr "predicable" "no")]) - -(define_insn "decscc" - [(set (match_operand:SI 0 "gpr_operand" "=d") - (minus:SI (match_operand:SI 1 "gpr_operand" "0") - (eq:SI (match_operand:CC 2 "br_flag_operand" "b") - (const_int 1))))] - "" - "sub%T2 %0,%1,1" - [(set_attr "length" "4") - (set_attr "type" "either") - ;; Not strictly true -- we could combine conditions. - (set_attr "predicable" "no")]) - -;; :::::::::::::::::::: -;; :: -;; :: Call and branch instructions -;; :: -;; :::::::::::::::::::: - -;; Subroutine call instruction returning no value. Operand 0 is the function -;; to call; operand 1 is the number of bytes of arguments pushed (in mode -;; `SImode', except it is normally a `const_int'); operand 2 is the number of -;; registers used as operands. - -;; On most machines, operand 2 is not actually stored into the RTL pattern. It -;; is supplied for the sake of some RISC machines which need to put this -;; information into the assembler code; they can put it in the RTL instead of -;; operand 1. - -(define_expand "call" - [(parallel [(call (match_operand 0 "call_operand" "") - (match_operand 1 "" "")) - (use (match_operand 2 "" "")) - (clobber (match_dup 3))])] - "" - " -{ - if (GET_CODE (XEXP (operands[0], 0)) == SUBREG) - XEXP (operands[0], 0) = copy_addr_to_reg (XEXP (operands[0], 0)); - - if (!operands[2]) - operands[2] = const0_rtx; - - operands[3] = gen_rtx (REG, Pmode, GPR_LINK); -}") - -(define_insn "*call_internal" - [(call (match_operand:QI 0 "call_operand" "R,S") - (match_operand 1 "" "")) - (use (match_operand 2 "" "")) - (clobber (match_operand 3 "" "=d,d"))] - "" - "@ - jsr%: %0 - bsr%: %0" - [(set_attr "length" "4,8") - (set_attr "type" "mu,long")]) - -;; Subroutine call instruction returning a value. Operand 0 is the hard -;; register in which the value is returned. There are three more operands, the -;; same as the three operands of the `call' instruction (but with numbers -;; increased by one). - -;; Subroutines that return `BLKmode' objects use the `call' insn. - -(define_expand "call_value" - [(parallel [(set (match_operand 0 "gpr_operand" "") - (call (match_operand 1 "call_operand" "") - (match_operand 2 "" ""))) - (use (match_operand 3 "" "")) - (clobber (match_dup 4))])] - "" - " -{ - if (GET_CODE (XEXP (operands[1], 0)) == SUBREG) - XEXP (operands[1], 0) = copy_addr_to_reg (XEXP (operands[1], 0)); - - if (!operands[3]) - operands[3] = const0_rtx; - - operands[4] = gen_rtx (REG, Pmode, GPR_LINK); -}") - -(define_insn "*call_value_internal" - [(set (match_operand 0 "gpr_operand" "=d,d") - (call (match_operand:QI 1 "call_operand" "R,S") - (match_operand 2 "" ""))) - (use (match_operand 3 "" "")) - (clobber (match_operand 4 "" "=d,d"))] - "" - "@ - jsr%: %1 - bsr%: %1" - [(set_attr "length" "4,8") - (set_attr "type" "mu,long")]) - -;; Subroutine return -(define_expand "return" - [(return)] - "direct_return ()" - "") - -(define_insn "*return_internal" - [(return)] - "reload_completed" - "jmp link" - [(set_attr "length" "4") - (set_attr "type" "mu") - (set_attr "predicable" "no")]) - -(define_insn "*cond_return_true" - [(set (pc) - (if_then_else (match_operator:CC 0 "condexec_branch_operator" - [(match_operand:CC 1 "br_flag_operand" "b") - (const_int 0)]) - (return) - (pc)))] - "reload_completed" - "jmp%F0 link" - [(set_attr "length" "4") - (set_attr "type" "mu") - (set_attr "predicable" "no")]) - -(define_insn "*cond_return_false" - [(set (pc) - (if_then_else (match_operator:CC 0 "condexec_branch_operator" - [(match_operand:CC 1 "br_flag_operand" "b") - (const_int 0)]) - (pc) - (return)))] - "reload_completed" - "jmp%T0 link" - [(set_attr "length" "4") - (set_attr "type" "mu") - (set_attr "predicable" "no")]) - -;; Normal unconditional jump -(define_insn "jump" - [(set (pc) (label_ref (match_operand 0 "" "")))] - "" - "bra %l0" - [(set_attr "type" "br") - (set_attr "predicable" "no")]) - -;; Indirect jump through a register -(define_insn "indirect_jump" - [(set (pc) (match_operand:SI 0 "gpr_operand" "d"))] - "" - "jmp %0" - [(set_attr "length" "4") - (set_attr "type" "mu") - (set_attr "predicable" "no")]) - -;; Instruction to jump to a variable address. This is a low-level capability -;; which can be used to implement a dispatch table when there is no `casesi' -;; pattern. - -;; This pattern requires two operands: the address or offset, and a label which -;; should immediately precede the jump table. If the macro -;; `CASE_VECTOR_PC_RELATIVE' is defined then the first operand is an offset -;; which counts from the address of the table; otherwise, it is an absolute -;; address to jump to. In either case, the first operand has mode `Pmode'. - -;; The `tablejump' insn is always the last insn before the jump table it uses. -;; Its assembler code normally has no need to use the second operand, but you -;; should incorporate it in the RTL pattern so that the jump optimizer will not -;; delete the table as unreachable code. - -(define_insn "tablejump" - [(set (pc) (match_operand:SI 0 "gpr_operand" "d")) - (use (label_ref (match_operand 1 "" "")))] - "" - "jmp %0" - [(set_attr "length" "4") - (set_attr "type" "mu") - (set_attr "predicable" "no")]) - - - -;; :::::::::::::::::::: -;; :: -;; :: Prologue and Epilogue instructions -;; :: -;; :::::::::::::::::::: - -;; Called after register allocation to add any instructions needed for the -;; prologue. Using a prologue insn is favored compared to putting all of the -;; instructions in output_function_prologue (), since it allows the scheduler -;; to intermix instructions with the saves of the caller saved registers. In -;; some cases, it might be necessary to emit a barrier instruction as the last -;; insn to prevent such scheduling. - -(define_expand "prologue" - [(const_int 1)] - "" - " -{ - d30v_expand_prologue (); - DONE; -}") - -;; Called after register allocation to add any instructions needed for the -;; epilogue. Using an epilogue insn is favored compared to putting all of the -;; instructions in output_function_epilogue (), since it allows the scheduler -;; to intermix instructions with the saves of the caller saved registers. In -;; some cases, it might be necessary to emit a barrier instruction as the last -;; insn to prevent such scheduling. - -(define_expand "epilogue" - [(const_int 2)] - "" - " -{ - d30v_expand_epilogue (); - DONE; -}") - -(define_expand "eh_epilogue" - [(use (match_operand:DI 0 "register_operand" "r")) - (use (match_operand:DI 1 "register_operand" "r")) - (use (match_operand:DI 2 "register_operand" "r"))] - "" - " -{ - cfun->machine->eh_epilogue_sp_ofs = operands[1]; - if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != GPR_LINK) - { - rtx ra = gen_rtx_REG (Pmode, GPR_LINK); - emit_move_insn (ra, operands[2]); - operands[2] = ra; - } -}") - - -;; :::::::::::::::::::: -;; :: -;; :: Conditional move instructions -;; :: -;; :::::::::::::::::::: - -;; Conditionally move operand 2 or operand 3 into operand 0 according to the -;; comparison in operand 1. If the comparison is true, operand 2 is moved into -;; operand 0, otherwise operand 3 is moved. - -;; The mode of the operands being compared need not be the same as the operands -;; being moved. Some machines, sparc64 for example, have instructions that -;; conditionally move an integer value based on the floating point condition -;; codes and vice versa. - -;; If the machine does not have conditional move instructions, do not -;; define these patterns. - -;; Note we don't allow the general form of conditional store to be generated -- -;; we always generate two separate if_then_elses's -(define_expand "movqicc" - [(set (match_operand:QI 0 "move_output_operand" "") - (if_then_else:QI (match_operand 1 "" "") - (match_operand:QI 2 "move_input_operand" "") - (match_operand:QI 3 "move_input_operand" "")))] - "TARGET_COND_MOVE" - " -{ - if (!d30v_emit_cond_move (operands[0], operands[1], operands[2], operands[3])) - FAIL; - - DONE; -}") - -(define_insn "*movqicc_internal" - [(set (match_operand:QI 0 "gpr_operand" "=d,d,d,d,d,c,d,d,d,d,d,c,?&d") - (if_then_else:QI (match_operator:CC 1 "condexec_test_operator" - [(match_operand:CC 2 "br_flag_operand" "b,b,b,b,b,b,b,b,b,b,b,b,b") - (const_int 0)]) - (match_operand:QI 3 "move_input_operand" "dI,i,Q,m,c,d,0,0,0,0,0,0,dim") - (match_operand:QI 4 "move_input_operand" "0,0,0,0,0,0,dI,i,Q,m,c,d,dim")))] - "" - "#" - [(set_attr "length" "4,8,4,8,4,4,4,8,4,8,4,4,16") - (set_attr "type" "either,long,sload,lload,mu,mu,either,long,sload,lload,mu,mu,multi") - (set_attr "predicable" "no")]) - -;; If we have: a = (test) ? a : b, or a = (test) ? b : a, we can split it -;; before reload to allow combine to substitute in early. -;; ??? Not until we teach reload how to do conditional spills, we can't. -(define_split - [(set (match_operand:QI 0 "move_output_operand" "") - (if_then_else:QI (match_operator:CC 1 "condexec_test_operator" - [(match_operand:CC 2 "br_flag_operand" "") - (const_int 0)]) - (match_operand:QI 3 "move_input_operand" "") - (match_dup 0)))] - "reload_completed" - [(cond_exec (match_dup 1) - (set (match_dup 0) (match_dup 3)))] - "") - -(define_split - [(set (match_operand:QI 0 "move_output_operand" "") - (if_then_else:QI (match_operator:CC 1 "condexec_test_operator" - [(match_operand:CC 2 "br_flag_operand" "") - (const_int 0)]) - (match_dup 0) - (match_operand:QI 3 "move_input_operand" "")))] - "reload_completed" - [(cond_exec (match_dup 4) - (set (match_dup 0) (match_dup 3)))] - " -{ - if (GET_CODE (operands[1]) == EQ) - operands[4] = gen_rtx_NE (CCmode, operands[2], const0_rtx); - else - operands[4] = gen_rtx_EQ (CCmode, operands[2], const0_rtx); -}") - -(define_split - [(set (match_operand:QI 0 "move_output_operand" "") - (if_then_else:QI (match_operator:CC 1 "condexec_test_operator" - [(match_operand:CC 2 "br_flag_operand" "") - (const_int 0)]) - (match_operand:QI 3 "move_input_operand" "") - (match_operand:QI 4 "move_input_operand" "")))] - "reload_completed" - [(cond_exec (match_dup 1) - (set (match_dup 0) (match_dup 3))) - (cond_exec (match_dup 5) - (set (match_dup 0) (match_dup 4)))] - " -{ - if (GET_CODE (operands[1]) == EQ) - operands[5] = gen_rtx_NE (CCmode, operands[2], const0_rtx); - else - operands[5] = gen_rtx_EQ (CCmode, operands[2], const0_rtx); -}") - -(define_expand "movhicc" - [(set (match_operand:HI 0 "move_output_operand" "") - (if_then_else:HI (match_operand 1 "" "") - (match_operand:HI 2 "move_input_operand" "") - (match_operand:HI 3 "move_input_operand" "")))] - "TARGET_COND_MOVE" - " -{ - if (!d30v_emit_cond_move (operands[0], operands[1], operands[2], operands[3])) - FAIL; - - DONE; -}") - -(define_insn "*movhicc_internal" - [(set (match_operand:HI 0 "gpr_operand" "=d,d,d,d,d,c,d,d,d,d,d,c,?&d") - (if_then_else:HI - (match_operator:CC 1 "condexec_test_operator" - [(match_operand:CC 2 "br_flag_operand" "b,b,b,b,b,b,b,b,b,b,b,b,b") - (const_int 0)]) - (match_operand:HI 3 "move_input_operand" "dI,i,Q,m,c,d,0,0,0,0,0,0,dim") - (match_operand:HI 4 "move_input_operand" "0,0,0,0,0,0,dI,i,Q,m,c,d,dim")))] - "" - "#" - [(set_attr "length" "4,8,4,8,4,4,4,8,4,8,4,4,16") - (set_attr "type" "either,long,sload,lload,mu,mu,either,long,sload,lload,mu,mu,multi") - (set_attr "predicable" "no")]) - -;; If we have: a = (test) ? a : b, or a = (test) ? b : a, we can split it -;; before reload to allow combine to substitute in early. -;; ??? Not until we teach reload how to do conditional spills, we can't. -(define_split - [(set (match_operand:HI 0 "move_output_operand" "") - (if_then_else:HI (match_operator:CC 1 "condexec_test_operator" - [(match_operand:CC 2 "br_flag_operand" "") - (const_int 0)]) - (match_operand:HI 3 "move_input_operand" "") - (match_dup 0)))] - "reload_completed" - [(cond_exec (match_dup 1) - (set (match_dup 0) (match_dup 3)))] - "") - -(define_split - [(set (match_operand:HI 0 "move_output_operand" "") - (if_then_else:HI (match_operator:CC 1 "condexec_test_operator" - [(match_operand:CC 2 "br_flag_operand" "") - (const_int 0)]) - (match_dup 0) - (match_operand:HI 3 "move_input_operand" "")))] - "reload_completed" - [(cond_exec (match_dup 4) - (set (match_dup 0) (match_dup 3)))] - " -{ - if (GET_CODE (operands[1]) == EQ) - operands[4] = gen_rtx_NE (CCmode, operands[2], const0_rtx); - else - operands[4] = gen_rtx_EQ (CCmode, operands[2], const0_rtx); -}") - -(define_split - [(set (match_operand:HI 0 "move_output_operand" "") - (if_then_else:HI (match_operator:CC 1 "condexec_test_operator" - [(match_operand:CC 2 "br_flag_operand" "") - (const_int 0)]) - (match_operand:HI 3 "move_input_operand" "") - (match_operand:HI 4 "move_input_operand" "")))] - "reload_completed" - [(cond_exec (match_dup 1) - (set (match_dup 0) (match_dup 3))) - (cond_exec (match_dup 5) - (set (match_dup 0) (match_dup 4)))] - " -{ - if (GET_CODE (operands[1]) == EQ) - operands[5] = gen_rtx_NE (CCmode, operands[2], const0_rtx); - else - operands[5] = gen_rtx_EQ (CCmode, operands[2], const0_rtx); -}") - -(define_expand "movsicc" - [(set (match_operand:SI 0 "move_output_operand" "") - (if_then_else:SI (match_operand 1 "" "") - (match_operand:SI 2 "move_input_operand" "") - (match_operand:SI 3 "move_input_operand" "")))] - "TARGET_COND_MOVE" - " -{ - if (!d30v_emit_cond_move (operands[0], operands[1], operands[2], operands[3])) - FAIL; - - DONE; -}") - -(define_insn "*movsicc_internal" - [(set (match_operand:SI 0 "move_output_operand" "=d,d,d,d,d,c,d,d,d,d,d,c,?&d") - (if_then_else:SI - (match_operator:CC 1 "condexec_test_operator" - [(match_operand:CC 2 "br_flag_operand" "b,b,b,b,b,b,b,b,b,b,b,b,b") - (const_int 0)]) - (match_operand:SI 3 "move_input_operand" "dI,i,Q,m,c,d,0,0,0,0,0,0,dim") - (match_operand:SI 4 "move_input_operand" "0,0,0,0,0,0,dI,i,Q,m,c,d,dim")))] - "" - "#" - [(set_attr "length" "4,8,4,8,4,4,4,8,4,8,4,4,16") - (set_attr "type" "either,long,sload,lload,mu,mu,either,long,sload,lload,mu,mu,multi") - (set_attr "predicable" "no")]) - -;; If we have: a = (test) ? a : b, or a = (test) ? b : a, we can split it -;; before reload to allow combine to substitute in early. -;; ??? Not until we teach reload how to do conditional spills, we can't. -(define_split - [(set (match_operand:SI 0 "move_output_operand" "") - (if_then_else:SI (match_operator:CC 1 "condexec_test_operator" - [(match_operand:CC 2 "br_flag_operand" "") - (const_int 0)]) - (match_operand:SI 3 "move_input_operand" "") - (match_dup 0)))] - "reload_completed" - [(cond_exec (match_dup 1) - (set (match_dup 0) (match_dup 3)))] - "") - -(define_split - [(set (match_operand:SI 0 "move_output_operand" "") - (if_then_else:SI (match_operator:CC 1 "condexec_test_operator" - [(match_operand:CC 2 "br_flag_operand" "") - (const_int 0)]) - (match_dup 0) - (match_operand:SI 3 "move_input_operand" "")))] - "reload_completed" - [(cond_exec (match_dup 4) - (set (match_dup 0) (match_dup 3)))] - " -{ - if (GET_CODE (operands[1]) == EQ) - operands[4] = gen_rtx_NE (CCmode, operands[2], const0_rtx); - else - operands[4] = gen_rtx_EQ (CCmode, operands[2], const0_rtx); -}") - -(define_split - [(set (match_operand:SI 0 "move_output_operand" "") - (if_then_else:SI (match_operator:CC 1 "condexec_test_operator" - [(match_operand:CC 2 "br_flag_operand" "") - (const_int 0)]) - (match_operand:SI 3 "move_input_operand" "") - (match_operand:SI 4 "move_input_operand" "")))] - "reload_completed" - [(cond_exec (match_dup 1) - (set (match_dup 0) (match_dup 3))) - (cond_exec (match_dup 5) - (set (match_dup 0) (match_dup 4)))] - " -{ - if (GET_CODE (operands[1]) == EQ) - operands[5] = gen_rtx_NE (CCmode, operands[2], const0_rtx); - else - operands[5] = gen_rtx_EQ (CCmode, operands[2], const0_rtx); -}") - -(define_expand "movsfcc" - [(set (match_operand:SF 0 "move_output_operand" "") - (if_then_else:SF (match_operand 1 "" "") - (match_operand:SF 2 "move_input_operand" "") - (match_operand:SF 3 "move_input_operand" "")))] - "TARGET_COND_MOVE" - " -{ - if (!d30v_emit_cond_move (operands[0], operands[1], operands[2], operands[3])) - FAIL; - - DONE; -}") - -(define_insn "*movsfcc_internal" - [(set (match_operand:SF 0 "gpr_operand" "=d,d,d,d,d,d,d,d,?&d") - (if_then_else:SF - (match_operator:CC 1 "condexec_test_operator" - [(match_operand:CC 2 "br_flag_operand" "b,b,b,b,b,b,b,b,b") - (const_int 0)]) - (match_operand:SF 3 "move_input_operand" "dG,F,Q,m,0,0,0,0,dim") - (match_operand:SF 4 "move_input_operand" "0,0,0,0,dG,F,Q,m,dim")))] - "" - "#" - [(set_attr "length" "4,8,4,8,4,8,4,8,16") - (set_attr "type" "either,long,sload,lload,either,long,sload,lload,multi") - (set_attr "predicable" "no")]) - -(define_split - [(set (match_operand:SF 0 "move_output_operand" "") - (if_then_else:SF (match_operator:CC 1 "condexec_test_operator" - [(match_operand:CC 2 "br_flag_operand" "") - (const_int 0)]) - (match_operand:SF 3 "move_input_operand" "") - (match_dup 0)))] - "reload_completed" - [(cond_exec (match_dup 1) - (set (match_dup 0) (match_dup 3)))] - "") - -(define_split - [(set (match_operand:SF 0 "move_output_operand" "") - (if_then_else:SF (match_operator:CC 1 "condexec_test_operator" - [(match_operand:CC 2 "br_flag_operand" "") - (const_int 0)]) - (match_dup 0) - (match_operand:SF 3 "move_input_operand" "")))] - "reload_completed" - [(cond_exec (match_dup 4) - (set (match_dup 0) (match_dup 3)))] - " -{ - if (GET_CODE (operands[1]) == EQ) - operands[4] = gen_rtx_NE (CCmode, operands[2], const0_rtx); - else - operands[4] = gen_rtx_EQ (CCmode, operands[2], const0_rtx); -}") - -(define_split - [(set (match_operand:SF 0 "move_output_operand" "") - (if_then_else:SF (match_operator:CC 1 "condexec_test_operator" - [(match_operand:CC 2 "br_flag_operand" "") - (const_int 0)]) - (match_operand:SF 3 "move_input_operand" "") - (match_operand:SF 4 "move_input_operand" "")))] - "reload_completed" - [(cond_exec (match_dup 1) - (set (match_dup 0) (match_dup 3))) - (cond_exec (match_dup 5) - (set (match_dup 0) (match_dup 4)))] - " -{ - if (GET_CODE (operands[1]) == EQ) - operands[5] = gen_rtx_NE (CCmode, operands[2], const0_rtx); - else - operands[5] = gen_rtx_EQ (CCmode, operands[2], const0_rtx); -}") - - -;; :::::::::::::::::::: -;; :: -;; :: Miscellaneous instructions -;; :: -;; :::::::::::::::::::: - -;; No operation, needed in case the user uses -g but not -O. -(define_insn "nop" - [(const_int 0)] - "" - "nop || nop" - [(set_attr "length" "8") - (set_attr "type" "long") - (set_attr "predicable" "no")]) - -;; Pseudo instruction that prevents the scheduler from moving code above this -;; point. -(define_insn "blockage" - [(unspec_volatile [(const_int 0)] 0)] - "" - "" - [(set_attr "length" "0") - (set_attr "type" "unknown") - (set_attr "predicable" "no")]) - -;; :::::::::::::::::::: -;; :: -;; :: Conditional execution -;; :: -;; :::::::::::::::::::: - -(define_cond_exec - [(match_operator:CC 0 "condexec_test_operator" - [(match_operand:CC 1 "br_flag_operand" "b") - (const_int 0)])] - "" - "") diff --git a/gcc/config/d30v/libgcc1.asm b/gcc/config/d30v/libgcc1.asm deleted file mode 100644 index ed359fc552e..00000000000 --- a/gcc/config/d30v/libgcc1.asm +++ /dev/null @@ -1,187 +0,0 @@ -/* Assembly support functions for libgcc. - * - * Copyright (C) 1997 Free Software Foundation, Inc. - * Contributed by Cygnus Support - * - * This file is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * In addition to the permissions in the GNU General Public License, the - * Free Software Foundation gives you unlimited permission to link the - * compiled version of this file into combinations with other programs, - * and to distribute those combinations without any restriction coming - * from the use of this file. (The General Public License restrictions - * do apply in other respects; for example, they cover modification of - * the file, and distribution when not linked into a combine - * executable.) - * - * This file is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - - -#ifdef L_udivsi3 - -/* For division, we use the following algorithm: - * - * unsigned - * __divsi3 (unsigned a, unsigned b) - * { - * unsigned al = a; - * unsigned ah = 0; - * unsigned tmpf; - * int i; - * - * for (i = 32; i > 0; i--) - * { - * ah = (ah << 1) | (al >> 31); - * tmpf = (ah >= b) ? 1 : 0; - * ah -= ((tmpf) ? b : 0); - * al = (al << 1) | tmpf; - * } - * - * return al; // for __udivsi3 - * return ah; // for __umodsi3 - * } - */ - - .file "_udivsi3" - .text - .globl __umodsi3 - .globl __udivsi3 - .type __umodsi3,@function - .type __udivsi3,@function - .stabs "libgcc1.asm",100,0,0,__umodsi3 - .stabs "int:t(0,1)=r(0,1);-2147483648;2147483647;",128,0,0,0 - .stabs "__umodsi3:F(0,1)",36,0,1,__umodsi3 - .stabs "a:P(0,1)",64,0,1,2 - .stabs "b:P(0,1)",64,0,1,3 - -__umodsi3: - bra.s .Lmerge || orfg f1,f1,1 ; indicate this is __umodsi3 -.Lumod: - .size __umodsi3,.Lumod-__umodsi3 - .stabs "",36,0,0,.Lumod-__umodsi3 - - .stabs "__udivsi3:F(0,1)",36,0,1,__udivsi3 - .stabs "a:P(0,1)",64,0,1,2 - .stabs "b:P(0,1)",64,0,1,3 -__udivsi3: - andfg f1,f1,0 || nop ; indicate this is __udivsi3 - -.Lmerge: - ; r2 = al - ; r3 = b - ; r4 = ah - ; r5 = loop counter - ; f0 = tmpf - ; f1 = 1 if this is mod, 0 if this is div - or r4,r0,0 || sub r5,r0,-32 ; ah = 0, loop = 32 - -.Lloop: - src r4,r2,-1 || sub r5,r5,1 ; ah = (ah << 1) | (al >> 31); decrement loop count - cmpuge f0,r4,r3 || sra r2,r2,-1 ; f0 = (ah >= b); al <<= 1 - sub/tx r4,r4,r3 || or/tx r2,r2,1 ; ah -= (tmpf) ? b : 0; al |= tmpf - bratnz.s r5,.Lloop || nop ; loop back if not done - jmp link || or/xt r2,r0,r4 ; if mod, update register, then return to user -.Ludiv: - .size __udivsi3,.Ludiv-__udivsi3 - .stabs "",36,0,0,.Ludiv-__udivsi3 - -#endif /* L_udivsi3 */ - - -#ifdef L_divsi3 - -/* For division, we use the following algorithm: - * - * unsigned - * __divsi3 (unsigned a, unsigned b) - * { - * unsigned al = __builtin_abs (a); - * unsigned b2 = __builtin_abs (b); - * unsigned ah = 0; - * unsigned tmpf; - * int i; - * - * for (i = 32; i > 0; i--) - * { - * ah = (ah << 1) | (al >> 31); - * tmpf = (ah >= b2) ? 1 : 0; - * ah -= ((tmpf) ? b2 : 0); - * al = (al << 1) | tmpf; - * } - * - * if (a < 0) - * ah = -ah, al = -al; - * - * if (b < 0) - * al = -al; - * - * return al; // for __divsi3 - * return ah; // for __modsi3 - * } - */ - - .file "_divsi3" - .text - .globl __modsi3 - .globl __divsi3 - .type __modsi3,@function - .type __divsi3,@function - .stabs "libgcc1.asm",100,0,0,__modsi3 - .stabs "int:t(0,1)=r(0,1);-2147483648;2147483647;",128,0,0,0 - .stabs "__modsi3:F(0,1)",36,0,1,__modsi3 - .stabs "a:P(0,1)",64,0,1,2 - .stabs "b:P(0,1)",64,0,1,3 - -__modsi3: - bra.s .Lmerge || orfg f1,f1,1 ; indicate this is __modsi3 -.Lmod: - .size __modsi3,.Lmod-__modsi3 - .stabs "",36,0,0,.Lmod-__modsi3 - - .stabs "__divsi3:F(0,1)",36,0,1,__divsi3 - .stabs "a:P(0,1)",64,0,1,2 - .stabs "b:P(0,1)",64,0,1,3 -__divsi3: - andfg f1,f1,0 || nop ; indicate this is __divsi3 - -.Lmerge: - ; r2 = al - ; r3 = b2 - ; r4 = ah - ; r5 = loop counter - ; r6 = a - ; r7 = b - ; f0 = tmpf - ; f1 = 1 if this is mod, 0 if this is div - or r6,r0,r2 || or r7,r0,r3 ; copy original inputs - abs r2,r2 || abs r3,r3 ; make both postive - or r4,r0,0 || sub r5,r0,-32 ; ah = 0, loop = 32 - -.Lloop: - src r4,r2,-1 || sub r5,r5,1 ; ah = (ah << 1) | (al >> 31); decrement loop count - cmpuge f0,r4,r3 || sra r2,r2,-1 ; f0 = (ah >= b); al <<= 1 - sub/tx r4,r4,r3 || or/tx r2,r2,1 ; ah -= (tmpf) ? b : 0; al |= tmpf - bratnz.s r5,.Lloop || nop ; loop back if not done - cmplt f0,r6,0 || nop ; f0 = (a < 0) - - sub/tx r2,r0,r2 || sub/tx r4,r0,r4 ; negate both al, ah if (a < 0) - cmplt f0,r7,0 -> sub/tx r2,r0,r2 ; negate al if (b < 0) - jmp link || or/xt r2,r0,r4 ; update result if mod; return to user -.Ldiv: - .size __divsi3,.Ldiv-__divsi3 - .stabs "",36,0,0,.Ldiv-__divsi3 - -#endif /* L_divsi3 */ diff --git a/gcc/config/d30v/t-d30v b/gcc/config/d30v/t-d30v deleted file mode 100644 index 2544f3db35e..00000000000 --- a/gcc/config/d30v/t-d30v +++ /dev/null @@ -1,32 +0,0 @@ -LIB1ASMSRC = d30v/libgcc1.asm -LIB1ASMFUNCS = _udivsi3 _divsi3 - -# Turn on full debug for libgcc.a. -LIBGCC2_DEBUG_CFLAGS = -g - -# We want fine grained libraries, so use the new code to build the -# floating point emulation libraries. -FPBIT = fp-bit.c -DPBIT = dp-bit.c - -dp-bit.c: $(srcdir)/config/fp-bit.c config.status - cat $(srcdir)/config/fp-bit.c > dp-bit.c - -fp-bit.c: $(srcdir)/config/fp-bit.c config.status - echo '#define FLOAT' > fp-bit.c - echo '#define _fpadd_parts _fpadd_parts_sf' >> fp-bit.c - cat $(srcdir)/config/fp-bit.c >> fp-bit.c - -# For svr4 we build crtbegin.o and crtend.o which serve to add begin and -# end labels to the .ctors and .dtors section when we link using gcc. - -EXTRA_PARTS=crtbegin.o crtend.o - -# We need to use -fPIC when we are using gcc to compile the routines in -# crtstuff.c. This is only really needed when we are going to use gcc/g++ -# to produce a shared library, but since we don't know ahead of time when -# we will be doing that, we just always use -fPIC when compiling the -# routines in crtstuff.c. - -# Right now, disable, since we don't support shared libraries on d30v yet. -#CRTSTUFF_T_CFLAGS = -fPIC diff --git a/gcc/config/dsp16xx/dsp16xx-modes.def b/gcc/config/dsp16xx/dsp16xx-modes.def deleted file mode 100644 index 968e271ff44..00000000000 --- a/gcc/config/dsp16xx/dsp16xx-modes.def +++ /dev/null @@ -1,23 +0,0 @@ -/* DSP16xx extra modes. - Copyright (C) 2003 Free Software Foundation, Inc. - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GCC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/* HFmode is the DSP16xx's equivalent of SFmode. - FIXME: What format is this anyway? */ -FLOAT_MODE (HF, 2, 0); diff --git a/gcc/config/dsp16xx/dsp16xx-protos.h b/gcc/config/dsp16xx/dsp16xx-protos.h deleted file mode 100644 index 802c69b62ec..00000000000 --- a/gcc/config/dsp16xx/dsp16xx-protos.h +++ /dev/null @@ -1,86 +0,0 @@ -/* Definitions of target machine for GNU compiler. AT&T DSP1600. - Copyright (C) 2000 Free Software Foundation, Inc. - Contributed by Michael Collison (collison@world.std.com). - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GCC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -#ifdef RTX_CODE -extern struct rtx_def *gen_compare_reg (enum rtx_code, rtx, rtx); -extern int call_address_operand (rtx, enum machine_mode); -extern int arith_reg_operand (rtx, enum machine_mode); -extern int symbolic_address_operand (rtx, enum machine_mode); -extern int Y_address_operand (rtx, enum machine_mode); -extern int sp_operand (rtx, enum machine_mode); -extern int sp_operand2 (rtx, enum machine_mode); -extern int nonmemory_arith_operand (rtx, enum machine_mode); -extern int dsp16xx_comparison_operator (rtx, enum machine_mode); -extern int unx_comparison_operator (rtx, enum machine_mode); -extern int signed_comparison_operator (rtx, enum machine_mode); - -extern void notice_update_cc (rtx); -extern void double_reg_from_memory (rtx[]); -extern void double_reg_to_memory (rtx[]); -extern enum rtx_code next_cc_user_code (rtx); -extern int next_cc_user_unsigned (rtx); -extern struct rtx_def *gen_tst_reg (rtx); -extern const char *output_block_move (rtx[]); -extern enum reg_class preferred_reload_class (rtx, enum reg_class); -extern enum reg_class secondary_reload_class (enum reg_class, - enum machine_mode, rtx); -extern int emit_move_sequence (rtx *, enum machine_mode); -extern void print_operand (FILE *, rtx, int); -extern void print_operand_address (FILE *, rtx); -extern void output_dsp16xx_float_const (rtx *); -extern void emit_1600_core_shift (enum rtx_code, rtx *, int); -extern int symbolic_address_p (rtx); -extern int uns_comparison_operator (rtx, enum machine_mode); -#endif /* RTX_CODE */ - - -#ifdef TREE_CODE -extern struct rtx_def *dsp16xx_function_arg (CUMULATIVE_ARGS, - enum machine_mode, - tree, int); -extern void dsp16xx_function_arg_advance (CUMULATIVE_ARGS *, - enum machine_mode, - tree, int); -#endif /* TREE_CODE */ - -extern void dsp16xx_invalid_register_for_compare (void); -extern int class_max_nregs (enum reg_class, enum machine_mode); -extern enum reg_class limit_reload_class (enum reg_class, enum machine_mode); -extern int dsp16xx_register_move_cost (enum reg_class, enum reg_class); -extern int dsp16xx_makes_calls (void); -extern long compute_frame_size (int); -extern int dsp16xx_call_saved_register (int); -extern int dsp16xx_call_saved_register (int); -extern void init_emulation_routines (void); -extern int ybase_regs_ever_used (void); -extern void override_options (void); -extern int dsp16xx_starting_frame_offset (void); -extern int initial_frame_pointer_offset (void); -extern void asm_output_common (FILE *, const char *, int, int); -extern void asm_output_local (FILE *, const char *, int, int); -extern void asm_output_float (FILE *, double); -extern bool dsp16xx_compare_gen; -extern int hard_regno_mode_ok (int, enum machine_mode); -extern enum reg_class dsp16xx_reg_class_from_letter (int); -extern int regno_reg_class (int); -extern void function_prologue (FILE *, int); -extern void function_epilogue (FILE *, int); -extern int num_1600_core_shifts (int); diff --git a/gcc/config/dsp16xx/dsp16xx.c b/gcc/config/dsp16xx/dsp16xx.c deleted file mode 100644 index 14d9c5e088e..00000000000 --- a/gcc/config/dsp16xx/dsp16xx.c +++ /dev/null @@ -1,2632 +0,0 @@ -/* Subroutines for assembler code output on the DSP1610. - Copyright (C) 1994, 1995, 1997, 1998, 2001 Free Software Foundation, Inc. - Contributed by Michael Collison (collison@isisinc.net). - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GCC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/* Some output-actions in dsp1600.md need these. */ -#include "config.h" -#include "system.h" -#include "coretypes.h" -#include "tm.h" -#include "rtl.h" -#include "regs.h" -#include "hard-reg-set.h" -#include "real.h" -#include "insn-config.h" -#include "conditions.h" -#include "output.h" -#include "insn-attr.h" -#include "tree.h" -#include "expr.h" -#include "function.h" -#include "flags.h" -#include "ggc.h" -#include "toplev.h" -#include "recog.h" -#include "tm_p.h" -#include "target.h" -#include "target-def.h" - -const char *text_seg_name; -const char *rsect_text; -const char *data_seg_name; -const char *rsect_data; -const char *bss_seg_name; -const char *rsect_bss; -const char *const_seg_name; -const char *rsect_const; - -const char *chip_name; -const char *save_chip_name; - -/* Save the operands of a compare. The 16xx has not lt or gt, so - in these cases we swap the operands and reverse the condition. */ - -rtx dsp16xx_compare_op0; -rtx dsp16xx_compare_op1; -bool dsp16xx_compare_gen; - -static const char *fp; -static const char *sp; -static const char *rr; -static const char *a1h; - -struct dsp16xx_frame_info current_frame_info; -struct dsp16xx_frame_info zero_frame_info; - -rtx dsp16xx_addhf3_libcall = (rtx) 0; -rtx dsp16xx_subhf3_libcall = (rtx) 0; -rtx dsp16xx_mulhf3_libcall = (rtx) 0; -rtx dsp16xx_divhf3_libcall = (rtx) 0; -rtx dsp16xx_cmphf3_libcall = (rtx) 0; -rtx dsp16xx_fixhfhi2_libcall = (rtx) 0; -rtx dsp16xx_floathihf2_libcall = (rtx) 0; -rtx dsp16xx_neghf2_libcall = (rtx) 0; - -rtx dsp16xx_mulhi3_libcall = (rtx) 0; -rtx dsp16xx_udivqi3_libcall = (rtx) 0; -rtx dsp16xx_udivhi3_libcall = (rtx) 0; -rtx dsp16xx_divqi3_libcall = (rtx) 0; -rtx dsp16xx_divhi3_libcall = (rtx) 0; -rtx dsp16xx_modqi3_libcall = (rtx) 0; -rtx dsp16xx_modhi3_libcall = (rtx) 0; -rtx dsp16xx_umodqi3_libcall = (rtx) 0; -rtx dsp16xx_umodhi3_libcall = (rtx) 0; -rtx dsp16xx_ashrhi3_libcall = (rtx) 0; -rtx dsp16xx_ashlhi3_libcall = (rtx) 0; -rtx dsp16xx_ucmphi2_libcall = (rtx) 0; -rtx dsp16xx_lshrhi3_libcall = (rtx) 0; - -static const char *const himode_reg_name[] = HIMODE_REGISTER_NAMES; - -#define SHIFT_INDEX_1 0 -#define SHIFT_INDEX_4 1 -#define SHIFT_INDEX_8 2 -#define SHIFT_INDEX_16 3 - -static const char *const ashift_right_asm[] = -{ - "%0=%0>>1", - "%0=%0>>4", - "%0=%0>>8", - "%0=%0>>16" -}; - -static const char *const ashift_right_asm_first[] = -{ - "%0=%1>>1", - "%0=%1>>4", - "%0=%1>>8", - "%0=%1>>16" -}; - -static const char *const ashift_left_asm[] = -{ - "%0=%0<<1", - "%0=%0<<4", - "%0=%0<<8", - "%0=%0<<16" -}; - -static const char *const ashift_left_asm_first[] = -{ - "%0=%1<<1", - "%0=%1<<4", - "%0=%1<<8", - "%0=%1<<16" -}; - -static const char *const lshift_right_asm[] = -{ - "%0=%0>>1\n\t%0=%b0&0x7fff", - "%0=%0>>4\n\t%0=%b0&0x0fff", - "%0=%0>>8\n\t%0=%b0&0x00ff", - "%0=%0>>16\n\t%0=%b0&0x0000" -}; - -static const char *const lshift_right_asm_first[] = -{ - "%0=%1>>1\n\t%0=%b0&0x7fff", - "%0=%1>>4\n\t%0=%b0&0x0fff", - "%0=%1>>8\n\t%0=%b0&0x00ff", - "%0=%1>>16\n\t%0=%b0&0x0000" -}; - -static int reg_save_size (void); -static void dsp16xx_output_function_prologue (FILE *, HOST_WIDE_INT); -static void dsp16xx_output_function_epilogue (FILE *, HOST_WIDE_INT); -static void dsp16xx_file_start (void); -static bool dsp16xx_rtx_costs (rtx, int, int, int *); -static int dsp16xx_address_cost (rtx); - -/* Initialize the GCC target structure. */ - -#undef TARGET_ASM_BYTE_OP -#define TARGET_ASM_BYTE_OP "\tint\t" -#undef TARGET_ASM_ALIGNED_HI_OP -#define TARGET_ASM_ALIGNED_HI_OP NULL -#undef TARGET_ASM_ALIGNED_SI_OP -#define TARGET_ASM_ALIGNED_SI_OP NULL - -#undef TARGET_ASM_FUNCTION_PROLOGUE -#define TARGET_ASM_FUNCTION_PROLOGUE dsp16xx_output_function_prologue -#undef TARGET_ASM_FUNCTION_EPILOGUE -#define TARGET_ASM_FUNCTION_EPILOGUE dsp16xx_output_function_epilogue - -#undef TARGET_ASM_FILE_START -#define TARGET_ASM_FILE_START dsp16xx_file_start - -#undef TARGET_RTX_COSTS -#define TARGET_RTX_COSTS dsp16xx_rtx_costs -#undef TARGET_ADDRESS_COST -#define TARGET_ADDRESS_COST dsp16xx_address_cost - -struct gcc_target targetm = TARGET_INITIALIZER; - -int -hard_regno_mode_ok (regno, mode) - int regno; - enum machine_mode mode; -{ - switch ((int) mode) - { - case VOIDmode: - return 1; - - /* We can't use the c0-c2 for QImode, since they are only - 8 bits in length. */ - - case QImode: - if (regno != REG_C0 && regno != REG_C1 && regno != REG_C2) - return 1; - else - return 0; - - /* We only allow a0, a1, y, and p to be allocated for 32-bit modes. - Additionally we allow the virtual ybase registers to be used for 32-bit - modes. */ - - case HFmode: - case HImode: -#if 0 /* ??? These modes do not appear in the machine description nor - are there library routines for them. */ - case SFmode: - case DFmode: - case XFmode: - case SImode: - case DImode: -#endif - if (regno == REG_A0 || regno == REG_A1 || regno == REG_Y || regno == REG_PROD - || (IS_YBASE_REGISTER_WINDOW(regno) && ((regno & 1) == 0))) - return 1; - else - return 0; - - default: - return 0; - } -} - -enum reg_class -dsp16xx_reg_class_from_letter (c) - int c; -{ - switch (c) - { - case 'A': - return ACCUM_REGS; - - case 'l': - return A0_REG; - - case 'C': - return A1_REG; - - case 'h': - return ACCUM_HIGH_REGS; - - case 'j': - return A0H_REG; - - case 'k': - return A0L_REG; - - case 'q': - return A1H_REG; - - case 'u': - return A1L_REG; - - case 'x': - return X_REG; - - case 'y': - return YH_REG; - - case 'z': - return YL_REG; - - case 't': - return P_REG; - - case 'Z': - return Y_OR_P_REGS; - - case 'd': - return ACCUM_Y_OR_P_REGS; - - case 'a': - return Y_ADDR_REGS; - - case 'B': - return (TARGET_BMU ? BMU_REGS : NO_REGS); - - case 'Y': - return YBASE_VIRT_REGS; - - case 'v': - return PH_REG; - - case 'w': - return PL_REG; - - case 'W': - return J_REG; - - case 'e': - return YBASE_ELIGIBLE_REGS; - - case 'b': - return ACCUM_LOW_REGS; - - case 'c': - return NON_YBASE_REGS; - - case 'f': - return Y_REG; - - case 'D': - return SLOW_MEM_LOAD_REGS; - - default: - return NO_REGS; - } -} - -/* Return the class number of the smallest class containing - reg number REGNO. */ - -int -regno_reg_class(regno) - int regno; -{ - switch (regno) - { - case REG_A0L: - return (int) A0L_REG; - case REG_A1L: - return (int) A1L_REG; - - case REG_A0: - return (int) A0H_REG; - case REG_A1: - return (int) A1H_REG; - - case REG_X: - return (int) X_REG; - - case REG_Y: - return (int) YH_REG; - case REG_YL: - return (int) YL_REG; - - case REG_PROD: - return (int) PH_REG; - case REG_PRODL: - return (int) PL_REG; - - case REG_R0: case REG_R1: case REG_R2: case REG_R3: - return (int) Y_ADDR_REGS; - - case REG_J: - return (int) J_REG; - case REG_K: - return (int) GENERAL_REGS; - - case REG_YBASE: - return (int) GENERAL_REGS; - - case REG_PT: - return (int) GENERAL_REGS; - - case REG_AR0: case REG_AR1: case REG_AR2: case REG_AR3: - return (int) BMU_REGS; - - case REG_C0: case REG_C1: case REG_C2: - return (int) GENERAL_REGS; - - case REG_PR: - return (int) GENERAL_REGS; - - case REG_RB: - return (int) GENERAL_REGS; - - case REG_YBASE0: case REG_YBASE1: case REG_YBASE2: case REG_YBASE3: - case REG_YBASE4: case REG_YBASE5: case REG_YBASE6: case REG_YBASE7: - case REG_YBASE8: case REG_YBASE9: case REG_YBASE10: case REG_YBASE11: - case REG_YBASE12: case REG_YBASE13: case REG_YBASE14: case REG_YBASE15: - case REG_YBASE16: case REG_YBASE17: case REG_YBASE18: case REG_YBASE19: - case REG_YBASE20: case REG_YBASE21: case REG_YBASE22: case REG_YBASE23: - case REG_YBASE24: case REG_YBASE25: case REG_YBASE26: case REG_YBASE27: - case REG_YBASE28: case REG_YBASE29: case REG_YBASE30: case REG_YBASE31: - return (int) YBASE_VIRT_REGS; - - default: - return (int) NO_REGS; - } -} - -/* A C expression for the maximum number of consecutive registers of class CLASS - needed to hold a value of mode MODE. */ - -int -class_max_nregs(class, mode) - enum reg_class class ATTRIBUTE_UNUSED; - enum machine_mode mode; -{ - return (GET_MODE_SIZE(mode)); -} - -enum reg_class -limit_reload_class (mode, class) - enum machine_mode mode ATTRIBUTE_UNUSED; - enum reg_class class; -{ - return class; -} - -int -dsp16xx_register_move_cost (from, to) - enum reg_class from, to; -{ - if (from == A0H_REG || from == A0L_REG || from == A0_REG || - from == A1H_REG || from == ACCUM_HIGH_REGS || from == A1L_REG || - from == ACCUM_LOW_REGS || from == A1_REG || from == ACCUM_REGS) - { - if (to == Y_REG || to == P_REG) - return 4; - else - return 2; - } - - if (to == A0H_REG || to == A0L_REG || to == A0_REG || - to == A1H_REG || to == ACCUM_HIGH_REGS || to == A1L_REG || - to == ACCUM_LOW_REGS || to == A1_REG || to == ACCUM_REGS) - { - return 2; - } - - if (from == YBASE_VIRT_REGS) - { - if (to == YBASE_VIRT_REGS) - return 16; - - if (to == X_REG || to == YH_REG || to == YL_REG || - to == Y_REG || to == PL_REG || to == PH_REG || - to == P_REG || to == Y_ADDR_REGS || to == YBASE_ELIGIBLE_REGS || - to == Y_OR_P_REGS) - { - return 8; - } - else - return 10; - } - - if (to == YBASE_VIRT_REGS) - { - if (from == X_REG || from == YH_REG || from == YL_REG || - from == Y_REG || from == PL_REG || from == PH_REG || - from == P_REG || from == Y_ADDR_REGS || from == YBASE_ELIGIBLE_REGS || - from == Y_OR_P_REGS) - { - return 8; - } - else - return 10; - } - - return 8; -} - -/* Given an rtx X being reloaded into a reg required to be - in class CLASS, return the class of reg to actually use. - In general this is just CLASS; but on some machines - in some cases it is preferable to use a more restrictive class. - Also, we must ensure that a PLUS is reloaded either - into an accumulator or an address register. */ - -enum reg_class -preferred_reload_class (x, class) - rtx x; - enum reg_class class; -{ - /* The ybase registers cannot have constants copied directly - to them. */ - - if (CONSTANT_P (x)) - { - switch ((int) class) - { - case YBASE_VIRT_REGS: - return (!reload_in_progress ? NO_REGS : class); - - case ACCUM_LOW_OR_YBASE_REGS: - return ACCUM_LOW_REGS; - - case ACCUM_OR_YBASE_REGS: - return ACCUM_REGS; - - case X_OR_YBASE_REGS: - return X_REG; - - case Y_OR_YBASE_REGS: - return Y_REG; - - case ACCUM_LOW_YL_PL_OR_YBASE_REGS: - return YL_OR_PL_OR_ACCUM_LOW_REGS; - - case P_OR_YBASE_REGS: - return P_REG; - - case ACCUM_Y_P_OR_YBASE_REGS: - return ACCUM_Y_OR_P_REGS; - - case Y_ADDR_OR_YBASE_REGS: - return Y_ADDR_REGS; - - case YBASE_OR_NOHIGH_YBASE_ELIGIBLE_REGS: - return NON_HIGH_YBASE_ELIGIBLE_REGS;; - - case YBASE_OR_YBASE_ELIGIBLE_REGS: - return YBASE_ELIGIBLE_REGS; - - case NO_HIGH_ALL_REGS: - return NOHIGH_NON_YBASE_REGS; - - case ALL_REGS: - return NON_YBASE_REGS; - - default: - return class; - } - } - - /* If x is not an accumulator or a ybase register, restrict the class of registers - we can copy the register into. */ - - if (REG_P (x) && !IS_ACCUM_REG (REGNO (x)) && !IS_YBASE_REGISTER_WINDOW (REGNO (x))) - { - switch ((int) class) - { - case NO_REGS: - case A0H_REG: case A0L_REG: case A0_REG: case A1H_REG: - case ACCUM_HIGH_REGS: case A1L_REG: case ACCUM_LOW_REGS: - case A1_REG: case ACCUM_REGS: - return class; - - case X_REG: - return (!reload_in_progress ? NO_REGS : class); - - case X_OR_ACCUM_LOW_REGS: - return ACCUM_LOW_REGS; - - case X_OR_ACCUM_REGS: - return ACCUM_REGS; - - case YH_REG: - return (!reload_in_progress ? NO_REGS : class); - - case YH_OR_ACCUM_HIGH_REGS: - return ACCUM_HIGH_REGS; - - case X_OR_YH_REGS: - case YL_REG: - return (!reload_in_progress ? NO_REGS : class); - - case YL_OR_ACCUM_LOW_REGS: - return ACCUM_LOW_REGS; - - case X_OR_YL_REGS: - case X_OR_Y_REGS: case Y_REG: - return (!reload_in_progress ? NO_REGS : class); - - case ACCUM_OR_Y_REGS: - return ACCUM_REGS; - - case PH_REG: - case X_OR_PH_REGS: case PL_REG: - return (!reload_in_progress ? NO_REGS : class); - - case PL_OR_ACCUM_LOW_REGS: - return ACCUM_LOW_REGS; - - case X_OR_PL_REGS: - return (!reload_in_progress ? NO_REGS : class); - - case YL_OR_PL_OR_ACCUM_LOW_REGS: - return ACCUM_LOW_REGS; - - case P_REG: - return (!reload_in_progress ? NO_REGS : class); - - case ACCUM_OR_P_REGS: - return ACCUM_REGS; - - case YL_OR_P_REGS: - return (!reload_in_progress ? NO_REGS : class); - - case ACCUM_LOW_OR_YL_OR_P_REGS: - return ACCUM_LOW_REGS; - - case Y_OR_P_REGS: - return (!reload_in_progress ? NO_REGS : class); - - case ACCUM_Y_OR_P_REGS: - return ACCUM_REGS; - - case NO_FRAME_Y_ADDR_REGS: - case Y_ADDR_REGS: - return (!reload_in_progress ? NO_REGS : class); - - case ACCUM_LOW_OR_Y_ADDR_REGS: - return ACCUM_LOW_REGS; - - case ACCUM_OR_Y_ADDR_REGS: - return ACCUM_REGS; - - case X_OR_Y_ADDR_REGS: - case Y_OR_Y_ADDR_REGS: - case P_OR_Y_ADDR_REGS: - return (!reload_in_progress ? NO_REGS : class); - - case NON_HIGH_YBASE_ELIGIBLE_REGS: - return ACCUM_LOW_REGS; - - case YBASE_ELIGIBLE_REGS: - return ACCUM_REGS; - - case J_REG: - case J_OR_DAU_16_BIT_REGS: - case BMU_REGS: - return (!reload_in_progress ? NO_REGS : class); - - case YBASE_VIRT_REGS: - if (IS_YBASE_ELIGIBLE_REG (REGNO (x))) - return class; - else - return (!reload_in_progress ? NO_REGS : class); - - case ACCUM_LOW_OR_YBASE_REGS: - if (IS_YBASE_ELIGIBLE_REG (REGNO (x))) - return class; - else - return ACCUM_LOW_REGS; - - case ACCUM_OR_YBASE_REGS: - if (IS_YBASE_ELIGIBLE_REG (REGNO (x))) - return class; - else - return ACCUM_REGS; - - case X_OR_YBASE_REGS: - case Y_OR_YBASE_REGS: - if (IS_YBASE_ELIGIBLE_REG (REGNO (x))) - return YBASE_VIRT_REGS; - else - return (!reload_in_progress ? NO_REGS : class); - - case ACCUM_LOW_YL_PL_OR_YBASE_REGS: - if (IS_YBASE_ELIGIBLE_REG (REGNO (x))) - return ACCUM_LOW_OR_YBASE_REGS; - else - return ACCUM_LOW_REGS; - - case P_OR_YBASE_REGS: - if (IS_YBASE_ELIGIBLE_REG (REGNO (x))) - return YBASE_VIRT_REGS; - else - return (!reload_in_progress ? NO_REGS : class); - - case ACCUM_Y_P_OR_YBASE_REGS: - if (IS_YBASE_ELIGIBLE_REG (REGNO (x))) - return ACCUM_OR_YBASE_REGS; - else - return ACCUM_REGS; - - case Y_ADDR_OR_YBASE_REGS: - if (IS_YBASE_ELIGIBLE_REG (REGNO (x))) - return YBASE_VIRT_REGS; - else - return (!reload_in_progress ? NO_REGS : class); - - case YBASE_OR_NOHIGH_YBASE_ELIGIBLE_REGS: - if (IS_YBASE_ELIGIBLE_REG (REGNO (x))) - return ACCUM_LOW_OR_YBASE_REGS; - else - return ACCUM_LOW_REGS; - - case YBASE_OR_YBASE_ELIGIBLE_REGS: - if (IS_YBASE_ELIGIBLE_REG (REGNO (x))) - return ACCUM_OR_YBASE_REGS; - else - return ACCUM_REGS; - - case NO_HIGH_ALL_REGS: - if (IS_YBASE_ELIGIBLE_REG (REGNO (x))) - return ACCUM_LOW_OR_YBASE_REGS; - else - return ACCUM_LOW_REGS; - - case ALL_REGS: - if (IS_YBASE_ELIGIBLE_REG (REGNO (x))) - return ACCUM_OR_YBASE_REGS; - else - return ACCUM_REGS; - - case NOHIGH_NON_ADDR_REGS: - return ACCUM_LOW_REGS; - - case NON_ADDR_REGS: - case SLOW_MEM_LOAD_REGS: - return ACCUM_REGS; - - case NOHIGH_NON_YBASE_REGS: - return ACCUM_LOW_REGS; - - case NO_ACCUM_NON_YBASE_REGS: - return (!reload_in_progress ? NO_REGS : class); - - case NON_YBASE_REGS: - return ACCUM_REGS; - - default: - return class; - } - } - - /* If x (the input) is a ybase register, restrict the class of registers - we can copy the register into. */ - - if (REG_P (x) && !TARGET_RESERVE_YBASE - && IS_YBASE_REGISTER_WINDOW (REGNO(x))) - { - switch ((int) class) - { - case NO_REGS: - case A0H_REG: case A0L_REG: case A0_REG: case A1H_REG: - case ACCUM_HIGH_REGS: case A1L_REG: case ACCUM_LOW_REGS: - case A1_REG: case ACCUM_REGS: case X_REG: - case X_OR_ACCUM_LOW_REGS: case X_OR_ACCUM_REGS: - case YH_REG: case YH_OR_ACCUM_HIGH_REGS: - case X_OR_YH_REGS: case YL_REG: - case YL_OR_ACCUM_LOW_REGS: case X_OR_YL_REGS: - case X_OR_Y_REGS: case Y_REG: - case ACCUM_OR_Y_REGS: case PH_REG: - case X_OR_PH_REGS: case PL_REG: - case PL_OR_ACCUM_LOW_REGS: case X_OR_PL_REGS: - case YL_OR_PL_OR_ACCUM_LOW_REGS: case P_REG: - case ACCUM_OR_P_REGS: case YL_OR_P_REGS: - case ACCUM_LOW_OR_YL_OR_P_REGS: case Y_OR_P_REGS: - case ACCUM_Y_OR_P_REGS: case NO_FRAME_Y_ADDR_REGS: - case Y_ADDR_REGS: case ACCUM_LOW_OR_Y_ADDR_REGS: - case ACCUM_OR_Y_ADDR_REGS: case X_OR_Y_ADDR_REGS: - case Y_OR_Y_ADDR_REGS: case P_OR_Y_ADDR_REGS: - case NON_HIGH_YBASE_ELIGIBLE_REGS: case YBASE_ELIGIBLE_REGS: - default: - return class; - - case J_REG: - return (!reload_in_progress ? NO_REGS : class); - - case J_OR_DAU_16_BIT_REGS: - return ACCUM_HIGH_REGS; - - case BMU_REGS: - case YBASE_VIRT_REGS: - return (!reload_in_progress ? NO_REGS : class); - - case ACCUM_LOW_OR_YBASE_REGS: - return ACCUM_LOW_REGS; - - case ACCUM_OR_YBASE_REGS: - return ACCUM_REGS; - - case X_OR_YBASE_REGS: - return X_REG; - - case Y_OR_YBASE_REGS: - return Y_REG; - - case ACCUM_LOW_YL_PL_OR_YBASE_REGS: - return YL_OR_PL_OR_ACCUM_LOW_REGS; - - case P_OR_YBASE_REGS: - return P_REG; - - case ACCUM_Y_P_OR_YBASE_REGS: - return ACCUM_Y_OR_P_REGS; - - case Y_ADDR_OR_YBASE_REGS: - return Y_ADDR_REGS; - - case YBASE_OR_NOHIGH_YBASE_ELIGIBLE_REGS: - return NON_HIGH_YBASE_ELIGIBLE_REGS; - - case YBASE_OR_YBASE_ELIGIBLE_REGS: - return YBASE_ELIGIBLE_REGS; - - case NO_HIGH_ALL_REGS: - return NON_HIGH_YBASE_ELIGIBLE_REGS; - - case ALL_REGS: - return YBASE_ELIGIBLE_REGS; - - case NOHIGH_NON_ADDR_REGS: - return ACCUM_LOW_OR_YL_OR_P_REGS; - - case NON_ADDR_REGS: - return ACCUM_Y_OR_P_REGS; - - case SLOW_MEM_LOAD_REGS: - return ACCUM_OR_Y_ADDR_REGS; - - case NOHIGH_NON_YBASE_REGS: - return NON_HIGH_YBASE_ELIGIBLE_REGS; - - case NO_ACCUM_NON_YBASE_REGS: - return Y_ADDR_REGS; - - case NON_YBASE_REGS: - return YBASE_ELIGIBLE_REGS; - } - } - - if (GET_CODE (x) == PLUS) - { - if (GET_MODE (x) == QImode - && REG_P (XEXP (x,0)) - && (XEXP (x,0) == frame_pointer_rtx - || XEXP (x,0) == stack_pointer_rtx) - && (GET_CODE (XEXP (x,1)) == CONST_INT)) - { - if (class == ACCUM_HIGH_REGS) - return class; - - /* If the accumulators are not part of the class - being reloaded into, return NO_REGS. */ -#if 0 - if (!reg_class_subset_p (ACCUM_REGS, class)) - return (!reload_in_progress ? NO_REGS : class); -#endif - if (reg_class_subset_p (ACCUM_HIGH_REGS, class)) - return ACCUM_HIGH_REGS; - - /* We will use accumulator 'a1l' for reloading a - PLUS. We can only use one accumulator because - 'reload_inqi' only allows one alternative to be - used. */ - - else if (class == ACCUM_LOW_REGS) - return A1L_REG; - else if (class == A0L_REG) - return NO_REGS; - else - return class; - } - - if (class == NON_YBASE_REGS || class == YBASE_ELIGIBLE_REGS) - return Y_ADDR_REGS; - else - return class; - } - else if (GET_CODE (x) == MEM) - { - /* We can't copy from a memory location into a - ybase register. */ - if (reg_class_subset_p(YBASE_VIRT_REGS, class)) - { - switch ((int) class) - { - case YBASE_VIRT_REGS: - return (!reload_in_progress ? NO_REGS : class); - - case ACCUM_LOW_OR_YBASE_REGS: - return ACCUM_LOW_REGS; - - case ACCUM_OR_YBASE_REGS: - return ACCUM_REGS; - - case X_OR_YBASE_REGS: - return X_REG; - - case Y_OR_YBASE_REGS: - return Y_REG; - - case ACCUM_LOW_YL_PL_OR_YBASE_REGS: - return YL_OR_PL_OR_ACCUM_LOW_REGS; - - case P_OR_YBASE_REGS: - return P_REG; - - case ACCUM_Y_P_OR_YBASE_REGS: - return ACCUM_Y_OR_P_REGS; - - case Y_ADDR_OR_YBASE_REGS: - return Y_ADDR_REGS; - - case YBASE_OR_NOHIGH_YBASE_ELIGIBLE_REGS: - return NON_HIGH_YBASE_ELIGIBLE_REGS; - - case YBASE_OR_YBASE_ELIGIBLE_REGS: - return YBASE_ELIGIBLE_REGS; - - case NO_HIGH_ALL_REGS: - return NOHIGH_NON_YBASE_REGS; - - case ALL_REGS: - return NON_YBASE_REGS; - - default: - return class; - } - } - else - return class; - } - else - return class; -} - -/* Return the register class of a scratch register needed to copy IN into - or out of a register in CLASS in MODE. If it can be done directly, - NO_REGS is returned. */ - -enum reg_class -secondary_reload_class (class, mode, in) - enum reg_class class; - enum machine_mode mode; - rtx in; -{ - int regno = -1; - - if (GET_CODE (in) == REG || GET_CODE (in) == SUBREG) - regno = true_regnum (in); - - /* If we are reloading a plus into a high accumulator register, - we need a scratch low accumulator, because the low half gets - clobbered. */ - - if (class == ACCUM_HIGH_REGS - || class == A1H_REG - || class == A0H_REG) - { - if (GET_CODE (in) == PLUS && mode == QImode) - return ACCUM_LOW_REGS; - } - - if (class == ACCUM_HIGH_REGS - || class == ACCUM_LOW_REGS - || class == A1L_REG - || class == A0L_REG - || class == A1H_REG - || class == A0H_REG) - { - if (GET_CODE (in) == PLUS && mode == QImode) - { - rtx addr0 = XEXP (in, 0); - rtx addr1 = XEXP (in, 1); - - /* If we are reloading a plus (reg:QI) (reg:QI) - we need an additional register. */ - if (REG_P (addr0) && REG_P (addr1)) - return NO_REGS; - } - } - - /* We can place anything into ACCUM_REGS and can put ACCUM_REGS - into anything. */ - - if ((class == ACCUM_REGS || class == ACCUM_HIGH_REGS || - class == ACCUM_LOW_REGS || class == A0H_REG || class == A0L_REG || - class == A1H_REG || class == A1_REG) || - (regno >= REG_A0 && regno < REG_A1L + 1)) - return NO_REGS; - - if (class == ACCUM_OR_YBASE_REGS && REG_P(in) - && IS_YBASE_ELIGIBLE_REG(regno)) - { - return NO_REGS; - } - - /* We can copy the ybase registers into: - r0-r3, a0-a1, y, p, & x or the union of - any of these. */ - - if (!TARGET_RESERVE_YBASE && IS_YBASE_REGISTER_WINDOW(regno)) - { - switch ((int) class) - { - case (int) X_REG: - case (int) X_OR_ACCUM_LOW_REGS: - case (int) X_OR_ACCUM_REGS: - case (int) YH_REG: - case (int) YH_OR_ACCUM_HIGH_REGS: - case (int) X_OR_YH_REGS: - case (int) YL_REG: - case (int) YL_OR_ACCUM_LOW_REGS: - case (int) X_OR_Y_REGS: - case (int) X_OR_YL_REGS: - case (int) Y_REG: - case (int) ACCUM_OR_Y_REGS: - case (int) PH_REG: - case (int) X_OR_PH_REGS: - case (int) PL_REG: - case (int) PL_OR_ACCUM_LOW_REGS: - case (int) X_OR_PL_REGS: - case (int) YL_OR_PL_OR_ACCUM_LOW_REGS: - case (int) P_REG: - case (int) ACCUM_OR_P_REGS: - case (int) YL_OR_P_REGS: - case (int) ACCUM_LOW_OR_YL_OR_P_REGS: - case (int) Y_OR_P_REGS: - case (int) ACCUM_Y_OR_P_REGS: - case (int) Y_ADDR_REGS: - case (int) ACCUM_LOW_OR_Y_ADDR_REGS: - case (int) ACCUM_OR_Y_ADDR_REGS: - case (int) X_OR_Y_ADDR_REGS: - case (int) Y_OR_Y_ADDR_REGS: - case (int) P_OR_Y_ADDR_REGS: - case (int) YBASE_ELIGIBLE_REGS: - return NO_REGS; - - default: - return ACCUM_HIGH_REGS; - } - } - - /* We can copy r0-r3, a0-a1, y, & p - directly to the ybase registers. In addition - we can use any of the ybase virtual registers - as the secondary reload registers when copying - between any of these registers. */ - - if (!TARGET_RESERVE_YBASE && regno != -1) - { - switch (regno) - { - case REG_A0: - case REG_A0L: - case REG_A1: - case REG_A1L: - case REG_X: - case REG_Y: - case REG_YL: - case REG_PROD: - case REG_PRODL: - case REG_R0: - case REG_R1: - case REG_R2: - case REG_R3: - if (class == YBASE_VIRT_REGS) - return NO_REGS; - else - { - switch ((int) class) - { - case (int) X_REG: - case (int) X_OR_ACCUM_LOW_REGS: - case (int) X_OR_ACCUM_REGS: - case (int) YH_REG: - case (int) YH_OR_ACCUM_HIGH_REGS: - case (int) X_OR_YH_REGS: - case (int) YL_REG: - case (int) YL_OR_ACCUM_LOW_REGS: - case (int) X_OR_Y_REGS: - case (int) X_OR_YL_REGS: - case (int) Y_REG: - case (int) ACCUM_OR_Y_REGS: - case (int) PH_REG: - case (int) X_OR_PH_REGS: - case (int) PL_REG: - case (int) PL_OR_ACCUM_LOW_REGS: - case (int) X_OR_PL_REGS: - case (int) YL_OR_PL_OR_ACCUM_LOW_REGS: - case (int) P_REG: - case (int) ACCUM_OR_P_REGS: - case (int) YL_OR_P_REGS: - case (int) ACCUM_LOW_OR_YL_OR_P_REGS: - case (int) Y_OR_P_REGS: - case (int) ACCUM_Y_OR_P_REGS: - case (int) Y_ADDR_REGS: - case (int) ACCUM_LOW_OR_Y_ADDR_REGS: - case (int) ACCUM_OR_Y_ADDR_REGS: - case (int) X_OR_Y_ADDR_REGS: - case (int) Y_OR_Y_ADDR_REGS: - case (int) P_OR_Y_ADDR_REGS: - case (int) YBASE_ELIGIBLE_REGS: - return YBASE_VIRT_REGS; - - default: - break; - } - } - } - } - - /* Memory or constants can be moved from or to any register - except the ybase virtual registers. */ - if (regno == -1 && GET_CODE(in) != PLUS) - { - if (class == YBASE_VIRT_REGS) - return NON_YBASE_REGS; - else - return NO_REGS; - } - - if (GET_CODE (in) == PLUS && mode == QImode) - { - rtx addr0 = XEXP (in, 0); - rtx addr1 = XEXP (in, 1); - - /* If we are reloading a plus (reg:QI) (reg:QI) - we need a low accumulator, not a high one. */ - if (REG_P (addr0) && REG_P (addr1)) - return ACCUM_LOW_REGS; - } - -#if 0 - if (REG_P(in)) - return ACCUM_REGS; -#endif - - /* Otherwise, we need a high accumulator(s). */ - return ACCUM_HIGH_REGS; -} - -int -symbolic_address_operand (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - return (symbolic_address_p (op)); -} - -int -symbolic_address_p (op) - rtx op; -{ - switch (GET_CODE (op)) - { - case SYMBOL_REF: - case LABEL_REF: - return 1; - - case CONST: - op = XEXP (op, 0); - return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF - || GET_CODE (XEXP (op, 0)) == LABEL_REF) - && GET_CODE (XEXP (op, 1)) == CONST_INT - && INTVAL (XEXP (op,1)) < 0x20); - - default: - return 0; - } -} - -/* For a Y address space operand we allow only *rn, *rn++, *rn--. - This routine only recognizes *rn, the '<>' constraints recognize - (*rn++), and (*rn--). */ - -int -Y_address_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return (memory_address_p (mode, op) && !symbolic_address_p (op)); -} - -int -sp_operand (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - return (GET_CODE (op) == PLUS - && (XEXP (op, 0) == stack_pointer_rtx - || XEXP (op, 0) == frame_pointer_rtx) - && GET_CODE (XEXP (op,1)) == CONST_INT); -} - -int -sp_operand2 (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - if ((GET_CODE (op) == PLUS - && (XEXP (op, 0) == stack_pointer_rtx - || XEXP (op, 0) == frame_pointer_rtx) - && (REG_P (XEXP (op,1)) - && IS_ADDRESS_REGISTER (REGNO (XEXP(op, 1)))))) - return 1; - else if ((GET_CODE (op) == PLUS - && (XEXP (op, 1) == stack_pointer_rtx - || XEXP (op, 1) == frame_pointer_rtx) - && (REG_P (XEXP (op,0)) - && IS_ADDRESS_REGISTER (REGNO (XEXP(op, 1)))))) - return 1; - else - return 0; -} - -int -nonmemory_arith_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return (immediate_operand (op, mode) || arith_reg_operand (op, mode)); -} - -int -arith_reg_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return (register_operand (op, mode) - && (GET_CODE (op) != REG - || REGNO (op) >= FIRST_PSEUDO_REGISTER - || (!(IS_YBASE_REGISTER_WINDOW (REGNO (op))) - && REGNO (op) != FRAME_POINTER_REGNUM))); -} - -int -call_address_operand (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - if (symbolic_address_p (op) || REG_P(op)) - { - return 1; - } - - return 0; -} - -int -dsp16xx_comparison_operator (op, mode) - register rtx op; - enum machine_mode mode; -{ - return ((mode == VOIDmode || GET_MODE (op) == mode) - && GET_RTX_CLASS (GET_CODE (op)) == '<' - && (GET_CODE(op) != GE && GET_CODE (op) != LT && - GET_CODE (op) != GEU && GET_CODE (op) != LTU)); -} - -void -notice_update_cc(exp) - rtx exp; -{ - if (GET_CODE (exp) == SET) - { - /* Jumps do not alter the cc's. */ - - if (SET_DEST (exp) == pc_rtx) - return; - - /* Moving register or memory into a register: - it doesn't alter the cc's, but it might invalidate - the RTX's which we remember the cc's came from. - (Note that moving a constant 0 or 1 MAY set the cc's). */ - if (REG_P (SET_DEST (exp)) - && (REG_P (SET_SRC (exp)) || GET_CODE (SET_SRC (exp)) == MEM)) - { - if (cc_status.value1 - && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1)) - cc_status.value1 = 0; - if (cc_status.value2 - && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2)) - cc_status.value2 = 0; - return; - } - /* Moving register into memory doesn't alter the cc's. - It may invalidate the RTX's which we remember the cc's came from. */ - if (GET_CODE (SET_DEST (exp)) == MEM && REG_P (SET_SRC (exp))) - { - if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM) - cc_status.value1 = 0; - if (cc_status.value2 && GET_CODE (cc_status.value2) == MEM) - cc_status.value2 = 0; - return; - } - /* Function calls clobber the cc's. */ - else if (GET_CODE (SET_SRC (exp)) == CALL) - { - CC_STATUS_INIT; - return; - } - /* Tests and compares set the cc's in predictable ways. */ - else if (SET_DEST (exp) == cc0_rtx) - { - CC_STATUS_INIT; - cc_status.value1 = SET_SRC (exp); - return; - } - /* Certain instructions effect the condition codes. */ - else if (GET_MODE_CLASS (GET_MODE (SET_SRC (exp))) == MODE_INT) - switch (GET_CODE (SET_SRC (exp))) - { - case PLUS: - case MINUS: - if (REG_P (SET_DEST (exp))) - { - /* Address registers don't set the condition codes. */ - if (IS_ADDRESS_REGISTER (REGNO (SET_DEST (exp)))) - { - CC_STATUS_INIT; - break; - } - } - case ASHIFTRT: - case LSHIFTRT: - case ASHIFT: - case AND: - case IOR: - case XOR: - case MULT: - case NEG: - case NOT: - cc_status.value1 = SET_SRC (exp); - cc_status.value2 = SET_DEST (exp); - break; - - default: - CC_STATUS_INIT; - } - else - { - CC_STATUS_INIT; - } - } - else if (GET_CODE (exp) == PARALLEL - && GET_CODE (XVECEXP (exp, 0, 0)) == SET) - { - if (SET_DEST (XVECEXP (exp, 0, 0)) == pc_rtx) - return; - - if (SET_DEST (XVECEXP (exp, 0, 0)) == cc0_rtx) - { - CC_STATUS_INIT; - cc_status.value1 = SET_SRC (XVECEXP (exp, 0, 0)); - return; - } - - CC_STATUS_INIT; - } - else - { - CC_STATUS_INIT; - } -} - -int -dsp16xx_makes_calls () -{ - rtx insn; - - for (insn = get_insns (); insn; insn = next_insn (insn)) - if (GET_CODE (insn) == CALL_INSN) - return (1); - - return 0; -} - -long -compute_frame_size (size) - int size; -{ - long total_size; - long var_size; - long args_size; - long extra_size; - long reg_size; - - /* This value is needed to compute reg_size. */ - current_frame_info.function_makes_calls = !leaf_function_p (); - - reg_size = 0; - extra_size = 0; - var_size = size; - args_size = current_function_outgoing_args_size; - reg_size = reg_save_size (); - - total_size = var_size + args_size + extra_size + reg_size; - - - /* Save other computed information. */ - current_frame_info.total_size = total_size; - current_frame_info.var_size = var_size; - current_frame_info.args_size = args_size; - current_frame_info.extra_size = extra_size; - current_frame_info.reg_size = reg_size; - current_frame_info.initialized = reload_completed; - current_frame_info.reg_size = reg_size / UNITS_PER_WORD; - - if (reg_size) - { - unsigned long offset = args_size + var_size + reg_size; - current_frame_info.sp_save_offset = offset; - current_frame_info.fp_save_offset = offset - total_size; - } - - return total_size; -} - -int -dsp16xx_call_saved_register (regno) - int regno; -{ -#if 0 - if (regno == REG_PR && current_frame_info.function_makes_calls) - return 1; -#endif - return (regs_ever_live[regno] && !call_used_regs[regno] && - !IS_YBASE_REGISTER_WINDOW(regno)); -} - -int -ybase_regs_ever_used () -{ - int regno; - int live = 0; - - for (regno = REG_YBASE0; regno <= REG_YBASE31; regno++) - if (regs_ever_live[regno]) - { - live = 1; - break; - } - - return live; -} - -static void -dsp16xx_output_function_prologue (file, size) - FILE *file; - HOST_WIDE_INT size; -{ - int regno; - long total_size; - fp = reg_names[FRAME_POINTER_REGNUM]; - sp = reg_names[STACK_POINTER_REGNUM]; - rr = reg_names[RETURN_ADDRESS_REGNUM]; /* return address register */ - a1h = reg_names[REG_A1]; - - total_size = compute_frame_size (size); - - fprintf (file, "\t/* FUNCTION PROLOGUE: */\n"); - fprintf (file, "\t/* total=%ld, vars= %ld, regs= %d, args=%d, extra= %ld */\n", - current_frame_info.total_size, - current_frame_info.var_size, - current_frame_info.reg_size, - current_function_outgoing_args_size, - current_frame_info.extra_size); - - fprintf (file, "\t/* fp save offset= %ld, sp save_offset= %ld */\n\n", - current_frame_info.fp_save_offset, - current_frame_info.sp_save_offset); - /* Set up the 'ybase' register window. */ - - if (ybase_regs_ever_used()) - { - fprintf (file, "\t%s=%s\n", a1h, reg_names[REG_YBASE]); - if (TARGET_YBASE_HIGH) - fprintf (file, "\t%s=%sh-32\n", reg_names[REG_A1], a1h); - else - fprintf (file, "\t%s=%sh+32\n", reg_names[REG_A1], a1h); - fprintf (file, "\t%s=%s\n", reg_names[REG_YBASE], a1h); - } - - if (current_frame_info.var_size) - { - if (current_frame_info.var_size == 1) - fprintf (file, "\t*%s++\n", sp); - else - { - if (SMALL_INTVAL(current_frame_info.var_size) && ((current_frame_info.var_size & 0x8000) == 0)) - fprintf (file, "\t%s=%ld\n\t*%s++%s\n", reg_names[REG_J], current_frame_info.var_size, sp, reg_names[REG_J]); - else - fatal_error ("stack size > 32k"); - } - } - - /* Save any registers this function uses, unless they are - used in a call, in which case we don't need to. */ - - for(regno = 0; regno < FIRST_PSEUDO_REGISTER; ++ regno) - if (dsp16xx_call_saved_register (regno)) - { - fprintf (file, "\tpush(*%s)=%s\n", sp, reg_names[regno]); - } - - /* For debugging purposes, we want the return address to be at a predictable - location. */ - if (current_frame_info.function_makes_calls) - fprintf (file, "\tpush(*%s)=%s\n", sp, reg_names[RETURN_ADDRESS_REGNUM]); - - if (current_frame_info.args_size) - { - if (current_frame_info.args_size == 1) - fprintf (file, "\t*%s++\n", sp); - else - error ("stack size > 32k"); - } - - if (frame_pointer_needed) - { - fprintf (file, "\t%s=%s\n", a1h, sp); - fprintf (file, "\t%s=%s\n", fp, a1h); /* Establish new base frame */ - fprintf (file, "\t%s=%ld\n", reg_names[REG_J], -total_size); - fprintf (file, "\t*%s++%s\n", fp, reg_names[REG_J]); - } - - fprintf (file, "\t/* END FUNCTION PROLOGUE: */\n\n"); -} - -void -init_emulation_routines () -{ - dsp16xx_addhf3_libcall = (rtx) 0; - dsp16xx_subhf3_libcall = (rtx) 0; - dsp16xx_mulhf3_libcall = (rtx) 0; - dsp16xx_divhf3_libcall = (rtx) 0; - dsp16xx_cmphf3_libcall = (rtx) 0; - dsp16xx_fixhfhi2_libcall = (rtx) 0; - dsp16xx_floathihf2_libcall = (rtx) 0; - dsp16xx_neghf2_libcall = (rtx) 0; - - dsp16xx_mulhi3_libcall = (rtx) 0; - dsp16xx_udivqi3_libcall = (rtx) 0; - dsp16xx_udivhi3_libcall = (rtx) 0; - dsp16xx_divqi3_libcall = (rtx) 0; - dsp16xx_divhi3_libcall = (rtx) 0; - dsp16xx_modqi3_libcall = (rtx) 0; - dsp16xx_modhi3_libcall = (rtx) 0; - dsp16xx_umodqi3_libcall = (rtx) 0; - dsp16xx_umodhi3_libcall = (rtx) 0; - dsp16xx_ashrhi3_libcall = (rtx) 0; - dsp16xx_ashlhi3_libcall = (rtx) 0; - dsp16xx_ucmphi2_libcall = (rtx) 0; - dsp16xx_lshrhi3_libcall = (rtx) 0; - -} -static void -dsp16xx_output_function_epilogue (file, size) - FILE *file; - HOST_WIDE_INT size ATTRIBUTE_UNUSED; -{ - int regno; - - fp = reg_names[FRAME_POINTER_REGNUM]; - sp = reg_names[STACK_POINTER_REGNUM]; - rr = reg_names[RETURN_ADDRESS_REGNUM]; /* return address register */ - a1h = reg_names[REG_A1]; - - fprintf (file, "\n\t/* FUNCTION EPILOGUE: */\n"); - - if (current_frame_info.args_size) - { - if (current_frame_info.args_size == 1) - fprintf (file, "\t*%s--\n", sp); - else - { - fprintf (file, "\t%s=%ld\n\t*%s++%s\n", - reg_names[REG_J], -current_frame_info.args_size, sp, reg_names[REG_J]); - } - } - - if (ybase_regs_ever_used()) - { - fprintf (file, "\t%s=%s\n", a1h, reg_names[REG_YBASE]); - if (TARGET_YBASE_HIGH) - fprintf (file, "\t%s=%sh+32\n", reg_names[REG_A1], a1h); - else - fprintf (file, "\t%s=%sh-32\n", reg_names[REG_A1], a1h); - fprintf (file, "\t%s=%s\n", reg_names[REG_YBASE], a1h); - } - - if (current_frame_info.function_makes_calls) - fprintf (file, "\t%s=pop(*%s)\n", reg_names[RETURN_ADDRESS_REGNUM], sp); - - for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; --regno) - if (dsp16xx_call_saved_register(regno)) - { - fprintf (file, "\t%s=pop(*%s)\n", reg_names[regno], sp); - } - - if (current_frame_info.var_size) - { - if (current_frame_info.var_size == 1) - fprintf (file, "\t*%s--\n", sp); - else - { - fprintf (file, "\t%s=%ld\n\t*%s++%s\n", - reg_names[REG_J], -current_frame_info.var_size, sp, reg_names[REG_J]); - } - } - - fprintf (file, "\treturn\n"); - /* Reset the frame info for the next function. */ - current_frame_info = zero_frame_info; - init_emulation_routines (); -} - -/* Emit insns to move operands[1] into operands[0]. - - Return 1 if we have written out everything that needs to be done to - do the move. Otherwise, return 0 and the caller will emit the move - normally. */ - -int -emit_move_sequence (operands, mode) - rtx *operands; - enum machine_mode mode; -{ - register rtx operand0 = operands[0]; - register rtx operand1 = operands[1]; - - /* We can only store registers to memory. */ - - if (GET_CODE (operand0) == MEM && GET_CODE (operand1) != REG) - operands[1] = force_reg (mode, operand1); - - return 0; -} - -void -double_reg_from_memory (operands) - rtx operands[]; -{ - rtx xoperands[4]; - - if (GET_CODE(XEXP(operands[1],0)) == POST_INC) - { - output_asm_insn ("%u0=%1", operands); - output_asm_insn ("%w0=%1", operands); - } - else if (GET_CODE(XEXP(operands[1],0)) == POST_DEC) - { - xoperands[1] = XEXP (XEXP (operands[1], 0), 0); - xoperands[0] = operands[0]; - - /* We can't use j anymore since the compiler can allocate it. */ -/* output_asm_insn ("j=-3\n\t%u0=*%1++\n\t%w0=*%1++j", xoperands); */ - output_asm_insn ("%u0=*%1++\n\t%w0=*%1--\n\t*%1--\n\t*%1--", xoperands); - } - else if (GET_CODE(XEXP(operands[1],0)) == PLUS) - { - rtx addr; - int offset = 0; - - output_asm_insn ("%u0=%1", operands); - - - /* In order to print out the least significant word we must - use 'offset + 1'. */ - addr = XEXP (operands[1], 0); - if (GET_CODE (XEXP(addr,0)) == CONST_INT) - offset = INTVAL(XEXP(addr,0)) + 1; - else if (GET_CODE (XEXP(addr,1)) == CONST_INT) - offset = INTVAL(XEXP(addr,1)) + 1; - - fprintf (asm_out_file, "\t%s=*(%d)\n", reg_names[REGNO(operands[0]) + 1], offset + 31); - } - else - { - xoperands[1] = XEXP(operands[1],0); - xoperands[0] = operands[0]; - - output_asm_insn ("%u0=*%1++\n\t%w0=*%1--", xoperands); - } -} - - -void -double_reg_to_memory (operands) - rtx operands[]; -{ - rtx xoperands[4]; - - if (GET_CODE(XEXP(operands[0],0)) == POST_INC) - { - output_asm_insn ("%0=%u1", operands); - output_asm_insn ("%0=%w1", operands); - } - else if (GET_CODE(XEXP(operands[0],0)) == POST_DEC) - { - xoperands[0] = XEXP (XEXP (operands[0], 0), 0); - xoperands[1] = operands[1]; - - /* We can't use j anymore since the compiler can allocate it. */ - -/* output_asm_insn ("j=-3\n\t*%0++=%u1\n\t*%0++j=%w1", xoperands); */ - output_asm_insn ("*%0++=%u1\n\t*%0--=%w1\n\t*%0--\n\t*%0--", xoperands); - - } - else if (GET_CODE(XEXP(operands[0],0)) == PLUS) - { - rtx addr; - int offset = 0; - - output_asm_insn ("%0=%u1", operands); - - /* In order to print out the least significant word we must - use 'offset + 1'. */ - addr = XEXP (operands[0], 0); - if (GET_CODE (XEXP(addr,0)) == CONST_INT) - offset = INTVAL(XEXP(addr,0)) + 1; - else if (GET_CODE (XEXP(addr,1)) == CONST_INT) - offset = INTVAL(XEXP(addr,1)) + 1; - else - fatal_error ("invalid addressing mode"); - - fprintf (asm_out_file, "\t*(%d)=%s\n", offset + 31, reg_names[REGNO(operands[1]) + 1]); - } - else - { - xoperands[0] = XEXP(operands[0],0); - xoperands[1] = operands[1]; - - output_asm_insn ("*%0++=%u1\n\t*%0--=%w1", xoperands); - } -} - -void -override_options () -{ - if (chip_name == (char *) 0) - chip_name = DEFAULT_CHIP_NAME; - - if (text_seg_name == (char *) 0) - text_seg_name = DEFAULT_TEXT_SEG_NAME; - - if (data_seg_name == (char *) 0) - data_seg_name = DEFAULT_DATA_SEG_NAME; - - if (bss_seg_name == (char *) 0) - bss_seg_name = DEFAULT_BSS_SEG_NAME; - - if (const_seg_name == (char *) 0) - const_seg_name = DEFAULT_CONST_SEG_NAME; - - save_chip_name = xstrdup (chip_name); - - rsect_text = concat (".rsect \"", text_seg_name, "\"", NULL); - rsect_data = concat (".rsect \"", data_seg_name, "\"", NULL); - rsect_bss = concat (".rsect \"", bss_seg_name, "\"", NULL); - rsect_const = concat (".rsect \"", const_seg_name, "\"", NULL); -} - -int -next_cc_user_unsigned (insn) - rtx insn; -{ - switch (next_cc_user_code (insn)) - { - case GTU: - case GEU: - case LTU: - case LEU: - return 1; - default: - return 0; - } -} - -enum rtx_code -next_cc_user_code (insn) - rtx insn; -{ - /* If no insn could be found we assume that the jump has been - deleted and the compare will be deleted later. */ - - if (!(insn = next_cc0_user (insn))) - return (enum rtx_code) 0; - else if (GET_CODE (insn) == JUMP_INSN - && GET_CODE (PATTERN (insn)) == SET - && GET_CODE (SET_SRC (PATTERN (insn))) == IF_THEN_ELSE) - return GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 0)); - else if (GET_CODE (insn) == INSN - && GET_CODE (PATTERN (insn)) == SET - && comparison_operator (SET_SRC (PATTERN (insn)), VOIDmode)) - return GET_CODE (SET_SRC (PATTERN (insn))); - else - abort (); -} - -void -print_operand(file, op, letter) - FILE *file; - rtx op; - int letter; -{ - enum rtx_code code; - - code = GET_CODE(op); - - switch (letter) - { - case 'I': - code = reverse_condition (code); - /* Fallthrough */ - - case 'C': - if (code == EQ) - { - fputs ("eq", file); - return; - } - else if (code == NE) - { - fputs ("ne", file); - return; - } - else if (code == GT || code == GTU) - { - fputs ("gt", file); - return; - } - else if (code == LT || code == LTU) - { - fputs ("mi", file); - return; - } - else if (code == GE || code == GEU) - { - fputs ("pl", file); - return; - } - else if (code == LE || code == LEU) - { - fputs ("le", file); - return; - } - else - abort (); - break; - - default: - break; - } - - if (code == REG) - { - /* Print the low half of a 32-bit register pair. */ - if (letter == 'w') - fprintf (file, "%s", reg_names[REGNO (op) + 1]); - else if (letter == 'u' || !letter) - fprintf (file, "%s", reg_names[REGNO (op)]); - else if (letter == 'b') - fprintf (file, "%sh", reg_names[REGNO (op)]); - else if (letter == 'm') - fprintf (file, "%s", himode_reg_name[REGNO (op)]); - else - output_operand_lossage ("bad register extension code"); - } - else if (code == MEM) - output_address (XEXP(op,0)); - else if (code == CONST_INT) - { - HOST_WIDE_INT val = INTVAL (op); - - if (letter == 'H') - fprintf (file, HOST_WIDE_INT_PRINT_HEX, val & 0xffff); - else if (letter == 'h') - fprintf (file, HOST_WIDE_INT_PRINT_DEC, val); - else if (letter == 'U') - fprintf (file, HOST_WIDE_INT_PRINT_HEX, (val >> 16) & 0xffff); - else - output_addr_const(file, op); - } - else if (code == CONST_DOUBLE && GET_MODE(op) != DImode) - { - long l; - REAL_VALUE_TYPE r; - REAL_VALUE_FROM_CONST_DOUBLE (r, op); - REAL_VALUE_TO_TARGET_SINGLE (r, l); - fprintf (file, "0x%lx", l); - } - else if (code == CONST) - { - rtx addr = XEXP (op, 0); - - if (GET_CODE (addr) != PLUS) - { - output_addr_const(file, op); - return; - } - - if ((GET_CODE (XEXP (addr, 0)) == SYMBOL_REF - || GET_CODE (XEXP (addr, 0)) == LABEL_REF) - && (GET_CODE (XEXP (addr, 1)) == CONST_INT)) - { - int n = INTVAL (XEXP(addr, 1)); - output_addr_const (file, XEXP (addr, 0)); - - if (n >= 0) - fprintf (file, "+"); - - n = (int) (short) n; - fprintf (file, "%d", n); - } - else if ((GET_CODE (XEXP (addr, 1)) == SYMBOL_REF - || GET_CODE (XEXP (addr, 1)) == LABEL_REF) - && (GET_CODE (XEXP (addr, 0)) == CONST_INT)) - { - int n = INTVAL (XEXP(addr, 0)); - output_addr_const (file, XEXP (addr, 1)); - - if (n >= 0) - fprintf (file, "+"); - - n = (int) (short) n; - fprintf (file, "%d", n); - } - else - output_addr_const(file, op); - } - else - output_addr_const (file, op); -} - - -void -print_operand_address(file, addr) - FILE *file; - rtx addr; -{ - rtx base; - int offset = 0;; - - switch (GET_CODE (addr)) - { - case REG: - fprintf (file, "*%s", reg_names[REGNO (addr)]); - break; - case POST_DEC: - fprintf (file, "*%s--", reg_names[REGNO (XEXP (addr, 0))]); - break; - case POST_INC: - fprintf (file, "*%s++", reg_names[REGNO (XEXP (addr, 0))]); - break; - case PLUS: - if (GET_CODE (XEXP(addr,0)) == CONST_INT) - offset = INTVAL(XEXP(addr,0)), base = XEXP(addr,1); - else if (GET_CODE (XEXP(addr,1)) == CONST_INT) - offset = INTVAL(XEXP(addr,1)), base = XEXP(addr,0); - else - abort(); - if (GET_CODE (base) == REG && REGNO(base) == STACK_POINTER_REGNUM) - { - if (offset >= -31 && offset <= 0) - offset = 31 + offset; - else - fatal_error ("invalid offset in ybase addressing"); - } - else - fatal_error ("invalid register in ybase addressing"); - - fprintf (file, "*(%d)", offset); - break; - - default: - if (FITS_5_BITS (addr)) - fprintf (file, "*(0x%x)", (int)(INTVAL (addr) & 0x20)); - else - output_addr_const (file, addr); - } -} - -void -output_dsp16xx_float_const (operands) - rtx *operands; -{ - rtx src = operands[1]; - - REAL_VALUE_TYPE d; - long value; - - REAL_VALUE_FROM_CONST_DOUBLE (d, src); - REAL_VALUE_TO_TARGET_SINGLE (d, value); - - operands[1] = GEN_INT (value); - output_asm_insn ("%u0=%U1\n\t%w0=%H1", operands); -} - -static int -reg_save_size () -{ - int reg_save_size = 0; - int regno; - - for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) - if (dsp16xx_call_saved_register (regno)) - { - reg_save_size += UNITS_PER_WORD; - } - - /* If the function makes calls we will save need to save the 'pr' register. */ - if (current_frame_info.function_makes_calls) - reg_save_size += 1; - - return (reg_save_size); -} - -#if 0 -int -dsp16xx_starting_frame_offset() -{ - int reg_save_size = 0; - int regno; - - for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) - if (dsp16xx_call_saved_register (regno)) - { - reg_save_size += UNITS_PER_WORD; - } - - return (reg_save_size); -} -#endif - -int -initial_frame_pointer_offset() -{ - int offset = 0; - - offset = compute_frame_size (get_frame_size()); - -#ifdef STACK_GROWS_DOWNWARD - return (offset); -#else - return (-offset); -#endif -} - -/* Generate the minimum number of 1600 core shift instructions - to shift by 'shift_amount'. */ - -#if 0 -void -emit_1600_core_shift (shift_op, operands, shift_amount, mode) - enum rtx_code shift_op; - rtx *operands; - int shift_amount; - enum machine_mode mode; -{ - int quotient; - int i; - int first_shift_emitted = 0; - - while (shift_amount != 0) - { - if (shift_amount/16) - { - quotient = shift_amount/16; - shift_amount = shift_amount - (quotient * 16); - for (i = 0; i < quotient; i++) - emit_insn (gen_rtx_SET (VOIDmode, operands[0], - gen_rtx (shift_op, mode, - first_shift_emitted - ? operands[0] : operands[1], - GEN_INT (16)))); - first_shift_emitted = 1; - } - else if (shift_amount/8) - { - quotient = shift_amount/8; - shift_amount = shift_amount - (quotient * 8); - for (i = 0; i < quotient; i++) - emit_insn (gen_rtx_SET (VOIDmode, operands[0], - gen_rtx (shift_op, mode, - first_shift_emitted - ? operands[0] : operands[1], - GEN_INT (8)))); - first_shift_emitted = 1; - } - else if (shift_amount/4) - { - quotient = shift_amount/4; - shift_amount = shift_amount - (quotient * 4); - for (i = 0; i < quotient; i++) - emit_insn (gen_rtx_SET (VOIDmode, operands[0], - gen_rtx (shift_op, mode, - first_shift_emitted - ? operands[0] : operands[1], - GEN_INT (4)))); - first_shift_emitted = 1; - } - else if (shift_amount/1) - { - quotient = shift_amount/1; - shift_amount = shift_amount - (quotient * 1); - for (i = 0; i < quotient; i++) - emit_insn (gen_rtx_SET (VOIDmode, operands[0], - gen_rtx (shift_op, mode, - first_shift_emitted - ? operands[0] : operands[1], - GEN_INT (1)))); - first_shift_emitted = 1; - } - } -} -#else -void -emit_1600_core_shift (shift_op, operands, shift_amount) - enum rtx_code shift_op; - rtx *operands; - int shift_amount; -{ - int quotient; - int i; - int first_shift_emitted = 0; - const char * const *shift_asm_ptr; - const char * const *shift_asm_ptr_first; - - if (shift_op == ASHIFT) - { - shift_asm_ptr = ashift_left_asm; - shift_asm_ptr_first = ashift_left_asm_first; - } - else if (shift_op == ASHIFTRT) - { - shift_asm_ptr = ashift_right_asm; - shift_asm_ptr_first = ashift_right_asm_first; - } - else if (shift_op == LSHIFTRT) - { - shift_asm_ptr = lshift_right_asm; - shift_asm_ptr_first = lshift_right_asm_first; - } - else - fatal_error ("invalid shift operator in emit_1600_core_shift"); - - while (shift_amount != 0) - { - if (shift_amount/16) - { - quotient = shift_amount/16; - shift_amount = shift_amount - (quotient * 16); - for (i = 0; i < quotient; i++) - output_asm_insn ((first_shift_emitted ? shift_asm_ptr[SHIFT_INDEX_16] - : shift_asm_ptr_first[SHIFT_INDEX_16]), operands); - first_shift_emitted = 1; - } - else if (shift_amount/8) - { - quotient = shift_amount/8; - shift_amount = shift_amount - (quotient * 8); - for (i = 0; i < quotient; i++) - output_asm_insn ((first_shift_emitted ? shift_asm_ptr[SHIFT_INDEX_8] - : shift_asm_ptr_first[SHIFT_INDEX_8]), operands); - first_shift_emitted = 1; - } - else if (shift_amount/4) - { - quotient = shift_amount/4; - shift_amount = shift_amount - (quotient * 4); - for (i = 0; i < quotient; i++) - output_asm_insn ((first_shift_emitted ? shift_asm_ptr[SHIFT_INDEX_4] - : shift_asm_ptr_first[SHIFT_INDEX_4]), operands); - first_shift_emitted = 1; - } - else if (shift_amount/1) - { - quotient = shift_amount/1; - shift_amount = shift_amount - (quotient * 1); - for (i = 0; i < quotient; i++) - output_asm_insn ((first_shift_emitted ? shift_asm_ptr[SHIFT_INDEX_1] - : shift_asm_ptr_first[SHIFT_INDEX_1]), operands); - first_shift_emitted = 1; - } - } -} -#endif - -int -num_1600_core_shifts (shift_amount) -int shift_amount; -{ - int quotient; - int i; - int first_shift_emitted = 0; - int num_shifts = 0; - - while (shift_amount != 0) - { - if (shift_amount/16) - { - quotient = shift_amount/16; - shift_amount = shift_amount - (quotient * 16); - for (i = 0; i < quotient; i++) - num_shifts++; - first_shift_emitted = 1; - } - else if (shift_amount/8) - { - quotient = shift_amount/8; - shift_amount = shift_amount - (quotient * 8); - for (i = 0; i < quotient; i++) - num_shifts++; - - first_shift_emitted = 1; - } - else if (shift_amount/4) - { - quotient = shift_amount/4; - shift_amount = shift_amount - (quotient * 4); - for (i = 0; i < quotient; i++) - num_shifts++; - - first_shift_emitted = 1; - } - else if (shift_amount/1) - { - quotient = shift_amount/1; - shift_amount = shift_amount - (quotient * 1); - for (i = 0; i < quotient; i++) - num_shifts++; - - first_shift_emitted = 1; - } - } - return num_shifts; -} - -void -asm_output_common(file, name, size, rounded) - FILE *file; - const char *name; - int size ATTRIBUTE_UNUSED; - int rounded; -{ - bss_section (); - (*targetm.asm_out.globalize_label) (file, name); - assemble_name (file, name); - fputs (":", file); - if (rounded > 1) - fprintf (file, "%d * int\n", rounded); - else - fprintf (file, "int\n"); -} - -void -asm_output_local(file, name, size, rounded) - FILE *file; - const char *name; - int size ATTRIBUTE_UNUSED; - int rounded; -{ - bss_section (); - assemble_name (file, name); - fputs (":", file); - if (rounded > 1) - fprintf (file, "%d * int\n", rounded); - else - fprintf (file, "int\n"); -} - -static int -dsp16xx_address_cost (addr) - rtx addr; -{ - switch (GET_CODE (addr)) - { - default: - break; - - case REG: - return 1; - - case CONST: - { - rtx offset = const0_rtx; - addr = eliminate_constant_term (addr, &offset); - - if (GET_CODE (addr) == LABEL_REF) - return 2; - - if (GET_CODE (addr) != SYMBOL_REF) - return 4; - - if (INTVAL (offset) == 0) - return 2; - } - /* fall through */ - - case POST_INC: case POST_DEC: - return (GET_MODE (addr) == QImode ? 1 : 2); - - case SYMBOL_REF: case LABEL_REF: - return 2; - - case PLUS: - { - register rtx plus0 = XEXP (addr, 0); - register rtx plus1 = XEXP (addr, 1); - - if (GET_CODE (plus0) != REG && GET_CODE (plus1) == REG) - { - plus0 = XEXP (addr, 1); - plus1 = XEXP (addr, 0); - } - - if (GET_CODE (plus0) != REG) - break; - - switch (GET_CODE (plus1)) - { - default: - break; - - case CONST_INT: - return 4; - - case CONST: - case SYMBOL_REF: - case LABEL_REF: - return dsp16xx_address_cost (plus1) + 1; - } - } - } - - return 4; -} - - -/* Determine whether a function argument is passed in a register, and - which register. - - The arguments are CUM, which summarizes all the previous - arguments; MODE, the machine mode of the argument; TYPE, - the data type of the argument as a tree node or 0 if that is not known - (which happens for C support library functions); and NAMED, - which is 1 for an ordinary argument and 0 for nameless arguments that - correspond to `...' in the called function's prototype. - - The value of the expression should either be a `reg' RTX for the - hard register in which to pass the argument, or zero to pass the - argument on the stack. - - On the dsp1610 the first four words of args are normally in registers - and the rest are pushed. If we a long or on float mode, the argument - must begin on an even register boundary - - Note that FUNCTION_ARG and FUNCTION_INCOMING_ARG were different. - For structures that are passed in memory, but could have been - passed in registers, we first load the structure into the - register, and then when the last argument is passed, we store - the registers into the stack locations. This fixes some bugs - where GCC did not expect to have register arguments, followed. */ - -struct rtx_def * -dsp16xx_function_arg (args_so_far, mode, type, named) - CUMULATIVE_ARGS args_so_far; - enum machine_mode mode; - tree type; - int named; -{ - if (TARGET_REGPARM) - { - if ((args_so_far & 1) != 0 - && (mode == HImode || GET_MODE_CLASS(mode) == MODE_FLOAT)) - args_so_far++; - - if (type == void_type_node) - return (struct rtx_def *) 0; - - if (named && args_so_far < 4 && !MUST_PASS_IN_STACK (mode,type)) - return gen_rtx_REG (mode, args_so_far + FIRST_REG_FOR_FUNCTION_ARG); - else - return (struct rtx_def *) 0; - } - else - return (struct rtx_def *) 0; -} - -/* Advance the argument to the next argument position. */ - -void -dsp16xx_function_arg_advance (cum, mode, type, named) - CUMULATIVE_ARGS *cum; /* current arg information */ - enum machine_mode mode; /* current arg mode */ - tree type; /* type of the argument or 0 if lib support */ - int named ATTRIBUTE_UNUSED;/* whether or not the argument was named */ -{ - if (TARGET_REGPARM) - { - if ((*cum & 1) != 0 - && (mode == HImode || GET_MODE_CLASS(mode) == MODE_FLOAT)) - *cum += 1; - - if (mode != BLKmode) - *cum += GET_MODE_SIZE (mode); - else - *cum += int_size_in_bytes (type); - } -} - -static void -dsp16xx_file_start () -{ - fprintf (asm_out_file, "#include <%s.h>\n", save_chip_name); -} - -rtx -gen_tst_reg (x) - rtx x; -{ - enum machine_mode mode; - - mode = GET_MODE (x); - - if (mode == QImode) - emit_insn (gen_rtx_PARALLEL - (VOIDmode, - gen_rtvec (2, gen_rtx_SET (VOIDmode, cc0_rtx, x), - gen_rtx_CLOBBER (VOIDmode, - gen_rtx_SCRATCH (QImode))))); - else if (mode == HImode) - emit_insn (gen_rtx_SET (VOIDmode, cc0_rtx, x)); - else - fatal_error ("invalid mode for gen_tst_reg"); - - return cc0_rtx; -} - -rtx -gen_compare_reg (code, x, y) - enum rtx_code code; - rtx x, y; -{ - enum machine_mode mode; - - mode = GET_MODE (x); - /* For floating point compare insns, a call is generated so don't - do anything here. */ - - if (GET_MODE_CLASS (mode) == MODE_FLOAT) - return cc0_rtx; - - if (mode == QImode) - { - if (code == GTU || code == GEU - || code == LTU || code == LEU) - { - emit_insn (gen_rtx_PARALLEL - (VOIDmode, - gen_rtvec (3, - gen_rtx_SET (VOIDmode, cc0_rtx, - gen_rtx_COMPARE (mode, x, y)), - gen_rtx_CLOBBER (VOIDmode, - gen_rtx_SCRATCH (QImode)), - gen_rtx_CLOBBER (VOIDmode, - gen_rtx_SCRATCH (QImode))))); - } - else - { - emit_insn (gen_rtx_PARALLEL - (VOIDmode, - gen_rtvec (3, gen_rtx_SET (VOIDmode, cc0_rtx, - gen_rtx_COMPARE (mode, x, y)), - gen_rtx_CLOBBER (VOIDmode, - gen_rtx_SCRATCH (QImode)), - gen_rtx_CLOBBER (VOIDmode, - gen_rtx_SCRATCH (QImode))))); - } - } - else if (mode == HImode) - { - if (code == GTU || code == GEU - || code == LTU || code == LEU) - { - emit_insn (gen_rtx_PARALLEL - (VOIDmode, - gen_rtvec (5, - gen_rtx_SET (VOIDmode, cc0_rtx, - gen_rtx_COMPARE (VOIDmode, x, y)), - gen_rtx_CLOBBER (VOIDmode, - gen_rtx_SCRATCH (QImode)), - gen_rtx_CLOBBER (VOIDmode, - gen_rtx_SCRATCH (QImode)), - gen_rtx_CLOBBER (VOIDmode, - gen_rtx_SCRATCH (QImode)), - gen_rtx_CLOBBER (VOIDmode, - gen_rtx_SCRATCH (QImode))))); - } - else - emit_insn (gen_rtx_SET (VOIDmode, cc0_rtx, - gen_rtx_COMPARE (VOIDmode, - force_reg (HImode, x), - force_reg (HImode,y)))); - } - else - fatal_error ("invalid mode for integer comparison in gen_compare_reg"); - - return cc0_rtx; -} - -const char * -output_block_move (operands) - rtx operands[]; -{ - int loop_count = INTVAL(operands[2]); - rtx xoperands[4]; - - fprintf (asm_out_file, "\tdo %d {\n", loop_count); - xoperands[0] = operands[4]; - xoperands[1] = operands[1]; - output_asm_insn ("%0=*%1++", xoperands); - - xoperands[0] = operands[0]; - xoperands[1] = operands[4]; - output_asm_insn ("*%0++=%1", xoperands); - - fprintf (asm_out_file, "\t}\n"); - return ""; -} - -int -uns_comparison_operator (op, mode) - rtx op; - enum machine_mode mode; -{ - if (mode == VOIDmode || GET_MODE (op) == mode) - { - enum rtx_code code; - - code = GET_CODE(op); - - if (code == LEU || code == LTU || code == GEU - || code == GTU) - { - return 1; - } - else - return 0; - } - - return 0; -} - -int -signed_comparison_operator (op, mode) - rtx op; - enum machine_mode mode; -{ - if (mode == VOIDmode || GET_MODE (op) == mode) - { - enum rtx_code code; - - code = GET_CODE(op); - - if (!(code == LEU || code == LTU || code == GEU - || code == GTU)) - { - return 1; - } - else - return 0; - } - - return 0; -} - -static bool -dsp16xx_rtx_costs (x, code, outer_code, total) - rtx x; - int code; - int outer_code ATTRIBUTE_UNUSED; - int *total; -{ - switch (code) - { - case CONST_INT: - *total = (unsigned HOST_WIDE_INT) INTVAL (x) < 65536 ? 0 : 2; - return true; - - case LABEL_REF: - case SYMBOL_REF: - case CONST: - *total = COSTS_N_INSNS (1); - return true; - - case CONST_DOUBLE: - *total = COSTS_N_INSNS (2); - return true; - - case MEM: - *total = COSTS_N_INSNS (GET_MODE (x) == QImode ? 2 : 4); - return true; - - case DIV: - case MOD: - *total = COSTS_N_INSNS (38); - return true; - - case MULT: - if (GET_MODE (x) == QImode) - *total = COSTS_N_INSNS (2); - else - *total = COSTS_N_INSNS (38); - return true; - - case PLUS: - case MINUS: - case AND: - case IOR: - case XOR: - if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT) - { - *total = 1; - return false; - } - else - { - *total = COSTS_N_INSNS (38); - return true; - } - - case NEG: - case NOT: - *total = COSTS_N_INSNS (1); - return true; - - case ASHIFT: - case ASHIFTRT: - case LSHIFTRT: - if (GET_CODE (XEXP (x, 1)) == CONST_INT) - { - HOST_WIDE_INT number = INTVAL (XEXP (x, 1)); - if (number == 1 || number == 4 || number == 8 - || number == 16) - *total = COSTS_N_INSNS (1); - else if (TARGET_BMU) - *total = COSTS_N_INSNS (2); - else - *total = COSTS_N_INSNS (num_1600_core_shifts (number)); - return true; - } - break; - } - - if (TARGET_BMU) - *total = COSTS_N_INSNS (1); - else - *total = COSTS_N_INSNS (15); - return true; -} diff --git a/gcc/config/dsp16xx/dsp16xx.h b/gcc/config/dsp16xx/dsp16xx.h deleted file mode 100644 index cea995ca104..00000000000 --- a/gcc/config/dsp16xx/dsp16xx.h +++ /dev/null @@ -1,1767 +0,0 @@ -/* Definitions of target machine for GNU compiler. AT&T DSP1600. - Copyright (C) 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003 - Free Software Foundation, Inc. - Contributed by Michael Collison (collison@isisinc.net). - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GCC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -extern const char *low_reg_names[]; -extern const char *text_seg_name; -extern const char *rsect_text; -extern const char *data_seg_name; -extern const char *rsect_data; -extern const char *bss_seg_name; -extern const char *rsect_bss; -extern const char *const_seg_name; -extern const char *rsect_const; -extern const char *chip_name; -extern const char *save_chip_name; -extern GTY(()) rtx dsp16xx_compare_op0; -extern GTY(()) rtx dsp16xx_compare_op1; -extern GTY(()) rtx dsp16xx_addhf3_libcall; -extern GTY(()) rtx dsp16xx_subhf3_libcall; -extern GTY(()) rtx dsp16xx_mulhf3_libcall; -extern GTY(()) rtx dsp16xx_divhf3_libcall; -extern GTY(()) rtx dsp16xx_cmphf3_libcall; -extern GTY(()) rtx dsp16xx_fixhfhi2_libcall; -extern GTY(()) rtx dsp16xx_floathihf2_libcall; -extern GTY(()) rtx dsp16xx_neghf2_libcall; -extern GTY(()) rtx dsp16xx_mulhi3_libcall; -extern GTY(()) rtx dsp16xx_udivqi3_libcall; -extern GTY(()) rtx dsp16xx_udivhi3_libcall; -extern GTY(()) rtx dsp16xx_divqi3_libcall; -extern GTY(()) rtx dsp16xx_divhi3_libcall; -extern GTY(()) rtx dsp16xx_modqi3_libcall; -extern GTY(()) rtx dsp16xx_modhi3_libcall; -extern GTY(()) rtx dsp16xx_umodqi3_libcall; -extern GTY(()) rtx dsp16xx_umodhi3_libcall; - -extern GTY(()) rtx dsp16xx_ashrhi3_libcall; -extern GTY(()) rtx dsp16xx_ashlhi3_libcall; -extern GTY(()) rtx dsp16xx_lshrhi3_libcall; - -/* RUN-TIME TARGET SPECIFICATION */ -#define DSP16XX 1 - -/* Name of the AT&T assembler */ - -#define ASM_PROG "as1600" - -/* Name of the AT&T linker */ - -#define LD_PROG "ld1600" - -/* Define which switches take word arguments */ -#define WORD_SWITCH_TAKES_ARG(STR) \ - (!strcmp (STR, "ifile") ? 1 : \ - 0) - -#undef CC1_SPEC -#define CC1_SPEC "%{!O*:-O}" - -/* Define this as a spec to call the AT&T assembler */ - -#define CROSS_ASM_SPEC "%{!S:as1600 %a %i\n }" - -/* Define this as a spec to call the AT&T linker */ - -#define CROSS_LINK_SPEC "%{!c:%{!M:%{!MM:%{!E:%{!S:ld1600 %l %X %{o*} %{m} \ - %{r} %{s} %{t} %{u*} %{x}\ - %{!A:%{!nostdlib:%{!nostartfiles:%S}}} %{static:}\ - %{L*} %D %o %{!nostdlib:-le1600 %L -le1600}\ - %{!A:%{!nostdlib:%{!nostartfiles:%E}}}\n }}}}}" - -/* Nothing complicated here, just link with libc.a under normal - circumstances */ -#define LIB_SPEC "-lc" - -/* Specify the startup file to link with. */ -#define STARTFILE_SPEC "%{mmap1:m1_crt0.o%s} \ -%{mmap2:m2_crt0.o%s} \ -%{mmap3:m3_crt0.o%s} \ -%{mmap4:m4_crt0.o%s} \ -%{!mmap*: %{!ifile*: m4_crt0.o%s} %{ifile*: \ -%ea -ifile option requires a -map option}}" - -/* Specify the end file to link with */ - -#define ENDFILE_SPEC "%{mmap1:m1_crtn.o%s} \ -%{mmap2:m2_crtn.o%s} \ -%{mmap3:m3_crtn.o%s} \ -%{mmap4:m4_crtn.o%s} \ -%{!mmap*: %{!ifile*: m4_crtn.o%s} %{ifile*: \ -%ea -ifile option requires a -map option}}" - - -/* Tell gcc where to look for the startfile */ -/*#define STANDARD_STARTFILE_PREFIX "/d1600/lib"*/ - -/* Tell gcc where to look for it's executables */ -/*#define STANDARD_EXEC_PREFIX "/d1600/bin"*/ - -/* Command line options to the AT&T assembler */ -#define ASM_SPEC "%{V} %{v:%{!V:-V}} %{g*:-g}" - -/* Command line options for the AT&T linker */ - -#define LINK_SPEC "%{V} %{v:%{!V:-V}} %{minit:-i} \ -%{!ifile*:%{mmap1:m1_deflt.if%s} \ - %{mmap2:m2_deflt.if%s} \ - %{mmap3:m3_deflt.if%s} \ - %{mmap4:m4_deflt.if%s} \ - %{!mmap*:m4_deflt.if%s}} \ -%{ifile*:%*} %{r}" - -/* Include path is determined from the environment variable */ -#define INCLUDE_DEFAULTS \ -{ \ - { 0, 0, 0, 0, 0 } \ -} - -/* Names to predefine in the preprocessor for this target machine. */ -#define TARGET_CPU_CPP_BUILTINS() \ - do \ - { \ - builtin_define_std ("dsp1600"); \ - builtin_define_std ("DSP1600"); \ - } \ - while (0) - -#ifdef __MSDOS__ -# define TARGET_OS_CPP_BUILTINS() \ - do \ - { \ - builtin_define_std ("MSDOS"); \ - } \ - while (0) -#else -# define TARGET_OS_CPP_BUILTINS() \ - do \ - { \ - builtin_define_std ("dsp1610"); \ - builtin_define_std ("DSP1610"); \ - } \ - while (0) -#endif - -/* Run-time compilation parameters selecting different hardware subsets. */ - -extern int target_flags; - -/* Macros used in the machine description to test the flags. */ - -#define MASK_REGPARM 0x00000001 /* Pass parameters in registers */ -#define MASK_NEAR_CALL 0x00000002 /* The call is on the same 4k page */ -#define MASK_NEAR_JUMP 0x00000004 /* The jump is on the same 4k page */ -#define MASK_BMU 0x00000008 /* Use the 'bmu' shift instructions */ -#define MASK_MAP1 0x00000040 /* Link with map1 */ -#define MASK_MAP2 0x00000080 /* Link with map2 */ -#define MASK_MAP3 0x00000100 /* Link with map3 */ -#define MASK_MAP4 0x00000200 /* Link with map4 */ -#define MASK_YBASE_HIGH 0x00000400 /* The ybase register window starts high */ -#define MASK_INIT 0x00000800 /* Have the linker generate tables to - initialize data at startup */ -#define MASK_RESERVE_YBASE 0x00002000 /* Reserved the ybase registers */ -#define MASK_DEBUG 0x00004000 /* Debugging turned on*/ -#define MASK_SAVE_TEMPS 0x00008000 /* Save temps. option seen */ - -/* Compile passing first two args in regs 0 and 1. - This exists only to test compiler features that will - be needed for RISC chips. It is not usable - and is not intended to be usable on this cpu. */ -#define TARGET_REGPARM (target_flags & MASK_REGPARM) - -/* The call is on the same 4k page, so instead of loading - the 'pt' register and branching, we can branch directly */ - -#define TARGET_NEAR_CALL (target_flags & MASK_NEAR_CALL) - -/* The jump is on the same 4k page, so instead of loading - the 'pt' register and branching, we can branch directly */ - -#define TARGET_NEAR_JUMP (target_flags & MASK_NEAR_JUMP) - -/* Generate shift instructions to use the 1610 Bit Manipulation - Unit. */ -#define TARGET_BMU (target_flags & MASK_BMU) - -#define TARGET_YBASE_HIGH (target_flags & MASK_YBASE_HIGH) - -/* Direct the linker to output extra info for initialized data */ -#define TARGET_MASK_INIT (target_flags & MASK_INIT) - -#define TARGET_INLINE_MULT (target_flags & MASK_INLINE_MULT) - -/* Reserve the ybase registers *(0) - *(31) */ -#define TARGET_RESERVE_YBASE (target_flags & MASK_RESERVE_YBASE) - -/* We turn this option on internally after seeing "-g" */ -#define TARGET_DEBUG (target_flags & MASK_DEBUG) - -/* We turn this option on internally after seeing "-save-temps */ -#define TARGET_SAVE_TEMPS (target_flags & MASK_SAVE_TEMPS) - - -/* Macro to define tables used to set the flags. - This is a list in braces of pairs in braces, - each pair being { "NAME", VALUE } - where VALUE is the bits to set or minus the bits to clear. - An empty string NAME is used to identify the default VALUE. */ - - -#define TARGET_SWITCHES \ - { \ - { "regparm", MASK_REGPARM, \ - N_("Pass parameters in registers (default)") }, \ - { "no-regparm", -MASK_REGPARM, \ - N_("Don't pass parameters in registers") }, \ - { "near-call", MASK_NEAR_JUMP, \ - N_("Generate code for near calls") }, \ - { "no-near-call", -MASK_NEAR_CALL, \ - N_("Don't generate code for near calls") }, \ - { "near-jump", MASK_NEAR_JUMP, \ - N_("Generate code for near jumps") }, \ - { "no-near-jump", -MASK_NEAR_JUMP, \ - N_("Don't generate code for near jumps") }, \ - { "bmu", MASK_BMU, \ - N_("Generate code for a bit-manipulation unit") }, \ - { "no-bmu", -MASK_BMU, \ - N_("Don't generate code for a bit-manipulation unit") }, \ - { "map1", MASK_MAP1, \ - N_("Generate code for memory map1") }, \ - { "map2", MASK_MAP2, \ - N_("Generate code for memory map2") }, \ - { "map3", MASK_MAP3, \ - N_("Generate code for memory map3") }, \ - { "map4", MASK_MAP4, \ - N_("Generate code for memory map4") }, \ - { "init", MASK_INIT, \ - N_("Ouput extra code for initialized data") }, \ - { "reserve-ybase", MASK_RESERVE_YBASE, \ - N_("Don't let reg. allocator use ybase registers") }, \ - { "debug", MASK_DEBUG, \ - N_("Output extra debug info in Luxworks environment") }, \ - { "save-temporaries", MASK_SAVE_TEMPS, \ - N_("Save temp. files in Luxworks environment") }, \ - { "", TARGET_DEFAULT, ""} \ - } - -/* Default target_flags if no switches are specified */ -#ifndef TARGET_DEFAULT -#define TARGET_DEFAULT MASK_REGPARM|MASK_YBASE_HIGH -#endif - -#define TARGET_OPTIONS \ -{ \ - { "text=", &text_seg_name, \ - N_("Specify alternate name for text section"), 0}, \ - { "data=", &data_seg_name, \ - N_("Specify alternate name for data section"), 0}, \ - { "bss=", &bss_seg_name, \ - N_("Specify alternate name for bss section"), 0}, \ - { "const=", &const_seg_name, \ - N_("Specify alternate name for constant section"), 0}, \ - { "chip=", &chip_name, \ - N_("Specify alternate name for dsp16xx chip"), 0}, \ -} - -/* Sometimes certain combinations of command options do not make sense - on a particular target machine. You can define a macro - `OVERRIDE_OPTIONS' to take account of this. This macro, if - defined, is executed once just after all the command options have - been parsed. - - Don't use this macro to turn on various extra optimizations for - `-O'. That is what `OPTIMIZATION_OPTIONS' is for. */ - -#define OVERRIDE_OPTIONS override_options () - -#define OPTIMIZATION_OPTIONS(LEVEL,SIZE) \ -{ \ - if (LEVEL >= 2) \ - { \ - /* The dsp16xx family has so few registers \ - * that running the first instruction \ - * scheduling is bad for reg. allocation \ - * since it increases lifetimes of pseudos. \ - * So turn of first scheduling pass. \ - */ \ - flag_schedule_insns = FALSE; \ - } \ -} - -/* STORAGE LAYOUT */ - -/* Define this if most significant bit is lowest numbered - in instructions that operate on numbered bit-fields. - */ -#define BITS_BIG_ENDIAN 0 - -/* Define this if most significant byte of a word is the lowest numbered. - We define big-endian, but since the 1600 series cannot address bytes - it does not matter. */ -#define BYTES_BIG_ENDIAN 1 - -/* Define this if most significant word of a multiword number is numbered. - For the 1600 we can decide arbitrarily since there are no machine instructions for them. */ -#define WORDS_BIG_ENDIAN 1 - -/* number of bits in an addressable storage unit */ -#define BITS_PER_UNIT 16 - -/* Maximum number of bits in a word. */ -#define MAX_BITS_PER_WORD 16 - -/* Width of a word, in units (bytes). */ -#define UNITS_PER_WORD 1 - -/* Allocation boundary (in *bits*) for storing pointers in memory. */ -#define POINTER_BOUNDARY 16 - -/* Allocation boundary (in *bits*) for storing arguments in argument list. */ -#define PARM_BOUNDARY 16 - -/* Boundary (in *bits*) on which stack pointer should be aligned. */ -#define STACK_BOUNDARY 16 - -/* Allocation boundary (in *bits*) for the code of a function. */ -#define FUNCTION_BOUNDARY 16 - -/* Biggest alignment that any data type can require on this machine, in bits. */ -#define BIGGEST_ALIGNMENT 16 - -/* Biggest alignment that any structure field can require on this machine, in bits */ -#define BIGGEST_FIELD_ALIGNMENT 16 - -/* Alignment of field after `int : 0' in a structure. */ -#define EMPTY_FIELD_BOUNDARY 16 - -/* Number of bits which any structure or union's size must be a multiple of. Each structure - or union's size is rounded up to a multiple of this */ -#define STRUCTURE_SIZE_BOUNDARY 16 - -/* Define this if move instructions will actually fail to work - when given unaligned data. */ -#define STRICT_ALIGNMENT 1 - -/* An integer expression for the size in bits of the largest integer machine mode that - should actually be used. All integer machine modes of this size or smaller can be - used for structures and unions with the appropriate sizes. */ -#define MAX_FIXED_MODE_SIZE 32 - -/* LAYOUT OF SOURCE LANGUAGE DATA TYPES */ - -#define SHORT_TYPE_SIZE 16 -#define INT_TYPE_SIZE 16 -#define LONG_TYPE_SIZE 32 -#define LONG_LONG_TYPE_SIZE 32 -#define FLOAT_TYPE_SIZE 32 -#define DOUBLE_TYPE_SIZE 32 -#define LONG_DOUBLE_TYPE_SIZE 32 - -/* An expression whose value is 1 or 0, according to whether the type char should be - signed or unsigned by default. */ - -#define DEFAULT_SIGNED_CHAR 1 - -/* A C expression to determine whether to give an enum type only as many bytes - as it takes to represent the range of possible values of that type. A nonzero - value means to do that; a zero value means all enum types should be allocated - like int. */ - -#define DEFAULT_SHORT_ENUMS 0 - -/* A C expression for a string describing the name of the data type to use for - size values. */ - -#define SIZE_TYPE "unsigned int" - -/* A C expression for a string describing the name of the data type to use for the - result of subtracting two pointers */ - -#define PTRDIFF_TYPE "int" - - -/* REGISTER USAGE. */ - -#define ALL_16_BIT_REGISTERS 1 - -/* Number of actual hardware registers. - The hardware registers are assigned numbers for the compiler - from 0 to FIRST_PSEUDO_REGISTER-1 */ - -#define FIRST_PSEUDO_REGISTER (REG_YBASE31 + 1) - -/* 1 for registers that have pervasive standard uses - and are not available for the register allocator. - - The registers are laid out as follows: - - {a0,a0l,a1,a1l,x,y,yl,p,pl} - Data Arithmetic Unit - {r0,r1,r2,r3,j,k,ybase} - Y Space Address Arithmetic Unit - {pt} - X Space Address Arithmetic Unit - {ar0,ar1,ar2,ar3} - Bit Manipulation UNit - {pr} - Return Address Register - - We reserve r2 for the Stack Pointer. - We specify r3 for the Frame Pointer but allow the compiler - to omit it when possible since we have so few pointer registers. */ - -#define REG_A0 0 -#define REG_A0L 1 -#define REG_A1 2 -#define REG_A1L 3 -#define REG_X 4 -#define REG_Y 5 -#define REG_YL 6 -#define REG_PROD 7 -#define REG_PRODL 8 -#define REG_R0 9 -#define REG_R1 10 -#define REG_R2 11 -#define REG_R3 12 -#define REG_J 13 -#define REG_K 14 -#define REG_YBASE 15 -#define REG_PT 16 -#define REG_AR0 17 -#define REG_AR1 18 -#define REG_AR2 19 -#define REG_AR3 20 -#define REG_C0 21 -#define REG_C1 22 -#define REG_C2 23 -#define REG_PR 24 -#define REG_RB 25 -#define REG_YBASE0 26 -#define REG_YBASE1 27 -#define REG_YBASE2 28 -#define REG_YBASE3 29 -#define REG_YBASE4 30 -#define REG_YBASE5 31 -#define REG_YBASE6 32 -#define REG_YBASE7 33 -#define REG_YBASE8 34 -#define REG_YBASE9 35 -#define REG_YBASE10 36 -#define REG_YBASE11 37 -#define REG_YBASE12 38 -#define REG_YBASE13 39 -#define REG_YBASE14 40 -#define REG_YBASE15 41 -#define REG_YBASE16 42 -#define REG_YBASE17 43 -#define REG_YBASE18 44 -#define REG_YBASE19 45 -#define REG_YBASE20 46 -#define REG_YBASE21 47 -#define REG_YBASE22 48 -#define REG_YBASE23 49 -#define REG_YBASE24 50 -#define REG_YBASE25 51 -#define REG_YBASE26 52 -#define REG_YBASE27 53 -#define REG_YBASE28 54 -#define REG_YBASE29 55 -#define REG_YBASE30 56 -#define REG_YBASE31 57 - -/* Do we have an accumulator register? */ -#define IS_ACCUM_REG(REGNO) IN_RANGE ((REGNO), REG_A0, REG_A1L) -#define IS_ACCUM_LOW_REG(REGNO) ((REGNO) == REG_A0L || (REGNO) == REG_A1L) - -/* Do we have a virtual ybase register */ -#define IS_YBASE_REGISTER_WINDOW(REGNO) ((REGNO) >= REG_YBASE0 && (REGNO) <= REG_YBASE31) - -#define IS_YBASE_ELIGIBLE_REG(REGNO) (IS_ACCUM_REG (REGNO) || IS_ADDRESS_REGISTER(REGNO) \ - || REGNO == REG_X || REGNO == REG_Y || REGNO == REG_YL \ - || REGNO == REG_PROD || REGNO == REG_PRODL) - -#define IS_ADDRESS_REGISTER(REGNO) ((REGNO) >= REG_R0 && (REGNO) <= REG_R3) - -#define FIXED_REGISTERS \ -{0, 0, 0, 0, 0, 0, 0, 0, 0, \ - 0, 0, 0, 1, 0, 0, 1, \ - 1, \ - 0, 0, 0, 0, \ - 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} - -/* 1 for registers not available across function calls. - These must include the FIXED_REGISTERS and also any - registers that can be used without being saved. - The latter must include the registers where values are returned - and the register where structure-value addresses are passed. - On the 1610 'a0' holds return values from functions. 'r0' holds - structure-value addresses. - - In addition we don't save either j, k, ybase or any of the - bit manipulation registers. */ - - -#define CALL_USED_REGISTERS \ -{1, 1, 1, 1, 0, 1, 1, 1, 1, /* 0-8 */ \ - 1, 0, 0, 1, 1, 1, 1, /* 9-15 */ \ - 1, /* 16 */ \ - 0, 0, 1, 1, /* 17-20 */ \ - 1, 1, 1, /* 21-23 */ \ - 1, 1, /* 24-25 */ \ - 0, 0, 0, 0, 0, 0, 0, 0, /* 26-33 */ \ - 0, 0, 0, 0, 0, 0, 0, 0, /* 34-41 */ \ - 0, 0, 0, 0, 0, 0, 0, 0, /* 42-49 */ \ - 0, 0, 0, 0, 0, 0, 0, 0} /* 50-57 */ - -/* List the order in which to allocate registers. Each register must be - listed once, even those in FIXED_REGISTERS. - - We allocate in the following order: - */ - -#if 0 -#define REG_ALLOC_ORDER \ -{ REG_R0, REG_R1, REG_R2, REG_PROD, REG_Y, REG_X, \ - REG_PRODL, REG_YL, REG_AR0, REG_AR1, \ - REG_RB, REG_A0, REG_A1, REG_A0L, \ - REG_A1L, REG_AR2, REG_AR3, \ - REG_YBASE, REG_J, REG_K, REG_PR, REG_PT, REG_C0, \ - REG_C1, REG_C2, REG_R3, \ - REG_YBASE0, REG_YBASE1, REG_YBASE2, REG_YBASE3, \ - REG_YBASE4, REG_YBASE5, REG_YBASE6, REG_YBASE7, \ - REG_YBASE8, REG_YBASE9, REG_YBASE10, REG_YBASE11, \ - REG_YBASE12, REG_YBASE13, REG_YBASE14, REG_YBASE15, \ - REG_YBASE16, REG_YBASE17, REG_YBASE18, REG_YBASE19, \ - REG_YBASE20, REG_YBASE21, REG_YBASE22, REG_YBASE23, \ - REG_YBASE24, REG_YBASE25, REG_YBASE26, REG_YBASE27, \ - REG_YBASE28, REG_YBASE29, REG_YBASE30, REG_YBASE31 } -#else -#define REG_ALLOC_ORDER \ -{ \ - REG_A0, REG_A0L, REG_A1, REG_A1L, REG_Y, REG_YL, \ - REG_PROD, \ - REG_PRODL, REG_R0, REG_J, REG_K, REG_AR2, REG_AR3, \ - REG_X, REG_R1, REG_R2, REG_RB, REG_AR0, REG_AR1, \ - REG_YBASE0, REG_YBASE1, REG_YBASE2, REG_YBASE3, \ - REG_YBASE4, REG_YBASE5, REG_YBASE6, REG_YBASE7, \ - REG_YBASE8, REG_YBASE9, REG_YBASE10, REG_YBASE11, \ - REG_YBASE12, REG_YBASE13, REG_YBASE14, REG_YBASE15, \ - REG_YBASE16, REG_YBASE17, REG_YBASE18, REG_YBASE19, \ - REG_YBASE20, REG_YBASE21, REG_YBASE22, REG_YBASE23, \ - REG_YBASE24, REG_YBASE25, REG_YBASE26, REG_YBASE27, \ - REG_YBASE28, REG_YBASE29, REG_YBASE30, REG_YBASE31, \ - REG_R3, REG_YBASE, REG_PT, REG_C0, REG_C1, REG_C2, \ - REG_PR } -#endif -/* Zero or more C statements that may conditionally modify two - variables `fixed_regs' and `call_used_regs' (both of type `char - []') after they have been initialized from the two preceding - macros. - - This is necessary in case the fixed or call-clobbered registers - depend on target flags. - - You need not define this macro if it has no work to do. - - If the usage of an entire class of registers depends on the target - flags, you may indicate this to GCC by using this macro to modify - `fixed_regs' and `call_used_regs' to 1 for each of the registers in - the classes which should not be used by GCC. Also define the macro - `REG_CLASS_FROM_LETTER' to return `NO_REGS' if it is called with a - letter for a class that shouldn't be used. - - (However, if this class is not included in `GENERAL_REGS' and all - of the insn patterns whose constraints permit this class are - controlled by target switches, then GCC will automatically avoid - using these registers when the target switches are opposed to - them.) If the user tells us there is no BMU, we can't use - ar0-ar3 for register allocation */ - -#define CONDITIONAL_REGISTER_USAGE \ -do \ - { \ - if (!TARGET_BMU) \ - { \ - int regno; \ - \ - for (regno = REG_AR0; regno <= REG_AR3; regno++) \ - fixed_regs[regno] = call_used_regs[regno] = 1; \ - } \ - if (TARGET_RESERVE_YBASE) \ - { \ - int regno; \ - \ - for (regno = REG_YBASE0; regno <= REG_YBASE31; regno++) \ - fixed_regs[regno] = call_used_regs[regno] = 1; \ - } \ - } \ -while (0) - -/* Determine which register classes are very likely used by spill registers. - local-alloc.c won't allocate pseudos that have these classes as their - preferred class unless they are "preferred or nothing". */ - -#define CLASS_LIKELY_SPILLED_P(CLASS) \ - ((CLASS) != ALL_REGS && (CLASS) != YBASE_VIRT_REGS) - -/* Return number of consecutive hard regs needed starting at reg REGNO - to hold something of mode MODE. - This is ordinarily the length in words of a value of mode MODE - but can be less for certain modes in special long registers. */ - -#define HARD_REGNO_NREGS(REGNO, MODE) \ - (GET_MODE_SIZE(MODE)) - -/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. */ - -#define HARD_REGNO_MODE_OK(REGNO, MODE) hard_regno_mode_ok(REGNO, MODE) - -/* Value is 1 if it is a good idea to tie two pseudo registers - when one has mode MODE1 and one has mode MODE2. - If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2, - for any hard reg, then this must be 0 for correct output. */ -#define MODES_TIEABLE_P(MODE1, MODE2) \ - (((MODE1) == (MODE2)) || \ - (GET_MODE_CLASS((MODE1)) == MODE_FLOAT) \ - == (GET_MODE_CLASS((MODE2)) == MODE_FLOAT)) - -/* Specify the registers used for certain standard purposes. - The values of these macros are register numbers. */ - -/* DSP1600 pc isn't overloaded on a register. */ -/* #define PC_REGNUM */ - -/* Register to use for pushing function arguments. - This is r3 in our case */ -#define STACK_POINTER_REGNUM REG_R3 - -/* Base register for access to local variables of the function. - This is r2 in our case */ -#define FRAME_POINTER_REGNUM REG_R2 - -/* We can debug without the frame pointer */ -#define CAN_DEBUG_WITHOUT_FP 1 - -/* The 1610 saves the return address in this register */ -#define RETURN_ADDRESS_REGNUM REG_PR - -/* Base register for access to arguments of the function. */ -#define ARG_POINTER_REGNUM FRAME_POINTER_REGNUM - -/* Register in which static-chain is passed to a function. */ - -#define STATIC_CHAIN_REGNUM 4 - -/* Register in which address to store a structure value - is passed to a function. This is 'r0' in our case */ -#define STRUCT_VALUE_REGNUM REG_R0 - -/* Define the classes of registers for register constraints in the - machine description. Also define ranges of constants. - - One of the classes must always be named ALL_REGS and include all hard regs. - If there is more than one class, another class must be named NO_REGS - and contain no registers. - - The name GENERAL_REGS must be the name of a class (or an alias for - another name such as ALL_REGS). This is the class of registers - that is allowed by "g" or "r" in a register constraint. - Also, registers outside this class are allocated only when - instructions express preferences for them. - - The classes must be numbered in nondecreasing order; that is, - a larger-numbered class must never be contained completely - in a smaller-numbered class. - - For any two classes, it is very desirable that there be another - class that represents their union. */ - - -enum reg_class -{ - NO_REGS, - A0H_REG, - A0L_REG, - A0_REG, - A1H_REG, - ACCUM_HIGH_REGS, - A1L_REG, - ACCUM_LOW_REGS, - A1_REG, - ACCUM_REGS, - X_REG, - X_OR_ACCUM_LOW_REGS, - X_OR_ACCUM_REGS, - YH_REG, - YH_OR_ACCUM_HIGH_REGS, - X_OR_YH_REGS, - YL_REG, - YL_OR_ACCUM_LOW_REGS, - X_OR_YL_REGS, - X_OR_Y_REGS, - Y_REG, - ACCUM_OR_Y_REGS, - PH_REG, - X_OR_PH_REGS, - PL_REG, - PL_OR_ACCUM_LOW_REGS, - X_OR_PL_REGS, - YL_OR_PL_OR_ACCUM_LOW_REGS, - P_REG, - ACCUM_OR_P_REGS, - YL_OR_P_REGS, - ACCUM_LOW_OR_YL_OR_P_REGS, - Y_OR_P_REGS, - ACCUM_Y_OR_P_REGS, - NO_FRAME_Y_ADDR_REGS, - Y_ADDR_REGS, - ACCUM_LOW_OR_Y_ADDR_REGS, - ACCUM_OR_Y_ADDR_REGS, - X_OR_Y_ADDR_REGS, - Y_OR_Y_ADDR_REGS, - P_OR_Y_ADDR_REGS, - NON_HIGH_YBASE_ELIGIBLE_REGS, - YBASE_ELIGIBLE_REGS, - J_REG, - J_OR_DAU_16_BIT_REGS, - BMU_REGS, - NOHIGH_NON_ADDR_REGS, - NON_ADDR_REGS, - SLOW_MEM_LOAD_REGS, - NOHIGH_NON_YBASE_REGS, - NO_ACCUM_NON_YBASE_REGS, - NON_YBASE_REGS, - YBASE_VIRT_REGS, - ACCUM_LOW_OR_YBASE_REGS, - ACCUM_OR_YBASE_REGS, - X_OR_YBASE_REGS, - Y_OR_YBASE_REGS, - ACCUM_LOW_YL_PL_OR_YBASE_REGS, - P_OR_YBASE_REGS, - ACCUM_Y_P_OR_YBASE_REGS, - Y_ADDR_OR_YBASE_REGS, - YBASE_OR_NOHIGH_YBASE_ELIGIBLE_REGS, - YBASE_OR_YBASE_ELIGIBLE_REGS, - NO_HIGH_ALL_REGS, - ALL_REGS, - LIM_REG_CLASSES -}; - -/* GENERAL_REGS must be the name of a register class */ -#define GENERAL_REGS ALL_REGS - -#define N_REG_CLASSES (int) LIM_REG_CLASSES - -/* Give names of register classes as strings for dump file. */ - -#define REG_CLASS_NAMES \ -{ \ - "NO_REGS", \ - "A0H_REG", \ - "A0L_REG", \ - "A0_REG", \ - "A1H_REG", \ - "ACCUM_HIGH_REGS", \ - "A1L_REG", \ - "ACCUM_LOW_REGS", \ - "A1_REG", \ - "ACCUM_REGS", \ - "X_REG", \ - "X_OR_ACCUM_LOW_REGS", \ - "X_OR_ACCUM_REGS", \ - "YH_REG", \ - "YH_OR_ACCUM_HIGH_REGS", \ - "X_OR_YH_REGS", \ - "YL_REG", \ - "YL_OR_ACCUM_LOW_REGS", \ - "X_OR_YL_REGS", \ - "X_OR_Y_REGS", \ - "Y_REG", \ - "ACCUM_OR_Y_REGS", \ - "PH_REG", \ - "X_OR_PH_REGS", \ - "PL_REG", \ - "PL_OR_ACCUM_LOW_REGS", \ - "X_OR_PL_REGS", \ - "PL_OR_YL_OR_ACCUM_LOW_REGS", \ - "P_REG", \ - "ACCUM_OR_P_REGS", \ - "YL_OR_P_REGS", \ - "ACCUM_LOW_OR_YL_OR_P_REGS", \ - "Y_OR_P_REGS", \ - "ACCUM_Y_OR_P_REGS", \ - "NO_FRAME_Y_ADDR_REGS", \ - "Y_ADDR_REGS", \ - "ACCUM_LOW_OR_Y_ADDR_REGS", \ - "ACCUM_OR_Y_ADDR_REGS", \ - "X_OR_Y_ADDR_REGS", \ - "Y_OR_Y_ADDR_REGS", \ - "P_OR_Y_ADDR_REGS", \ - "NON_HIGH_YBASE_ELIGIBLE_REGS", \ - "YBASE_ELIGIBLE_REGS", \ - "J_REG", \ - "J_OR_DAU_16_BIT_REGS", \ - "BMU_REGS", \ - "NOHIGH_NON_ADDR_REGS", \ - "NON_ADDR_REGS", \ - "SLOW_MEM_LOAD_REGS", \ - "NOHIGH_NON_YBASE_REGS", \ - "NO_ACCUM_NON_YBASE_REGS", \ - "NON_YBASE_REGS", \ - "YBASE_VIRT_REGS", \ - "ACCUM_LOW_OR_YBASE_REGS", \ - "ACCUM_OR_YBASE_REGS", \ - "X_OR_YBASE_REGS", \ - "Y_OR_YBASE_REGS", \ - "ACCUM_LOW_YL_PL_OR_YBASE_REGS", \ - "P_OR_YBASE_REGS", \ - "ACCUM_Y_P_OR_YBASE_REGS", \ - "Y_ADDR_OR_YBASE_REGS", \ - "YBASE_OR_NOHIGH_YBASE_ELIGIBLE_REGS", \ - "YBASE_OR_YBASE_ELIGIBLE_REGS", \ - "NO_HIGH_ALL_REGS", \ - "ALL_REGS" \ -} - -/* Define which registers fit in which classes. - This is an initializer for a vector of HARD_REG_SET - of length N_REG_CLASSES. */ - -#define REG_CLASS_CONTENTS \ -{ \ - {0x00000000, 0x00000000}, /* no reg */ \ - {0x00000001, 0x00000000}, /* a0h */ \ - {0x00000002, 0x00000000}, /* a0l */ \ - {0x00000003, 0x00000000}, /* a0h:a0l */ \ - {0x00000004, 0x00000000}, /* a1h */ \ - {0x00000005, 0x00000000}, /* accum high */ \ - {0x00000008, 0x00000000}, /* a1l */ \ - {0x0000000A, 0x00000000}, /* accum low */ \ - {0x0000000c, 0x00000000}, /* a1h:a1l */ \ - {0x0000000f, 0x00000000}, /* accum regs */ \ - {0x00000010, 0x00000000}, /* x reg */ \ - {0x0000001A, 0x00000000}, /* x & accum_low_regs */ \ - {0x0000001f, 0x00000000}, /* x & accum regs */ \ - {0x00000020, 0x00000000}, /* y high */ \ - {0x00000025, 0x00000000}, /* yh, accum high */ \ - {0x00000030, 0x00000000}, /* x & yh */ \ - {0x00000040, 0x00000000}, /* y low */ \ - {0x0000004A, 0x00000000}, /* y low, accum_low */ \ - {0x00000050, 0x00000000}, /* x & yl */ \ - {0x00000060, 0x00000000}, /* yl:yh */ \ - {0x00000070, 0x00000000}, /* x, yh,a nd yl */ \ - {0x0000006F, 0x00000000}, /* accum, y */ \ - {0x00000080, 0x00000000}, /* p high */ \ - {0x00000090, 0x00000000}, /* x & ph */ \ - {0x00000100, 0x00000000}, /* p low */ \ - {0x0000010A, 0x00000000}, /* p_low and accum_low */ \ - {0x00000110, 0x00000000}, /* x & pl */ \ - {0x0000014A, 0x00000000}, /* pl,yl,a1l,a0l */ \ - {0x00000180, 0x00000000}, /* pl:ph */ \ - {0x0000018F, 0x00000000}, /* accum, p */ \ - {0x000001C0, 0x00000000}, /* pl:ph and yl */ \ - {0x000001CA, 0x00000000}, /* pl:ph, yl, a0l, a1l */ \ - {0x000001E0, 0x00000000}, /* y or p */ \ - {0x000001EF, 0x00000000}, /* accum, y or p */ \ - {0x00000E00, 0x00000000}, /* r0-r2 */ \ - {0x00001E00, 0x00000000}, /* r0-r3 */ \ - {0x00001E0A, 0x00000000}, /* r0-r3, accum_low */ \ - {0x00001E0F, 0x00000000}, /* accum,r0-r3 */ \ - {0x00001E10, 0x00000000}, /* x,r0-r3 */ \ - {0x00001E60, 0x00000000}, /* y,r0-r3 */ \ - {0x00001F80, 0x00000000}, /* p,r0-r3 */ \ - {0x00001FDA, 0x00000000}, /* ph:pl, r0-r3, x,a0l,a1l */ \ - {0x00001fff, 0x00000000}, /* accum,x,y,p,r0-r3 */ \ - {0x00002000, 0x00000000}, /* j */ \ - {0x00002025, 0x00000000}, /* j, yh, a1h, a0h */ \ - {0x001E0000, 0x00000000}, /* ar0-ar3 */ \ - {0x03FFE1DA, 0x00000000}, /* non_addr except yh,a0h,a1h */ \ - {0x03FFE1FF, 0x00000000}, /* non_addr regs */ \ - {0x03FFFF8F, 0x00000000}, /* non ybase except yh, yl, and x */ \ - {0x03FFFFDA, 0x00000000}, /* non ybase regs except yh,a0h,a1h */ \ - {0x03FFFFF0, 0x00000000}, /* non ybase except a0,a0l,a1,a1l */ \ - {0x03FFFFFF, 0x00000000}, /* non ybase regs */ \ - {0xFC000000, 0x03FFFFFF}, /* virt ybase regs */ \ - {0xFC00000A, 0x03FFFFFF}, /* accum_low, virt ybase regs */ \ - {0xFC00000F, 0x03FFFFFF}, /* accum, virt ybase regs */ \ - {0xFC000010, 0x03FFFFFF}, /* x,virt ybase regs */ \ - {0xFC000060, 0x03FFFFFF}, /* y,virt ybase regs */ \ - {0xFC00014A, 0x03FFFFFF}, /* accum_low, yl, pl, ybase */ \ - {0xFC000180, 0x03FFFFFF}, /* p,virt ybase regs */ \ - {0xFC0001EF, 0x03FFFFFF}, /* accum,y,p,ybase regs */ \ - {0xFC001E00, 0x03FFFFFF}, /* r0-r3, ybase regs */ \ - {0xFC001FDA, 0x03FFFFFF}, /* r0-r3, pl:ph,yl,x,a1l,a0l */ \ - {0xFC001FFF, 0x03FFFFFF}, /* virt ybase, ybase eligible regs */ \ - {0xFCFFFFDA, 0x03FFFFFF}, /* all regs except yh,a0h,a1h */ \ - {0xFFFFFFFF, 0x03FFFFFF} /* all regs */ \ -} - - -/* The same information, inverted: - Return the class number of the smallest class containing - reg number REGNO. This could be a conditional expression - or could index an array. */ - -#define REGNO_REG_CLASS(REGNO) regno_reg_class(REGNO) - -/* The class value for index registers, and the one for base regs. */ - -#define INDEX_REG_CLASS NO_REGS -#define BASE_REG_CLASS Y_ADDR_REGS - -/* Get reg_class from a letter such as appears in the machine description. */ - -#define REG_CLASS_FROM_LETTER(C) \ - dsp16xx_reg_class_from_letter(C) - -#define SECONDARY_RELOAD_CLASS(CLASS, MODE, X) \ - secondary_reload_class(CLASS, MODE, X) - -/* When defined, the compiler allows registers explicitly used in the - rtl to be used as spill registers but prevents the compiler from - extending the lifetime of these registers. */ - -#define SMALL_REGISTER_CLASSES 1 - -/* Macros to check register numbers against specific register classes. */ - -/* These assume that REGNO is a hard or pseudo reg number. - They give nonzero only if REGNO is a hard reg of the suitable class - or a pseudo reg currently allocated to a suitable hard reg. - Since they use reg_renumber, they are safe only once reg_renumber - has been allocated, which happens in local-alloc.c. */ - -/* A C expression which is nonzero if register REGNO is suitable for use - as a base register in operand addresses. It may be either a suitable - hard register or a pseudo register that has been allocated such a - hard register. - - On the 1610 the Y address pointers can be used as a base registers */ -#define REGNO_OK_FOR_BASE_P(REGNO) \ -(((REGNO) >= REG_R0 && (REGNO) < REG_R3 + 1) || ((unsigned) reg_renumber[REGNO] >= REG_R0 \ - && (unsigned) reg_renumber[REGNO] < REG_R3 + 1)) - -#define REGNO_OK_FOR_YBASE_P(REGNO) \ - (((REGNO) == REG_YBASE) || ((unsigned) reg_renumber[REGNO] == REG_YBASE)) - -#define REGNO_OK_FOR_INDEX_P(REGNO) 0 - -#ifdef ALL_16_BIT_REGISTERS -#define IS_32_BIT_REG(REGNO) 0 -#else -#define IS_32_BIT_REG(REGNO) \ - ((REGNO) == REG_A0 || (REGNO) == REG_A1 || (REGNO) == REG_Y || (REGNO) == REG_PROD) -#endif - -/* Given an rtx X being reloaded into a reg required to be - in class CLASS, return the class of reg to actually use. - In general this is just CLASS; but on some machines - in some cases it is preferable to use a more restrictive class. - Also, we must ensure that a PLUS is reloaded either - into an accumulator or an address register. */ - -#define PREFERRED_RELOAD_CLASS(X,CLASS) preferred_reload_class (X, CLASS) - -/* A C expression that places additional restrictions on the register - class to use when it is necessary to be able to hold a value of - mode MODE in a reload register for which class CLASS would - ordinarily be used. - - Unlike `PREFERRED_RELOAD_CLASS', this macro should be used when - there are certain modes that simply can't go in certain reload - classes. - - The value is a register class; perhaps CLASS, or perhaps another, - smaller class. - - Don't define this macro unless the target machine has limitations - which require the macro to do something nontrivial. */ - -#if 0 -#define LIMIT_RELOAD_CLASS(MODE, CLASS) dsp16xx_limit_reload_class (MODE, CLASS) -#endif - -/* A C expression for the maximum number of consecutive registers of class CLASS - needed to hold a value of mode MODE */ -#define CLASS_MAX_NREGS(CLASS, MODE) \ - class_max_nregs(CLASS, MODE) - -/* The letters 'I' through 'P' in a register constraint string - can be used to stand for particular ranges of immediate operands. - This macro defines what the ranges are. - C is the letter, and VALUE is a constant value. - Return 1 if VALUE is in the range specified by C. - - For the 16xx, the following constraints are used: - 'I' requires a non-negative 16-bit value. - 'J' requires a non-negative 9-bit value - 'K' requires a constant 0 operand. - 'L' constant for use in add or sub from low 16-bits - 'M' 32-bit value -- low 16-bits zero - 'N' constant for use incrementing or decrementing an address register - 'O' constant for use with and'ing only high 16-bit - 'P' constant for use with and'ing only low 16-bit - */ - -#define SMALL_INT(X) (SMALL_INTVAL (INTVAL (X))) -#define SMALL_INTVAL(I) ((unsigned) (I) < 0x10000) -#define SHORT_IMMEDIATE(X) (SHORT_INTVAL (INTVAL(X))) -#define SHORT_INTVAL(I) ((unsigned) (I) < 0x100) -#define ADD_LOW_16(I) ((I) >= 0 && (I) <= 32767) -#define ADD_HIGH_16(I) (((I) & 0x0000ffff) == 0) -#define AND_LOW_16(I) ((I) >= 0 && (I) <= 32767) -#define AND_HIGH_16(I) (((I) & 0x0000ffff) == 0) - -#define CONST_OK_FOR_LETTER_P(VALUE, C) \ - ((C) == 'I' ? (SMALL_INTVAL(VALUE)) \ - : (C) == 'J' ? (SHORT_INTVAL(VALUE)) \ - : (C) == 'K' ? ((VALUE) == 0) \ - : (C) == 'L' ? ((VALUE) >= 0 && (VALUE) <= 32767) \ - : (C) == 'M' ? (((VALUE) & 0x0000ffff) == 0) \ - : (C) == 'N' ? ((VALUE) == -1 || (VALUE) == 1 \ - || (VALUE) == -2 || (VALUE) == 2) \ - : (C) == 'O' ? (((VALUE) & 0xffff0000) == 0xffff0000) \ - : (C) == 'P' ? (((VALUE) & 0x0000ffff) == 0xffff) \ - : 0) - -#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) 1 - -/* Optional extra constraints for this machine */ -#define EXTRA_CONSTRAINT(OP,C) \ - ((C) == 'R' ? symbolic_address_p (OP) \ - : 0) - -/* DESCRIBING STACK LAYOUT AND CALLING CONVENTIONS */ - -/* Define this if pushing a word on the stack - makes the stack pointer a smaller address. */ -/* #define STACK_GROWS_DOWNWARD */ - -/* Define this if the nominal address of the stack frame - is at the high-address end of the local variables; - that is, each additional local variable allocated - goes at a more negative offset in the frame. */ -/* #define FRAME_GROWS_DOWNWARD */ - -#define ARGS_GROW_DOWNWARD - -/* We use post decrement on the 1600 because there isn't - a pre-decrement addressing mode. This means that we - assume the stack pointer always points at the next - FREE location on the stack. */ -#define STACK_PUSH_CODE POST_INC - -/* Offset within stack frame to start allocating local variables at. - If FRAME_GROWS_DOWNWARD, this is the offset to the END of the - first local allocated. Otherwise, it is the offset to the BEGINNING - of the first local allocated. */ -#define STARTING_FRAME_OFFSET 0 - -/* Offset from the stack pointer register to the first - location at which outgoing arguments are placed. */ -#define STACK_POINTER_OFFSET (0) - -struct dsp16xx_frame_info -{ - unsigned long total_size; /* # bytes that the entire frame takes up */ - unsigned long var_size; /* # bytes that variables take up */ - unsigned long args_size; /* # bytes that outgoing arguments take up */ - unsigned long extra_size; /* # bytes of extra gunk */ - unsigned int reg_size; /* # bytes needed to store regs */ - long fp_save_offset; /* offset from vfp to store registers */ - unsigned long sp_save_offset; /* offset from new sp to store registers */ - int pr_save_offset; /* offset to saved PR */ - int initialized; /* != 0 if frame size already calculated */ - int num_regs; /* number of registers saved */ - int function_makes_calls; /* Does the function make calls */ -}; - -extern struct dsp16xx_frame_info current_frame_info; - -#define RETURN_ADDR_OFF current_frame_info.pr_save_offset - -/* If we generate an insn to push BYTES bytes, - this says how many the stack pointer really advances by. */ -/* #define PUSH_ROUNDING(BYTES) ((BYTES)) */ - -/* If defined, the maximum amount of space required for outgoing - arguments will be computed and placed into the variable - 'current_function_outgoing_args_size'. No space will be pushed - onto the stack for each call; instead, the function prologue should - increase the stack frame size by this amount. - - It is not proper to define both 'PUSH_ROUNDING' and - 'ACCUMULATE_OUTGOING_ARGS'. */ -#define ACCUMULATE_OUTGOING_ARGS 1 - -/* Offset of first parameter from the argument pointer - register value. */ - -#define FIRST_PARM_OFFSET(FNDECL) (0) - -/* Value is 1 if returning from a function call automatically - pops the arguments described by the number-of-args field in the call. - FUNDECL is the declaration node of the function (as a tree), - FUNTYPE is the data type of the function (as a tree), - or for a library call it is an identifier node for the subroutine name. */ - -#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) 0 - -/* Define how to find the value returned by a function. - VALTYPE is the data type of the value (as a tree). - If the precise function being called is known, FUNC is its FUNCTION_DECL; - otherwise, FUNC is 0. On the 1610 all function return their values - in a0 (i.e. the upper 16 bits). If the return value is 32-bits the - entire register is significant. */ - -#define VALUE_REGNO(MODE) (REG_Y) - -#define FUNCTION_VALUE(VALTYPE, FUNC) \ - gen_rtx_REG (TYPE_MODE (VALTYPE), VALUE_REGNO(TYPE_MODE(VALTYPE))) - -/* Define how to find the value returned by a library function - assuming the value has mode MODE. */ -#define LIBCALL_VALUE(MODE) gen_rtx_REG (MODE, VALUE_REGNO(MODE)) - -/* 1 if N is a possible register number for a function value. */ -#define FUNCTION_VALUE_REGNO_P(N) ((N) == REG_Y) - - -/* Define where to put the arguments to a function. - Value is zero to push the argument on the stack, - or a hard register in which to store the argument. - - MODE is the argument's machine mode. - TYPE is the data type of the argument (as a tree). - This is null for libcalls where that information may - not be available. - CUM is a variable of type CUMULATIVE_ARGS which gives info about - the preceding args and about the function being called. - NAMED is nonzero if this argument is a named parameter - (otherwise it is an extra parameter matching an ellipsis). */ - -/* On the 1610 all args are pushed, except if -mregparm is specified - then the first two words of arguments are passed in a0, a1. */ -#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ - dsp16xx_function_arg (CUM, MODE, TYPE, NAMED) - -/* Define the first register to be used for argument passing */ -#define FIRST_REG_FOR_FUNCTION_ARG REG_Y - -/* Define the profitability of saving registers around calls. - NOTE: For now we turn this off because of a bug in the - caller-saves code and also because i'm not sure it is helpful - on the 1610. */ - -#define CALLER_SAVE_PROFITABLE(REFS,CALLS) 0 - -/* This indicates that an argument is to be passed with an invisible reference - (i.e., a pointer to the object is passed). - - On the dsp16xx, we do this if it must be passed on the stack. */ - -#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \ - (MUST_PASS_IN_STACK (MODE, TYPE)) - -/* For an arg passed partly in registers and partly in memory, - this is the number of registers used. - For args passed entirely in registers or entirely in memory, zero. */ - -#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) (0) - -/* Define a data type for recording info about an argument list - during the scan of that argument list. This data type should - hold all necessary information about the function itself - and about the args processed so far, enough to enable macros - such as FUNCTION_ARG to determine where the next arg should go. */ -#define CUMULATIVE_ARGS int - -/* Initialize a variable CUM of type CUMULATIVE_ARGS - for a call to a function whose data type is FNTYPE. - For a library call, FNTYPE is 0. */ -#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) ((CUM) = 0) - -/* Update the data in CUM to advance over an argument - of mode MODE and data type TYPE. - (TYPE is null for libcalls where that information may not be available.) */ - -#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ - dsp16xx_function_arg_advance (&CUM, MODE,TYPE, NAMED) - -/* 1 if N is a possible register number for function argument passing. */ -#define FUNCTION_ARG_REGNO_P(N) \ - ((N) == REG_Y || (N) == REG_YL || (N) == REG_PROD || (N) == REG_PRODL) - -/* Output assembler code to FILE to increment profiler label # LABELNO - for profiling a function entry. */ - -#define FUNCTION_PROFILER(FILE, LABELNO) \ - internal_error ("profiling not implemented yet") - -/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function, - the stack pointer does not matter. The value is tested only in - functions that have frame pointers. - No definition is equivalent to always zero. */ - -#define EXIT_IGNORE_STACK (0) - -#define TRAMPOLINE_TEMPLATE(FILE) \ - internal_error ("trampolines not yet implemented"); - -/* Length in units of the trampoline for entering a nested function. - This is a dummy value */ - -#define TRAMPOLINE_SIZE 20 - -/* Emit RTL insns to initialize the variable parts of a trampoline. - FNADDR is an RTX for the address of the function's pure code. - CXT is an RTX for the static chain value for the function. */ - -#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \ - internal_error ("trampolines not yet implemented"); - -/* A C expression which is nonzero if a function must have and use a - frame pointer. If its value is nonzero the functions will have a - frame pointer. */ -#define FRAME_POINTER_REQUIRED (current_function_calls_alloca) - -/* A C statement to store in the variable 'DEPTH' the difference - between the frame pointer and the stack pointer values immediately - after the function prologue. */ -#define INITIAL_FRAME_POINTER_OFFSET(DEPTH) \ -{ (DEPTH) = initial_frame_pointer_offset(); \ -} - -/* IMPLICIT CALLS TO LIBRARY ROUTINES */ - -#define ADDHF3_LIBCALL "__Emulate_addhf3" -#define SUBHF3_LIBCALL "__Emulate_subhf3" -#define MULHF3_LIBCALL "__Emulate_mulhf3" -#define DIVHF3_LIBCALL "__Emulate_divhf3" -#define CMPHF3_LIBCALL "__Emulate_cmphf3" -#define FIXHFHI2_LIBCALL "__Emulate_fixhfhi2" -#define FLOATHIHF2_LIBCALL "__Emulate_floathihf2" -#define NEGHF2_LIBCALL "__Emulate_neghf2" - -#define UMULHI3_LIBCALL "__Emulate_umulhi3" -#define MULHI3_LIBCALL "__Emulate_mulhi3" -#define UDIVQI3_LIBCALL "__Emulate_udivqi3" -#define UDIVHI3_LIBCALL "__Emulate_udivhi3" -#define DIVQI3_LIBCALL "__Emulate_divqi3" -#define DIVHI3_LIBCALL "__Emulate_divhi3" -#define MODQI3_LIBCALL "__Emulate_modqi3" -#define MODHI3_LIBCALL "__Emulate_modhi3" -#define UMODQI3_LIBCALL "__Emulate_umodqi3" -#define UMODHI3_LIBCALL "__Emulate_umodhi3" -#define ASHRHI3_LIBCALL "__Emulate_ashrhi3" -#define LSHRHI3_LIBCALL "__Emulate_lshrhi3" -#define ASHLHI3_LIBCALL "__Emulate_ashlhi3" -#define LSHLHI3_LIBCALL "__Emulate_lshlhi3" /* NOT USED */ - -/* Define this macro if calls to the ANSI C library functions memcpy and - memset should be generated instead of the BSD function bcopy & bzero. */ -#define TARGET_MEM_FUNCTIONS - - -/* ADDRESSING MODES */ - -/* The 1610 has post-increment and decrement, but no pre-modify */ -#define HAVE_POST_INCREMENT 1 -#define HAVE_POST_DECREMENT 1 - -/* Recognize any constant value that is a valid address. */ -#define CONSTANT_ADDRESS_P(X) CONSTANT_P (X) - -/* Maximum number of registers that can appear in a valid memory address. */ -#define MAX_REGS_PER_ADDRESS 1 - -/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx - and check its validity for a certain class. - We have two alternate definitions for each of them. - The usual definition accepts all pseudo regs; the other rejects - them unless they have been allocated suitable hard regs. - The symbol REG_OK_STRICT causes the latter definition to be used. - - Most source files want to accept pseudo regs in the hope that - they will get allocated to the class that the insn wants them to be in. - Source files for reload pass need to be strict. - After reload, it makes no difference, since pseudo regs have - been eliminated by then. */ - -#ifndef REG_OK_STRICT - -/* 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) 0 - -/* Nonzero if X is a hard reg that can be used as a base reg - or if it is a pseudo reg. */ -#define REG_OK_FOR_BASE_P(X) \ - ((REGNO (X) >= REG_R0 && REGNO (X) < REG_R3 + 1 ) \ - || (REGNO (X) >= FIRST_PSEUDO_REGISTER)) - -/* Nonzero if X is the 'ybase' register */ -#define REG_OK_FOR_YBASE_P(X) \ - (REGNO(X) == REG_YBASE || (REGNO (X) >= FIRST_PSEUDO_REGISTER)) -#else - -/* Nonzero if X is a hard reg that can be used as an index. */ -#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X)) - -/* Nonzero if X is a hard reg that can be used as a base reg. */ -#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X)) - -/* Nonzero if X is the 'ybase' register */ -#define REG_OK_FOR_YBASE_P(X) REGNO_OK_FOR_YBASE_P (REGNO(X)) - -#endif - -/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression - that is a valid memory address for an instruction. - The MODE argument is the machine mode for the MEM expression - that wants to use this address. - - On the 1610, the actual legitimate addresses must be N (N must fit in - 5 bits), *rn (register indirect), *rn++, or *rn-- */ - -#define INT_FITS_5_BITS(I) ((unsigned long) (I) < 0x20) -#define INT_FITS_16_BITS(I) ((unsigned long) (I) < 0x10000) -#define YBASE_CONST_OFFSET(I) ((I) >= -31 && (I) <= 0) -#define YBASE_OFFSET(X) (GET_CODE (X) == CONST_INT && YBASE_CONST_OFFSET (INTVAL(X))) - -#define FITS_16_BITS(X) (GET_CODE (X) == CONST_INT && INT_FITS_16_BITS(INTVAL(X))) -#define FITS_5_BITS(X) (GET_CODE (X) == CONST_INT && INT_FITS_5_BITS(INTVAL(X))) -#define ILLEGAL_HIMODE_ADDR(MODE, CONST) ((MODE) == HImode && CONST == -31) - -#define INDIRECTABLE_ADDRESS_P(X) \ - ((GET_CODE(X) == REG && REG_OK_FOR_BASE_P(X)) \ - || ((GET_CODE(X) == POST_DEC || GET_CODE(X) == POST_INC) \ - && REG_P(XEXP(X,0)) && REG_OK_FOR_BASE_P(XEXP(X,0))) \ - || (GET_CODE(X) == CONST_INT && (unsigned long) (X) < 0x20)) - - -#define INDEXABLE_ADDRESS_P(X,MODE) \ - ((GET_CODE(X) == PLUS && GET_CODE (XEXP (X,0)) == REG && \ - XEXP(X,0) == stack_pointer_rtx && YBASE_OFFSET(XEXP(X,1)) && \ - !ILLEGAL_HIMODE_ADDR(MODE, INTVAL(XEXP(X,1)))) || \ - (GET_CODE(X) == PLUS && GET_CODE (XEXP (X,1)) == REG && \ - XEXP(X,1) == stack_pointer_rtx && YBASE_OFFSET(XEXP(X,0)) && \ - !ILLEGAL_HIMODE_ADDR(MODE, INTVAL(XEXP(X,0))))) - -#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ -{ \ - if (INDIRECTABLE_ADDRESS_P(X)) \ - goto ADDR; \ -} - - -/* Try machine-dependent ways of modifying an illegitimate address - to be legitimate. If we find one, return the new, valid address. - This macro is used in only one place: `memory_address' in explow.c. - - OLDX is the address as it was before break_out_memory_refs was called. - In some cases it is useful to look at this to decide what needs to be done. - - MODE and WIN are passed so that this macro can use - GO_IF_LEGITIMATE_ADDRESS. - - It is always safe for this macro to do nothing. It exists to recognize - opportunities to optimize the output. - - For the 1610, we need not do anything. However, if we don't, - `memory_address' will try lots of things to get a valid address, most of - which will result in dead code and extra pseudos. So we make the address - valid here. - - This is easy: The only valid addresses are an offset from a register - and we know the address isn't valid. So just call either `force_operand' - or `force_reg' unless this is a (plus (reg ...) (const_int 0)). */ - -#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \ -{ if (GET_CODE (X) == PLUS && XEXP (X, 1) == const0_rtx) \ - X = XEXP (x, 0); \ - if (GET_CODE (X) == MULT || GET_CODE (X) == PLUS) \ - X = force_operand (X, 0); \ - else \ - X = force_reg (Pmode, X); \ - goto WIN; \ -} - -/* Go to LABEL if ADDR (a legitimate address expression) - has an effect that depends on the machine mode it is used for. - On the 1610, only postdecrement and postincrement address depend thus - (the amount of decrement or increment being the length of the operand). */ - -#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) \ - if (GET_CODE (ADDR) == POST_INC || GET_CODE (ADDR) == POST_DEC) goto LABEL - -/* Nonzero if the constant value X is a legitimate general operand. - It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. */ -#define LEGITIMATE_CONSTANT_P(X) (1) - - -/* CONDITION CODE INFORMATION */ - -/* Store in cc_status the expressions - that the condition codes will describe - after execution of an instruction whose pattern is EXP. - Do not alter them if the instruction would not alter the cc's. */ - -#define NOTICE_UPDATE_CC(EXP, INSN) \ - notice_update_cc( (EXP) ) - -/* DESCRIBING RELATIVE COSTS OF OPERATIONS */ - -/* A c expression for the cost of moving data from a register in - class FROM to one in class TO. The classes are expressed using - the enumeration values such as GENERAL_REGS. A value of 2 is - the default. */ -#define REGISTER_MOVE_COST(MODE,FROM,TO) dsp16xx_register_move_cost (FROM, TO) - -/* A C expression for the cost of moving data of mode MODE between - a register and memory. A value of 2 is the default. */ -#define MEMORY_MOVE_COST(MODE,CLASS,IN) \ - (GET_MODE_CLASS(MODE) == MODE_INT && MODE == QImode ? 12 \ - : 16) - -/* A C expression for the cost of a branch instruction. A value of - 1 is the default; */ -#define BRANCH_COST 1 - - -/* Define this because otherwise gcc will try to put the function address - in any old pseudo register. We can only use pt. */ -#define NO_FUNCTION_CSE - -/* Define this macro as a C expression which is nonzero if accessing less - than a word of memory (i.e a char or short) is no faster than accessing - a word of memory, i.e if such access require more than one instruction - or if there is no difference in cost between byte and (aligned) word - loads. */ -#define SLOW_BYTE_ACCESS 1 - -/* Define this macro if unaligned accesses have a cost many times greater than - aligned accesses, for example if they are emulated in a trap handler */ -/* define SLOW_UNALIGNED_ACCESS(MODE, ALIGN) */ - - -/* DIVIDING THE OUTPUT IN SECTIONS */ -/* Output before read-only data. */ - -#define DEFAULT_TEXT_SEG_NAME ".text" -#define TEXT_SECTION_ASM_OP rsect_text - -/* Output before constants and strings */ -#define DEFAULT_CONST_SEG_NAME ".const" -#define READONLY_DATA_SECTION_ASM_OP rsect_const - -/* Output before writable data. */ -#define DEFAULT_DATA_SEG_NAME ".data" -#define DATA_SECTION_ASM_OP rsect_data - -#define DEFAULT_BSS_SEG_NAME ".bss" -#define BSS_SECTION_ASM_OP rsect_bss - -/* We will default to using 1610 if the user doesn't - specify it. */ -#define DEFAULT_CHIP_NAME "1610" - -/* THE OVERALL FRAMEWORK OF AN ASSEMBLER FILE */ - -/* A C string constant describing how to begin a comment in the target - assembler language. */ -#define ASM_COMMENT_START "" -#define ASM_COMMENT_END "" - -/* Output to assembler file text saying following lines - may contain character constants, extra white space, comments, etc. */ -#define ASM_APP_ON "" - -/* Output to assembler file text saying following lines - no longer contain unusual constructs. */ -#define ASM_APP_OFF "" - -/* OUTPUT OF DATA */ - -/* This is how we output a 'c' character string. For the 16xx - assembler we have to do it one letter at a time */ - -#define ASCII_LENGTH 10 - -#define ASM_OUTPUT_ASCII(MYFILE, MYSTRING, MYLENGTH) \ - do { \ - FILE *_hide_asm_out_file = (MYFILE); \ - const unsigned char *_hide_p = (const unsigned char *) (MYSTRING); \ - int _hide_thissize = (MYLENGTH); \ - { \ - FILE *asm_out_file = _hide_asm_out_file; \ - const unsigned char *p = _hide_p; \ - int thissize = _hide_thissize; \ - int i; \ - \ - for (i = 0; i < thissize; i++) \ - { \ - register int c = p[i]; \ - \ - if (i % ASCII_LENGTH == 0) \ - fprintf (asm_out_file, "\tint "); \ - \ - if (c >= ' ' && c < 0177 && c != '\'') \ - { \ - putc ('\'', asm_out_file); \ - putc (c, asm_out_file); \ - putc ('\'', asm_out_file); \ - } \ - else \ - { \ - fprintf (asm_out_file, "%d", c); \ - /* After an octal-escape, if a digit follows, \ - terminate one string constant and start another. \ - The VAX assembler fails to stop reading the escape \ - after three digits, so this is the only way we \ - can get it to parse the data properly. \ - if (i < thissize - 1 && ISDIGIT (p[i + 1])) \ - fprintf (asm_out_file, "\'\n\tint \'"); \ - */ \ - } \ - /* if: \ - we are not at the last char (i != thissize -1) \ - and (we are not at a line break multiple \ - but i == 0) (it will be the very first time) \ - then put out a comma to extend. \ - */ \ - if ((i != thissize - 1) && ((i + 1) % ASCII_LENGTH)) \ - fprintf(asm_out_file, ","); \ - if (!((i + 1) % ASCII_LENGTH)) \ - fprintf (asm_out_file, "\n"); \ - } \ - fprintf (asm_out_file, "\n"); \ - } \ - } \ - while (0) - -#define ASM_PN_FORMAT "*L%s_%lu" - -/* OUTPUT OF UNINITIALIZED VARIABLES */ - -/* This says how to output an assembler line - to define a global common symbol. */ - -#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \ - asm_output_common (FILE, NAME, SIZE, ROUNDED); - -/* This says how to output an assembler line - to define a local common symbol. */ - -#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \ - asm_output_local (FILE, NAME, SIZE, ROUNDED); - -/* OUTPUT AND GENERATION OF LABELS */ - -/* Globalizing directive for a label. */ -#define GLOBAL_ASM_OP ".global " - -/* A C statement to output to the stdio stream any text necessary - for declaring the name of an external symbol named name which - is referenced in this compilation but not defined. */ - -#define ASM_OUTPUT_EXTERNAL(FILE, DECL, NAME) \ -{ \ - fprintf (FILE, ".extern "); \ - assemble_name (FILE, NAME); \ - fprintf (FILE, "\n"); \ -} -/* A C statement to output on stream an assembler pseudo-op to - declare a library function named external. */ - -#define ASM_OUTPUT_EXTERNAL_LIBCALL(FILE, FUN) \ -{ \ - fprintf (FILE, ".extern "); \ - assemble_name (FILE, XSTR (FUN, 0)); \ - fprintf (FILE, "\n"); \ -} - -/* The prefix to add to user-visible assembler symbols. */ - -#define USER_LABEL_PREFIX "_" - -/* This is how to store into the string LABEL - the symbol_ref name of an internal numbered label where - PREFIX is the class of label and NUM is the number within the class. - This is suitable for output with `assemble_name'. */ -#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \ - sprintf (LABEL, "*%s%lu", PREFIX, (unsigned long)(NUM)) - - -/* OUTPUT OF ASSEMBLER INSTRUCTIONS */ - -/* How to refer to registers in assembler output. - This sequence is indexed by compiler's hard-register-number (see above). */ - -#define REGISTER_NAMES \ -{"a0", "a0l", "a1", "a1l", "x", "y", "yl", "p", "pl", \ - "r0", "r1", "r2", "r3", "j", "k", "ybase", "pt", \ - "ar0", "ar1", "ar2", "ar3", \ - "c0", "c1", "c2", "pr", "rb", \ - "*(0)", "*(1)", "*(2)", "*(3)", "*(4)", "*(5)", \ - "*(6)", "*(7)", "*(8)", "*(9)", "*(10)", "*(11)", \ - "*(12)", "*(13)", "*(14)", "*(15)", "*(16)", "*(17)", \ - "*(18)", "*(19)", "*(20)", "*(21)", "*(22)", "*(23)", \ - "*(24)", "*(25)", "*(26)", "*(27)", "*(28)", "*(29)", \ - "*(30)", "*(31)" } - -#define HIMODE_REGISTER_NAMES \ -{"a0", "a0", "a1", "a1", "x", "y", "y", "p", "p", \ - "r0", "r1", "r2", "r3", "j", "k", "ybase", "pt", \ - "ar0", "ar1", "ar2", "ar3", \ - "c0", "c1", "c2", "pr", "rb", \ - "*(0)", "*(1)", "*(2)", "*(3)", "*(4)", "*(5)", \ - "*(6)", "*(7)", "*(8)", "*(9)", "*(10)", "*(11)", \ - "*(12)", "*(13)", "*(14)", "*(15)", "*(16)", "*(17)", \ - "*(18)", "*(19)", "*(20)", "*(21)", "*(22)", "*(23)", \ - "*(24)", "*(25)", "*(26)", "*(27)", "*(28)", "*(29)", \ - "*(30)", "*(31)" } - -#define PRINT_OPERAND_PUNCT_VALID_P(CODE) 0 - -/* Print operand X (an rtx) in assembler syntax to file FILE. - CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified. - For `%' followed by punctuation, CODE is the punctuation and X is null. - - DSP1610 extensions for operand codes: - - %H - print lower 16 bits of constant - %U - print upper 16 bits of constant - %w - print low half of register (e.g 'a0l') - %u - print upper half of register (e.g 'a0') - %b - print high half of accumulator for F3 ALU instructions - %h - print constant in decimal */ - -#define PRINT_OPERAND(FILE, X, CODE) print_operand(FILE, X, CODE) - - -/* Print a memory address as an operand to reference that memory location. */ - -#define PRINT_OPERAND_ADDRESS(FILE, ADDR) print_operand_address (FILE, ADDR) - -/* This is how to output an insn to push a register on the stack. - It need not be very fast code since it is used only for profiling */ -#define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \ - internal_error ("profiling not implemented yet"); - -/* This is how to output an insn to pop a register from the stack. - It need not be very fast code since it is used only for profiling */ -#define ASM_OUTPUT_REG_POP(FILE,REGNO) \ - internal_error ("profiling not implemented yet"); - -/* OUTPUT OF DISPATCH TABLES */ - -/* This macro should be provided on machines where the addresses in a dispatch - table are relative to the table's own address. */ -#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ - fprintf (FILE, "\tint L%d-L%d\n", VALUE, REL) - -/* This macro should be provided on machines where the addresses in a dispatch - table are absolute. */ -#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ - fprintf (FILE, "\tint L%d\n", VALUE) - -/* ASSEMBLER COMMANDS FOR ALIGNMENT */ - -/* This is how to output an assembler line that says to advance - the location counter to a multiple of 2**LOG bytes. We should - not have to do any alignment since the 1610 is a word machine. */ -#define ASM_OUTPUT_ALIGN(FILE,LOG) - -/* Define this macro if ASM_OUTPUT_SKIP should not be used in the text section - because it fails to put zero1 in the bytes that are skipped. */ -#define ASM_NO_SKIP_IN_TEXT 1 - -#define ASM_OUTPUT_SKIP(FILE,SIZE) \ - fprintf (FILE, "\t%d * int 0\n", (int)(SIZE)) - -/* CONTROLLING DEBUGGING INFORMATION FORMAT */ - -#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG - -#define ASM_OUTPUT_DEF(asm_out_file, LABEL1, LABEL2) \ - do { \ - fprintf (asm_out_file, ".alias " ); \ - ASM_OUTPUT_LABELREF(asm_out_file, LABEL1); \ - fprintf (asm_out_file, "=" ); \ - ASM_OUTPUT_LABELREF(asm_out_file, LABEL2); \ - fprintf (asm_out_file, "\n" ); \ - } while (0) - - -/* MISCELLANEOUS PARAMETERS */ - -/* Specify the machine mode that this machine uses - for the index in the tablejump instruction. */ -#define CASE_VECTOR_MODE QImode - -/* Define as C expression which evaluates to nonzero if the tablejump - instruction expects the table to contain offsets from the address of the - table. - Do not define this if the table should contain absolute addresses. */ -/* #define CASE_VECTOR_PC_RELATIVE 1 */ - -/* Max number of bytes we can move from memory to memory - in one reasonably fast instruction. */ -#define MOVE_MAX 1 - -/* Defining this macro causes the compiler to omit a sign-extend, zero-extend, - or bitwise 'and' instruction that truncates the count of a shift operation - to a width equal to the number of bits needed to represent the size of the - object being shifted. Do not define this macro unless the truncation applies - to both shift operations and bit-field operations (if any). */ -/* #define SHIFT_COUNT_TRUNCATED */ - -/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits - is done just by pretending it is already truncated. */ -#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1 - -/* When a prototype says `char' or `short', really pass an `int'. */ -#define PROMOTE_PROTOTYPES 1 - -/* An alias for the machine mode used for pointers */ -#define Pmode QImode - -/* A function address in a call instruction - is a byte address (for indexing purposes) - so give the MEM rtx a byte's mode. */ -#define FUNCTION_MODE QImode - -#if !defined(__DATE__) -#define TARGET_VERSION fprintf (stderr, " (%s)", VERSION_INFO1) -#else -#define TARGET_VERSION fprintf (stderr, " (%s, %s)", VERSION_INFO1, __DATE__) -#endif - -#define VERSION_INFO1 "Lucent DSP16xx C Cross Compiler, version 1.3.0b" - - -/* Define this as 1 if `char' should by default be signed; else as 0. */ -#define DEFAULT_SIGNED_CHAR 1 - -/* Define this so gcc does not output a call to __main, since we - are not currently supporting c++. */ -#define INIT_SECTION_ASM_OP 1 - diff --git a/gcc/config/dsp16xx/dsp16xx.md b/gcc/config/dsp16xx/dsp16xx.md deleted file mode 100644 index fffd2a9d9e0..00000000000 --- a/gcc/config/dsp16xx/dsp16xx.md +++ /dev/null @@ -1,3049 +0,0 @@ -;;- Machine description for the AT&T DSP1600 for GCC -;; Copyright (C) 1994, 1995, 1997, 1998, 2001, 2002 -;; Free Software Foundation, Inc. -;; Contributed by Michael Collison (collison@isisinc.net). - -;; This file is part of GCC. - -;; GCC is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; GCC is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GCC; see the file COPYING. If not, write to -;; the Free Software Foundation, 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - - -;;- See file "rtl.def" for documentation on define_insn, match_*, et. al. - -;; Attribute specifications - -; Type of each instruction. Default is arithmetic. -; I'd like to write the list as this, but genattrtab won't accept it. -; -; "jump,cond_jump,call, ; flow-control instructions -; load_i,load, store, move ; Y space address arithmetic instructions -; malu,special,f3_alu,f3_alu_i ; data arithmetic unit instructions -; shift_i,shift, bfield_i, bfield ; bit manipulation unit instructions -; arith, ; integer unit instructions -; nop - -; Classification of each insn. Some insns of TYPE_BRANCH are multi-word. -(define_attr "type" - "jump,cond_jump,call,load_i,load,move,store,malu,malu_mul,tstqi,special,special_2,f3_alu,f3_alu_i,f3_alu_i_mult,shift_i,shift,shift_multiple,shift_i_multiple,bfield_i,bfield,nop,ld_short_i,data_move,data_move_i,data_move_memory,data_move_memory_2,data_move_short_i,data_move_multiple,data_move_2,nothing" - (const_string "malu")) - -;; Data arithmetic unit -(define_function_unit "dau" 1 1 (eq_attr "type" "data_move,data_move_i,f3_alu_i") 2 0) - -(define_function_unit "dau" 1 1 (eq_attr "type" "special_2") 3 0) - -(define_function_unit "dau" 1 1 (eq_attr "type" "data_move_2") 4 0) - -;; Bit manipulation -(define_function_unit "bmu" 1 1 (eq_attr "type" "shift_i,shift_i_multiple") 2 0) - -(define_function_unit "bmu" 1 1 (eq_attr "type" "shift_multiple") 4 0) - -;; Y-memory addressing arithmetic unit -(define_function_unit "yaau" 1 1 (eq_attr "type" "data_move_memory") 2 0) - -(define_function_unit "yaau" 1 1 (eq_attr "type" "data_move_memory_2") 4 0) - - -;; .................... -;; -;; Test against 0 instructions -;; -;; .................... - -(define_expand "tsthi" - [(set (cc0) - (match_operand:HI 0 "register_operand" ""))] - "" - " -{ - dsp16xx_compare_gen = false; - dsp16xx_compare_op0 = operands[0]; - dsp16xx_compare_op1 = const0_rtx; - DONE; -}") - -(define_insn "tsthi_1" - [(set (cc0) - (match_operand:HI 0 "register_operand" "A"))] - "" - "%0=%0" - [(set_attr "type" "malu")]) - -(define_expand "tstqi" - [(set (cc0) - (match_operand:QI 0 "register_operand" ""))] - "" - " -{ - dsp16xx_compare_gen = false; - dsp16xx_compare_op0 = operands[0]; - dsp16xx_compare_op1 = const0_rtx; - DONE; -}") - -(define_split - [(set (cc0) - (match_operand:QI 0 "register_operand" "j,q")) - (clobber (match_scratch:QI 1 "=k,u"))] - "reload_completed" - [(set (match_dup 1) - (const_int 0)) - (parallel [(set (cc0) - (match_dup 0)) - (use (match_dup 1))])] - "") - -(define_insn "tstqi_split" - [(set (cc0) - (match_operand:QI 0 "register_operand" "j,q")) - (use (match_scratch:QI 1 "=k,u"))] - "" - "@ - %b0-0 - %b0-0" - [(set_attr "type" "f3_alu_i,f3_alu_i")]) - -(define_insn "tstqi_1" - [(set (cc0) - (match_operand:QI 0 "register_operand" "j,q")) - (clobber (match_scratch:QI 1 "=k,u"))] - "" - "@ - %1=0\;%b0-0 - %1=0\;%b0-0" - [(set_attr "type" "tstqi,tstqi")]) - - -;; -;; .................... -;; -;; Bit test instructions -;; -;; .................... - -(define_insn "" - [(set (cc0) - (and:HI (match_operand:HI 0 "register_operand" "A,!A") - (match_operand:HI 1 "register_operand" "Z,A")))] - "" - "* -{ - switch (which_alternative) - { - case 0: - case 1: - return \"%0&%1\"; - default: - abort(); - } -}" - [(set_attr "type" "f3_alu,f3_alu")]) - - -;;(define_insn "" -;; [(set (cc0) -;; (and:QI (match_operand:QI 0 "register_operand" "h") -;; (match_operand:QI 1 "const_int_operand" "I")))] -;; "" -;; "%b0&%H1" -;; [(set_attr "type" "f3_alu_i")]) - -;; -;; -;; Compare Instructions -;; - -(define_expand "cmphi" - [(parallel [(set (cc0) - (compare (match_operand:HI 0 "general_operand" "") - (match_operand:HI 1 "general_operand" ""))) - (clobber (match_scratch:QI 2 "")) - (clobber (match_scratch:QI 3 "")) - (clobber (match_scratch:QI 4 "")) - (clobber (match_scratch:QI 5 ""))])] - "" - " -{ - if (GET_CODE (operands[1]) == CONST_INT) - operands[1] = force_reg (HImode, operands[1]); - - dsp16xx_compare_gen = true; - dsp16xx_compare_op0 = operands[0]; - dsp16xx_compare_op1 = operands[1]; - DONE; -}") - -(define_insn "" - [(set (cc0) - (compare (match_operand:HI 0 "general_operand" "Z*r*m*i") - (match_operand:HI 1 "general_operand" "Z*r*m*i"))) - (clobber (match_scratch:QI 2 "=&A")) - (clobber (match_scratch:QI 3 "=&A")) - (clobber (match_scratch:QI 4 "=&A")) - (clobber (match_scratch:QI 5 "=&A"))] - "next_cc_user_unsigned (insn)" - "* -{ - if (GET_CODE(operands[0]) == REG) - { - if (REGNO (operands[0]) == REG_Y || - REGNO (operands[0]) == REG_PROD) - { - output_asm_insn (\"a0=%0\", operands); - } - else if (IS_YBASE_REGISTER_WINDOW (REGNO (operands[0]))) - output_asm_insn (\"a0=%u0\;a0l=%w0\", operands); - else - fatal_error (\"Invalid register for compare\"); - } - else if (GET_CODE(operands[0]) == CONST_INT) - output_asm_insn (\"a0=%U0\;a0l=%H0\", operands); - else if (GET_CODE (operands[0]) == MEM) - { - rtx xoperands[2]; - - xoperands[0] = gen_rtx_REG (HImode, REG_A0); - xoperands[1] = operands[0]; - double_reg_from_memory (xoperands); - } - - if (GET_CODE(operands[1]) == REG) - { - if (REGNO (operands[1]) == REG_Y || REGNO (operands[1]) == REG_PROD) - output_asm_insn (\"a1=%1\", operands); - else if (IS_YBASE_REGISTER_WINDOW (REGNO (operands[1]))) - output_asm_insn (\"a1=%u1\;a1l=%w1\", operands); - else - fatal_error (\"Invalid register for compare\"); - } - else if (GET_CODE (operands[1]) == MEM) - { - rtx xoperands[2]; - - xoperands[0] = gen_rtx_REG (HImode, REG_A1); - xoperands[1] = operands[1]; - double_reg_from_memory (xoperands); - } - else if (GET_CODE(operands[1]) == CONST_INT) - { - output_asm_insn (\"a1=%U1\;a1l=%H1\", operands); - } - - return \"psw = 0\;a0 - a1\"; -}") - -(define_insn "" - [(set (cc0) (compare (match_operand:HI 0 "register_operand" "A,!A") - (match_operand:HI 1 "register_operand" "Z,*A")))] - "" - "@ - %0-%1 - %0-%1" - [(set_attr "type" "malu,f3_alu")]) - -(define_expand "cmpqi" - [(parallel [(set (cc0) - (compare (match_operand:QI 0 "register_operand" "") - (match_operand:QI 1 "nonmemory_operand" ""))) - (clobber (match_operand:QI 2 "register_operand" "")) - (clobber (match_operand:QI 3 "register_operand" ""))])] - "" - " - { - if (operands[0]) /* Avoid unused code warning */ - { - dsp16xx_compare_gen = true; - dsp16xx_compare_op0 = operands[0]; - dsp16xx_compare_op1 = operands[1]; - DONE; - } - }") - -(define_split - [(set (cc0) - (compare (match_operand:QI 0 "register_operand" "") - (match_operand:QI 1 "register_operand" ""))) - (clobber (match_scratch:QI 2 "")) - (clobber (match_scratch:QI 3 ""))] - "reload_completed && next_cc_user_unsigned (insn)" - [(set (match_dup 2) - (const_int 0)) - (set (match_dup 3) - (const_int 0)) - (parallel [(set (cc0) - (compare (match_dup 0) - (match_dup 1))) - (use (match_dup 2)) - (use (match_dup 3))])] - "") - -(define_split - [(set (cc0) - (compare (match_operand:QI 0 "register_operand" "") - (match_operand:QI 1 "const_int_operand" ""))) - (clobber (match_scratch:QI 2 "")) - (clobber (match_scratch:QI 3 ""))] - "reload_completed && next_cc_user_unsigned (insn)" - [(set (match_dup 2) - (const_int 0)) - (parallel [(set (cc0) - (compare (match_dup 0) - (match_dup 1))) - (use (match_dup 2))])] - "") - -(define_insn "cmpqi_split_unsigned_reg" - [(set (cc0) (compare (match_operand:QI 0 "register_operand" "k,k,!k,u,u,!u") - (match_operand:QI 1 "register_operand" "w,z,u,w,z,k"))) - (use (match_scratch:QI 2 "=j,j,j,q,q,q")) - (use (match_scratch:QI 3 "=v,y,q,v,y,j"))] - "next_cc_user_unsigned (insn)" - "@ - %2-%3 - %2-%3 - %2-%3 - %2-%3 - %2-%3 - %2-%3" - [(set_attr "type" "malu,malu,malu,malu,malu,malu")]) - -(define_insn "cmpqi_split_unsigned_int" - [(set (cc0) (compare (match_operand:QI 0 "register_operand" "k,u") - (match_operand:QI 1 "const_int_operand" "i,i"))) - (use (match_scratch:QI 2 "=j,q"))] - "next_cc_user_unsigned (insn)" - "@ - %0-%H1 - %0-%H1" - [(set_attr "type" "f3_alu_i,f3_alu_i")]) - -(define_insn "" - [(set (cc0) (compare (match_operand:QI 0 "register_operand" "k,k,!k,k,u,u,!u,u") - (match_operand:QI 1 "nonmemory_operand" "w,z,u,i,w,z,k,i"))) - (clobber (match_scratch:QI 2 "=j,j,j,j,q,q,q,q")) - (clobber (match_scratch:QI 3 "=v,y,q,X,v,y,j,X"))] - "next_cc_user_unsigned (insn)" - "@ - %2=0\;%3=0\;%2-%3 - %2=0\;%3=0\;%2-%3 - %2=0\;%3=0\;%2-%3 - %2=0\;%0-%H1 - %2=0\;%3=0\;%2-%3 - %2=0\;%3=0\;%2-%3 - %2=0\;%3=0\;%2-%3 - %2=0\;%0-%H1") - -(define_split - [(set (cc0) - (compare (match_operand:QI 0 "register_operand" "") - (match_operand:QI 1 "register_operand" ""))) - (clobber (match_scratch:QI 2 "")) - (clobber (match_scratch:QI 3 ""))] - "reload_completed" - [(set (match_dup 2) - (const_int 0)) - (set (match_dup 3) - (const_int 0)) - (parallel [(set (cc0) - (compare (match_dup 0) - (match_dup 1))) - (use (match_dup 2)) - (use (match_dup 3))])] - "") - -(define_split - [(set (cc0) - (compare (match_operand:QI 0 "register_operand" "") - (match_operand:QI 1 "const_int_operand" ""))) - (clobber (match_scratch:QI 2 "")) - (clobber (match_scratch:QI 3 ""))] - "reload_completed" - [(set (match_dup 2) - (const_int 0)) - (parallel [(set (cc0) - (compare (match_dup 0) - (match_dup 1))) - (use (match_dup 2))])] - "") - -(define_insn "cmpqi_split_reg" - [(set (cc0) (compare (match_operand:QI 0 "register_operand" "j,j,!j,q,q,!q") - (match_operand:QI 1 "register_operand" "v,y,q,v,y,j"))) - (use (match_scratch:QI 2 "=k,k,k,u,u,u")) - (use (match_scratch:QI 3 "=w,z,u,w,z,k"))] - "" - "@ - %0-%1 - %0-%1 - %0-%1 - %0-%1 - %0-%1 - %0-%1" - [(set_attr "type" "malu,malu,malu,malu,malu,malu")]) - - -(define_insn "cmpqi_split_int" - [(set (cc0) (compare (match_operand:QI 0 "register_operand" "j,q") - (match_operand:QI 1 "const_int_operand" "i,i"))) - (use (match_scratch:QI 2 "=k,u"))] - "" - "@ - %b0-%H1 - %b0-%H1" - [(set_attr "type" "f3_alu_i,f3_alu_i")]) - -(define_insn "" - [(set (cc0) (compare (match_operand:QI 0 "register_operand" "j,j,!j,j,q,q,!q,q") - (match_operand:QI 1 "nonmemory_operand" "v,y,q,i,v,y,j,i"))) - (clobber (match_scratch:QI 2 "=k,k,k,k,u,u,u,u")) - (clobber (match_scratch:QI 3 "=w,z,u,X,w,z,k,X"))] - "" - "@ - %2=0\;%3=0\;%0-%1 - %2=0\;%3=0\;%0-%1 - %2=0\;%3=0\;%0-%1 - %2=0\;%b0-%H1 - %2=0\;%3=0\;%0-%1 - %2=0\;%3=0\;%0-%1 - %2=0\;%3=0\;%0-%1 - %2=0\;%b0-%H1") - - -(define_expand "cmphf" - [(set (cc0) - (compare (match_operand:HF 0 "register_operand" "") - (match_operand:HF 1 "nonmemory_operand" "")))] - "" - " -{ - if (!dsp16xx_cmphf3_libcall) - dsp16xx_cmphf3_libcall = gen_rtx_SYMBOL_REF (Pmode, CMPHF3_LIBCALL); - - dsp16xx_compare_gen = true; - dsp16xx_compare_op0 = operands[0]; - dsp16xx_compare_op1 = operands[1]; - emit_library_call (dsp16xx_cmphf3_libcall, 1, HImode, 2, - operands[0], HFmode, - operands[1], HFmode); - emit_insn (gen_tsthi_1 (copy_to_reg(hard_libcall_value (HImode)))); - DONE; -}") - - -;; .................... -;; -;; Add instructions -;; -;; .................... - -(define_split - [(set (match_operand:HI 0 "register_operand" "") - (plus:HI (match_operand:HI 1 "register_operand" "") - (match_operand:HI 2 "const_int_operand" "")))] - "reload_completed && !ADD_LOW_16(INTVAL(operands[2])) && - !ADD_HIGH_16(INTVAL(operands[2]))" - [(parallel [(set (match_dup 3) - (plus:QI (match_dup 4) - (match_dup 5))) - (clobber (match_dup 6))]) - - (parallel [(set (match_dup 6) - (plus:QI (match_dup 7) - (match_dup 8))) - (clobber (match_scratch:QI 9 ""))])] - " -{ - operands[3] = gen_lowpart(QImode, operands[0]); - operands[4] = gen_lowpart(QImode, operands[1]); - operands[5] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) & 0xffff); - - operands[6] = gen_highpart(QImode, operands[0]); - operands[7] = gen_highpart(QImode, operands[0]); - operands[8] = gen_rtx (CONST_INT, VOIDmode, (((INTVAL (operands[2]) & 0xffff0000) >> 16) & 0xffff)); -}") - - -(define_insn "addhi3" - [(set (match_operand:HI 0 "register_operand" "=A,A,A,A,A") - (plus:HI (match_operand:HI 1 "register_operand" "%A,A,A,A,A") - (match_operand:HI 2 "nonmemory_operand" "Z,d,L,M,?i")))] - "" - "@ - %0=%1+%2 - %0=%1+%2 - %0=%w1+%H2 - %0=%b1+%U2 - %0=%w1+%H2\;%0=%b0+%U2" - [(set_attr "type" "malu,malu,f3_alu_i,f3_alu_i,f3_alu_i")]) - -(define_insn "" - [(set (match_operand:QI 0 "register_operand" "=k,u,!k,!u") - (plus:QI (plus:QI (match_operand:QI 1 "register_operand" "uk,uk,uk,uk") - (match_operand:QI 2 "register_operand" "wz,wz,uk,uk")) - (match_operand:QI 3 "immediate_operand" "i,i,i,i"))) - (clobber (match_scratch:QI 4 "=j,q,j,q"))] - "" - "@ - %m0=%m1+%m2\;%m0=%0+%H3 - %m0=%m1+%m2\;%m0=%0+%H3 - %m0=%m1+%m2\;%m0=%0+%H3 - %m0=%m1+%m2\;%m0=%0+%H3") - -(define_expand "addqi3" - [(parallel [(set (match_operand:QI 0 "register_operand" "") - (plus:QI (match_operand:QI 1 "register_operand" "") - (match_operand:QI 2 "nonmemory_operand" ""))) - (clobber (match_scratch:QI 3 ""))])] - "" - " -{ - if (reload_in_progress) - { - if (REG_P (operands[1]) && - (REGNO(operands[1]) == STACK_POINTER_REGNUM || - REGNO(operands[1]) == FRAME_POINTER_REGNUM) && - GET_CODE (operands[2]) == CONST_INT) - { - if (REG_P (operands[0]) && IS_ACCUM_REG(REGNO(operands[0]))) - emit_move_insn (operands[0], operands[1]); - - operands[1] = operands[0]; - } - } -}") - - -(define_insn "match_addqi3" - [(set (match_operand:QI 0 "register_operand" "=a,a,k,u,k,u,!k,!u,j,j,q,q") - (plus:QI (match_operand:QI 1 "register_operand" "0,0,uk,uk,uk,uk,uk,uk,0,q,0,j") - (match_operand:QI 2 "nonmemory_operand" "W,N,i,i,wz,wz,uk,uk,i,i,i,i"))) - (clobber (match_scratch:QI 3 "=X,X,j,q,j,q,j,q,X,k,X,u"))] - "" - "* -{ - switch (which_alternative) - { - case 0: - return \"*%0++%2\"; - - case 1: - switch (INTVAL (operands[2])) - { - case -1: - return \"*%0--\"; - - case 1: - return \"*%0++\"; - - case -2: - return \"*%0--\;*%0--\"; - - case 2: - return \"*%0++\;*%0++\"; - default: - abort(); - } - - case 2: - case 3: - return \"%m0=%1+%H2\"; - - case 4: - case 5: - return \"%m0=%m1+%m2\"; - - - case 6: - case 7: - return \"%m0=%m1+%m2\"; - - case 8: - case 9: - case 10: - case 11: - return \"%0=%b1+%H2\"; - default: - abort(); - } -}" -[(set_attr "type" "data_move_memory,data_move_multiple,f3_alu_i,f3_alu_i,f3_alu,f3_alu,f3_alu,f3_alu,f3_alu_i,f3_alu_i,f3_alu_i,f3_alu_i")]) - - -(define_expand "addhf3" - [(set (match_operand:HF 0 "register_operand" "") - (plus:HF (match_operand:HF 1 "register_operand" "") - (match_operand:HF 2 "nonmemory_operand" "")))] - "" - " -{ - if (!dsp16xx_addhf3_libcall) - dsp16xx_addhf3_libcall = gen_rtx_SYMBOL_REF (Pmode, ADDHF3_LIBCALL); - - emit_library_call (dsp16xx_addhf3_libcall, 1, HFmode, 2, - operands[1], HFmode, - operands[2], HFmode); - emit_move_insn (operands[0], hard_libcall_value(HFmode)); - DONE; -}") - - -;; -;; .................... -;; -;; Subtract instructions -;; -;; .................... - -(define_split - [(set (match_operand:HI 0 "register_operand" "") - (minus:HI (match_operand:HI 1 "register_operand" "") - (match_operand:HI 2 "const_int_operand" "")))] - "reload_completed && !ADD_LOW_16(INTVAL(operands[2])) && - !ADD_HIGH_16(INTVAL(operands[2]))" - [(parallel [(set (match_dup 3) - (minus:QI (match_dup 4) - (match_dup 5))) - (clobber (match_dup 6))]) - - (parallel [(set (match_dup 6) - (minus:QI (match_dup 7) - (match_dup 8))) - (clobber (match_scratch:QI 9 ""))])] - " -{ - operands[3] = gen_lowpart(QImode, operands[0]); - operands[4] = gen_lowpart(QImode, operands[1]); - operands[5] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) & 0xffff); - - operands[6] = gen_highpart(QImode, operands[0]); - operands[7] = gen_highpart(QImode, operands[0]); - operands[8] = gen_rtx (CONST_INT, VOIDmode, (((INTVAL (operands[2]) & 0xffff0000) >> 16) & 0xffff)); -}") - - -(define_insn "subhi3" - [(set (match_operand:HI 0 "register_operand" "=A,A,A,A,A") - (minus:HI (match_operand:HI 1 "register_operand" "A,A,A,A,A") - (match_operand:HI 2 "nonmemory_operand" "Z,d,L,M,?i")))] - "" - "@ - %0=%1-%2 - %0=%1-%2 - %0=%w1-%H2 - %0=%b1-%U2 - %0=%w1-%H2\;%0=%b0-%U2" - [(set_attr "type" "malu,malu,f3_alu_i,f3_alu_i,f3_alu_i")]) - -(define_insn "subqi3" - [(set (match_operand:QI 0 "register_operand" "=a,k,u,k,u,!k,!u,j,j,q,q") - (minus:QI (match_operand:QI 1 "register_operand" "0,uk,uk,uk,uk,uk,uk,0,q,0,j") - (match_operand:QI 2 "nonmemory_operand" "N,i,i,wz,wz,uk,uk,i,i,i,i"))) - (clobber (match_scratch:QI 3 "=X,j,q,j,q,j,q,X,k,X,u"))] - "" - "* -{ - switch (which_alternative) - { - case 0: - switch (INTVAL (operands[2])) - { - case 1: - return \"*%0--\"; - - case -1: - return \"*%0++\"; - - default: - operands[2] = GEN_INT (-INTVAL (operands[2])); - - if (SHORT_IMMEDIATE(operands[2])) - return \"set %3=%H2\;*%0++%3\"; - else - return \"%3=%H2\;*%0++%3\"; - } - - case 1: - case 2: - return \"%m0=%1-%H2\"; - - case 3: - case 4: - return \"%m0=%m1-%m2\"; - - case 5: - case 6: - return \"%m0=%m1-%m2\"; - - case 7: case 8: - case 9: case 10: - return \"%0=%b1-%H2\"; - default: - abort(); - } -}" -[(set_attr "type" "data_move_multiple,f3_alu_i,f3_alu_i,f3_alu,f3_alu,f3_alu,f3_alu,f3_alu_i,f3_alu_i,f3_alu_i,f3_alu_i")]) - -(define_expand "subhf3" - [(set (match_operand:HF 0 "register_operand" "") - (minus:HF (match_operand:HF 1 "register_operand" "") - (match_operand:HF 2 "nonmemory_operand" "")))] - "" - " -{ - if (!dsp16xx_subhf3_libcall) - dsp16xx_subhf3_libcall = gen_rtx_SYMBOL_REF (Pmode, SUBHF3_LIBCALL); - - emit_library_call (dsp16xx_subhf3_libcall, 1, HFmode, 2, - operands[1], HFmode, - operands[2], HFmode); - emit_move_insn (operands[0], hard_libcall_value(HFmode)); - DONE; -}") - -(define_insn "neghi2" - [(set (match_operand:HI 0 "register_operand" "=A") - (neg:HI (match_operand:HI 1 "register_operand" "A")))] - "" - "%0=-%1" - [(set_attr "type" "special")]) - -(define_expand "neghf2" - [(set (match_operand:HF 0 "register_operand" "") - (neg:HF (match_operand:HF 1 "register_operand" "")))] - "" - " -{ - rtx result; - rtx target; - - { - target = gen_lowpart(HImode, operands[0]); - result = expand_binop (HImode, xor_optab, - gen_lowpart(HImode, operands[1]), - GEN_INT(0x80000000), target, 0, OPTAB_WIDEN); - if (result == 0) - abort (); - - if (result != target) - emit_move_insn (result, target); - - /* Make a place for REG_EQUAL. */ - emit_move_insn (operands[0], operands[0]); - DONE; - } -}") - -;; -;; .................... -;; -;; Multiply instructions -;; - -(define_expand "mulhi3" - [(set (match_operand:HI 0 "register_operand" "") - (mult:HI (match_operand:HI 1 "register_operand" "") - (match_operand:HI 2 "nonmemory_operand" "")))] - "" - " -{ - if (!dsp16xx_mulhi3_libcall) - dsp16xx_mulhi3_libcall = gen_rtx_SYMBOL_REF (Pmode, MULHI3_LIBCALL); - - emit_library_call (dsp16xx_mulhi3_libcall, 1, HImode, 2, - operands[1], HImode, - operands[2], HImode); - emit_move_insn (operands[0], hard_libcall_value(HImode)); - DONE; -}") - -(define_insn "mulqi3" - [(set (match_operand:QI 0 "register_operand" "=w") - (mult:QI (match_operand:QI 1 "register_operand" "%x") - (match_operand:QI 2 "register_operand" "y"))) - (clobber (match_scratch:QI 3 "=v"))] - "" - "%m0=%1*%2" - [(set_attr "type" "malu_mul")]) - -(define_insn "mulqihi3" - [(set (match_operand:HI 0 "register_operand" "=t") - (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "%x")) - (sign_extend:HI (match_operand:QI 2 "register_operand" "y"))))] - "" - "%0=%1*%2" - [(set_attr "type" "malu_mul")]) - -(define_expand "mulhf3" - [(set (match_operand:HF 0 "register_operand" "") - (mult:HF (match_operand:HF 1 "register_operand" "") - (match_operand:HF 2 "nonmemory_operand" "")))] - "" - " -{ - if (!dsp16xx_mulhf3_libcall) - dsp16xx_mulhf3_libcall = gen_rtx_SYMBOL_REF (Pmode, MULHF3_LIBCALL); - - emit_library_call (dsp16xx_mulhf3_libcall, 1, HFmode, 2, - operands[1], HFmode, - operands[2], HFmode); - emit_move_insn (operands[0], hard_libcall_value(HFmode)); - DONE; -}") - - - -;; -;; ******************* -;; -;; Divide Instructions -;; - -(define_expand "divhi3" - [(set (match_operand:HI 0 "register_operand" "") - (div:HI (match_operand:HI 1 "register_operand" "") - (match_operand:HI 2 "nonmemory_operand" "")))] - "" - " -{ - if (!dsp16xx_divhi3_libcall) - dsp16xx_divhi3_libcall = gen_rtx_SYMBOL_REF (Pmode, DIVHI3_LIBCALL); - - emit_library_call (dsp16xx_divhi3_libcall, 1, HImode, 2, - operands[1], HImode, - operands[2], HImode); - emit_move_insn (operands[0], hard_libcall_value(HImode)); - DONE; -}") - -(define_expand "udivhi3" - [(set (match_operand:HI 0 "register_operand" "") - (udiv:HI (match_operand:HI 1 "register_operand" "") - (match_operand:HI 2 "nonmemory_operand" "")))] - "" - " -{ - if (!dsp16xx_udivhi3_libcall) - dsp16xx_udivhi3_libcall = gen_rtx_SYMBOL_REF (Pmode, UDIVHI3_LIBCALL); - - emit_library_call (dsp16xx_udivhi3_libcall, 1, HImode, 2, - operands[1], HImode, - operands[2], HImode); - emit_move_insn (operands[0], hard_libcall_value(HImode)); - DONE; -}") - -(define_expand "divqi3" - [(set (match_operand:QI 0 "register_operand" "") - (div:QI (match_operand:QI 1 "register_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] - "" - " -{ - if (!dsp16xx_divqi3_libcall) - dsp16xx_divqi3_libcall = gen_rtx_SYMBOL_REF (Pmode, DIVQI3_LIBCALL); - - emit_library_call (dsp16xx_divqi3_libcall, 1, QImode, 2, - operands[1], QImode, - operands[2], QImode); - emit_move_insn (operands[0], hard_libcall_value(QImode)); - DONE; -}") - -(define_expand "udivqi3" - [(set (match_operand:QI 0 "register_operand" "") - (udiv:QI (match_operand:QI 1 "register_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] - "" - " -{ - if (!dsp16xx_udivqi3_libcall) - dsp16xx_udivqi3_libcall = gen_rtx_SYMBOL_REF (Pmode, UDIVQI3_LIBCALL); - - emit_library_call (dsp16xx_udivqi3_libcall, 1, QImode, 2, - operands[1], QImode, - operands[2], QImode); - emit_move_insn (operands[0], hard_libcall_value(QImode)); - DONE; -}") - -;; -;; .................... -;; -;; Modulo instructions -;; -;; .................... - -(define_expand "modhi3" - [(set (match_operand:HI 0 "register_operand" "") - (mod:HI (match_operand:HI 1 "register_operand" "") - (match_operand:HI 2 "nonmemory_operand" "")))] - "" - " -{ - if (!dsp16xx_modhi3_libcall) - dsp16xx_modhi3_libcall = gen_rtx_SYMBOL_REF (Pmode, MODHI3_LIBCALL); - - emit_library_call (dsp16xx_modhi3_libcall, 1, HImode, 2, - operands[1], HImode, - operands[2], HImode); - emit_move_insn (operands[0], hard_libcall_value(HImode)); - DONE; -}") - -(define_expand "umodhi3" - [(set (match_operand:HI 0 "register_operand" "") - (umod:HI (match_operand:HI 1 "register_operand" "") - (match_operand:HI 2 "nonmemory_operand" "")))] - "" - " -{ - if (!dsp16xx_umodhi3_libcall) - dsp16xx_umodhi3_libcall = gen_rtx_SYMBOL_REF (Pmode, UMODHI3_LIBCALL); - - emit_library_call (dsp16xx_umodhi3_libcall, 1, HImode, 2, - operands[1], HImode, - operands[2], HImode); - emit_move_insn (operands[0], hard_libcall_value(HImode)); - DONE; -}") - -(define_expand "modqi3" - [(set (match_operand:QI 0 "register_operand" "") - (mod:QI (match_operand:QI 1 "register_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] - "" - " -{ - if (!dsp16xx_modqi3_libcall) - dsp16xx_modqi3_libcall = gen_rtx_SYMBOL_REF (Pmode, MODQI3_LIBCALL); - - emit_library_call (dsp16xx_modqi3_libcall, 1, QImode, 2, - operands[1], QImode, - operands[2], QImode); - emit_move_insn (operands[0], hard_libcall_value(QImode)); - DONE; -}") - -(define_expand "umodqi3" - [(set (match_operand:QI 0 "register_operand" "") - (umod:QI (match_operand:QI 1 "register_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] - "" - " -{ - if (!dsp16xx_umodqi3_libcall) - dsp16xx_umodqi3_libcall = gen_rtx_SYMBOL_REF (Pmode, UMODQI3_LIBCALL); - - emit_library_call (dsp16xx_umodqi3_libcall, 1, QImode, 2, - operands[1], QImode, - operands[2], QImode); - emit_move_insn (operands[0], hard_libcall_value(QImode)); - DONE; -}") - -(define_expand "divhf3" - [(set (match_operand:HF 0 "register_operand" "") - (div:HF (match_operand:HF 1 "register_operand" "") - (match_operand:HF 2 "nonmemory_operand" "")))] - "" - " -{ - if (!dsp16xx_divhf3_libcall) - dsp16xx_divhf3_libcall = gen_rtx_SYMBOL_REF (Pmode, DIVHF3_LIBCALL); - - emit_library_call (dsp16xx_divhf3_libcall, 1, HFmode, 2, - operands[1], HFmode, - operands[2], HFmode); - emit_move_insn (operands[0], hard_libcall_value(HFmode)); - DONE; -}") - - - -;; -;; ******************** -;; -;; Logical Instructions -;; - -(define_split - [(set (match_operand:HI 0 "register_operand" "") - (and:HI (match_operand:HI 1 "register_operand" "") - (match_operand:HI 2 "const_int_operand" "")))] - "reload_completed && !AND_LOW_16(INTVAL(operands[2])) && - !AND_HIGH_16(INTVAL(operands[2])) - && (REGNO (operands[0]) == REGNO (operands[1]))" - [(parallel [(set (match_dup 3) - (and:QI (match_dup 4) - (match_dup 5))) - (clobber (match_scratch:QI 6 ""))]) - (parallel [(set (match_dup 7) - (and:QI (match_dup 8) - (match_dup 9))) - (clobber (match_scratch:QI 10 ""))])] - " -{ - operands[3] = gen_lowpart(QImode, operands[0]); - operands[4] = gen_lowpart(QImode, operands[1]); - operands[5] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) & 0xffff); - - operands[7] = gen_highpart(QImode, operands[0]); - operands[8] = gen_highpart(QImode, operands[0]); - operands[9] = gen_rtx (CONST_INT, VOIDmode, (((INTVAL (operands[2]) & 0xffff0000) >> 16) & 0xffff)); -}") - -(define_split - [(set (match_operand:HI 0 "register_operand" "") - (and:HI (match_operand:HI 1 "register_operand" "") - (match_operand:HI 2 "const_int_operand" "")))] - "reload_completed && !AND_LOW_16(INTVAL(operands[2])) && - !AND_HIGH_16(INTVAL(operands[2])) - && (REGNO (operands[0]) != REGNO (operands[1]))" - [(parallel [(set (match_dup 3) - (and:QI (match_dup 4) - (match_dup 5))) - (clobber (match_dup 6))]) - (parallel [(set (match_dup 6) - (and:QI (match_dup 7) - (match_dup 8))) - (clobber (match_scratch:QI 9 ""))])] - " -{ - operands[3] = gen_lowpart(QImode, operands[0]); - operands[4] = gen_lowpart(QImode, operands[1]); - operands[5] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) & 0xffff); - - operands[6] = gen_highpart(QImode, operands[0]); - operands[7] = gen_highpart(QImode, operands[0]); - operands[8] = gen_rtx (CONST_INT, VOIDmode, (((INTVAL (operands[2]) & 0xffff0000) >> 16) & 0xffff)); -}") - -(define_insn "andhi3" - [(set (match_operand:HI 0 "register_operand" "=A,A,A,A,?A") - (and:HI (match_operand:HI 1 "register_operand" "%A,!A,A,A,A") - (match_operand:HI 2 "nonmemory_operand" "Z,A,O,P,i")))] - "" - "@ - %0=%1&%2 - %0=%1&%2 - %0=%w1&%H2 - %0=%b1&%U2 - %0=%w1&%H2\;%0=%b0&%U2" - [(set_attr "type" "f3_alu,f3_alu,f3_alu_i,f3_alu_i,f3_alu_i_mult")]) - -(define_insn "andqi3" - [(set (match_operand:QI 0 "register_operand" "=k,u,!k,!u,k,u,k,u,j,q,j,q,j,q,!j,!q") - (and:QI (match_operand:QI 1 "register_operand" "%uk,uk,uk,uk,0,0,u,k,jq,jq,0,0,q,j,jq,jq") - (match_operand:QI 2 "nonmemory_operand" "wz,wz,uk,uk,i,i,i,i,yv,yv,i,i,i,i,jq,jq"))) - (clobber (match_scratch:QI 3 "=j,q,j,q,X,X,j,q,k,u,X,X,k,u,k,u"))] - "" - "@ - %m0=%m1&%m2 - %m0=%m1&%m2 - %m0=%m1&%m2 - %m0=%m1&%m2 - %m0=%1&%H2 - %m0=%1&%H2 - %m0=%1&%H2 - %m0=%1&%H2 - %m0=%m1&%m2 - %m0=%m1&%m2 - %m0=%b1&%H2 - %m0=%b1&%H2 - %m0=%b1&%H2 - %m0=%b1&%H2 - %m0=%m1&%m2 - %m0=%m1&%m2" - [(set_attr "type" "f3_alu,f3_alu,f3_alu,f3_alu,f3_alu_i,f3_alu_i,f3_alu_i,f3_alu_i,f3_alu,f3_alu,f3_alu_i,f3_alu_i,f3_alu_i,f3_alu_i,f3_alu,f3_alu")]) - - -(define_split - [(set (match_operand:HI 0 "register_operand" "") - (ior:HI (match_operand:HI 1 "register_operand" "") - (match_operand:HI 2 "const_int_operand" "")))] - "reload_completed && !SMALL_INTVAL(INTVAL(operands[2])) && - !ADD_HIGH_16(INTVAL(operands[2])) - && (REGNO (operands[0]) == REGNO (operands[1]))" - [(parallel [(set (match_dup 3) - (ior:QI (match_dup 4) - (match_dup 5))) - (clobber (match_scratch:QI 6 ""))]) - (parallel [(set (match_dup 7) - (ior:QI (match_dup 8) - (match_dup 9))) - (clobber (match_scratch:QI 10 ""))])] - " -{ - operands[3] = gen_lowpart(QImode, operands[0]); - operands[4] = gen_lowpart(QImode, operands[1]); - operands[5] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) & 0xffff); - - operands[7] = gen_highpart(QImode, operands[0]); - operands[8] = gen_highpart(QImode, operands[0]); - operands[9] = gen_rtx (CONST_INT, VOIDmode, (((INTVAL (operands[2]) & 0xffff0000) >> 16) & 0xffff)); -}") - -(define_split - [(set (match_operand:HI 0 "register_operand" "") - (ior:HI (match_operand:HI 1 "register_operand" "") - (match_operand:HI 2 "const_int_operand" "")))] - "reload_completed && !SMALL_INTVAL(INTVAL(operands[2])) && - !ADD_HIGH_16(INTVAL(operands[2])) - && (REGNO (operands[0]) != REGNO (operands[1]))" - [(parallel [(set (match_dup 3) - (ior:QI (match_dup 4) - (match_dup 5))) - (clobber (match_dup 6))]) - (parallel [(set (match_dup 6) - (ior:QI (match_dup 7) - (match_dup 8))) - (clobber (match_scratch:QI 9 ""))])] - " -{ - operands[3] = gen_lowpart(QImode, operands[0]); - operands[4] = gen_lowpart(QImode, operands[1]); - operands[5] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) & 0xffff); - - operands[6] = gen_highpart(QImode, operands[0]); - operands[7] = gen_highpart(QImode, operands[0]); - operands[8] = gen_rtx (CONST_INT, VOIDmode, (((INTVAL (operands[2]) & 0xffff0000) >> 16) & 0xffff)); -}") - - -(define_insn "iorhi3" - [(set (match_operand:HI 0 "register_operand" "=A,A,A,A,?A") - (ior:HI (match_operand:HI 1 "register_operand" "%A,!A,A,A,A") - (match_operand:HI 2 "nonmemory_operand" "Z,A,I,M,i")))] - "" - "@ - %0=%u1|%u2 - %0=%u1|%u2 - %0=%w1|%H2 - %0=%b1|%U2 - %0=%w1|%H2\;%0=%b0|%U2" - [(set_attr "type" "f3_alu,f3_alu,f3_alu_i,f3_alu_i,f3_alu_i_mult")]) - -(define_insn "iorqi3" - [(set (match_operand:QI 0 "register_operand" "=k,u,!k,!u,k,u,k,u,j,q,j,q,j,q,!j,!q") - (ior:QI (match_operand:QI 1 "register_operand" "%uk,uk,uk,uk,0,0,u,k,jq,jq,0,0,q,j,jq,jq") - (match_operand:QI 2 "nonmemory_operand" "wz,wz,uk,uk,i,i,i,i,yv,yv,i,i,i,i,jq,jq"))) - (clobber (match_scratch:QI 3 "=j,q,j,q,X,X,j,q,k,u,X,X,k,u,k,u"))] - "" - "@ - %m0=%m1|%m2 - %m0=%m1|%m2 - %m0=%m1|%m2 - %m0=%m1|%m2 - %m0=%1|%H2 - %m0=%1|%H2 - %m0=%1|%H2 - %m0=%1|%H2 - %m0=%m1|%m2 - %m0=%m1|%m2 - %m0=%b1|%H2 - %m0=%b1|%H2 - %m0=%b1|%H2 - %m0=%b1|%H2 - %m0=%m1|%m2 - %m0=%m1|%m2" - [(set_attr "type" "f3_alu,f3_alu,f3_alu,f3_alu,f3_alu_i,f3_alu_i,f3_alu_i,f3_alu_i,f3_alu,f3_alu,f3_alu_i,f3_alu_i,f3_alu_i,f3_alu_i,f3_alu,f3_alu")]) - - - -(define_split - [(set (match_operand:HI 0 "register_operand" "") - (xor:HI (match_operand:HI 1 "register_operand" "") - (match_operand:HI 2 "const_int_operand" "")))] - "reload_completed && !SMALL_INTVAL(INTVAL(operands[2])) && - !ADD_HIGH_16(INTVAL(operands[2])) - && (REGNO (operands[0]) == REGNO (operands[1]))" - [(parallel [(set (match_dup 3) - (xor:QI (match_dup 4) - (match_dup 5))) - (clobber (match_scratch:QI 6 ""))]) - (parallel [(set (match_dup 7) - (xor:QI (match_dup 8) - (match_dup 9))) - (clobber (match_scratch:QI 10 ""))])] - " -{ - operands[3] = gen_lowpart(QImode, operands[0]); - operands[4] = gen_lowpart(QImode, operands[1]); - operands[5] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) & 0xffff); - - operands[7] = gen_highpart(QImode, operands[0]); - operands[8] = gen_highpart(QImode, operands[0]); - operands[9] = gen_rtx (CONST_INT, VOIDmode, (((INTVAL (operands[2]) & 0xffff0000) >> 16) & 0xffff)); -}") - -(define_split - [(set (match_operand:HI 0 "register_operand" "") - (xor:HI (match_operand:HI 1 "register_operand" "") - (match_operand:HI 2 "const_int_operand" "")))] - "reload_completed && !SMALL_INTVAL(INTVAL(operands[2])) && - !ADD_HIGH_16(INTVAL(operands[2])) - && (REGNO (operands[0]) != REGNO (operands[1]))" - [(parallel [(set (match_dup 3) - (xor:QI (match_dup 4) - (match_dup 5))) - (clobber (match_dup 6))]) - (parallel [(set (match_dup 6) - (xor:QI (match_dup 7) - (match_dup 8))) - (clobber (match_scratch:QI 9 ""))])] - " -{ - operands[3] = gen_lowpart(QImode, operands[0]); - operands[4] = gen_lowpart(QImode, operands[1]); - operands[5] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) & 0xffff); - - operands[6] = gen_highpart(QImode, operands[0]); - operands[7] = gen_highpart(QImode, operands[0]); - operands[8] = gen_rtx (CONST_INT, VOIDmode, (((INTVAL (operands[2]) & 0xffff0000) >> 16) & 0xffff)); -}") - -(define_insn "xorhi3" - [(set (match_operand:HI 0 "register_operand" "=A,A,A,A,?A") - (xor:HI (match_operand:HI 1 "register_operand" "%A,!A,A,A,A") - (match_operand:HI 2 "nonmemory_operand" "Z,A,I,M,i")))] - "" - "@ - %0=%1^%2 - %0=%1^%2 - %0=%w1^%H2 - %0=%b1^%U2 - %0=%w1^%H2\;%0=%b0^%U2" - [(set_attr "type" "f3_alu,f3_alu,f3_alu_i,f3_alu_i,f3_alu_i_mult")]) - -(define_insn "xorqi3" - [(set (match_operand:QI 0 "register_operand" "=k,u,!k,!u,k,u,k,u,j,q,j,q,j,q,!j,!q") - (xor:QI (match_operand:QI 1 "register_operand" "%uk,uk,uk,uk,0,0,u,k,jq,jq,0,0,q,j,jq,jq") - (match_operand:QI 2 "nonmemory_operand" "wz,wz,uk,uk,i,i,i,i,yv,yv,i,i,i,i,jq,jq"))) - (clobber (match_scratch:QI 3 "=j,q,j,q,X,X,j,q,k,u,X,X,k,u,k,u"))] - "" - "@ - %m0=%m1^%m2 - %m0=%m1^%m2 - %m0=%m1^%m2 - %m0=%m1^%m2 - %m0=%1^%H2 - %m0=%1^%H2 - %m0=%1^%H2 - %m0=%1^%H2 - %m0=%m1^%m2 - %m0=%m1^%m2 - %m0=%b1^%H2 - %m0=%b1^%H2 - %m0=%b1^%H2 - %m0=%b1^%H2 - %m0=%m1^%m2 - %m0=%m1^%m2" - [(set_attr "type" "f3_alu,f3_alu,f3_alu,f3_alu,f3_alu_i,f3_alu_i,f3_alu_i,f3_alu_i,f3_alu,f3_alu,f3_alu_i,f3_alu_i,f3_alu_i,f3_alu_i,f3_alu,f3_alu")]) - -(define_insn "one_cmplhi2" - [(set (match_operand:HI 0 "register_operand" "=A") - (not:HI (match_operand:HI 1 "register_operand" "A")))] - "" - "%0= ~%1" - [(set_attr "type" "special")]) - - -(define_insn "one_cmplqi2" - [(set (match_operand:QI 0 "register_operand" "=k,k,u,u,j,j,q,q") - (not:QI (match_operand:QI 1 "register_operand" "0,u,0,q,0,q,0,j"))) - (clobber (match_scratch:QI 2 "=X,j,X,q,X,k,X,u"))] - "" - "@ - %m0= %1 ^ 0xffff - %m0= %1 ^ 0xffff - %m0= %1 ^ 0xffff - %m0= %1 ^ 0xffff - %m0= %b1 ^ 0xffff - %m0= %b1 ^ 0xffff - %m0= %b1 ^ 0xffff - %m0= %b1 ^ 0xffff" - [(set_attr "type" "f3_alu_i,f3_alu_i,f3_alu_i,f3_alu_i,f3_alu_i,f3_alu_i,f3_alu_i,f3_alu_i")]) - - -;; -;; MOVE INSTRUCTIONS -;; - -(define_split - [(set (mem:HI (match_operand:QI 0 "register_operand" "")) - (match_operand:HI 1 "register_operand" ""))] - "reload_completed && (operands[0] != stack_pointer_rtx)" - [(set (mem:QI (post_inc:QI (match_dup 0))) - (match_dup 2)) - (set (mem:QI (post_dec:QI (match_dup 0))) - (match_dup 3))] - " -{ - operands[2] = gen_highpart(QImode, operands[1]); - operands[3] = gen_lowpart(QImode, operands[1]); -}") - - -(define_split - [(set (match_operand:HI 0 "register_operand" "") - (mem:HI (match_operand:QI 1 "register_operand" "")))] - "reload_completed && (operands[1] != stack_pointer_rtx)" - [(set (match_dup 2) - (mem:QI (post_inc:QI (match_dup 1)))) - (set (match_dup 3) - (mem:QI (post_dec:QI (match_dup 1))))] - " -{ - operands[2] = gen_highpart(QImode, operands[0]); - operands[3] = gen_lowpart(QImode, operands[0]); -}") - -(define_split - [(set (mem:HI (post_inc:HI (match_operand:QI 0 "register_operand" ""))) - (match_operand:HI 1 "register_operand" ""))] - "reload_completed" - [(set (mem:QI (post_inc:QI (match_dup 0))) - (match_dup 2)) - (set (mem:QI (post_inc:QI (match_dup 0))) - (match_dup 3))] - " -{ - operands[2] = gen_highpart(QImode, operands[1]); - operands[3] = gen_lowpart(QImode, operands[1]); -}") - -(define_split - [(set (match_operand:HI 0 "register_operand" "") - (mem:HI (post_inc:HI (match_operand:QI 1 "register_operand" ""))))] - "reload_completed" - [(set (match_dup 2) - (mem:QI (post_inc:QI (match_dup 1)))) - (set (match_dup 3) - (mem:QI (post_inc:QI (match_dup 1))))] - " -{ - operands[2] = gen_highpart(QImode, operands[0]); - operands[3] = gen_lowpart(QImode, operands[0]); -}") - - -(define_split - [(set (match_operand:HI 0 "register_operand" "") - (match_operand:HI 1 "register_operand" ""))] - "reload_completed && - !(IS_ACCUM_REG (REGNO(operands[0])) && - (REGNO(operands[1]) == REG_PROD || REGNO(operands[1]) == REG_Y))" - [(set (match_dup 2) - (match_dup 3)) - (set (match_dup 4) - (match_dup 5))] - " -{ - operands[2] = gen_highpart(QImode, operands[0]); - operands[3] = gen_highpart(QImode, operands[1]); - operands[4] = gen_lowpart(QImode, operands[0]); - operands[5] = gen_lowpart(QImode, operands[1]); -}") - -(define_split - [(set (match_operand:HI 0 "register_operand" "") - (match_operand:HI 1 "const_int_operand" ""))] - "reload_completed" - [(set (match_dup 2) - (match_dup 3)) - (set (match_dup 4) - (match_dup 5))] - " -{ - operands[2] = gen_lowpart(QImode, operands[0]); - operands[3] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) & 0xffff); - - operands[4] = gen_highpart(QImode, operands[0]); - operands[5] = gen_rtx (CONST_INT, VOIDmode, (((INTVAL (operands[1]) & 0xffff0000) >> 16) & 0xffff)); -}") - -(define_expand "movhi" - [(set (match_operand:HI 0 "general_operand" "") - (match_operand:HI 1 "general_operand" ""))] - "" - " -{ - if (emit_move_sequence (operands, HImode)) - DONE; -}") - - -(define_insn "match_movhi1" - [(set (match_operand:HI 0 "nonimmediate_operand" "=A,Z,A,d,d,m,?d,*Y,t,f") - (match_operand:HI 1 "general_operand" "d,A,K,i,m,d,*Y,?d,t,f"))] - "register_operand(operands[0], HImode) - || register_operand(operands[1], HImode)" - "* -{ - switch (which_alternative) - { - /* register to accumulator */ - case 0: - return \"%0=%1\"; - case 1: - return \"%u0=%u1\;%w0=%w1\"; - case 2: - return \"%0=%0^%0\"; - case 3: - return \"%u0=%U1\;%w0=%H1\"; - case 4: - double_reg_from_memory(operands); - return \"\"; - case 5: - double_reg_to_memory(operands); - return \"\"; - case 6: - case 7: - return \"%u0=%u1\;%w0=%w1\"; - case 8: - case 9: - return \"\"; - default: - abort(); - } -}" -[(set_attr "type" "special,data_move_multiple,f3_alu,data_move_multiple,data_move_multiple,data_move_multiple,data_move_multiple,data_move_multiple,nothing,nothing")]) - - -;; NOTE: It is cheaper to do 'y = *r0', than 'r0 = *r0'. - -(define_expand "movqi" - [(set (match_operand:QI 0 "nonimmediate_operand" "") - (match_operand:QI 1 "general_operand" ""))] - "" - " -{ - if (emit_move_sequence (operands, QImode)) - DONE; -}") - -;; The movqi pattern with the parallel is used for addqi insns (which have a parallel) -;; that are turned into moveqi insns by the flow phase. This happens when an auto-increment -;; is detected. - -(define_insn "match_movqi1" - [(parallel [(set (match_operand:QI 0 "nonimmediate_operand" "=A,r,aW,c,?D,m<>,e,Y,r,xyz,m<>") - (match_operand:QI 1 "general_operand" "r,A,J,i,m<>,D,Y,e,0,m<>,xyz")) - (clobber (match_scratch:QI 2 "=X,X,X,X,X,X,X,X,X,X,X"))])] - "register_operand(operands[0], QImode) - || register_operand(operands[1], QImode)" - "* -{ - switch (which_alternative) - { - case 0: - /* We have to use the move mneumonic otherwise the 1610 will - attempt to transfer all 32-bits of 'y', 'p' or an accumulator - , which we don't want */ - if (REGNO(operands[1]) == REG_Y || REGNO(operands[1]) == REG_PROD - || IS_ACCUM_REG(REGNO(operands[1]))) - return \"move %0=%1\"; - else - return \"%0=%1\"; - - case 1: - return \"%0=%1\"; - - case 2: - return \"set %0=%H1\"; - - case 3: - return \"%0=%H1\"; - - case 4: - return \"%0=%1\"; - - case 5: - case 6: - return \"%0=%1\"; - - case 7: - return \"%0=%1\"; - - case 8: - return \"\"; - - case 9: case 10: - return \"%0=%1\"; - default: - abort(); - } -}" -[(set_attr "type" "data_move,data_move,data_move_short_i,data_move_i,data_move_memory,data_move_memory,data_move_memory,data_move_memory,nothing,malu,malu")]) - -(define_insn "match_movqi2" - [(set (match_operand:QI 0 "nonimmediate_operand" "=A,r,aW,c,?D,m<>,e,Y,r,xyz,m<>") - (match_operand:QI 1 "general_operand" "r,A,J,i,m<>,D,Y,e,0,m<>,xyz"))] - "register_operand(operands[0], QImode) - || register_operand(operands[1], QImode)" - "* -{ - switch (which_alternative) - { - case 0: - /* We have to use the move mneumonic otherwise the 1610 will - attempt to transfer all 32-bits of 'y', 'p' or an accumulator - , which we don't want */ - if (REGNO(operands[1]) == REG_Y || REGNO(operands[1]) == REG_PROD - || IS_ACCUM_REG(REGNO(operands[1]))) - return \"move %0=%1\"; - else - return \"%0=%1\"; - - case 1: - return \"%0=%1\"; - - case 2: - return \"set %0=%H1\"; - - case 3: - return \"%0=%H1\"; - - case 4: - return \"%0=%1\"; - - case 5: - case 6: - return \"%0=%1\"; - - case 7: - return \"%0=%1\"; - - case 8: - return \"\"; - - case 9: case 10: - return \"%0=%1\"; - default: - abort(); - } -}" -[(set_attr "type" "data_move,data_move,data_move_short_i,data_move_i,data_move_memory,data_move_memory,data_move_memory,data_move_memory,nothing,malu,malu")]) - -(define_expand "reload_inqi" - [(set (match_operand:QI 0 "register_operand" "=u") - (match_operand:QI 1 "sp_operand" "")) - (clobber (match_operand:QI 2 "register_operand" "=&q"))] - "" - " -{ - rtx addr_reg = XEXP (operands[1], 0); - rtx offset = XEXP (operands[1], 1); - - /* First, move the frame or stack pointer to the accumulator */ - emit_move_insn (operands[0], addr_reg); - - /* Then generate the add insn */ - emit_insn (gen_rtx_PARALLEL - (VOIDmode, - gen_rtvec (2, - gen_rtx_SET (VOIDmode, operands[0], - gen_rtx_PLUS (QImode, operands[0], - offset)), - gen_rtx_CLOBBER (VOIDmode, operands[2])))); - DONE; -}") - -(define_expand "reload_inhi" - [(set (match_operand:HI 0 "register_operand" "=r") - (match_operand:HI 1 "register_operand" "r")) - (clobber (match_operand:QI 2 "register_operand" "=&h"))] - "" - " -{ - /* Check for an overlap of operand 2 (an accumulator) with - the msw of operand 0. If we have an overlap we must reverse - the order of the moves. */ - - if (REGNO(operands[2]) == REGNO(operands[0])) - { - emit_move_insn (operands[2], operand_subword (operands[1], 1, 0, HImode)); - emit_move_insn (operand_subword (operands[0], 1, 0, HImode), operands[2]); - emit_move_insn (operands[2], operand_subword (operands[1], 0, 0, HImode)); - emit_move_insn (operand_subword (operands[0], 0, 0, HImode), operands[2]); - } - else - { - emit_move_insn (operands[2], operand_subword (operands[1], 0, 0, HImode)); - emit_move_insn (operand_subword (operands[0], 0, 0, HImode), operands[2]); - emit_move_insn (operands[2], operand_subword (operands[1], 1, 0, HImode)); - emit_move_insn (operand_subword (operands[0], 1, 0, HImode), operands[2]); - } - - DONE; -}") - - -(define_expand "reload_outhi" - [(set (match_operand:HI 0 "register_operand" "=r") - (match_operand:HI 1 "register_operand" "r")) - (clobber (match_operand:QI 2 "register_operand" "=&h"))] - "" - " -{ - emit_move_insn (operands[2], operand_subword (operands[1], 0, 0, HImode)); - emit_move_insn (operand_subword (operands[0], 0, 0, HImode), operands[2]); - emit_move_insn (operands[2], operand_subword (operands[1], 1, 0, HImode)); - emit_move_insn (operand_subword (operands[0], 1, 0, HImode), operands[2]); - DONE; -}") - -(define_expand "movstrqi" - [(parallel [(set (match_operand:BLK 0 "memory_operand" "") - (match_operand:BLK 1 "memory_operand" "")) - (use (match_operand:QI 2 "const_int_operand" "")) - (use (match_operand:QI 3 "const_int_operand" "")) - (clobber (match_scratch:QI 4 "")) - (clobber (match_dup 5)) - (clobber (match_dup 6))])] - "" - " -{ - rtx addr0, addr1; - - if (GET_CODE (operands[2]) != CONST_INT) - FAIL; - - if (INTVAL(operands[2]) > 127) - FAIL; - - addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0)); - addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0)); - - operands[5] = addr0; - operands[6] = addr1; - - operands[0] = change_address (operands[0], VOIDmode, addr0); - operands[1] = change_address (operands[1], VOIDmode, addr1); -}") - -(define_insn "" - [(set (mem:BLK (match_operand:QI 0 "register_operand" "a")) - (mem:BLK (match_operand:QI 1 "register_operand" "a"))) - (use (match_operand:QI 2 "const_int_operand" "n")) - (use (match_operand:QI 3 "immediate_operand" "i")) - (clobber (match_scratch:QI 4 "=x")) - (clobber (match_dup 0)) - (clobber (match_dup 1))] - "" - "* -{ return output_block_move (operands); }") - - -;; Floating point move insns - - -(define_expand "movhf" - [(set (match_operand:HF 0 "general_operand" "") - (match_operand:HF 1 "general_operand" ""))] - "" - " -{ - if (emit_move_sequence (operands, HFmode)) - DONE; -}") - -(define_insn "match_movhf" - [(set (match_operand:HF 0 "nonimmediate_operand" "=A,Z,d,d,m,d,Y") - (match_operand:HF 1 "general_operand" "d,A,F,m,d,Y,d"))] - "" - "* -{ - /* NOTE: When loading the register 16 bits at a time we - MUST load the high half FIRST (because the 1610 zeros - the low half) and then load the low half */ - - switch (which_alternative) - { - /* register to accumulator */ - case 0: - return \"%0=%1\"; - case 1: - return \"%u0=%u1\;%w0=%w1\"; - case 2: - output_dsp16xx_float_const(operands); - return \"\"; - case 3: - double_reg_from_memory(operands); - return \"\"; - case 4: - double_reg_to_memory(operands); - return \"\"; - case 5: - case 6: - return \"%u0=%u1\;%w0=%w1\"; - default: - abort(); - } -}" -[(set_attr "type" "move,move,load_i,load,store,load,store")]) - - - -(define_expand "reload_inhf" - [(set (match_operand:HF 0 "register_operand" "=r") - (match_operand:HF 1 "register_operand" "r")) - (clobber (match_operand:QI 2 "register_operand" "=&h"))] - "" - " -{ - /* Check for an overlap of operand 2 (an accumulator) with - the msw of operand 0. If we have an overlap we must reverse - the order of the moves. */ - - if (REGNO(operands[2]) == REGNO(operands[0])) - { - emit_move_insn (operands[2], operand_subword (operands[1], 1, 0, HFmode)); - emit_move_insn (operand_subword (operands[0], 1, 0, HFmode), operands[2]); - emit_move_insn (operands[2], operand_subword (operands[1], 0, 0, HFmode)); - emit_move_insn (operand_subword (operands[0], 0, 0, HFmode), operands[2]); - } - else - { - emit_move_insn (operands[2], operand_subword (operands[1], 0, 0, HFmode)); - emit_move_insn (operand_subword (operands[0], 0, 0, HFmode), operands[2]); - emit_move_insn (operands[2], operand_subword (operands[1], 1, 0, HFmode)); - emit_move_insn (operand_subword (operands[0], 1, 0, HFmode), operands[2]); - } - - DONE; -}") - -(define_expand "reload_outhf" - [(set (match_operand:HF 0 "register_operand" "=r") - (match_operand:HF 1 "register_operand" "r")) - (clobber (match_operand:QI 2 "register_operand" "=&h"))] - "" - " -{ - emit_move_insn (operands[2], operand_subword (operands[1], 0, 0, HFmode)); - emit_move_insn (operand_subword (operands[0], 0, 0, HFmode), operands[2]); - emit_move_insn (operands[2], operand_subword (operands[1], 1, 0, HFmode)); - emit_move_insn (operand_subword (operands[0], 1, 0, HFmode), operands[2]); - DONE; -}") - - -;; -;; CONVERSION INSTRUCTIONS -;; - -(define_expand "extendqihi2" - [(clobber (match_dup 2)) - (set (match_dup 3) (match_operand:QI 1 "register_operand" "")) - (set (match_operand:HI 0 "register_operand" "") - (ashift:HI (match_dup 2) - (const_int 16))) - (set (match_dup 0) - (ashiftrt:HI (match_dup 0) (const_int 16)))] - "" - " -{ - operands[2] = gen_reg_rtx (HImode); - operands[3] = gen_rtx_SUBREG (QImode, operands[2], 1); -}") - -(define_insn "internal_extendqihi2" - [(set (match_operand:HI 0 "register_operand" "=A") - (sign_extend:HI (match_operand:QI 1 "register_operand" "ku")))] - "TARGET_BMU" - "%0 = extracts(%m1, 0x1000)" -[(set_attr "type" "shift_i")]) - -;;(define_insn "extendqihi2" -;; [(set (match_operand:HI 0 "register_operand" "=A") -;; (sign_extend:HI (match_operand:QI 1 "register_operand" "h")))] -;; "" -;; "%0 = %1 >> 16") - -;;(define_insn "zero_extendqihi2" -;; [(set (match_operand:HI 0 "register_operand" "=t,f,A,?d,?A") -;; (zero_extend:HI (match_operand:QI 1 "register_operand" "w,z,ku,A,r")))] -;; "" -;; "* -;; { -;; switch (which_alternative) -;; { -;; case 0: -;; case 1: -;; return \"%0=0\"; -;; -;; case 2: -;; if (REGNO(operands[1]) == (REGNO(operands[0]) + 1)) -;; return \"%0=0\"; -;; else -;; return \"%w0=%1\;%0=0\"; -;; case 3: -;; return \"%w0=%1\;%0=0\"; -;; -;; case 4: -;; if (REGNO(operands[1]) == REG_Y || REGNO(operands[1]) == REG_PROD -;; || IS_ACCUM_REG(REGNO(operands[1]))) -;; return \"move %w0=%1\;%0=0\"; -;; else -;; return \"%w0=%1\;%0=0\"; -;; default: -;; abort(); -;; } -;; }") - -;;(define_expand "zero_extendqihi2" -;; [(clobber (match_dup 2)) -;; (set (match_dup 3) (match_operand:QI 1 "register_operand" "")) -;; (set (match_operand:HI 0 "register_operand" "") -;; (ashift:HI (match_dup 2) -;; (const_int 16))) -;; (set (match_dup 0) -;; (lshiftrt:HI (match_dup 0) (const_int 16)))] -;; "" -;; " -;;{ -;; operands[2] = gen_reg_rtx (HImode); -;; operands[3] = gen_rtx (SUBREG, QImode, operands[2], 1); -;;}") - -(define_expand "zero_extendqihi2" - [(set (match_operand:HI 0 "register_operand" "") - (zero_extend:HI (match_operand:QI 1 "register_operand" "")))] - "" - "") - - -(define_insn "match_zero_extendqihi_bmu" - [(set (match_operand:HI 0 "register_operand" "=?*Z,?*Z,?A,A") - (zero_extend:HI (match_operand:QI 1 "register_operand" "?A,?*Y,*Z*x*a*W*Y,ku")))] - "TARGET_BMU" - "* - { - switch (which_alternative) - { - case 0: - return \"%w0=%1\;%0=0\"; - - case 1: - return \"%w0=%1\;%0=0\"; - - case 2: - if (REGNO(operands[1]) == (REGNO(operands[0]) + 1)) - return \"%0=0\"; - else if (REGNO(operands[1]) == REG_Y || REGNO(operands[1]) == REG_PROD - || IS_ACCUM_REG(REGNO(operands[1]))) - { - return \"move %w0=%1\;%0=0\"; - } - else - return \"%w0=%1\;%0=0\"; - - case 3: - return \"%0 = extractz(%m1, 0x1000)\"; - default: - abort(); - } - }" - [(set_attr "type" "data_move_2,data_move_2,data_move_2,shift_i")]) - -(define_insn "match_zero_extendqihi2_nobmu" - [(set (match_operand:HI 0 "register_operand" "=?Z,?Z,A") - (zero_extend:HI (match_operand:QI 1 "register_operand" "A,Y,r")))] - "" - "* - { - switch (which_alternative) - { - case 0: - return \"%w0=%1\;%0=0\"; - - case 1: - return \"%w0=%1\;%0=0\"; - - case 2: - if (REGNO(operands[1]) + 1 == (REGNO(operands[0]) + 1)) - return \"%0=0\"; - else if (REGNO(operands[1]) == REG_Y || REGNO(operands[1]) == REG_PROD - || IS_ACCUM_REG(REGNO(operands[1]))) - { - return \"move %w0=%1\;%0=0\"; - } - else - return \"%w0=%1\;%0=0\"; - default: - abort(); - } - }" - [(set_attr "type" "data_move_2,data_move_2,data_move_2")]) - -;; -;; Floating point conversions -;; -(define_expand "floathihf2" - [(set (match_operand:HF 0 "register_operand" "") - (float:HF (match_operand:HI 1 "register_operand" "")))] - "" - " -{ - if (!dsp16xx_floathihf2_libcall) - dsp16xx_floathihf2_libcall = gen_rtx_SYMBOL_REF (Pmode, FLOATHIHF2_LIBCALL); - - emit_library_call (dsp16xx_floathihf2_libcall, 1, HFmode, 1, - operands[1], HImode); - emit_move_insn (operands[0], hard_libcall_value(HFmode)); - DONE; -}") - -(define_expand "fix_trunchfhi2" - [(set (match_operand:HI 0 "register_operand" "") - (fix:HI (match_operand:HF 1 "register_operand" "")))] - "" - " -{ - if (!dsp16xx_fixhfhi2_libcall) - dsp16xx_fixhfhi2_libcall = gen_rtx_SYMBOL_REF (Pmode, FIXHFHI2_LIBCALL); - - emit_library_call (dsp16xx_fixhfhi2_libcall, 1, HImode, 1, - operands[1], HFmode); - emit_move_insn (operands[0], hard_libcall_value(HImode)); - DONE; -}") - -(define_expand "fixuns_trunchfhi2" - [(set (match_operand:HI 0 "register_operand" "") - (unsigned_fix:HI (match_operand:HF 1 "register_operand" "")))] - "" - " -{ - rtx reg1 = gen_reg_rtx (HFmode); - rtx reg2 = gen_reg_rtx (HFmode); - rtx reg3 = gen_reg_rtx (HImode); - rtx label1 = gen_label_rtx (); - rtx label2 = gen_label_rtx (); - REAL_VALUE_TYPE offset; - - real_2expN (&offset, 31); - - if (reg1) /* turn off complaints about unreached code */ - { - emit_move_insn (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, HFmode)); - do_pending_stack_adjust (); - - emit_insn (gen_cmphf (operands[1], reg1)); - emit_jump_insn (gen_bge (label1)); - - emit_insn (gen_fix_trunchfhi2 (operands[0], operands[1])); - emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, - gen_rtx_LABEL_REF (VOIDmode, label2))); - emit_barrier (); - - emit_label (label1); - emit_insn (gen_subhf3 (reg2, operands[1], reg1)); - emit_move_insn (reg3, GEN_INT (0x80000000));; - - emit_insn (gen_fix_trunchfhi2 (operands[0], reg2)); - emit_insn (gen_iorhi3 (operands[0], operands[0], reg3)); - - emit_label (label2); - - /* allow REG_NOTES to be set on last insn (labels don't have enough - fields, and can't be used for REG_NOTES anyway). */ - emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx)); - DONE; - } -}") - -;; -;; SHIFT INSTRUCTIONS -;; - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=A") - (ashiftrt:HI (match_operand:HI 1 "register_operand" "A") - (const_int 1)))] - "" - "%0=%1>>1" - [(set_attr "type" "special")]) - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=A") - (ashiftrt:HI (match_operand:HI 1 "register_operand" "A") - (const_int 4)))] - "" - "%0=%1>>4" - [(set_attr "type" "special")]) - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=A") - (ashiftrt:HI (match_operand:HI 1 "register_operand" "A") - (const_int 8)))] - "" - "%0=%1>>8" - [(set_attr "type" "special")]) - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=A") - (ashiftrt:HI (match_operand:HI 1 "register_operand" "A") - (const_int 16)))] - "" - "%0=%1>>16" - [(set_attr "type" "special")]) - -;; -;; Arithmetic Right shift - -(define_expand "ashrhi3" - [(set (match_operand:HI 0 "register_operand" "") - (ashiftrt:HI (match_operand:HI 1 "register_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] - "" - " -{ - if (!TARGET_BMU) - { - /* If we are shifting by a constant we can do it in 1 or more - 1600 core shift instructions. The core instructions can - shift by 1, 4, 8, or 16. */ - - if (GET_CODE(operands[2]) == CONST_INT) - ; - else - { - rtx label1 = gen_label_rtx (); - rtx label2 = gen_label_rtx (); - -#if 0 - if (!dsp16xx_ashrhi3_libcall) - dsp16xx_ashrhi3_libcall - = gen_rtx_SYMBOL_REF (Pmode, ASHRHI3_LIBCALL); - - emit_library_call (dsp16xx_ashrhi3_libcall, 1, HImode, 2, - operands[1], HImode, - operands[2], QImode); - emit_move_insn (operands[0], hard_libcall_value(HImode)); - DONE; -#else - do_pending_stack_adjust (); - emit_insn (gen_tstqi (operands[2])); - emit_jump_insn (gen_bne (label1)); - emit_move_insn (operands[0], operands[1]); - emit_jump_insn (gen_jump (label2)); - emit_barrier (); - emit_label (label1); - - if (GET_CODE(operands[2]) != MEM) - { - rtx stack_slot; - - stack_slot = assign_stack_temp (QImode, GET_MODE_SIZE(QImode), 0); - stack_slot = change_address (stack_slot, VOIDmode, XEXP (stack_slot, 0)); - emit_move_insn (stack_slot, operands[2]); - operands[2] = stack_slot; - } - - emit_insn (gen_match_ashrhi3_nobmu (operands[0], operands[1], operands[2])); - emit_label (label2); - DONE; -#endif - } - } -}") - -(define_insn "match_ashrhi3_bmu" - [(set (match_operand:HI 0 "register_operand" "=A,A,A") - (ashiftrt:HI (match_operand:HI 1 "register_operand" "A,A,!A") - (match_operand:QI 2 "nonmemory_operand" "B,I,h")))] - "TARGET_BMU" - "@ - %0=%1>>%2 - %0=%1>>%H2 - %0=%1>>%2" - [(set_attr "type" "shift,shift_i,shift")]) - -(define_insn "match_ashrhi3_nobmu" - [(set (match_operand:HI 0 "register_operand" "=A,A") - (ashiftrt:HI (match_operand:HI 1 "register_operand" "A,0") - (match_operand:QI 2 "general_operand" "n,m")))] - "!TARGET_BMU" - "* -{ - if (which_alternative == 0) - { - emit_1600_core_shift (ASHIFTRT, operands, INTVAL(operands[2])); - return \"\"; - } - else - { - output_asm_insn (\"cloop=%2\", operands); - output_asm_insn (\"do 0 {\", operands); - output_asm_insn (\"%0=%0>>1\", operands); - return \"}\"; - } -}") - - - -;; -;; Logical Right Shift - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=A") - (lshiftrt:HI (match_operand:HI 1 "register_operand" "A") - (const_int 1)))] - "!TARGET_BMU" - "%0=%1>>1\;%0=%b0&0x7fff" - [(set_attr "type" "special")]) - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=A") - (lshiftrt:HI (match_operand:HI 1 "register_operand" "A") - (const_int 4)))] - "!TARGET_BMU" - "%0=%1>>4\;%0=%b0&0x0fff" - [(set_attr "type" "special")]) - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=A") - (lshiftrt:HI (match_operand:HI 1 "register_operand" "A") - (const_int 8)))] - "!TARGET_BMU" - "%0=%1>>8\;%0=%b0&0x00ff" - [(set_attr "type" "special")]) - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=A") - (lshiftrt:HI (match_operand:HI 1 "register_operand" "A") - (const_int 16)))] - "!TARGET_BMU" - "%0=%1>>16\;%0=%b0&0x0000" - [(set_attr "type" "special")]) - -(define_expand "lshrhi3" - [(set (match_operand:HI 0 "register_operand" "") - (lshiftrt:HI (match_operand:HI 1 "register_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] - "" - " -{ - if (!TARGET_BMU) - { - /* If we are shifting by a constant we can do it in 1 or more - 1600 core shift instructions. The core instructions can - shift by 1, 4, 8, or 16. */ - - if (GET_CODE(operands[2]) == CONST_INT) - emit_insn (gen_match_lshrhi3_nobmu (operands[0], operands[1], operands[2])); - else - { - rtx label1 = gen_label_rtx (); - rtx label2 = gen_label_rtx (); -#if 0 - if (!dsp16xx_lshrhi3_libcall) - dsp16xx_lshrhi3_libcall - = gen_rtx_SYMBOL_REF (Pmode, LSHRHI3_LIBCALL); - - emit_library_call (dsp16xx_lshrhi3_libcall, 1, HImode, 2, - operands[1], HImode, - operands[2], QImode); - emit_move_insn (operands[0], hard_libcall_value(HImode)); - DONE; -#else - do_pending_stack_adjust (); - emit_insn (gen_tstqi (operands[2])); - emit_jump_insn (gen_bne (label1)); - emit_move_insn (operands[0], operands[1]); - emit_jump_insn (gen_jump (label2)); - emit_barrier (); - emit_label (label1); - - if (GET_CODE(operands[2]) != MEM) - { - rtx stack_slot; - - stack_slot = assign_stack_temp (QImode, GET_MODE_SIZE(QImode), 0); - stack_slot = change_address (stack_slot, VOIDmode, XEXP (stack_slot, 0)); - emit_move_insn (stack_slot, operands[2]); - operands[2] = stack_slot; - } - - emit_insn (gen_match_lshrhi3_nobmu (operands[0], operands[1], operands[2])); - emit_label (label2); - DONE; -#endif - } - } -}") - -(define_insn "match_lshrhi3" - [(set (match_operand:HI 0 "register_operand" "=A,A,A") - (lshiftrt:HI (match_operand:HI 1 "register_operand" "A,A,!A") - (match_operand:QI 2 "nonmemory_operand" "B,I,h")))] - "TARGET_BMU" - "@ - %0=%1>>>%2 - %0=%1>>>%H2 - %0=%1>>>%2" - [(set_attr "type" "shift,shift_i,shift")]) - -(define_insn "match_lshrhi3_nobmu" - [(set (match_operand:HI 0 "register_operand" "=A,A") - (lshiftrt:HI (match_operand:HI 1 "register_operand" "A,0") - (match_operand:QI 2 "general_operand" "n,m"))) - (clobber (match_scratch:QI 3 "=X,Y"))] - "!TARGET_BMU" - "* -{ - if (which_alternative == 0) - { - emit_1600_core_shift (LSHIFTRT, operands, INTVAL(operands[2])); - return \"\"; - } - else - { - output_asm_insn (\"%3=psw\;psw=0\",operands); - output_asm_insn (\"cloop=%2\", operands); - output_asm_insn (\"do 0 {\", operands); - output_asm_insn (\"%0=%0>>1\", operands); - output_asm_insn (\"}\", operands); - return \"psw=%3\"; - } -}") - - -;; -;; Arithmetic Left shift - -;; Start off with special case arithmetic left shift by 1,4,8 or 16. - - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=A") - (ashift:HI (match_operand:HI 1 "register_operand" "A") - (const_int 1)))] - "" - "%0=%1<<1" - [(set_attr "type" "special")]) - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=A") - (ashift:HI (match_operand:HI 1 "register_operand" "A") - (const_int 4)))] - "" - "%0=%1<<4" - [(set_attr "type" "special")]) - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=A") - (ashift:HI (match_operand:HI 1 "register_operand" "A") - (const_int 8)))] - "" - "%0=%1<<8" - [(set_attr "type" "special")]) - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=A") - (ashift:HI (match_operand:HI 1 "general_operand" "A") - (const_int 16)))] - "" - "%0=%1<<16" - [(set_attr "type" "special")]) - - - -;; Normal Arithmetic Shift Left - - -(define_expand "ashlhi3" - [(set (match_operand:HI 0 "register_operand" "") - (ashift:HI (match_operand:HI 1 "register_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] - "" - " -{ - if (!TARGET_BMU) - { - /* If we are shifting by a constant we can do it in 1 or more - 1600 core shift instructions. The core instructions can - shift by 1, 4, 8, or 16. */ - - if (GET_CODE(operands[2]) == CONST_INT) - ; - else - { - rtx label1 = gen_label_rtx (); - rtx label2 = gen_label_rtx (); -#if 0 - if (!dsp16xx_ashlhi3_libcall) - dsp16xx_ashlhi3_libcall - = gen_rtx_SYMBOL_REF (Pmode, ASHLHI3_LIBCALL); - - emit_library_call (dsp16xx_ashlhi3_libcall, 1, HImode, 2, - operands[1], HImode, operands[2], QImode); - emit_move_insn (operands[0], hard_libcall_value(HImode)); - DONE; -#else - do_pending_stack_adjust (); - emit_insn (gen_tstqi (operands[2])); - emit_jump_insn (gen_bne (label1)); - emit_move_insn (operands[0], operands[1]); - emit_jump_insn (gen_jump (label2)); - emit_barrier (); - emit_label (label1); - - if (GET_CODE(operands[2]) != MEM) - { - rtx stack_slot; - - stack_slot = assign_stack_temp (QImode, GET_MODE_SIZE(QImode), 0); - stack_slot = change_address (stack_slot, VOIDmode, XEXP (stack_slot, 0)); - emit_move_insn (stack_slot, operands[2]); - operands[2] = stack_slot; - } - emit_insn (gen_match_ashlhi3_nobmu (operands[0], operands[1], operands[2])); - emit_label (label2); - DONE; -#endif - } - } -}") - -(define_insn "match_ashlhi3" - [(set (match_operand:HI 0 "register_operand" "=A,A,A") - (ashift:HI (match_operand:HI 1 "register_operand" "A,A,A") - (match_operand:QI 2 "nonmemory_operand" "B,I,!h")))] - "TARGET_BMU" - "@ - %0=%1<<%2\;move %u0=%u0 - %0=%1<<%H2\;move %u0=%u0 - %0=%1<<%2\;move %u0=%u0" - [(set_attr "type" "shift_multiple,shift_multiple,shift_multiple")]) - -(define_insn "match_ashlhi3_nobmu" - [(set (match_operand:HI 0 "register_operand" "=A,A") - (ashift:HI (match_operand:HI 1 "register_operand" "A,0") - (match_operand:QI 2 "general_operand" "n,m")))] - "!TARGET_BMU" - "* -{ - if (which_alternative == 0) - { - emit_1600_core_shift (ASHIFT, operands, INTVAL(operands[2])); - return \"\"; - } - else - { - output_asm_insn (\"cloop=%2\", operands); - output_asm_insn (\"do 0 {\", operands); - output_asm_insn (\"%0=%0<<1\", operands); - return \"}\"; - } -}") - - - - -(define_insn "extv" - [(set (match_operand:QI 0 "register_operand" "=k,u") - (sign_extract:QI (match_operand:QI 1 "register_operand" "ku,ku") - (match_operand:QI 2 "const_int_operand" "n,n") - (match_operand:QI 3 "const_int_operand" "n,n"))) - (clobber (match_scratch:QI 4 "=j,q"))] - "TARGET_BMU" - "* -{ - operands[5] - = GEN_INT ((INTVAL (operands[2]) << 8) + (INTVAL (operands[3]) & 0xff)); - return \"%m0 = extracts (%m1, %H5)\"; -}" -[(set_attr "type" "shift_i")]) - -(define_insn "extzv" - [(set (match_operand:QI 0 "register_operand" "=k,u") - (zero_extract:QI (match_operand:QI 1 "register_operand" "ku,ku") - (match_operand:QI 2 "const_int_operand" "n,n") - (match_operand:QI 3 "const_int_operand" "n,n"))) - (clobber (match_scratch:QI 4 "=j,q"))] - "TARGET_BMU" - "* -{ - operands[5] - = GEN_INT ((INTVAL (operands[2]) << 8) + (INTVAL (operands[3]) & 0xff)); - return \"%m0 = extractz (%m1, %H5)\"; -}" -[(set_attr "type" "shift_i")]) - -;; -;; conditional instructions -;; - -(define_expand "seq" - [(set (match_operand:QI 0 "register_operand" "") - (eq:QI (match_dup 1) (const_int 0)))] - "" - " -{ - if (dsp16xx_compare_gen) - operands[1] = gen_compare_reg (EQ, dsp16xx_compare_op0, dsp16xx_compare_op1); - else - operands[1] = gen_tst_reg (dsp16xx_compare_op0); -}") - -(define_expand "sne" - [(set (match_operand:QI 0 "register_operand" "") - (ne:QI (match_dup 1) (const_int 0)))] - "" - " -{ - if (dsp16xx_compare_gen) - operands[1] = gen_compare_reg (NE, dsp16xx_compare_op0, dsp16xx_compare_op1); - else - operands[1] = gen_tst_reg (dsp16xx_compare_op0); -}") - - -(define_expand "sgt" - [(set (match_operand:QI 0 "register_operand" "") - (gt:QI (match_dup 1) (const_int 0)))] - "" - " -{ - if (dsp16xx_compare_gen) - operands[1] = gen_compare_reg (GT, dsp16xx_compare_op0, dsp16xx_compare_op1); - else - operands[1] = gen_tst_reg (dsp16xx_compare_op0); -}") - - -(define_expand "slt" - [(set (match_operand:QI 0 "register_operand" "") - (lt:QI (match_dup 1) (const_int 0)))] - "" - " -{ - if (dsp16xx_compare_gen) - operands[1] = gen_compare_reg (LT, dsp16xx_compare_op0, dsp16xx_compare_op1); - else - operands[1] = gen_tst_reg (dsp16xx_compare_op0); -}") - -(define_expand "sge" - [(set (match_operand:QI 0 "register_operand" "") - (ge:QI (match_dup 1) (const_int 0)))] - "" - " -{ - if (dsp16xx_compare_gen) - operands[1] = gen_compare_reg (GE, dsp16xx_compare_op0, dsp16xx_compare_op1); - else - operands[1] = gen_tst_reg (dsp16xx_compare_op0); -}") - - -(define_expand "sle" - [(set (match_operand:QI 0 "register_operand" "") - (le:QI (match_dup 1) (const_int 0)))] - "" - " -{ - if (dsp16xx_compare_gen) - operands[1] = gen_compare_reg (LE, dsp16xx_compare_op0, dsp16xx_compare_op1); - else - operands[1] = gen_tst_reg (dsp16xx_compare_op0); -}") - - -(define_expand "sgtu" - [(set (match_operand:QI 0 "register_operand" "") - (gtu:QI (match_dup 1) (const_int 0)))] - "" - " -{ - if (dsp16xx_compare_gen) - operands[1] = gen_compare_reg (GTU, dsp16xx_compare_op0, dsp16xx_compare_op1); - else - operands[1] = gen_tst_reg (dsp16xx_compare_op0); -}") - - -(define_expand "sltu" - [(set (match_operand:QI 0 "register_operand" "") - (ltu:QI (match_dup 1) (const_int 0)))] - "" - " -{ - if (dsp16xx_compare_gen) - operands[1] = gen_compare_reg (LTU, dsp16xx_compare_op0, dsp16xx_compare_op1); - else - operands[1] = gen_tst_reg (dsp16xx_compare_op0); -}") - - -(define_expand "sgeu" - [(set (match_operand:QI 0 "register_operand" "") - (geu:QI (match_dup 1) (const_int 0)))] - "" - " -{ - if (dsp16xx_compare_gen) - operands[1] = gen_compare_reg (GEU, dsp16xx_compare_op0, dsp16xx_compare_op1); - else - operands[1] = gen_tst_reg (dsp16xx_compare_op0); -}") - - -(define_expand "sleu" - [(set (match_operand:QI 0 "register_operand" "") - (leu:QI (match_dup 1) (const_int 0)))] - "" - " -{ - if (dsp16xx_compare_gen) - operands[1] = gen_compare_reg (LEU, dsp16xx_compare_op0, dsp16xx_compare_op1); - else - operands[1] = gen_tst_reg (dsp16xx_compare_op0); -}") - - -(define_insn "scc" - [(set (match_operand:QI 0 "register_operand" "=jq") - (match_operator:QI 1 "comparison_operator" [(cc0) (const_int 0)]))] - "" - "%0 = 0\;if %C1 %b0 = %b0 + 1" - [(set_attr "type" "special_2")]) - -;; -;; Jump Instructions -;; - -(define_expand "beq" - [(set (pc) - (if_then_else (eq (match_dup 1) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (dsp16xx_compare_gen) - operands[1] = gen_compare_reg (EQ, dsp16xx_compare_op0, dsp16xx_compare_op1); - else - operands[1] = gen_tst_reg (dsp16xx_compare_op0); -}") - -(define_expand "bne" - [(set (pc) - (if_then_else (ne (match_dup 1) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (dsp16xx_compare_gen) - operands[1] = gen_compare_reg (NE, dsp16xx_compare_op0, dsp16xx_compare_op1); - else - operands[1] = gen_tst_reg (dsp16xx_compare_op0); -}") - - -(define_expand "bgt" - [(set (pc) - (if_then_else (gt (match_dup 1) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (dsp16xx_compare_gen) - operands[1] = gen_compare_reg (GT, dsp16xx_compare_op0, dsp16xx_compare_op1); - else - operands[1] = gen_tst_reg (dsp16xx_compare_op0); -}") - - -(define_expand "bge" - [(set (pc) - (if_then_else (ge (match_dup 1) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (dsp16xx_compare_gen) - operands[1] = gen_compare_reg (GE, dsp16xx_compare_op0, dsp16xx_compare_op1); - else - operands[1] = gen_tst_reg (dsp16xx_compare_op0); -}") - - -(define_expand "blt" - [(set (pc) - (if_then_else (lt (match_dup 1) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (dsp16xx_compare_gen) - operands[1] = gen_compare_reg (LT, dsp16xx_compare_op0, dsp16xx_compare_op1); - else - operands[1] = gen_tst_reg (dsp16xx_compare_op0); -}") - - -(define_expand "ble" - [(set (pc) - (if_then_else (le (match_dup 1) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (dsp16xx_compare_gen) - operands[1] = gen_compare_reg (LE, dsp16xx_compare_op0, dsp16xx_compare_op1); - else - operands[1] = gen_tst_reg (dsp16xx_compare_op0); -}") - - -(define_expand "bgtu" - [(set (pc) - (if_then_else (gtu (match_dup 1) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (dsp16xx_compare_gen) - operands[1] = gen_compare_reg (GTU, dsp16xx_compare_op0, dsp16xx_compare_op1); - else - operands[1] = gen_tst_reg (dsp16xx_compare_op0); -}") - - -(define_expand "bgeu" - [(set (pc) - (if_then_else (geu (match_dup 1) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (dsp16xx_compare_gen) - operands[1] = gen_compare_reg (GEU, dsp16xx_compare_op0, dsp16xx_compare_op1); - else - operands[1] = gen_tst_reg (dsp16xx_compare_op0); -}") - - -(define_expand "bltu" - [(set (pc) - (if_then_else (ltu (match_dup 1) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (dsp16xx_compare_gen) - operands[1] = gen_compare_reg (LTU, dsp16xx_compare_op0, dsp16xx_compare_op1); - else - operands[1] = gen_tst_reg (dsp16xx_compare_op0); -}") - - -(define_expand "bleu" - [(set (pc) - (if_then_else (leu (match_dup 1) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (dsp16xx_compare_gen) - operands[1] = gen_compare_reg (LEU, dsp16xx_compare_op0, dsp16xx_compare_op1); - else - operands[1] = gen_tst_reg (dsp16xx_compare_op0); -}") - - -(define_insn "" - [(set (pc) - (if_then_else (match_operator 1 "comparison_operator" - [(cc0) (const_int 0)]) - (label_ref (match_operand 0 "" "")) - (pc)))] - "!TARGET_NEAR_JUMP" - "pt=%l0\;if %C1 goto pt" - [(set_attr "type" "cond_jump")]) - -(define_insn "" - [(set (pc) - (if_then_else (match_operator 1 "comparison_operator" - [(cc0) (const_int 0)]) - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_NEAR_JUMP" - "if %C1 goto %l0" - [(set_attr "type" "cond_jump")]) - -;; -;; Negated conditional jump instructions. -;; These are necessary because jump optimization can turn -;; direct-conditional branches into reverse-conditional -;; branches. - -(define_insn "" - [(set (pc) - (if_then_else (match_operator 1 "comparison_operator" - [(cc0) (const_int 0)]) - (pc) - (label_ref (match_operand 0 "" ""))))] - "!TARGET_NEAR_JUMP" - "pt=%l0\;if %I1 goto pt" - [(set_attr "type" "cond_jump")]) - -(define_insn "" - [(set (pc) - (if_then_else (match_operator 1 "comparison_operator" - [(cc0) (const_int 0)]) - (pc) - (label_ref (match_operand 0 "" ""))))] - "TARGET_NEAR_JUMP" - "if %I1 goto %l0" - [(set_attr "type" "cond_jump")]) - - -;; -;; JUMPS -;; - -(define_insn "jump" - [(set (pc) - (label_ref (match_operand 0 "" "")))] - "" - "* - { - if (TARGET_NEAR_JUMP) - return \"goto %l0\"; - else - return \"pt=%l0\;goto pt\"; - }" - [(set_attr "type" "jump")]) - - -(define_insn "indirect_jump" - [(set (pc) (match_operand:QI 0 "register_operand" "A"))] - "" - "pt=%0\;goto pt" - [(set_attr "type" "jump")]) - -(define_insn "tablejump" - [(set (pc) (match_operand:QI 0 "register_operand" "A")) - (use (label_ref (match_operand 1 "" "")))] - "" - "pt=%0\;goto pt" - [(set_attr "type" "jump")]) - -;; -;; FUNCTION CALLS -;; - -;; Call subroutine with no return value. - - -(define_expand "call" - [(parallel [(call (match_operand:QI 0 "" "") - (match_operand 1 "" "")) - (clobber (reg:QI 24))])] - "" - " -{ - if (GET_CODE (operands[0]) == MEM - && ! call_address_operand (XEXP (operands[0], 0), QImode)) - operands[0] = gen_rtx_MEM (GET_MODE (operands[0]), - force_reg (Pmode, XEXP (operands[0], 0))); -}") - -(define_insn "" - [(parallel [(call (mem:QI (match_operand:QI 0 "call_address_operand" "hR")) - (match_operand 1 "" "")) - (clobber (reg:QI 24))])] - "" - "* -{ - if (GET_CODE (operands[0]) == REG || - (GET_CODE(operands[0]) == SYMBOL_REF && !TARGET_NEAR_CALL)) - return \"pt=%0\;call pt\"; - else - return \"call %0\"; -}" -[(set_attr "type" "call")]) - -;; Call subroutine with return value. - -(define_expand "call_value" - [(parallel [(set (match_operand 0 "register_operand" "=f") - (call (match_operand:QI 1 "call_address_operand" "hR") - (match_operand:QI 2 "" ""))) - (clobber (reg:QI 24))])] - "" - " -{ - if (GET_CODE (operands[1]) == MEM - && ! call_address_operand (XEXP (operands[1], 0), QImode)) - operands[1] = gen_rtx_MEM (GET_MODE (operands[1]), - force_reg (Pmode, XEXP (operands[1], 0))); -}") - -(define_insn "" - [(parallel [(set (match_operand 0 "register_operand" "=f") - (call (mem:QI (match_operand:QI 1 "call_address_operand" "hR")) - (match_operand:QI 2 "" ""))) - (clobber (reg:QI 24))])] - "" - "* -{ - if (GET_CODE (operands[1]) == REG || - (GET_CODE(operands[1]) == SYMBOL_REF && !TARGET_NEAR_CALL)) - return \"pt=%1\;call pt\"; - else - return \"call %1\"; -}" -[(set_attr "type" "call")]) - - -(define_expand "untyped_call" - [(parallel [(call (match_operand 0 "" "") - (const_int 0)) - (match_operand 1 "" "") - (match_operand 2 "" "")])] - "" - " -{ - int i; - - emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx)); - - for (i = 0; i < XVECLEN (operands[2], 0); i++) - { - rtx set = XVECEXP (operands[2], 0, i); - emit_move_insn (SET_DEST (set), SET_SRC (set)); - } - - /* The optimizer does not know that the call sets the function value - registers we stored in the result block. We avoid problems by - claiming that all hard registers are used and clobbered at this - point. */ - emit_insn (gen_blockage ()); - - DONE; -}") - -;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and -;; all of memory. This blocks insns from being moved across this point. - -(define_insn "blockage" - [(unspec_volatile [(const_int 0)] 0)] - "" - "") - -(define_insn "nop" - [(const_int 0)] - "" - "nop" - [(set_attr "type" "nop")]) - -;; -;; PEEPHOLE PATTERNS -;; - - -(define_peephole - [(parallel [(set (cc0) - (compare (match_operand:QI 0 "register_operand" "k,k,!k,u,u,!u") - (match_operand:QI 1 "register_operand" "w,z,u,w,z,k"))) - (use (match_operand:QI 2 "register_operand" "=j,j,j,q,q,q")) - (use (match_operand:QI 3 "register_operand" "=v,y,q,v,y,j"))]) - (set (pc) - (if_then_else (match_operator 5 "uns_comparison_operator" - [(cc0) (const_int 0)]) - (label_ref (match_operand 4 "" "")) - (pc)))] - "!TARGET_NEAR_JUMP" - "pt=%l4\;%2-%3\;if %C5 goto pt") - -(define_peephole - [(parallel [(set (cc0) - (compare (match_operand:QI 0 "register_operand" "k,k,!k,u,u,!u") - (match_operand:QI 1 "register_operand" "w,z,u,w,z,k"))) - (use (match_operand:QI 2 "register_operand" "=j,j,j,q,q,q")) - (use (match_operand:QI 3 "register_operand" "=v,y,q,v,y,j"))]) - (set (pc) - (if_then_else (match_operator 5 "uns_comparison_operator" - [(cc0) (const_int 0)]) - (pc) - (label_ref (match_operand 4 "" ""))))] - "!TARGET_NEAR_JUMP" - "pt=%l4\;%2-%3\;if %I5 goto pt") - - -(define_peephole - [(parallel [(set (cc0) - (compare (match_operand:QI 0 "register_operand" "k,u") - (match_operand:QI 1 "const_int_operand" "i,i"))) - (use (match_operand:QI 2 "register_operand" "=j,q"))]) - (set (pc) - (if_then_else (match_operator 4 "uns_comparison_operator" - [(cc0) (const_int 0)]) - (label_ref (match_operand 3 "" "")) - (pc)))] - "!TARGET_NEAR_JUMP" - "pt=%l3\;%0-%H1\;if %C4 goto pt") - -(define_peephole - [(parallel [(set (cc0) - (compare (match_operand:QI 0 "register_operand" "k,u") - (match_operand:QI 1 "const_int_operand" "i,i"))) - (use (match_operand:QI 2 "register_operand" "=j,q"))]) - (set (pc) - (if_then_else (match_operator 4 "uns_comparison_operator" - [(cc0) (const_int 0)]) - (pc) - (label_ref (match_operand 3 "" ""))))] - "!TARGET_NEAR_JUMP" - "pt=%l3\;%0-%H1\;if %I4 goto pt") - -;; -;;; QImode SIGNED COMPARE PEEPHOLE OPTIMIZATIONS -;; - -(define_peephole - [(parallel [(set (cc0) - (compare (match_operand:QI 0 "register_operand" "j,j,h,q,q,q") - (match_operand:QI 1 "register_operand" "v,y,q,v,y,j"))) - (use (match_operand:QI 2 "register_operand" "=k,k,k,u,u,u")) - (use (match_operand:QI 3 "register_operand" "=w,z,u,w,z,k"))]) - (set (pc) - (if_then_else (match_operator 5 "signed_comparison_operator" - [(cc0) (const_int 0)]) - (label_ref (match_operand 4 "" "")) - (pc)))] - "!TARGET_NEAR_JUMP" - "pt=%l4\;%0-%1\;if %C5 goto pt") - - -(define_peephole - [(parallel [(set (cc0) - (compare (match_operand:QI 0 "register_operand" "j,j,j,q,q,q") - (match_operand:QI 1 "register_operand" "v,y,q,v,y,j"))) - (use (match_operand:QI 2 "register_operand" "=k,k,k,u,u,u")) - (use (match_operand:QI 3 "register_operand" "=w,z,u,w,z,k"))]) - (set (pc) - (if_then_else (match_operator 5 "signed_comparison_operator" - [(cc0) (const_int 0)]) - (pc) - (label_ref (match_operand 4 "" ""))))] - "!TARGET_NEAR_JUMP" - "pt=%l4\;%0-%1\;if %I5 goto pt") - - -(define_peephole - [(parallel [(set (cc0) - (compare (match_operand:QI 0 "register_operand" "j,q") - (match_operand:QI 1 "const_int_operand" "i,i"))) - (use (match_operand:QI 2 "register_operand" "=k,u"))]) - (set (pc) - (if_then_else (match_operator 4 "signed_comparison_operator" - [(cc0) (const_int 0)]) - (label_ref (match_operand 3 "" "")) - (pc)))] - "!TARGET_NEAR_JUMP" - "pt=%l3\;%b0-%H1\;if %C4 goto pt") - -(define_peephole - [(parallel [(set (cc0) - (compare (match_operand:QI 0 "register_operand" "j,q") - (match_operand:QI 1 "const_int_operand" "i,i"))) - (use (match_operand:QI 2 "register_operand" "=k,u"))]) - (set (pc) - (if_then_else (match_operator 4 "signed_comparison_operator" - [(cc0) (const_int 0)]) - (pc) - (label_ref (match_operand 3 "" ""))))] - "!TARGET_NEAR_JUMP" - "pt=%l3\;%b0-%H1\;if %I4 goto pt") - -;; TST PEEPHOLE PATTERNS - -(define_peephole - [(parallel [(set (cc0) - (match_operand:QI 0 "register_operand" "j,q")) - (use (match_operand:QI 1 "register_operand" "=k,u"))]) - (set (pc) - (if_then_else (match_operator 3 "signed_comparison_operator" - [(cc0) (const_int 0)]) - (pc) - (label_ref (match_operand 2 "" ""))))] - "!TARGET_NEAR_JUMP" - "pt=%l2\;%b0-0\;if %I3 goto pt") - -(define_peephole - [(parallel [(set (cc0) - (match_operand:QI 0 "register_operand" "j,q")) - (use (match_operand:QI 1 "register_operand" "=k,u"))]) - (set (pc) - (if_then_else (match_operator 3 "signed_comparison_operator" - [(cc0) (const_int 0)]) - (label_ref (match_operand 2 "" "")) - (pc)))] - "!TARGET_NEAR_JUMP" - "pt=%l2\;%b0-0\;if %C3 goto pt") - -;; HImode peephole patterns - -(define_peephole - [(set (cc0) - (compare (match_operand:HI 0 "register_operand" "A,A") - (match_operand:HI 1 "register_operand" "Z,A"))) - (set (pc) - (if_then_else (match_operator 3 "signed_comparison_operator" - [(cc0) (const_int 0)]) - (label_ref (match_operand 2 "" "")) - (pc)))] - "!TARGET_NEAR_JUMP" - "pt=%l2\;%0-%1\;if %C3 goto pt") - -(define_peephole - [(set (cc0) - (compare (match_operand:HI 0 "register_operand" "A,A") - (match_operand:HI 1 "register_operand" "Z,A"))) - (set (pc) - (if_then_else (match_operator 3 "signed_comparison_operator" - [(cc0) (const_int 0)]) - (pc) - (label_ref (match_operand 2 "" ""))))] - "!TARGET_NEAR_JUMP" - "pt=%l2\;%0-%1\;if %I3 goto pt") diff --git a/gcc/config/i370/README b/gcc/config/i370/README deleted file mode 100644 index 56c6342dc64..00000000000 --- a/gcc/config/i370/README +++ /dev/null @@ -1,125 +0,0 @@ - -This directory contains code for building a compiler for the -32-bit ESA/390 architecture. It supports three different styles -of assembly: - --- MVS for use with the HLASM assembler --- Open Edition (USS Unix System Services) --- ELF/Linux for use with the binutils/gas GNU assembler. - - -Cross-compiling Hints ---------------------- -When building a cross-compiler on AIX, set the environment variable CC -and be sure to set the -ma and -qcpluscmt flags; i.e. - - export CC="cc -ma -qcpluscmt" - -do this *before* running configure, e.g. - - configure --target=i370-ibm-linux --prefix=/where/to/install/usr - -The Objective-C and FORTRAN front ends don't build. To avoid looking at -errors, do only - - make LANGUAGES=c - - -OpenEdition Hints ------------------ -The shell script "install" is handy for users of OpenEdition. - - -The ELF ABI ------------ -This compiler, in conjunction with the gas/binutils assembler, defines -a defacto ELF-based ABI for the ESA/390 architecture. Be warned: this -ABI has several major faults. It should be fixed. As it is fixed, -it is subject to change without warning. You should not commit to major -software systems without further exploring and fixing these problems. -Here are some of the problems: - --- No support for shared libraries or dynamically loadable objects. - This is because the compiler currently places address literals in - the text section. Although the GAS assembler supports a syntax for - USING that will place address literals in the data section, this forces - the use of two base registers, one for branches and one for the literal - pool. Work is needed to redesign the function prologue, epilogue and the - base register reloads to minimize the currently excessive use of reserved - registers. - - I beleive the best solution would be to add a toc or plt, and extending - the meaning of the USING directive to encompass this. This would - allow the continued use of the human-readable and familiar practice - of using =A() and =F'' to denote address literals, as opposed to more - difficult jump-table notation. - --- the stackframe is almost twice as big as it needs to be. - --- currently, r15 is used to return 32-bit values. Because this is the - last register, it prevents 64-bit ints and small structures from being - returned in registers, forcing return in memory. It would be more - efficient to use r14 to return 32-bit values, and r14+r15 to return - 64-bit values. - --- all arguments are currently passed in memory. It would be more efficient - to pass arguments in registers. - - - - -ChangeLog ---------- -Oct98-Dec98 -- add ELF back end; work on getting ABI more or less functional. -98.12.05 -- fix numerous MVC bugs -99.02.06 -- multiply insn sometimes not generated when needed. - -- extendsidi bugs, bad literal values printed - -- remove broken adddi subdi patterns -99.02.15 -- add clrstrsi pattern - -- fix -O2 divide bug -99.03.04 -- base & index reg usage bugs -99.03.15 -- fixes for returning long longs and structs (struct value return) -99.03.29 -- fix handling & alignment of shorts -99.03.31 -- clobbered register 14 is not always clobbered -99.04.02 -- operand constraints for cmphi -99.04.07 -- function pointer fixes for call, call_value patterns, - function pointers derefed once too often. -99.04.14 -- add pattern to print double-wide int - -- check intval<4096 for misc operands - -- add clrstrsi pattern - -- movstrsi fixes -99.04.16 -- use r2 to pass args into r11 in subroutine call. - -- fixes to movsi; some operand combinations impossible; - rework constraints - -- start work on forward jump optimization - -- char alignment bug -99.04.25 -- add untyped_call pattern so that builtin_apply works -99.04.27 -- fixes to compare logical under mask -99.04.28 -- reg 2 is clobbered by calls -99.04.30 -- fix rare mulsi bug -99.04.30 -- add constraints so that all RS, SI, SS forms insns have valid - addressing modes -99.04.30 -- major condition code fixes. The old code was just way off - w.r.t. which insns set condition code, and the codes that - were set. The extent of this damage was unbeleivable. -99.05.01 -- restructuring of operand constraints on many patterns, - many lead to invalid instructions being genned. -99.05.02 -- float pt fixes - -- fix movdi issue bugs -99.05.03 -- fix divide insn; was dividing incorrectly -99.05.05 -- fix sign extension problems on andhi - -- deprecate some constraints -99.05.06 -- add set_attr insn lengths; fix misc litpool sizes - -- add notes about how unsigned jumps work (i.e. - arithmetic vs. logical vs. signed vs unsigned). -99.05.11 -- use insn length to predict forward branch target; - use relative branchining where possible, - remove un-needed base register reload. -99.05.15 -- fix movstrsi, clrstrsi, cmpstrsi patterns as per conversation - w/ Richard Henderson - - - - - - diff --git a/gcc/config/i370/i370-c.c b/gcc/config/i370/i370-c.c deleted file mode 100644 index fe39191cfa2..00000000000 --- a/gcc/config/i370/i370-c.c +++ /dev/null @@ -1,64 +0,0 @@ -/* Subroutines for the C front end for System/370. - Copyright (C) 1989, 1993, 1995, 1997, 1998, 1999, 2000 - Free Software Foundation, Inc. - Contributed by Jan Stein (jan@cd.chalmers.se). - Modified for OS/390 LanguageEnvironment C by Dave Pitts (dpitts@cozx.com) - Hacked for Linux-ELF/390 by Linas Vepstas (linas@linas.org) - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GCC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -#include "config.h" -#include "system.h" -#include "coretypes.h" -#include "tm.h" -#include "tree.h" -#include "toplev.h" -#include "cpplib.h" -#include "c-pragma.h" -#include "tm_p.h" - -#ifdef TARGET_HLASM - -/* #pragma map (name, alias) - - In this implementation both name and alias are required to be - identifiers. The older code seemed to be more permissive. Can - anyone clarify? */ - -void -i370_pr_map (pfile) - cpp_reader *pfile ATTRIBUTE_UNUSED; -{ - tree name, alias, x; - - if (c_lex (&x) == CPP_OPEN_PAREN - && c_lex (&name) == CPP_NAME - && c_lex (&x) == CPP_COMMA - && c_lex (&alias) == CPP_NAME - && c_lex (&x) == CPP_CLOSE_PAREN) - { - if (c_lex (&x) != CPP_EOF) - warning ("junk at end of #pragma map"); - - mvs_add_alias (IDENTIFIER_POINTER (name), IDENTIFIER_POINTER (alias), 1); - return; - } - - warning ("malformed #pragma map, ignored"); -} - -#endif diff --git a/gcc/config/i370/i370-protos.h b/gcc/config/i370/i370-protos.h deleted file mode 100644 index 666db0b7aa6..00000000000 --- a/gcc/config/i370/i370-protos.h +++ /dev/null @@ -1,55 +0,0 @@ -/* Definitions of target machine for GNU compiler. System/370 version. - Copyright (C) 2000 Free Software Foundation, Inc. - Contributed by Jan Stein (jan@cd.chalmers.se). - Modified for OS/390 LanguageEnvironment C by Dave Pitts (dpitts@cozx.com) - Hacked for Linux-ELF/390 by Linas Vepstas (linas@linas.org) - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GCC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -#ifndef GCC_I370_PROTOS_H -#define GCC_I370_PROTOS_H - -extern void override_options (void); - -#ifdef RTX_CODE -extern int i370_branch_dest (rtx); -extern int i370_branch_length (rtx); -extern int i370_short_branch (rtx); -extern int s_operand (rtx, enum machine_mode); -extern int r_or_s_operand (rtx, enum machine_mode); -extern int unsigned_jump_follows_p (rtx); -#endif /* RTX_CODE */ - -#ifdef TREE_CODE -extern int handle_pragma (int (*)(void), void (*)(int), const char *); -#endif /* TREE_CODE */ - -extern void mvs_add_label (int); -extern int mvs_check_label (int); -extern int mvs_check_page (FILE *, int, int); -extern int mvs_function_check (const char *); -extern void mvs_add_alias (const char *, const char *, int); -extern int mvs_need_alias (const char *); -extern int mvs_get_alias (const char *, char *); -extern int mvs_check_alias (const char *, char *); -extern void check_label_emit (void); -extern void mvs_free_label_list (void); - -extern void i370_pr_map (struct cpp_reader *); - -#endif /* ! GCC_I370_PROTOS_H */ diff --git a/gcc/config/i370/i370.c b/gcc/config/i370/i370.c deleted file mode 100644 index 2cfe4fe3269..00000000000 --- a/gcc/config/i370/i370.c +++ /dev/null @@ -1,1514 +0,0 @@ -/* Subroutines for insn-output.c for System/370. - Copyright (C) 1989, 1993, 1995, 1997, 1998, 1999, 2000, 2002 - Free Software Foundation, Inc. - Contributed by Jan Stein (jan@cd.chalmers.se). - Modified for OS/390 LanguageEnvironment C by Dave Pitts (dpitts@cozx.com) - Hacked for Linux-ELF/390 by Linas Vepstas (linas@linas.org) - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GCC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -#include "config.h" -#include "system.h" -#include "coretypes.h" -#include "tm.h" -#include "rtl.h" -#include "tree.h" -#include "regs.h" -#include "hard-reg-set.h" -#include "real.h" -#include "insn-config.h" -#include "conditions.h" -#include "output.h" -#include "insn-attr.h" -#include "function.h" -#include "expr.h" -#include "flags.h" -#include "recog.h" -#include "toplev.h" -#include "cpplib.h" -#include "tm_p.h" -#include "target.h" -#include "target-def.h" - -extern FILE *asm_out_file; - -/* Label node. This structure is used to keep track of labels - on the various pages in the current routine. - The label_id is the numeric ID of the label, - The label_page is the page on which it actually appears, - The first_ref_page is the page on which the true first ref appears. - The label_addr is an estimate of its location in the current routine, - The label_first & last_ref are estimates of where the earliest and - latest references to this label occur. */ - -typedef struct label_node - { - struct label_node *label_next; - int label_id; - int label_page; - int first_ref_page; - - int label_addr; - int label_first_ref; - int label_last_ref; - } -label_node_t; - -/* Is 1 when a label has been generated and the base register must be reloaded. */ -int mvs_need_base_reload = 0; - -/* Current function starting base page. */ -int function_base_page; - -/* Length of the current page code. */ -int mvs_page_code; - -/* Length of the current page literals. */ -int mvs_page_lit; - -/* Current function name. */ -char *mvs_function_name = 0; - -/* Current function name length. */ -size_t mvs_function_name_length = 0; - -/* Page number for multi-page functions. */ -int mvs_page_num = 0; - -/* Label node list anchor. */ -static label_node_t *label_anchor = 0; - -/* Label node free list anchor. */ -static label_node_t *free_anchor = 0; - -/* Assembler source file descriptor. */ -static FILE *assembler_source = 0; - -static label_node_t * mvs_get_label (int); -static void i370_label_scan (void); -#ifdef TARGET_HLASM -static bool i370_hlasm_assemble_integer (rtx, unsigned int, int); -static void i370_globalize_label (FILE *, const char *); -#endif -static void i370_output_function_prologue (FILE *, HOST_WIDE_INT); -static void i370_output_function_epilogue (FILE *, HOST_WIDE_INT); -static void i370_file_start (void); -static void i370_file_end (void); - -#ifdef LONGEXTERNAL -static int mvs_hash_alias (const char *); -#endif -static void i370_internal_label (FILE *, const char *, unsigned long); -static bool i370_rtx_costs (rtx, int, int, int *); - -/* ===================================================== */ -/* defines and functions specific to the HLASM assembler */ -#ifdef TARGET_HLASM - -#define MVS_HASH_PRIME 999983 -#if HOST_CHARSET == HOST_CHARSET_EBCDIC -#define MVS_SET_SIZE 256 -#else -#define MVS_SET_SIZE 128 -#endif - -#ifndef MAX_MVS_LABEL_SIZE -#define MAX_MVS_LABEL_SIZE 8 -#endif - -#define MAX_LONG_LABEL_SIZE 255 - -/* Alias node, this structure is used to keep track of aliases to external - variables. The IBM assembler allows an alias to an external name - that is longer that 8 characters; but only once per assembly. - Also, this structure stores the #pragma map info. */ -typedef struct alias_node - { - struct alias_node *alias_next; - int alias_emitted; - char alias_name [MAX_MVS_LABEL_SIZE + 1]; - char real_name [MAX_LONG_LABEL_SIZE + 1]; - } -alias_node_t; - -/* Alias node list anchor. */ -static alias_node_t *alias_anchor = 0; - -/* Define the length of the internal MVS function table. */ -#define MVS_FUNCTION_TABLE_LENGTH 32 - -/* C/370 internal function table. These functions use non-standard linkage - and must handled in a special manner. */ -static const char *const mvs_function_table[MVS_FUNCTION_TABLE_LENGTH] = -{ -#if HOST_CHARSET == HOST_CHARSET_EBCDIC /* Changed for EBCDIC collating sequence */ - "ceil", "edc_acos", "edc_asin", "edc_atan", "edc_ata2", "edc_cos", - "edc_cosh", "edc_erf", "edc_erfc", "edc_exp", "edc_gamm", "edc_lg10", - "edc_log", "edc_sin", "edc_sinh", "edc_sqrt", "edc_tan", "edc_tanh", - "fabs", "floor", "fmod", "frexp", "hypot", "jn", - "j0", "j1", "ldexp", "modf", "pow", "yn", - "y0", "y1" -#else - "ceil", "edc_acos", "edc_asin", "edc_ata2", "edc_atan", "edc_cos", - "edc_cosh", "edc_erf", "edc_erfc", "edc_exp", "edc_gamm", "edc_lg10", - "edc_log", "edc_sin", "edc_sinh", "edc_sqrt", "edc_tan", "edc_tanh", - "fabs", "floor", "fmod", "frexp", "hypot", "j0", - "j1", "jn", "ldexp", "modf", "pow", "y0", - "y1", "yn" -#endif -}; - -#endif /* TARGET_HLASM */ -/* ===================================================== */ - - -/* Initialize the GCC target structure. */ -#ifdef TARGET_HLASM -#undef TARGET_ASM_BYTE_OP -#define TARGET_ASM_BYTE_OP NULL -#undef TARGET_ASM_ALIGNED_HI_OP -#define TARGET_ASM_ALIGNED_HI_OP NULL -#undef TARGET_ASM_ALIGNED_SI_OP -#define TARGET_ASM_ALIGNED_SI_OP NULL -#undef TARGET_ASM_INTEGER -#define TARGET_ASM_INTEGER i370_hlasm_assemble_integer -#undef TARGET_ASM_GLOBALIZE_LABEL -#define TARGET_ASM_GLOBALIZE_LABEL i370_globalize_label -#endif - -#undef TARGET_ASM_FUNCTION_PROLOGUE -#define TARGET_ASM_FUNCTION_PROLOGUE i370_output_function_prologue -#undef TARGET_ASM_FUNCTION_EPILOGUE -#define TARGET_ASM_FUNCTION_EPILOGUE i370_output_function_epilogue -#undef TARGET_ASM_FILE_START -#define TARGET_ASM_FILE_START i370_file_start -#undef TARGET_ASM_FILE_END -#define TARGET_ASM_FILE_END i370_file_end -#undef TARGET_ASM_INTERNAL_LABEL -#define TARGET_ASM_INTERNAL_LABEL i370_internal_label -#undef TARGET_RTX_COSTS -#define TARGET_RTX_COSTS i370_rtx_costs - -struct gcc_target targetm = TARGET_INITIALIZER; - -/* Set global variables as needed for the options enabled. */ - -void -override_options () -{ - /* We're 370 floating point, not IEEE floating point. */ - memset (real_format_for_mode, 0, sizeof real_format_for_mode); - REAL_MODE_FORMAT (SFmode) = &i370_single_format; - REAL_MODE_FORMAT (DFmode) = &i370_double_format; -} - -/* ===================================================== */ -/* The following three routines are used to determine whther - forward branch is on this page, or is a far jump. We use - the "length" attr on an insn [(set_atter "length" "4")] - to store the largest possible code length that insn - could have. This gives us a hint of the address of a - branch destination, and from that, we can work out - the length of the jump, and whether its on page or not. - */ - -/* Return the destination address of a branch. */ - -int -i370_branch_dest (branch) - rtx branch; -{ - rtx dest = SET_SRC (PATTERN (branch)); - int dest_uid; - int dest_addr; - - /* first, compute the estimated address of the branch target */ - if (GET_CODE (dest) == IF_THEN_ELSE) - dest = XEXP (dest, 1); - dest = XEXP (dest, 0); - dest_uid = INSN_UID (dest); - dest_addr = INSN_ADDRESSES (dest_uid); - - /* next, record the address of this insn as the true addr of first ref */ - { - label_node_t *lp; - rtx label = JUMP_LABEL (branch); - int labelno = CODE_LABEL_NUMBER (label); - - if (!label || CODE_LABEL != GET_CODE (label)) abort (); - - lp = mvs_get_label (labelno); - if (-1 == lp -> first_ref_page) lp->first_ref_page = mvs_page_num; - } - return dest_addr; -} - -int -i370_branch_length (insn) - rtx insn; -{ - int here, there; - here = INSN_ADDRESSES (INSN_UID (insn)); - there = i370_branch_dest (insn); - return (there - here); -} - - -int -i370_short_branch (insn) - rtx insn; -{ - int base_offset; - - base_offset = i370_branch_length(insn); - if (0 > base_offset) - { - base_offset += mvs_page_code; - } - else - { - /* avoid bumping into lit pool; use 2x to estimate max possible lits */ - base_offset *= 2; - base_offset += mvs_page_code + mvs_page_lit; - } - - /* make a conservative estimate of room left on page */ - if ((4060 >base_offset) && ( 0 < base_offset)) return 1; - return 0; -} - -/* The i370_label_scan() routine is supposed to loop over - all labels and label references in a compilation unit, - and determine whether all label refs appear on the same - code page as the label. If they do, then we can avoid - a reload of the base register for that label. - - Note that the instruction addresses used here are only - approximate, and make the sizes of the jumps appear - farther apart then they will actually be. This makes - this code far more conservative than it needs to be. - */ - -#define I370_RECORD_LABEL_REF(label,addr) { \ - label_node_t *lp; \ - int labelno = CODE_LABEL_NUMBER (label); \ - lp = mvs_get_label (labelno); \ - if (addr < lp -> label_first_ref) lp->label_first_ref = addr; \ - if (addr > lp -> label_last_ref) lp->label_last_ref = addr; \ -} - -static void -i370_label_scan () -{ - rtx insn; - label_node_t *lp; - int tablejump_offset = 0; - - for (insn = get_insns(); insn; insn = NEXT_INSN(insn)) - { - int here = INSN_ADDRESSES (INSN_UID (insn)); - enum rtx_code code = GET_CODE(insn); - - /* ??? adjust for tables embedded in the .text section that - * the compiler didn't take into account */ - here += tablejump_offset; - INSN_ADDRESSES (INSN_UID (insn)) = here; - - /* check to see if this insn is a label ... */ - if (CODE_LABEL == code) - { - int labelno = CODE_LABEL_NUMBER (insn); - - lp = mvs_get_label (labelno); - lp -> label_addr = here; -#if 0 - /* Supposedly, labels are supposed to have circular - lists of label-refs that reference them, - setup in flow.c, but this does not appear to be the case. */ - rtx labelref = LABEL_REFS (insn); - rtx ref = labelref; - do - { - rtx linsn = CONTAINING_INSN(ref); - ref = LABEL_NEXTREF(ref); - } while (ref && (ref != labelref)); -#endif - } - else - if (JUMP_INSN == code) - { - rtx label = JUMP_LABEL (insn); - - /* If there is no label for this jump, then this - had better be a ADDR_VEC or an ADDR_DIFF_VEC - and there had better be a vector of labels. */ - if (!label) - { - int j; - rtx body = PATTERN (insn); - if (ADDR_VEC == GET_CODE(body)) - { - for (j=0; j < XVECLEN (body, 0); j++) - { - rtx lref = XVECEXP (body, 0, j); - if (LABEL_REF != GET_CODE (lref)) abort (); - label = XEXP (lref,0); - if (CODE_LABEL != GET_CODE (label)) abort (); - tablejump_offset += 4; - here += 4; - I370_RECORD_LABEL_REF(label,here); - } - /* finished with the vector go do next insn */ - continue; - } - else - if (ADDR_DIFF_VEC == GET_CODE(body)) - { -/* XXX hack alert. - Right now, we leave this as a no-op, but strictly speaking, - this is incorrect. It is possible that a table-jump - driven off of a relative address could take us off-page, - to a place where we need to reload the base reg. So really, - we need to examing both labels, and compare thier values - to the current basereg value. - - More generally, this brings up a troubling issue overall: - what happens if a tablejump is split across two pages? I do - not beleive that this case is handled correctly at all, and - can only lead to horrible results if this were to occur. - - However, the current situation is not any worse than it was - last week, and so we punt for now. */ - - debug_rtx (insn); - for (j=0; j < XVECLEN (body, 0); j++) - { - } - /* finished with the vector go do next insn */ - continue; - } - else - { -/* XXX hack alert. - Compiling the exception handling (L_eh) in libgcc2.a will trip - up right here, with something that looks like - (set (pc) (mem:SI (plus:SI (reg/v:SI 1 r1) (const_int 4)))) - {indirect_jump} - I'm not sure of what leads up to this, but it looks like - the makings of a long jump which will surely get us into trouble - because the base & page registers don't get reloaded. For now - I'm not sure of what to do ... again we punt ... we are not worse - off than yesterday. */ - - /* print_rtl_single (stdout, insn); */ - debug_rtx (insn); - /* abort(); */ - continue; - } - } - else - { - /* At this point, this jump_insn had better be a plain-old - ordinary one, grap the label id and go */ - if (CODE_LABEL != GET_CODE (label)) abort (); - I370_RECORD_LABEL_REF(label,here); - } - } - - /* Sometimes, we take addresses of labels and use them - as instruction operands ... these show up as REG_NOTES */ - else - if (INSN == code) - { - if ('i' == GET_RTX_CLASS (code)) - { - rtx note; - for (note = REG_NOTES (insn); note; note = XEXP(note,1)) - { - if (REG_LABEL == REG_NOTE_KIND(note)) - { - rtx label = XEXP (note,0); - if (!label || CODE_LABEL != GET_CODE (label)) abort (); - - I370_RECORD_LABEL_REF(label,here); - } - } - } - } - } -} - -/* ===================================================== */ - -/* Emit reload of base register if indicated. This is to eliminate multiple - reloads when several labels are generated pointing to the same place - in the code. - - The page table is written at the end of the function. - The entries in the page table look like - .LPGT0: // PGT0 EQU * - .long .LPG0 // DC A(PG0) - .long .LPG1 // DC A(PG1) - while the prologue generates - L r4,=A(.LPGT0) - - Note that this paging scheme breaks down if a single subroutine - has more than about 10MB of code in it ... as long as humans write - code, this shouldn't be a problem ... - */ - -void -check_label_emit () -{ - if (mvs_need_base_reload) - { - mvs_need_base_reload = 0; - - mvs_page_code += 4; - fprintf (assembler_source, "\tL\t%d,%d(,%d)\n", - BASE_REGISTER, (mvs_page_num - function_base_page) * 4, - PAGE_REGISTER); - } -} - -/* Add the label to the current page label list. If a free element is available - it will be used for the new label. Otherwise, a label element will be - allocated from memory. - ID is the label number of the label being added to the list. */ - -static label_node_t * -mvs_get_label (id) - int id; -{ - label_node_t *lp; - - /* first, lets see if we already go one, if so, use that. */ - for (lp = label_anchor; lp; lp = lp->label_next) - { - if (lp->label_id == id) return lp; - } - - /* not found, get a new one */ - if (free_anchor) - { - lp = free_anchor; - free_anchor = lp->label_next; - } - else - { - lp = (label_node_t *) xmalloc (sizeof (label_node_t)); - } - - /* initialize for new label */ - lp->label_id = id; - lp->label_page = -1; - lp->label_next = label_anchor; - lp->label_first_ref = 2000123123; - lp->label_last_ref = -1; - lp->label_addr = -1; - lp->first_ref_page = -1; - label_anchor = lp; - - return lp; -} - -void -mvs_add_label (id) - int id; -{ - label_node_t *lp; - int fwd_distance; - - lp = mvs_get_label (id); - lp->label_page = mvs_page_num; - - /* OK, we just saw the label. Determine if this label - * needs a reload of the base register */ - if ((-1 != lp->first_ref_page) && - (lp->first_ref_page != mvs_page_num)) - { - /* Yep; the first label_ref was on a different page. */ - mvs_need_base_reload ++; - return; - } - - /* Hmm. Try to see if the estimated address of the last - label_ref is on the current page. If it is, then we - don't need a base reg reload. Note that this estimate - is very conservatively handled; we'll tend to have - a good bit more reloads than actually needed. Someday, - we should tighten the estimates (which are driven by - the (set_att "length") insn attibute. - - Currently, we estimate that number of page literals - same as number of insns, which is a vast overestimate, - esp that the estimate of each insn size is its max size. */ - - /* if latest ref comes before label, we are clear */ - if (lp->label_last_ref < lp->label_addr) return; - - fwd_distance = lp->label_last_ref - lp->label_addr; - - if (mvs_page_code + 2 * fwd_distance + mvs_page_lit < 4060) return; - - mvs_need_base_reload ++; -} - -/* Check to see if the label is in the list and in the current - page. If not found, we have to make worst case assumption - that label will be on a different page, and thus will have to - generate a load and branch on register. This is rather - ugly for forward-jumps, but what can we do? For backward - jumps on the same page we can branch directly to address. - ID is the label number of the label being checked. */ - -int -mvs_check_label (id) - int id; -{ - label_node_t *lp; - - for (lp = label_anchor; lp; lp = lp->label_next) - { - if (lp->label_id == id) - { - if (lp->label_page == mvs_page_num) - { - return 1; - } - else - { - return 0; - } - } - } - return 0; -} - -/* Get the page on which the label sits. This will be used to - determine is a register reload is really needed. */ - -#if 0 -int -mvs_get_label_page(int id) -{ - label_node_t *lp; - - for (lp = label_anchor; lp; lp = lp->label_next) - { - if (lp->label_id == id) - return lp->label_page; - } - return -1; -} -#endif - -/* The label list for the current page freed by linking the list onto the free - label element chain. */ - -void -mvs_free_label_list () -{ - - if (label_anchor) - { - label_node_t *last_lp = label_anchor; - while (last_lp->label_next) last_lp = last_lp->label_next; - last_lp->label_next = free_anchor; - free_anchor = label_anchor; - } - label_anchor = 0; -} - -/* ====================================================================== */ -/* If the page size limit is reached a new code page is started, and the base - register is set to it. This page break point is counted conservatively, - most literals that have the same value are collapsed by the assembler. - True is returned when a new page is started. - FILE is the assembler output file descriptor. - CODE is the length, in bytes, of the instruction to be emitted. - LIT is the length of the literal to be emitted. */ - -#ifdef TARGET_HLASM -int -mvs_check_page (file, code, lit) - FILE *file; - int code, lit; -{ - if (file) - assembler_source = file; - - if (mvs_page_code + code + mvs_page_lit + lit > MAX_MVS_PAGE_LENGTH) - { - fprintf (assembler_source, "\tB\tPGE%d\n", mvs_page_num); - fprintf (assembler_source, "\tDS\t0F\n"); - fprintf (assembler_source, "\tLTORG\n"); - fprintf (assembler_source, "\tDS\t0F\n"); - fprintf (assembler_source, "PGE%d\tEQU\t*\n", mvs_page_num); - fprintf (assembler_source, "\tDROP\t%d\n", BASE_REGISTER); - mvs_page_num++; - /* Safe to use BASR not BALR, since we are - * not switching addressing mode here ... */ - fprintf (assembler_source, "\tBASR\t%d,0\n", BASE_REGISTER); - fprintf (assembler_source, "PG%d\tEQU\t*\n", mvs_page_num); - fprintf (assembler_source, "\tUSING\t*,%d\n", BASE_REGISTER); - mvs_page_code = code; - mvs_page_lit = lit; - return 1; - } - mvs_page_code += code; - mvs_page_lit += lit; - return 0; -} -#endif /* TARGET_HLASM */ - - -#ifdef TARGET_ELF_ABI -int -mvs_check_page (file, code, lit) - FILE *file; - int code, lit; -{ - if (file) - assembler_source = file; - - if (mvs_page_code + code + mvs_page_lit + lit > MAX_MVS_PAGE_LENGTH) - { - /* hop past the literal pool */ - fprintf (assembler_source, "\tB\t.LPGE%d\n", mvs_page_num); - - /* dump the literal pool. The .baligns are optional, since - * ltorg will align to the size of the largest literal - * (which is possibly 8 bytes) */ - fprintf (assembler_source, "\t.balign\t4\n"); - fprintf (assembler_source, "\t.LTORG\n"); - fprintf (assembler_source, "\t.balign\t4\n"); - - /* we continue execution here ... */ - fprintf (assembler_source, ".LPGE%d:\n", mvs_page_num); - fprintf (assembler_source, "\t.DROP\t%d\n", BASE_REGISTER); - mvs_page_num++; - - /* BASR puts the contents of the PSW into r3 - * that is, r3 will be loaded with the address of "." */ - fprintf (assembler_source, "\tBASR\tr%d,0\n", BASE_REGISTER); - fprintf (assembler_source, ".LPG%d:\n", mvs_page_num); - fprintf (assembler_source, "\t.USING\t.,r%d\n", BASE_REGISTER); - mvs_page_code = code; - mvs_page_lit = lit; - return 1; - } - mvs_page_code += code; - mvs_page_lit += lit; - return 0; -} -#endif /* TARGET_ELF_ABI */ - -/* ===================================================== */ -/* defines and functions specific to the HLASM assembler */ -#ifdef TARGET_HLASM - -/* Check for C/370 runtime function, they don't use standard calling - conventions. True is returned if the function is in the table. - NAME is the name of the current function. */ - -int -mvs_function_check (name) - const char *name; -{ - int lower, middle, upper; - int i; - - lower = 0; - upper = MVS_FUNCTION_TABLE_LENGTH - 1; - while (lower <= upper) - { - middle = (lower + upper) / 2; - i = strcmp (name, mvs_function_table[middle]); - if (i == 0) - return 1; - if (i < 0) - upper = middle - 1; - else - lower = middle + 1; - } - return 0; -} - -/* Generate a hash for a given key. */ - -#ifdef LONGEXTERNAL -static int -mvs_hash_alias (key) - const char *key; -{ - int h; - int i; - int l = strlen (key); - - h = key[0]; - for (i = 1; i < l; i++) - h = ((h * MVS_SET_SIZE) + key[i]) % MVS_HASH_PRIME; - return (h); -} -#endif - -/* Add the alias to the current alias list. */ - -void -mvs_add_alias (realname, aliasname, emitted) - const char *realname; - const char *aliasname; - int emitted; -{ - alias_node_t *ap; - - ap = (alias_node_t *) xmalloc (sizeof (alias_node_t)); - if (strlen (realname) > MAX_LONG_LABEL_SIZE) - { - warning ("real name is too long - alias ignored"); - return; - } - if (strlen (aliasname) > MAX_MVS_LABEL_SIZE) - { - warning ("alias name is too long - alias ignored"); - return; - } - - strcpy (ap->real_name, realname); - strcpy (ap->alias_name, aliasname); - ap->alias_emitted = emitted; - ap->alias_next = alias_anchor; - alias_anchor = ap; -} - -/* Check to see if the name needs aliasing. ie. the name is either: - 1. Longer than 8 characters - 2. Contains an underscore - 3. Is mixed case */ - -int -mvs_need_alias (realname) - const char *realname; -{ - int i, j = strlen (realname); - - if (mvs_function_check (realname)) - return 0; -#if 0 - if (!strcmp (realname, "gccmain")) - return 0; - if (!strcmp (realname, "main")) - return 0; -#endif - if (j > MAX_MVS_LABEL_SIZE) - return 1; - if (strchr (realname, '_') != 0) - return 1; - if (ISUPPER (realname[0])) - { - for (i = 1; i < j; i++) - { - if (ISLOWER (realname[i])) - return 1; - } - } - else - { - for (i = 1; i < j; i++) - { - if (ISUPPER (realname[i])) - return 1; - } - } - - return 0; -} - -/* Get the alias from the list. - If 1 is returned then it's in the alias list, 0 if it was not */ - -int -mvs_get_alias (realname, aliasname) - const char *realname; - char *aliasname; -{ -#ifdef LONGEXTERNAL - alias_node_t *ap; - - for (ap = alias_anchor; ap; ap = ap->alias_next) - { - if (!strcmp (ap->real_name, realname)) - { - strcpy (aliasname, ap->alias_name); - return 1; - } - } - if (mvs_need_alias (realname)) - { - char c1, c2; - - c1 = realname[0]; - c2 = realname[1]; - if (ISLOWER (c1)) c1 = TOUPPER (c1); - else if (c1 == '_') c1 = 'A'; - if (ISLOWER (c2)) c2 = TOUPPER (c2); - else if (c2 == '_' || c2 == '\0') c2 = '#'; - - sprintf (aliasname, "%c%c%06d", c1, c2, mvs_hash_alias (realname)); - mvs_add_alias (realname, aliasname, 0); - return 1; - } -#else - if (strlen (realname) > MAX_MVS_LABEL_SIZE) - { - strncpy (aliasname, realname, MAX_MVS_LABEL_SIZE); - aliasname[MAX_MVS_LABEL_SIZE] = '\0'; - return 1; - } -#endif - return 0; -} - -/* Check to see if the alias is in the list. - If 1 is returned then it's in the alias list, 2 it was emitted */ - -int -mvs_check_alias (realname, aliasname) - const char *realname; - char *aliasname; -{ -#ifdef LONGEXTERNAL - alias_node_t *ap; - - for (ap = alias_anchor; ap; ap = ap->alias_next) - { - if (!strcmp (ap->real_name, realname)) - { - int rc = (ap->alias_emitted == 1) ? 1 : 2; - strcpy (aliasname, ap->alias_name); - ap->alias_emitted = 1; - return rc; - } - } - if (mvs_need_alias (realname)) - { - char c1, c2; - - c1 = realname[0]; - c2 = realname[1]; - if (ISLOWER (c1)) c1 = TOUPPER (c1); - else if (c1 == '_') c1 = 'A'; - if (ISLOWER (c2)) c2 = TOUPPER (c2); - else if (c2 == '_' || c2 == '\0') c2 = '#'; - - sprintf (aliasname, "%c%c%06d", c1, c2, mvs_hash_alias (realname)); - mvs_add_alias (realname, aliasname, 0); - alias_anchor->alias_emitted = 1; - return 2; - } -#else - if (strlen (realname) > MAX_MVS_LABEL_SIZE) - { - strncpy (aliasname, realname, MAX_MVS_LABEL_SIZE); - aliasname[MAX_MVS_LABEL_SIZE] = '\0'; - return 1; - } -#endif - return 0; -} - -/* defines and functions specific to the HLASM assembler */ -#endif /* TARGET_HLASM */ -/* ===================================================== */ -/* ===================================================== */ -/* defines and functions specific to the gas assembler */ -#ifdef TARGET_ELF_ABI - -/* Check for C/370 runtime function, they don't use standard calling - conventions. True is returned if the function is in the table. - NAME is the name of the current function. */ -/* no special calling conventions (yet ??) */ - -int -mvs_function_check (name) - const char *name ATTRIBUTE_UNUSED; -{ - return 0; -} - -#endif /* TARGET_ELF_ABI */ -/* ===================================================== */ - - -/* Return 1 if OP is a valid S operand for an RS, SI or SS type instruction. - OP is the current operation. - MODE is the current operation mode. */ - -int -s_operand (op, mode) - register rtx op; - enum machine_mode mode; -{ - extern int volatile_ok; - register enum rtx_code code = GET_CODE (op); - - if (CONSTANT_ADDRESS_P (op)) - return 1; - if (mode == VOIDmode || GET_MODE (op) != mode) - return 0; - if (code == MEM) - { - register rtx x = XEXP (op, 0); - - if (!volatile_ok && op->volatil) - return 0; - if (REG_P (x) && REG_OK_FOR_BASE_P (x)) - return 1; - if (GET_CODE (x) == PLUS - && REG_P (XEXP (x, 0)) && REG_OK_FOR_BASE_P (XEXP (x, 0)) - && GET_CODE (XEXP (x, 1)) == CONST_INT - && (unsigned) INTVAL (XEXP (x, 1)) < 4096) - return 1; - } - return 0; -} - - -/* Return 1 if OP is a valid R or S operand for an RS, SI or SS type - instruction. - OP is the current operation. - MODE is the current operation mode. */ - -int -r_or_s_operand (op, mode) - register rtx op; - enum machine_mode mode; -{ - extern int volatile_ok; - register enum rtx_code code = GET_CODE (op); - - if (CONSTANT_ADDRESS_P (op)) - return 1; - if (mode == VOIDmode || GET_MODE (op) != mode) - return 0; - if (code == REG) - return 1; - else if (code == MEM) - { - register rtx x = XEXP (op, 0); - - if (!volatile_ok && op->volatil) - return 0; - if (REG_P (x) && REG_OK_FOR_BASE_P (x)) - return 1; - if (GET_CODE (x) == PLUS - && REG_P (XEXP (x, 0)) && REG_OK_FOR_BASE_P (XEXP (x, 0)) - && GET_CODE (XEXP (x, 1)) == CONST_INT - && (unsigned) INTVAL (XEXP (x, 1)) < 4096) - return 1; - } - return 0; -} - - -/* Some remarks about unsigned_jump_follows_p(): - gcc is built around the assumption that branches are signed - or unsigned, whereas the 370 doesn't care; its the compares that - are signed or unsigned. Thus, we need to somehow know if we - need to do a signed or an unsigned compare, and we do this by - looking ahead in the instruction sequence until we find a jump. - We then note whether this jump is signed or unsigned, and do the - compare appropriately. Note that we have to scan ahead indefinitley, - as the gcc optimizer may insert any number of instructions between - the compare and the jump. - - Note that using conditional branch expanders seems to be be a more - elegant/correct way of doing this. See, for instance, the Alpha - cmpdi and bgt patterns. Note also that for the i370, various - arithmetic insn's set the condition code as well. - - The unsigned_jump_follows_p() routine returns a 1 if the next jump - is unsigned. INSN is the current instruction. */ - -int -unsigned_jump_follows_p (insn) - register rtx insn; -{ - rtx orig_insn = insn; - while (1) - { - register rtx tmp_insn; - enum rtx_code coda; - - insn = NEXT_INSN (insn); - if (!insn) fatal_insn ("internal error--no jump follows compare:", orig_insn); - - if (GET_CODE (insn) != JUMP_INSN) continue; - - tmp_insn = XEXP (insn, 3); - if (GET_CODE (tmp_insn) != SET) continue; - - if (GET_CODE (XEXP (tmp_insn, 0)) != PC) continue; - - tmp_insn = XEXP (tmp_insn, 1); - if (GET_CODE (tmp_insn) != IF_THEN_ELSE) continue; - - /* if we got to here, this instruction is a jump. Is it signed? */ - tmp_insn = XEXP (tmp_insn, 0); - coda = GET_CODE (tmp_insn); - - return coda != GE && coda != GT && coda != LE && coda != LT; - } -} - -#ifdef TARGET_HLASM - -/* Target hook for assembling integer objects. This version handles all - objects when TARGET_HLASM is defined. */ - -static bool -i370_hlasm_assemble_integer (x, size, aligned_p) - rtx x; - unsigned int size; - int aligned_p; -{ - const char *int_format = NULL; - - if (aligned_p) - switch (size) - { - case 1: - int_format = "\tDC\tX'%02X'\n"; - break; - - case 2: - int_format = "\tDC\tX'%04X'\n"; - break; - - case 4: - if (GET_CODE (x) == CONST_INT) - { - fputs ("\tDC\tF'", asm_out_file); - output_addr_const (asm_out_file, x); - fputs ("'\n", asm_out_file); - } - else - { - fputs ("\tDC\tA(", asm_out_file); - output_addr_const (asm_out_file, x); - fputs (")\n", asm_out_file); - } - return true; - } - - if (int_format && GET_CODE (x) == CONST_INT) - { - fprintf (asm_out_file, int_format, INTVAL (x)); - return true; - } - return default_assemble_integer (x, size, aligned_p); -} - -/* Generate the assembly code for function entry. FILE is a stdio - stream to output the code to. SIZE is an int: how many units of - temporary storage to allocate. - - Refer to the array `regs_ever_live' to determine which registers to - save; `regs_ever_live[I]' is nonzero if register number I is ever - used in the function. This function is responsible for knowing - which registers should not be saved even if used. */ - -static void -i370_output_function_prologue (f, l) - FILE *f; - HOST_WIDE_INT l; -{ -#if MACROPROLOGUE == 1 - fprintf (f, "* Function %s prologue\n", mvs_function_name); - fprintf (f, "\tEDCPRLG USRDSAL=%d,BASEREG=%d\n", - STACK_POINTER_OFFSET + l - 120 + - current_function_outgoing_args_size, BASE_REGISTER); -#else /* MACROPROLOGUE != 1 */ - static int function_label_index = 1; - static int function_first = 0; - static int function_year, function_month, function_day; - static int function_hour, function_minute, function_second; -#if defined(LE370) - if (!function_first) - { - struct tm *function_time; - time_t lcltime; - time (&lcltime); - function_time = localtime (&lcltime); - function_year = function_time->tm_year + 1900; - function_month = function_time->tm_mon + 1; - function_day = function_time->tm_mday; - function_hour = function_time->tm_hour; - function_minute = function_time->tm_min; - function_second = function_time->tm_sec; - } - fprintf (f, "* Function %s prologue\n", mvs_function_name); - fprintf (f, "FDSE%03d\tDSECT\n", function_label_index); - fprintf (f, "\tDS\tD\n"); - fprintf (f, "\tDS\tCL(" HOST_WIDE_INT_PRINT_DEC ")\n", - STACK_POINTER_OFFSET + l - + current_function_outgoing_args_size); - fprintf (f, "\tORG\tFDSE%03d\n", function_label_index); - fprintf (f, "\tDS\tCL(120+8)\n"); - fprintf (f, "\tORG\n"); - fprintf (f, "\tDS\t0D\n"); - fprintf (f, "FDSL%03d\tEQU\t*-FDSE%03d-8\n", function_label_index, - function_label_index); - fprintf (f, "\tDS\t0H\n"); - assemble_name (f, mvs_function_name); - fprintf (f, "\tCSECT\n"); - fprintf (f, "\tUSING\t*,15\n"); - fprintf (f, "\tB\tFENT%03d\n", function_label_index); - fprintf (f, "\tDC\tAL1(FNAM%03d+4-*)\n", function_label_index); - fprintf (f, "\tDC\tX'CE',X'A0',AL1(16)\n"); - fprintf (f, "\tDC\tAL4(FPPA%03d)\n", function_label_index); - fprintf (f, "\tDC\tAL4(0)\n"); - fprintf (f, "\tDC\tAL4(FDSL%03d)\n", function_label_index); - fprintf (f, "FNAM%03d\tEQU\t*\n", function_label_index); - fprintf (f, "\tDC\tAL2(%d),C'%s'\n", strlen (mvs_function_name), - mvs_function_name); - fprintf (f, "FPPA%03d\tDS\t0F\n", function_label_index); - fprintf (f, "\tDC\tX'03',X'00',X'33',X'00'\n"); - fprintf (f, "\tDC\tV(CEESTART)\n"); - fprintf (f, "\tDC\tAL4(0)\n"); - fprintf (f, "\tDC\tAL4(FTIM%03d)\n", function_label_index); - fprintf (f, "FTIM%03d\tDS\t0F\n", function_label_index); - fprintf (f, "\tDC\tCL4'%d',CL4'%02d%02d',CL6'%02d%02d00'\n", - function_year, function_month, function_day, - function_hour, function_minute); - fprintf (f, "\tDC\tCL2'01',CL4'0100'\n"); - fprintf (f, "FENT%03d\tDS\t0H\n", function_label_index); - fprintf (f, "\tSTM\t14,12,12(13)\n"); - fprintf (f, "\tL\t2,76(,13)\n"); - fprintf (f, "\tL\t0,16(,15)\n"); - fprintf (f, "\tALR\t0,2\n"); - fprintf (f, "\tCL\t0,12(,12)\n"); - fprintf (f, "\tBNH\t*+10\n"); - fprintf (f, "\tL\t15,116(,12)\n"); - fprintf (f, "\tBALR\t14,15\n"); - fprintf (f, "\tL\t15,72(,13)\n"); - fprintf (f, "\tSTM\t15,0,72(2)\n"); - fprintf (f, "\tMVI\t0(2),X'10'\n"); - fprintf (f, "\tST\t2,8(,13)\n "); - fprintf (f, "\tST\t13,4(,2)\n "); - fprintf (f, "\tLR\t13,2\n"); - fprintf (f, "\tDROP\t15\n"); - fprintf (f, "\tBALR\t%d,0\n", BASE_REGISTER); - fprintf (f, "\tUSING\t*,%d\n", BASE_REGISTER); - function_first = 1; - function_label_index ++; -#else /* !LE370 */ - if (!function_first) - { - struct tm *function_time; - time_t lcltime; - time (&lcltime); - function_time = localtime (&lcltime); - function_year = function_time->tm_year + 1900; - function_month = function_time->tm_mon + 1; - function_day = function_time->tm_mday; - function_hour = function_time->tm_hour; - function_minute = function_time->tm_min; - function_second = function_time->tm_sec; - fprintf (f, "PPA2\tDS\t0F\n"); - fprintf (f, "\tDC\tX'03',X'00',X'33',X'00'\n"); - fprintf (f, "\tDC\tV(CEESTART),A(0)\n"); - fprintf (f, "\tDC\tA(CEETIMES)\n"); - fprintf (f, "CEETIMES\tDS\t0F\n"); - fprintf (f, "\tDC\tCL4'%d',CL4'%02d%02d',CL6'%02d%02d00'\n", - function_year, function_month, function_day, - function_hour, function_minute, function_second); - fprintf (f, "\tDC\tCL2'01',CL4'0100'\n"); - } - fprintf (f, "* Function %s prologue\n", mvs_function_name); - fprintf (f, "FDSD%03d\tDSECT\n", function_label_index); - fprintf (f, "\tDS\tD\n"); - fprintf (f, "\tDS\tCL(%d)\n", STACK_POINTER_OFFSET + l - + current_function_outgoing_args_size); - fprintf (f, "\tORG\tFDSD%03d\n", function_label_index); - fprintf (f, "\tDS\tCL(120+8)\n"); - fprintf (f, "\tORG\n"); - fprintf (f, "\tDS\t0D\n"); - fprintf (f, "FDSL%03d\tEQU\t*-FDSD%03d-8\n", function_label_index, - function_label_index); - fprintf (f, "\tDS\t0H\n"); - assemble_name (f, mvs_function_name); - fprintf (f, "\tCSECT\n"); - fprintf (f, "\tUSING\t*,15\n"); - fprintf (f, "\tB\tFPL%03d\n", function_label_index); - fprintf (f, "\tDC\tAL1(FPL%03d+4-*)\n", function_label_index + 1); - fprintf (f, "\tDC\tX'CE',X'A0',AL1(16)\n"); - fprintf (f, "\tDC\tAL4(PPA2)\n"); - fprintf (f, "\tDC\tAL4(0)\n"); - fprintf (f, "\tDC\tAL4(FDSL%03d)\n", function_label_index); - fprintf (f, "FPL%03d\tEQU\t*\n", function_label_index + 1); - fprintf (f, "\tDC\tAL2(%d),C'%s'\n", strlen (mvs_function_name), - mvs_function_name); - fprintf (f, "FPL%03d\tDS\t0H\n", function_label_index); - fprintf (f, "\tSTM\t14,12,12(13)\n"); - fprintf (f, "\tL\t2,76(,13)\n"); - fprintf (f, "\tL\t0,16(,15)\n"); - fprintf (f, "\tALR\t0,2\n"); - fprintf (f, "\tCL\t0,12(,12)\n"); - fprintf (f, "\tBNH\t*+10\n"); - fprintf (f, "\tL\t15,116(,12)\n"); - fprintf (f, "\tBALR\t14,15\n"); - fprintf (f, "\tL\t15,72(,13)\n"); - fprintf (f, "\tSTM\t15,0,72(2)\n"); - fprintf (f, "\tMVI\t0(2),X'10'\n"); - fprintf (f, "\tST\t2,8(,13)\n "); - fprintf (f, "\tST\t13,4(,2)\n "); - fprintf (f, "\tLR\t13,2\n"); - fprintf (f, "\tDROP\t15\n"); - fprintf (f, "\tBALR\t%d,0\n", BASE_REGISTER); - fprintf (f, "\tUSING\t*,%d\n", BASE_REGISTER); - function_first = 1; - function_label_index += 2; -#endif /* !LE370 */ -#endif /* MACROPROLOGUE */ - fprintf (f, "PG%d\tEQU\t*\n", mvs_page_num ); - fprintf (f, "\tLR\t11,1\n"); - fprintf (f, "\tL\t%d,=A(PGT%d)\n", PAGE_REGISTER, mvs_page_num); - fprintf (f, "* Function %s code\n", mvs_function_name); - - mvs_free_label_list (); - mvs_page_code = 6; - mvs_page_lit = 4; - mvs_check_page (f, 0, 0); - function_base_page = mvs_page_num; - - /* find all labels in this routine */ - i370_label_scan (); -} - -static void -i370_globalize_label (stream, name) - FILE *stream; - const char *name; -{ - char temp[MAX_MVS_LABEL_SIZE + 1]; - if (mvs_check_alias (name, temp) == 2) - fprintf (stream, "%s\tALIAS\tC'%s'\n", temp, name); - fputs ("\tENTRY\t", stream); - assemble_name (stream, name); - putc ('\n', stream); -} -#endif /* TARGET_HLASM */ - - -#ifdef TARGET_ELF_ABI -/* - The 370_function_prolog() routine generates the current ELF ABI ES/390 prolog. - It implements a stack that grows downward. - It performs the following steps: - -- saves the callers non-volatile registers on the callers stack. - -- subtracts stackframe size from the stack pointer. - -- stores backpointer to old caller stack. - - XXX hack alert -- if the global var int leaf_function is nonzero, - then this is a leaf, and it might be possible to optimize the prologue - into doing even less, e.g. not grabbing a new stackframe or maybe just a - partial stack frame. - - XXX hack alert -- the current stack frame is bloated into twice the - needed size by unused entries. These entries make it marginally - compatible with MVS/OE/USS C environment, but really they're not used - and could probably chopped out. Modifications to i370.md would be needed - also, to quite using addresses 136, 140, etc. - */ - -static void -i370_output_function_prologue (f, frame_size) - FILE *f; - HOST_WIDE_INT frame_size; -{ - static int function_label_index = 1; - static int function_first = 0; - int stackframe_size, aligned_size; - - fprintf (f, "# Function prologue\n"); - /* define the stack, put it into its own data segment - FDSE == Function Stack Entry - FDSL == Function Stack Length */ - stackframe_size = - STACK_POINTER_OFFSET + current_function_outgoing_args_size + frame_size; - aligned_size = (stackframe_size + 7) >> 3; - aligned_size <<= 3; - - fprintf (f, "# arg_size=0x%x frame_size=" HOST_WIDE_INT_PRINT_HEX - " aligned size=0x%x\n", - current_function_outgoing_args_size, frame_size, aligned_size); - - fprintf (f, "\t.using\t.,r15\n"); - - /* Branch to exectuable part of prologue. */ - fprintf (f, "\tB\t.LFENT%03d\n", function_label_index); - - /* write the length of the stackframe */ - fprintf (f, "\t.long\t%d\n", aligned_size); - - /* FENT == function prologue entry */ - fprintf (f, "\t.balign 2\n.LFENT%03d:\n", - function_label_index); - - /* store multiple registers 14,15,0,...12 at 12 bytes from sp */ - fprintf (f, "\tSTM\tr14,r12,12(sp)\n"); - - /* r3 == saved callee stack pointer */ - fprintf (f, "\tLR\tr3,sp\n"); - - /* 4(r15) == stackframe size */ - fprintf (f, "\tSL\tsp,4(,r15)\n"); - - /* r11 points to arg list in callers stackframe; was passed in r2 */ - fprintf (f, "\tLR\tr11,r2\n"); - - /* store callee stack pointer at 8(sp) */ - /* fprintf (f, "\tST\tsp,8(,r3)\n "); wasted cycles, no one uses this ... */ - - /* backchain -- store caller sp at 4(callee_sp) */ - fprintf (f, "\tST\tr3,4(,sp)\n "); - - fprintf (f, "\t.drop\tr15\n"); - /* Place contents of the PSW into r3 - that is, place the address of "." into r3 */ - fprintf (f, "\tBASR\tr%d,0\n", BASE_REGISTER); - fprintf (f, "\t.using\t.,r%d\n", BASE_REGISTER); - function_first = 1; - function_label_index ++; - - fprintf (f, ".LPG%d:\n", mvs_page_num ); - fprintf (f, "\tL\tr%d,=A(.LPGT%d)\n", PAGE_REGISTER, mvs_page_num); - fprintf (f, "# Function code\n"); - - mvs_free_label_list (); - mvs_page_code = 6; - mvs_page_lit = 4; - mvs_check_page (f, 0, 0); - function_base_page = mvs_page_num; - - /* find all labels in this routine */ - i370_label_scan (); -} -#endif /* TARGET_ELF_ABI */ - -/* This function generates the assembly code for function exit. - Args are as for output_function_prologue (). - - The function epilogue should not depend on the current stack - pointer! It should use the frame pointer only. This is mandatory - because of alloca; we also take advantage of it to omit stack - adjustments before returning. */ - -static void -i370_output_function_epilogue (file, l) - FILE *file; - HOST_WIDE_INT l ATTRIBUTE_UNUSED; -{ - int i; - - check_label_emit (); - mvs_check_page (file, 14, 0); - fprintf (file, "* Function %s epilogue\n", mvs_function_name); - mvs_page_num++; - -#if MACROEPILOGUE == 1 - fprintf (file, "\tEDCEPIL\n"); -#else /* MACROEPILOGUE != 1 */ - fprintf (file, "\tL\t13,4(,13)\n"); - fprintf (file, "\tL\t14,12(,13)\n"); - fprintf (file, "\tLM\t2,12,28(13)\n"); - fprintf (file, "\tBALR\t1,14\n"); - fprintf (file, "\tDC\tA("); - assemble_name (file, mvs_function_name); - fprintf (file, ")\n" ); -#endif /* MACROEPILOGUE */ - - fprintf (file, "* Function %s literal pool\n", mvs_function_name); - fprintf (file, "\tDS\t0F\n" ); - fprintf (file, "\tLTORG\n"); - fprintf (file, "* Function %s page table\n", mvs_function_name); - fprintf (file, "\tDS\t0F\n"); - fprintf (file, "PGT%d\tEQU\t*\n", function_base_page); - - mvs_free_label_list(); - for (i = function_base_page; i < mvs_page_num; i++) - fprintf (file, "\tDC\tA(PG%d)\n", i); -} - -static void -i370_file_start () -{ - fputs ("\tRMODE\tANY\n\tCSECT\n", asm_out_file); -} - -static void -i370_file_end () -{ - fputs ("\tEND\n", asm_out_file); -} - -static void -i370_internal_label (stream, prefix, labelno) - FILE *stream; - const char *prefix; - unsigned long labelno; -{ - if (!strcmp (prefix, "L")) - mvs_add_label(labelno); - - default_internal_label (stream, prefix, labelno); -} - -static bool -i370_rtx_costs (x, code, outer_code, total) - rtx x; - int code; - int outer_code ATTRIBUTE_UNUSED; - int *total; -{ - switch (code) - { - case CONST_INT: - if ((unsigned HOST_WIDE_INT) INTVAL (x) < 0xfff) - { - *total = 1; - return true; - } - /* FALLTHRU */ - - case CONST: - case LABEL_REF: - case SYMBOL_REF: - *total = 2; - return true; - - case CONST_DOUBLE: - *total = 4; - return true; - - default: - return false; - } -} diff --git a/gcc/config/i370/i370.h b/gcc/config/i370/i370.h deleted file mode 100644 index 8109ddedc2e..00000000000 --- a/gcc/config/i370/i370.h +++ /dev/null @@ -1,1862 +0,0 @@ -/* Definitions of target machine for GNU compiler. System/370 version. - Copyright (C) 1989, 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, - 2003 Free Software Foundation, Inc. - Contributed by Jan Stein (jan@cd.chalmers.se). - Modified for OS/390 LanguageEnvironment C by Dave Pitts (dpitts@cozx.com) - Hacked for Linux-ELF/390 by Linas Vepstas (linas@linas.org) - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GCC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -#ifndef GCC_I370_H -#define GCC_I370_H - -/* Target CPU builtins. */ -#define TARGET_CPU_CPP_BUILTINS() \ - do \ - { \ - builtin_define_std ("GCC"); \ - builtin_define_std ("gcc"); \ - builtin_assert ("machine=i370"); \ - builtin_assert ("cpu=i370"); \ - } \ - while (0) - -/* Run-time compilation parameters selecting different hardware subsets. */ - -extern int target_flags; - -/* The sizes of the code and literals on the current page. */ - -extern int mvs_page_code, mvs_page_lit; - -/* The current page number and the base page number for the function. */ - -extern int mvs_page_num, function_base_page; - -/* The name of the current function. */ - -extern char *mvs_function_name; - -/* The length of the function name malloc'd area. */ - -extern size_t mvs_function_name_length; - -/* Compile using char instructions (mvc, nc, oc, xc). On 4341 use this since - these are more than twice as fast as load-op-store. - On 3090 don't use this since load-op-store is much faster. */ - -#define TARGET_CHAR_INSTRUCTIONS (target_flags & 1) - -/* Default target switches */ - -#define TARGET_DEFAULT 1 - -/* Macro to define tables used to set the flags. This is a list in braces - of pairs in braces, each pair being { "NAME", VALUE } - where VALUE is the bits to set or minus the bits to clear. - An empty string NAME is used to identify the default VALUE. */ - -#define TARGET_SWITCHES \ -{ { "char-instructions", 1, N_("Generate char instructions")}, \ - { "no-char-instructions", -1, N_("Do not generate char instructions")}, \ - { "", TARGET_DEFAULT, 0} } - -#define OVERRIDE_OPTIONS override_options () - -/* To use IBM supplied macro function prologue and epilogue, define the - following to 1. Should only be needed if IBM changes the definition - of their prologue and epilogue. */ - -#define MACROPROLOGUE 0 -#define MACROEPILOGUE 0 - -/* Target machine storage layout */ - -/* Define this if most significant bit is lowest numbered in instructions - that operate on numbered bit-fields. */ - -#define BITS_BIG_ENDIAN 1 - -/* Define this if most significant byte of a word is the lowest numbered. */ - -#define BYTES_BIG_ENDIAN 1 - -/* Define this if MS word of a multiword is the lowest numbered. */ - -#define WORDS_BIG_ENDIAN 1 - -/* Width of a word, in units (bytes). */ - -#define UNITS_PER_WORD 4 - -/* Allocation boundary (in *bits*) for storing pointers in memory. */ - -#define POINTER_BOUNDARY 32 - -/* Allocation boundary (in *bits*) for storing arguments in argument list. */ - -#define PARM_BOUNDARY 32 - -/* Boundary (in *bits*) on which stack pointer should be aligned. */ - -#define STACK_BOUNDARY 32 - -/* Allocation boundary (in *bits*) for the code of a function. */ - -#define FUNCTION_BOUNDARY 32 - -/* There is no point aligning anything to a rounder boundary than this. */ - -#define BIGGEST_ALIGNMENT 64 - -/* Alignment of field after `int : 0' in a structure. */ - -#define EMPTY_FIELD_BOUNDARY 32 - -/* Define this if move instructions will actually fail to work when given - unaligned data. */ - -#define STRICT_ALIGNMENT 0 - -/* Define target floating point format. */ - -#define TARGET_FLOAT_FORMAT IBM_FLOAT_FORMAT - -#ifdef TARGET_HLASM -/* HLASM requires #pragma map. */ -#define REGISTER_TARGET_PRAGMAS() c_register_pragma (0, "map", i370_pr_map) -#endif /* TARGET_HLASM */ - -/* Define maximum length of page minus page escape overhead. */ - -#define MAX_MVS_PAGE_LENGTH 4080 - -/* Define special register allocation order desired. - Don't fiddle with this. I did, and I got all sorts of register - spill errors when compiling even relatively simple programs... - I have no clue why ... - E.g. this one is bad: - { 0, 1, 2, 9, 8, 7, 6, 5, 10, 15, 14, 12, 3, 4, 16, 17, 18, 19, 11, 13 } - */ - -#define REG_ALLOC_ORDER \ -{ 0, 1, 2, 3, 14, 15, 12, 10, 9, 8, 7, 6, 5, 4, 16, 17, 18, 19, 11, 13 } - -/* Standard register usage. */ - -/* Number of actual hardware registers. The hardware registers are - assigned numbers for the compiler from 0 to just below - FIRST_PSEUDO_REGISTER. - All registers that the compiler knows about must be given numbers, - even those that are not normally considered general registers. - For the 370, we give the data registers numbers 0-15, - and the floating point registers numbers 16-19. */ - -#define FIRST_PSEUDO_REGISTER 20 - -/* Define base and page registers. */ - -#define BASE_REGISTER 3 -#define PAGE_REGISTER 4 - -#ifdef TARGET_HLASM -/* 1 for registers that have pervasive standard uses and are not available - for the register allocator. These are registers that must have fixed, - valid values stored in them for the entire length of the subroutine call, - and must not in any way be moved around, jiggered with, etc. That is, - they must never be clobbered, and, if clobbered, the register allocator - will never restore them back. - - We use five registers in this special way: - -- R3 which is used as the base register - -- R4 the page origin table pointer used to load R3, - -- R11 the arg pointer. - -- R12 the TCA pointer - -- R13 the stack (DSA) pointer - - A fifth register is also exceptional: R14 is used in many branch - instructions to hold the target of the branch. Technically, this - does not qualify R14 as a register with a long-term meaning; it should - be enough, theoretically, to note that these instructions clobber - R14, and let the compiler deal with that. In practice, however, - the "clobber" directive acts as a barrier to optimization, and the - optimizer appears to be unable to perform optimizations around branches. - Thus, a much better strategy appears to give R14 a pervasive use; - this eliminates it from the register pool witout hurting optimization. - - There are other registers which have special meanings, but its OK - for them to get clobbered, since other allocator config below will - make sure that they always have the right value. These are for - example: - -- R1 the returned structure pointer. - -- R10 the static chain reg. - -- R15 holds the value a subroutine returns. - - Notice that it is *almost* safe to mark R11 as available to the allocator. - By marking it as a call_used_register, in most cases, the compiler - can handle it being clobbered. However, there are a few rare - circumstances where the register allocator will allocate r11 and - also try to use it as the arg pointer ... thus it must be marked fixed. - I think this is a bug, but I can't track it down... - */ - -#define FIXED_REGISTERS \ -{ 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0 } -/*0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19*/ - -/* 1 for registers not available across function calls. These must include - the FIXED_REGISTERS and also any registers that can be used without being - saved. - The latter must include the registers where values are returned - and the register where structure-value addresses are passed. - NOTE: all floating registers are undefined across calls. -*/ - -#define CALL_USED_REGISTERS \ -{ 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1 } -/*0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19*/ - -/* Return number of consecutive hard regs needed starting at reg REGNO - to hold something of mode MODE. - This is ordinarily the length in words of a value of mode MODE - but can be less for certain modes in special long registers. - Note that DCmode (complex double) needs two regs. -*/ -#endif /* TARGET_HLASM */ - -/* ================= */ -#ifdef TARGET_ELF_ABI -/* The Linux/ELF ABI uses the same register layout as the - * the MVS/OE version, with the following exceptions: - * -- r12 (rtca) is not used. - */ - -#define FIXED_REGISTERS \ -{ 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0 } -/*0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19*/ - -#define CALL_USED_REGISTERS \ -{ 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1 } -/*0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19*/ - -#endif /* TARGET_ELF_ABI */ -/* ================= */ - - -#define HARD_REGNO_NREGS(REGNO, MODE) \ - ((REGNO) > 15 ? \ - ((GET_MODE_SIZE (MODE) + 2*UNITS_PER_WORD - 1) / (2*UNITS_PER_WORD)) : \ - (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. - On the 370, the cpu registers can hold QI, HI, SI, SF and DF. The - even registers can hold DI. The floating point registers can hold - either SF, DF, SC or DC. */ - -#define HARD_REGNO_MODE_OK(REGNO, MODE) \ - ((REGNO) < 16 ? (((REGNO) & 1) == 0 || \ - (((MODE) != DImode) && ((MODE) != DFmode))) \ - : ((MODE) == SFmode || (MODE) == DFmode) || \ - (MODE) == SCmode || (MODE) == DCmode) - -/* Value is 1 if it is a good idea to tie two pseudo registers when one has - mode MODE1 and one has mode MODE2. - If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2, - for any hard reg, then this must be 0 for correct output. */ - -#define MODES_TIEABLE_P(MODE1, MODE2) \ - (((MODE1) == SFmode || (MODE1) == DFmode) \ - == ((MODE2) == SFmode || (MODE2) == DFmode)) - -/* Specify the registers used for certain standard purposes. - The values of these macros are register numbers. */ - -/* 370 PC isn't overloaded on a register. */ - -/* #define PC_REGNUM */ - -/* Register to use for pushing function arguments. */ - -#define STACK_POINTER_REGNUM 13 - -/* Base register for access to local variables of the function. */ - -#define FRAME_POINTER_REGNUM 13 - -/* Value should be nonzero if functions must have frame pointers. - Zero means the frame pointer need not be set up (and parms may be - accessed via the stack pointer) in functions that seem suitable. - This is computed in `reload', in reload1.c. */ - -#define FRAME_POINTER_REQUIRED 1 - -/* Base register for access to arguments of the function. */ - -#define ARG_POINTER_REGNUM 11 - -/* R10 is register in which static-chain is passed to a function. - Static-chaining is done when a nested function references as a global - a stack variable of its parent: e.g. - int parent_func (int arg) { - int x; // x is in parents stack - void child_func (void) { x++: } // child references x as global var - ... - } - */ - -#define STATIC_CHAIN_REGNUM 10 - -/* R1 is register in which address to store a structure value is passed to - a function. This is used only when returning 64-bit long-long in a 32-bit arch - and when calling functions that return structs by value. e.g. - typedef struct A_s { int a,b,c; } A_t; - A_t fun_returns_value (void) { - A_t a; a.a=1; a.b=2 a.c=3; - return a; - } - In the above, the storage for the return value is in the callers stack, and - the R1 points at that mem location. - */ - -#define STRUCT_VALUE_REGNUM 1 - -/* Define the classes of registers for register constraints in the - machine description. Also define ranges of constants. - - One of the classes must always be named ALL_REGS and include all hard regs. - If there is more than one class, another class must be named NO_REGS - and contain no registers. - - The name GENERAL_REGS must be the name of a class (or an alias for - another name such as ALL_REGS). This is the class of registers - that is allowed by "g" or "r" in a register constraint. - Also, registers outside this class are allocated only when - instructions express preferences for them. - - The classes must be numbered in nondecreasing order; that is, - a larger-numbered class must never be contained completely - in a smaller-numbered class. - - For any two classes, it is very desirable that there be another - class that represents their union. */ - -enum reg_class - { - NO_REGS, ADDR_REGS, DATA_REGS, - FP_REGS, ALL_REGS, LIM_REG_CLASSES - }; - -#define GENERAL_REGS DATA_REGS -#define N_REG_CLASSES (int) LIM_REG_CLASSES - -/* Give names of register classes as strings for dump file. */ - -#define REG_CLASS_NAMES \ -{ "NO_REGS", "ADDR_REGS", "DATA_REGS", "FP_REGS", "ALL_REGS" } - -/* Define which registers fit in which classes. This is an initializer for - a vector of HARD_REG_SET of length N_REG_CLASSES. */ - -#define REG_CLASS_CONTENTS {{0}, {0x0fffe}, {0x0ffff}, {0xf0000}, {0xfffff}} - -/* The same information, inverted: - Return the class number of the smallest class containing - reg number REGNO. This could be a conditional expression - or could index an array. */ - -#define REGNO_REG_CLASS(REGNO) \ - ((REGNO) >= 16 ? FP_REGS : (REGNO) != 0 ? ADDR_REGS : DATA_REGS) - -/* The class value for index registers, and the one for base regs. */ - -#define INDEX_REG_CLASS ADDR_REGS -#define BASE_REG_CLASS ADDR_REGS - -/* Get reg_class from a letter such as appears in the machine description. */ - -#define REG_CLASS_FROM_LETTER(C) \ - ((C) == 'a' ? ADDR_REGS : \ - ((C) == 'd' ? DATA_REGS : \ - ((C) == 'f' ? FP_REGS : NO_REGS))) - -/* The letters I, J, K, L and M in a register constraint string can be used - to stand for particular ranges of immediate operands. - This macro defines what the ranges are. - C is the letter, and VALUE is a constant value. - Return 1 if VALUE is in the range specified by C. */ - -#define CONST_OK_FOR_LETTER_P(VALUE, C) \ - ((C) == 'I' ? (unsigned) (VALUE) < 256 : \ - (C) == 'J' ? (unsigned) (VALUE) < 4096 : \ - (C) == 'K' ? (VALUE) >= -32768 && (VALUE) < 32768 : 0) - -/* Similar, but for floating constants, and defining letters G and H. - Here VALUE is the CONST_DOUBLE rtx itself. */ - -#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) 1 - -/* see recog.c for details */ -#define EXTRA_CONSTRAINT(OP,C) \ - ((C) == 'R' ? r_or_s_operand (OP, GET_MODE(OP)) : \ - (C) == 'S' ? s_operand (OP, GET_MODE(OP)) : 0) \ - -/* Given an rtx X being reloaded into a reg required to be in class CLASS, - return the class of reg to actually use. In general this is just CLASS; - but on some machines in some cases it is preferable to use a more - restrictive class. - - XXX We reload CONST_INT's into ADDR not DATA regs because on certain - rare occasions when lots of egisters are spilled, reload() will try - to put a const int into r0 and then use r0 as an index register. -*/ - -#define PREFERRED_RELOAD_CLASS(X, CLASS) \ - (GET_CODE(X) == CONST_DOUBLE ? FP_REGS : \ - GET_CODE(X) == CONST_INT ? (reload_in_progress ? ADDR_REGS : DATA_REGS) : \ - GET_CODE(X) == LABEL_REF || \ - GET_CODE(X) == SYMBOL_REF || \ - GET_CODE(X) == CONST ? ADDR_REGS : (CLASS)) - -/* Return the maximum number of consecutive registers needed to represent - mode MODE in a register of class CLASS. - Note that DCmode (complex double) needs two regs. -*/ - -#define CLASS_MAX_NREGS(CLASS, MODE) \ - ((CLASS) == FP_REGS ? \ - ((GET_MODE_SIZE (MODE) + 2*UNITS_PER_WORD - 1) / (2*UNITS_PER_WORD)) : \ - (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) - -/* Stack layout; function entry, exit and calling. */ - -/* Define this if pushing a word on the stack makes the stack pointer a - smaller address. */ -/* ------------------------------------------------------------------- */ - -/* ================= */ -#ifdef TARGET_HLASM -/* #define STACK_GROWS_DOWNWARD */ - -/* Define this if the nominal address of the stack frame is at the - high-address end of the local variables; that is, each additional local - variable allocated goes at a more negative offset in the frame. */ - -/* #define FRAME_GROWS_DOWNWARD */ - -/* Offset within stack frame to start allocating local variables at. - If FRAME_GROWS_DOWNWARD, this is the offset to the END of the - first local allocated. Otherwise, it is the offset to the BEGINNING - of the first local allocated. */ - -#define STARTING_FRAME_OFFSET \ - (STACK_POINTER_OFFSET + current_function_outgoing_args_size) - -#define INITIAL_FRAME_POINTER_OFFSET(DEPTH) (DEPTH) = STARTING_FRAME_OFFSET - -/* If we generate an insn to push BYTES bytes, this says how many the stack - pointer really advances by. On the 370, we have no push instruction. */ - -#endif /* TARGET_HLASM */ - -/* ================= */ -#ifdef TARGET_ELF_ABI - -/* With ELF/Linux, stack is placed at large virtual addrs and grows down. - But we want the compiler to generate posistive displacements from the - stack pointer, and so we make the frame lie above the stack. */ - -#define STACK_GROWS_DOWNWARD -/* #define FRAME_GROWS_DOWNWARD */ - -/* Offset within stack frame to start allocating local variables at. - This is the offset to the BEGINNING of the first local allocated. */ - -#define STARTING_FRAME_OFFSET \ - (STACK_POINTER_OFFSET + current_function_outgoing_args_size) - -#define INITIAL_FRAME_POINTER_OFFSET(DEPTH) (DEPTH) = STARTING_FRAME_OFFSET - -#endif /* TARGET_ELF_ABI */ -/* ================= */ - -/* #define PUSH_ROUNDING(BYTES) */ - -/* Accumulate the outgoing argument count so we can request the right - DSA size and determine stack offset. */ - -#define ACCUMULATE_OUTGOING_ARGS 1 - -/* Define offset from stack pointer, to location where a parm can be - pushed. */ - -#define STACK_POINTER_OFFSET 148 - -/* Offset of first parameter from the argument pointer register value. */ - -#define FIRST_PARM_OFFSET(FNDECL) 0 - -/* 1 if N is a possible register number for function argument passing. - On the 370, no registers are used in this way. */ - -#define FUNCTION_ARG_REGNO_P(N) 0 - -/* Define a data type for recording info about an argument list during - the scan of that argument list. This data type should hold all - necessary information about the function itself and about the args - processed so far, enough to enable macros such as FUNCTION_ARG to - determine where the next arg should go. */ - -#define CUMULATIVE_ARGS int - -/* Initialize a variable CUM of type CUMULATIVE_ARGS for a call to - a function whose data type is FNTYPE. - For a library call, FNTYPE is 0. */ - -#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT) ((CUM) = 0) - -/* Update the data in CUM to advance over an argument of mode MODE and - data type TYPE. (TYPE is null for libcalls where that information - may not be available.) */ - -#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ - ((CUM) += ((MODE) == DFmode || (MODE) == SFmode \ - ? 256 \ - : (MODE) != BLKmode \ - ? (GET_MODE_SIZE (MODE) + 3) / 4 \ - : (int_size_in_bytes (TYPE) + 3) / 4)) - -/* Define where to put the arguments to a function. Value is zero to push - the argument on the stack, or a hard register in which to store the - argument. */ - -#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) 0 - -/* For an arg passed partly in registers and partly in memory, this is the - number of registers used. For args passed entirely in registers or - entirely in memory, zero. */ - -#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) 0 - -/* Define if returning from a function call automatically pops the - arguments described by the number-of-args field in the call. */ - -#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) 0 - -/* The FUNCTION_VALUE macro defines how to find the value returned by a - function. VALTYPE is the data type of the value (as a tree). - If the precise function being called is known, FUNC is its FUNCTION_DECL; - otherwise, FUNC is NULL. - - On the 370 the return value is in R15 or R16. However, - DImode (64-bit ints) scalars need to get returned on the stack, - with r15 pointing to the location. To accomplish this, we define - the RETURN_IN_MEMORY macro to be true for both blockmode (structures) - and the DImode scalars. - */ - -#define RET_REG(MODE) \ - (((MODE) == DCmode || (MODE) == SCmode \ - || (MODE) == DFmode || (MODE) == SFmode) ? 16 : 15) - -#define FUNCTION_VALUE(VALTYPE, FUNC) \ - gen_rtx_REG (TYPE_MODE (VALTYPE), RET_REG (TYPE_MODE (VALTYPE))) - -#define RETURN_IN_MEMORY(VALTYPE) \ - ((DImode == TYPE_MODE (VALTYPE)) || (BLKmode == TYPE_MODE (VALTYPE))) - -/* Define how to find the value returned by a library function assuming - the value has mode MODE. */ - -#define LIBCALL_VALUE(MODE) gen_rtx_REG (MODE, RET_REG (MODE)) - -/* 1 if N is a possible register number for a function value. - On the 370 under C/370, R15 and R16 are thus used. */ - -#define FUNCTION_VALUE_REGNO_P(N) ((N) == 15 || (N) == 16) - -/* This macro definition sets up a default value for `main' to return. */ - -#define DEFAULT_MAIN_RETURN c_expand_return (integer_zero_node) - - -/* Output assembler code for a block containing the constant parts of a - trampoline, leaving space for the variable parts. - - On the 370, the trampoline contains these instructions: - - BALR 14,0 - USING *,14 - L STATIC_CHAIN_REGISTER,X - L 15,Y - BR 15 - X DS 0F - Y DS 0F */ -/* - I am confused as to why this emitting raw binary, instead of instructions ... - see for example, rs6000/rs000.c for an example of a different way to - do this ... especially since BASR should probably be substituted for BALR. - */ - -#define TRAMPOLINE_TEMPLATE(FILE) \ -{ \ - assemble_aligned_integer (2, GEN_INT (0x05E0)); \ - assemble_aligned_integer (2, GEN_INT (0x5800 | STATIC_CHAIN_REGNUM << 4)); \ - assemble_aligned_integer (2, GEN_INT (0xE00A)); \ - assemble_aligned_integer (2, GEN_INT (0x58F0)); \ - assemble_aligned_integer (2, GEN_INT (0xE00E)); \ - assemble_aligned_integer (2, GEN_INT (0x07FF)); \ - assemble_aligned_integer (2, const0_rtx); \ - assemble_aligned_integer (2, const0_rtx); \ - assemble_aligned_integer (2, const0_rtx); \ - assemble_aligned_integer (2, const0_rtx); \ -} - -/* Length in units of the trampoline for entering a nested function. */ - -#define TRAMPOLINE_SIZE 20 - -/* Emit RTL insns to initialize the variable parts of a trampoline. */ - -#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \ -{ \ - emit_move_insn (gen_rtx_MEM (SImode, plus_constant (TRAMP, 12)), CXT); \ - emit_move_insn (gen_rtx_MEM (SImode, plus_constant (TRAMP, 16)), FNADDR); \ -} - -/* Define EXIT_IGNORE_STACK if, when returning from a function, the stack - pointer does not matter (provided there is a frame pointer). */ - -#define EXIT_IGNORE_STACK 1 - -/* Addressing modes, and classification of registers for them. */ - -/* These assume that REGNO is a hard or pseudo reg number. They give - nonzero only if REGNO is a hard reg of the suitable class or a pseudo - reg currently allocated to a suitable hard reg. - These definitions are NOT overridden anywhere. */ - -#define REGNO_OK_FOR_INDEX_P(REGNO) \ - (((REGNO) > 0 && (REGNO) < 16) \ - || (reg_renumber[REGNO] > 0 && reg_renumber[REGNO] < 16)) - -#define REGNO_OK_FOR_BASE_P(REGNO) REGNO_OK_FOR_INDEX_P(REGNO) - -#define REGNO_OK_FOR_DATA_P(REGNO) \ - ((REGNO) < 16 || (unsigned) reg_renumber[REGNO] < 16) - -#define REGNO_OK_FOR_FP_P(REGNO) \ - ((unsigned) ((REGNO) - 16) < 4 || (unsigned) (reg_renumber[REGNO] - 16) < 4) - -/* Now macros that check whether X is a register and also, - strictly, whether it is in a specified class. */ - -/* 1 if X is a data register. */ - -#define DATA_REG_P(X) (REG_P (X) && REGNO_OK_FOR_DATA_P (REGNO (X))) - -/* 1 if X is an fp register. */ - -#define FP_REG_P(X) (REG_P (X) && REGNO_OK_FOR_FP_P (REGNO (X))) - -/* 1 if X is an address register. */ - -#define ADDRESS_REG_P(X) (REG_P (X) && REGNO_OK_FOR_BASE_P (REGNO (X))) - -/* Maximum number of registers that can appear in a valid memory address. */ - -#define MAX_REGS_PER_ADDRESS 2 - -/* Recognize any constant value that is a valid address. */ - -#define CONSTANT_ADDRESS_P(X) \ - (GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \ - || GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST_DOUBLE \ - || (GET_CODE (X) == CONST \ - && GET_CODE (XEXP (XEXP (X, 0), 0)) == LABEL_REF) \ - || (GET_CODE (X) == CONST \ - && GET_CODE (XEXP (XEXP (X, 0), 0)) == SYMBOL_REF \ - && !SYMBOL_REF_EXTERNAL_P (XEXP (XEXP (X, 0), 0)))) - -/* Nonzero if the constant value X is a legitimate general operand. - It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. */ - -#define LEGITIMATE_CONSTANT_P(X) 1 - -/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx and check - its validity for a certain class. We have two alternate definitions - for each of them. The usual definition accepts all pseudo regs; the - other rejects them all. The symbol REG_OK_STRICT causes the latter - definition to be used. - - Most source files want to accept pseudo regs in the hope that they will - get allocated to the class that the insn wants them to be in. - Some source files that are used after register allocation - need to be strict. */ - -#ifndef REG_OK_STRICT - -/* 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) > 0 && REGNO(X) < 16) || REGNO(X) >= 20) - -/* Nonzero if X is a hard reg that can be used as a base reg or if it is - a pseudo reg. */ - -#define REG_OK_FOR_BASE_P(X) REG_OK_FOR_INDEX_P(X) - -#else /* REG_OK_STRICT */ - -/* Nonzero if X is a hard reg that can be used as an index. */ - -#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P(REGNO(X)) - -/* Nonzero if X is a hard reg that can be used as a base reg. */ - -#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P(REGNO(X)) - -#endif /* REG_OK_STRICT */ - -/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression that is a - valid memory address for an instruction. - The MODE argument is the machine mode for the MEM expression - that wants to use this address. - - The other macros defined here are used only in GO_IF_LEGITIMATE_ADDRESS, - except for CONSTANT_ADDRESS_P which is actually machine-independent. -*/ - -#define COUNT_REGS(X, REGS, FAIL) \ - if (REG_P (X)) { \ - if (REG_OK_FOR_BASE_P (X)) REGS += 1; \ - else goto FAIL; \ - } \ - else if (GET_CODE (X) != CONST_INT || (unsigned) INTVAL (X) >= 4096) \ - goto FAIL; - -#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ -{ \ - if (REG_P (X) && REG_OK_FOR_BASE_P (X)) \ - goto ADDR; \ - if (GET_CODE (X) == PLUS) \ - { \ - int regs = 0; \ - rtx x0 = XEXP (X, 0); \ - rtx x1 = XEXP (X, 1); \ - if (GET_CODE (x0) == PLUS) \ - { \ - COUNT_REGS (XEXP (x0, 0), regs, FAIL); \ - COUNT_REGS (XEXP (x0, 1), regs, FAIL); \ - COUNT_REGS (x1, regs, FAIL); \ - if (regs == 2) \ - goto ADDR; \ - } \ - else if (GET_CODE (x1) == PLUS) \ - { \ - COUNT_REGS (x0, regs, FAIL); \ - COUNT_REGS (XEXP (x1, 0), regs, FAIL); \ - COUNT_REGS (XEXP (x1, 1), regs, FAIL); \ - if (regs == 2) \ - goto ADDR; \ - } \ - else \ - { \ - COUNT_REGS (x0, regs, FAIL); \ - COUNT_REGS (x1, regs, FAIL); \ - if (regs != 0) \ - goto ADDR; \ - } \ - } \ - FAIL: ; \ -} - -/* The 370 has no mode dependent addresses. */ - -#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL) - -/* Macro: LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) - Try machine-dependent ways of modifying an illegitimate address - to be legitimate. If we find one, return the new, valid address. - This macro is used in only one place: `memory_address' in explow.c. - - Several comments: - (1) It's not obvious that this macro results in better code - than its omission does. For historical reasons we leave it in. - - (2) This macro may be (???) implicated in the accidental promotion - or RS operand to RX operands, which bombs out any RS, SI, SS - instruction that was expecting a simple address. Note that - this occurs fairly rarely ... - - (3) There is a bug somewhere that causes either r4 to be spilled, - or causes r0 to be used as a base register. Changeing the macro - below will make the bug move around, but will not make it go away - ... Note that this is a rare bug ... - - */ - -#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \ -{ \ - if (GET_CODE (X) == PLUS && CONSTANT_ADDRESS_P (XEXP (X, 1))) \ - (X) = gen_rtx_PLUS (SImode, XEXP (X, 0), \ - copy_to_mode_reg (SImode, XEXP (X, 1))); \ - if (GET_CODE (X) == PLUS && CONSTANT_ADDRESS_P (XEXP (X, 0))) \ - (X) = gen_rtx_PLUS (SImode, XEXP (X, 1), \ - copy_to_mode_reg (SImode, XEXP (X, 0))); \ - if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 0)) == MULT) \ - (X) = gen_rtx_PLUS (SImode, XEXP (X, 1), \ - force_operand (XEXP (X, 0), 0)); \ - if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 1)) == MULT) \ - (X) = gen_rtx_PLUS (SImode, XEXP (X, 0), \ - force_operand (XEXP (X, 1), 0)); \ - if (memory_address_p (MODE, X)) \ - goto WIN; \ -} - -/* Specify the machine mode that this machine uses for the index in the - tablejump instruction. */ - -#define CASE_VECTOR_MODE SImode - -/* Define this if the tablejump instruction expects the table to contain - offsets from the address of the table. - Do not define this if the table should contain absolute addresses. */ - -/* #define CASE_VECTOR_PC_RELATIVE */ - -/* Define this if fixuns_trunc is the same as fix_trunc. */ - -#define FIXUNS_TRUNC_LIKE_FIX_TRUNC - -/* We use "unsigned char" as default. */ - -#define DEFAULT_SIGNED_CHAR 0 - -/* Max number of bytes we can move from memory to memory in one reasonably - fast instruction. */ - -#define MOVE_MAX 256 - -/* Nonzero if access to memory by bytes is slow and undesirable. */ - -#define SLOW_BYTE_ACCESS 1 - -/* Define if shifts truncate the shift count which implies one can omit - a sign-extension or zero-extension of a shift count. */ - -/* #define SHIFT_COUNT_TRUNCATED */ - -/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits - is done just by pretending it is already truncated. */ - -#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) (OUTPREC != 16) - -/* ??? Investigate defining STORE_FLAG_VALUE to (-1). */ - -/* When a prototype says `char' or `short', really pass an `int'. */ - -#define PROMOTE_PROTOTYPES 1 - -/* Don't perform CSE on function addresses. */ - -#define NO_FUNCTION_CSE - -/* Specify the machine mode that pointers have. - After generation of rtl, the compiler makes no further distinction - between pointers and any other objects of this machine mode. */ - -#define Pmode SImode - -/* A function address in a call instruction is a byte address (for - indexing purposes) so give the MEM rtx a byte's mode. */ - -#define FUNCTION_MODE QImode - -/* A C statement (sans semicolon) to update the integer variable COST - based on the relationship between INSN that is dependent on - DEP_INSN through the dependence LINK. The default is to make no - adjustment to COST. This can be used for example to specify to - the scheduler that an output- or anti-dependence does not incur - the same cost as a data-dependence. - - We will want to use this to indicate that there is a cost associated - with the loading, followed by use of base registers ... -#define ADJUST_COST (INSN, LINK, DEP_INSN, COST) - */ - -/* Tell final.c how to eliminate redundant test instructions. */ - -/* Here we define machine-dependent flags and fields in cc_status - (see `conditions.h'). */ - -/* Store in cc_status the expressions that the condition codes will - describe after execution of an instruction whose pattern is EXP. - Do not alter them if the instruction would not alter the cc's. - - On the 370, load insns do not alter the cc's. However, in some - cases these instructions can make it possibly invalid to use the - saved cc's. In those cases we clear out some or all of the saved - cc's so they won't be used. - - Note that only some arith instructions set the CC. These include - add, subtract, complement, various shifts. Note that multiply - and divide do *not* set set the CC. Therefore, in the code below, - don't set the status for MUL, DIV, etc. - - Note that the bitwise ops set the condition code, but not in a - way that we can make use of it. So we treat these as clobbering, - rather than setting the CC. These are clobbered in the individual - instruction patterns that use them. Use CC_STATUS_INIT to clobber. -*/ - -#define NOTICE_UPDATE_CC(EXP, INSN) \ -{ \ - rtx exp = (EXP); \ - if (GET_CODE (exp) == PARALLEL) /* Check this */ \ - exp = XVECEXP (exp, 0, 0); \ - if (GET_CODE (exp) != SET) \ - CC_STATUS_INIT; \ - else \ - { \ - if (XEXP (exp, 0) == cc0_rtx) \ - { \ - cc_status.value1 = XEXP (exp, 0); \ - cc_status.value2 = XEXP (exp, 1); \ - cc_status.flags = 0; \ - } \ - else \ - { \ - if (cc_status.value1 \ - && reg_mentioned_p (XEXP (exp, 0), cc_status.value1)) \ - cc_status.value1 = 0; \ - if (cc_status.value2 \ - && reg_mentioned_p (XEXP (exp, 0), cc_status.value2)) \ - cc_status.value2 = 0; \ - switch (GET_CODE (XEXP (exp, 1))) \ - { \ - case PLUS: case MINUS: case NEG: \ - case NOT: case ABS: \ - CC_STATUS_SET (XEXP (exp, 0), XEXP (exp, 1)); \ - \ - /* mult and div don't set any cc codes !! */ \ - case MULT: /* case UMULT: */ case DIV: case UDIV: \ - /* and, or and xor set the cc's the wrong way !! */ \ - case AND: case IOR: case XOR: \ - /* some shifts set the CC some don't. */ \ - case ASHIFT: case ASHIFTRT: \ - do {} while (0); \ - default: \ - break; \ - } \ - } \ - } \ -} - - -#define CC_STATUS_SET(V1, V2) \ -{ \ - cc_status.flags = 0; \ - cc_status.value1 = (V1); \ - cc_status.value2 = (V2); \ - if (cc_status.value1 \ - && reg_mentioned_p (cc_status.value1, cc_status.value2)) \ - cc_status.value2 = 0; \ -} - -#define OUTPUT_JUMP(NORMAL, FLOAT, NO_OV) \ -{ if (cc_status.flags & CC_NO_OVERFLOW) return NO_OV; return NORMAL; } - -/* ------------------------------------------ */ -/* Control the assembler format that we output. */ - -/* Define standard character escape sequences for non-ASCII targets - only. */ - -#ifdef TARGET_EBCDIC -#define TARGET_ESC 39 -#define TARGET_BELL 47 -#define TARGET_BS 22 -#define TARGET_TAB 5 -#define TARGET_NEWLINE 21 -#define TARGET_VT 11 -#define TARGET_FF 12 -#define TARGET_CR 13 -#endif - -/* ======================================================== */ - -#ifdef TARGET_HLASM -#define TEXT_SECTION_ASM_OP "* Program text area" -#define DATA_SECTION_ASM_OP "* Program data area" -#define INIT_SECTION_ASM_OP "* Program initialization area" -#define SHARED_SECTION_ASM_OP "* Program shared data" -#define CTOR_LIST_BEGIN /* NO OP */ -#define CTOR_LIST_END /* NO OP */ -#define MAX_MVS_LABEL_SIZE 8 - -/* How to refer to registers in assembler output. This sequence is - indexed by compiler's hard-register-number (see above). */ - -#define REGISTER_NAMES \ -{ "0", "1", "2", "3", "4", "5", "6", "7", \ - "8", "9", "10", "11", "12", "13", "14", "15", \ - "0", "2", "4", "6" \ -} - -#define ASM_COMMENT_START "*" -#define ASM_APP_OFF "" -#define ASM_APP_ON "" - -#define ASM_OUTPUT_LABEL(FILE, NAME) \ -{ assemble_name (FILE, NAME); fputs ("\tEQU\t*\n", FILE); } - -#define ASM_OUTPUT_EXTERNAL(FILE, DECL, NAME) \ -{ \ - char temp[MAX_MVS_LABEL_SIZE + 1]; \ - if (mvs_check_alias (NAME, temp) == 2) \ - { \ - fprintf (FILE, "%s\tALIAS\tC'%s'\n", temp, NAME); \ - } \ -} - -/* MVS externals are limited to 8 characters, upper case only. - The '_' is mapped to '@', except for MVS functions, then '#'. */ - - -#define ASM_OUTPUT_LABELREF(FILE, NAME) \ -{ \ - char *bp, ch, temp[MAX_MVS_LABEL_SIZE + 1]; \ - if (!mvs_get_alias (NAME, temp)) \ - strcpy (temp, NAME); \ - if (!strcmp (temp,"main")) \ - strcpy (temp,"gccmain"); \ - if (mvs_function_check (temp)) \ - ch = '#'; \ - else \ - ch = '@'; \ - for (bp = temp; *bp; bp++) \ - *bp = (*bp == '_' ? ch : TOUPPER (*bp)); \ - fprintf (FILE, "%s", temp); \ -} - -#define ASM_GENERATE_INTERNAL_LABEL(LABEL, PREFIX, NUM) \ - sprintf (LABEL, "*%s%lu", PREFIX, (unsigned long)(NUM)) - -/* Generate case label. For HLASM we can change to the data CSECT - and put the vectors out of the code body. The assembler just - concatenates CSECTs with the same name. */ - -#define ASM_OUTPUT_CASE_LABEL(FILE, PREFIX, NUM, TABLE) \ - fprintf (FILE, "\tDS\t0F\n"); \ - fprintf (FILE,"\tCSECT\n"); \ - fprintf (FILE, "%s%d\tEQU\t*\n", PREFIX, NUM) - -/* Put the CSECT back to the code body */ - -#define ASM_OUTPUT_CASE_END(FILE, NUM, TABLE) \ - assemble_name (FILE, mvs_function_name); \ - fputs ("\tCSECT\n", FILE); - -/* This is how to output an element of a case-vector that is absolute. */ - -#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ - fprintf (FILE, "\tDC\tA(L%d)\n", VALUE) - -/* This is how to output an element of a case-vector that is relative. */ - -#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ - fprintf (FILE, "\tDC\tA(L%d-L%d)\n", VALUE, REL) - -/* This is how to output an insn to push a register on the stack. - It need not be very fast code. - Right now, PUSH & POP are used only when profiling is enabled, - and then, only to push the static chain reg and the function struct - value reg, and only if those are used. Since profiling is not - supported anyway, punt on this. */ - -#define ASM_OUTPUT_REG_PUSH(FILE, REGNO) \ - mvs_check_page (FILE, 8, 4); \ - fprintf (FILE, "\tS\t13,=F'4'\n\tST\t%s,%d(13)\n", \ - reg_names[REGNO], STACK_POINTER_OFFSET) - -/* This is how to output an insn to pop a register from the stack. - It need not be very fast code. */ - -#define ASM_OUTPUT_REG_POP(FILE, REGNO) \ - mvs_check_page (FILE, 8, 0); \ - fprintf (FILE, "\tL\t%s,%d(13)\n\tLA\t13,4(13)\n", \ - reg_names[REGNO], STACK_POINTER_OFFSET) - -/* This outputs a text string. The string are chopped up to fit into - an 80 byte record. Also, control and special characters, interpreted - by the IBM assembler, are output numerically. */ - -#define MVS_ASCII_TEXT_LENGTH 48 - -#define ASM_OUTPUT_ASCII(FILE, PTR, LEN) \ -{ \ - size_t i, limit = (LEN); \ - int j; \ - for (j = 0, i = 0; i < limit; j++, i++) \ - { \ - int c = (PTR)[i]; \ - if (ISCNTRL (c) || c == '&') \ - { \ - if (j % MVS_ASCII_TEXT_LENGTH != 0 ) \ - fprintf (FILE, "'\n"); \ - j = -1; \ - fprintf (FILE, "\tDC\tX'%X'\n", c ); \ - } \ - else \ - { \ - if (j % MVS_ASCII_TEXT_LENGTH == 0) \ - fprintf (FILE, "\tDC\tC'"); \ - if ( c == '\'' ) \ - fprintf (FILE, "%c%c", c, c); \ - else \ - fprintf (FILE, "%c", c); \ - if (j % MVS_ASCII_TEXT_LENGTH == MVS_ASCII_TEXT_LENGTH - 1) \ - fprintf (FILE, "'\n" ); \ - } \ - } \ - if (j % MVS_ASCII_TEXT_LENGTH != 0) \ - fprintf (FILE, "'\n"); \ -} - -/* This is how to output an assembler line that says to advance the - location counter to a multiple of 2**LOG bytes. */ - -#define ASM_OUTPUT_ALIGN(FILE, LOG) \ - if (LOG) \ - { \ - if ((LOG) == 1) \ - fprintf (FILE, "\tDS\t0H\n" ); \ - else \ - fprintf (FILE, "\tDS\t0F\n" ); \ - } \ - -/* The maximum length of memory that the IBM assembler will allow in one - DS operation. */ - -#define MAX_CHUNK 32767 - -/* A C statement to output to the stdio stream FILE an assembler - instruction to advance the location counter by SIZE bytes. Those - bytes should be zero when loaded. */ - -#define ASM_OUTPUT_SKIP(FILE, SIZE) \ -{ \ - unsigned HOST_WIDE_INT s; \ - int k; \ - for (s = (SIZE); s > 0; s -= MAX_CHUNK) \ - { \ - if (s > MAX_CHUNK) \ - k = MAX_CHUNK; \ - else \ - k = s; \ - fprintf (FILE, "\tDS\tXL%d\n", k); \ - } \ -} - -/* A C statement (sans semicolon) to output to the stdio stream - FILE the assembler definition of a common-label named NAME whose - size is SIZE bytes. The variable ROUNDED is the size rounded up - to whatever alignment the caller wants. */ - -#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \ -{ \ - char temp[MAX_MVS_LABEL_SIZE + 1]; \ - if (mvs_check_alias(NAME, temp) == 2) \ - { \ - fprintf (FILE, "%s\tALIAS\tC'%s'\n", temp, NAME); \ - } \ - fputs ("\tENTRY\t", FILE); \ - assemble_name (FILE, NAME); \ - fputs ("\n", FILE); \ - fprintf (FILE, "\tDS\t0F\n"); \ - ASM_OUTPUT_LABEL (FILE,NAME); \ - ASM_OUTPUT_SKIP (FILE,SIZE); \ -} - -/* A C statement (sans semicolon) to output to the stdio stream - FILE the assembler definition of a local-common-label named NAME - whose size is SIZE bytes. The variable ROUNDED is the size - rounded up to whatever alignment the caller wants. */ - -#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \ -{ \ - fprintf (FILE, "\tDS\t0F\n"); \ - ASM_OUTPUT_LABEL (FILE,NAME); \ - ASM_OUTPUT_SKIP (FILE,SIZE); \ -} - -#define ASM_PN_FORMAT "%s%lu" - -/* Print operand XV (an rtx) in assembler syntax to file FILE. - CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified. - For `%' followed by punctuation, CODE is the punctuation and XV is null. */ - -#define PRINT_OPERAND(FILE, XV, CODE) \ -{ \ - switch (GET_CODE (XV)) \ - { \ - static char curreg[4]; \ - case REG: \ - if (CODE == 'N') \ - strcpy (curreg, reg_names[REGNO (XV) + 1]); \ - else \ - strcpy (curreg, reg_names[REGNO (XV)]); \ - fprintf (FILE, "%s", curreg); \ - break; \ - case MEM: \ - { \ - rtx addr = XEXP (XV, 0); \ - if (CODE == 'O') \ - { \ - if (GET_CODE (addr) == PLUS) \ - fprintf (FILE, HOST_WIDE_INT_PRINT_DEC, INTVAL (XEXP (addr, 1))); \ - else \ - fprintf (FILE, "0"); \ - } \ - else if (CODE == 'R') \ - { \ - if (GET_CODE (addr) == PLUS) \ - fprintf (FILE, "%s", reg_names[REGNO (XEXP (addr, 0))]);\ - else \ - fprintf (FILE, "%s", reg_names[REGNO (addr)]); \ - } \ - else \ - output_address (XEXP (XV, 0)); \ - } \ - break; \ - case SYMBOL_REF: \ - case LABEL_REF: \ - mvs_page_lit += 4; \ - if (SYMBOL_REF_EXTERNAL_P (XV)) fprintf (FILE, "=V("); \ - else fprintf (FILE, "=A("); \ - output_addr_const (FILE, XV); \ - fprintf (FILE, ")"); \ - break; \ - case CONST_INT: \ - if (CODE == 'B') \ - fprintf (FILE, "%d", (int) (INTVAL (XV) & 0xff)); \ - else if (CODE == 'X') \ - fprintf (FILE, "%02X", (int) (INTVAL (XV) & 0xff)); \ - else if (CODE == 'h') \ - fprintf (FILE, HOST_WIDE_INT_PRINT_DEC, (INTVAL (XV) << 16) >> 16); \ - else if (CODE == 'H') \ - { \ - mvs_page_lit += 2; \ - fprintf (FILE, "=H'" HOST_WIDE_INT_PRINT_DEC "'", (INTVAL (XV) << 16) >> 16); \ - } \ - else if (CODE == 'K') \ - { \ - /* auto sign-extension of signed 16-bit to signed 32-bit */ \ - mvs_page_lit += 4; \ - fprintf (FILE, "=F'" HOST_WIDE_INT_PRINT_DEC "'", (INTVAL (XV) << 16) >> 16); \ - } \ - else if (CODE == 'W') \ - { \ - /* hand-built sign-extension of signed 32-bit to 64-bit */ \ - mvs_page_lit += 8; \ - if (0 <= INTVAL (XV)) { \ - fprintf (FILE, "=XL8'00000000"); \ - } else { \ - fprintf (FILE, "=XL8'FFFFFFFF"); \ - } \ - fprintf (FILE, "%08X'", INTVAL (XV)); \ - } \ - else \ - { \ - mvs_page_lit += 4; \ - fprintf (FILE, "=F'" HOST_WIDE_INT_PRINT_DEC "'", INTVAL (XV)); \ - } \ - break; \ - case CONST_DOUBLE: \ - if (GET_MODE (XV) == DImode) \ - { \ - if (CODE == 'M') \ - { \ - mvs_page_lit += 4; \ - fprintf (FILE, "=XL4'%08X'", CONST_DOUBLE_LOW (XV)); \ - } \ - else if (CODE == 'L') \ - { \ - mvs_page_lit += 4; \ - fprintf (FILE, "=XL4'%08X'", CONST_DOUBLE_HIGH (XV)); \ - } \ - else \ - { \ - mvs_page_lit += 8; \ - fprintf (FILE, "=XL8'%08X%08X'", CONST_DOUBLE_LOW (XV), \ - CONST_DOUBLE_HIGH (XV)); \ - } \ - } \ - else \ - { \ - char buf[50]; \ - if (GET_MODE (XV) == SFmode) \ - { \ - mvs_page_lit += 4; \ - real_to_decimal (buf, CONST_DOUBLE_REAL_VALUE (XV), \ - sizeof (buf), 0, 1); \ - fprintf (FILE, "=E'%s'", buf); \ - } \ - else if (GET_MODE (XV) == DFmode) \ - { \ - mvs_page_lit += 8; \ - real_to_decimal (buf, CONST_DOUBLE_REAL_VALUE (XV), \ - sizeof (buf), 0, 1); \ - fprintf (FILE, "=D'%s'", buf); \ - } \ - else /* VOIDmode */ \ - { \ - mvs_page_lit += 8; \ - fprintf (FILE, "=XL8'%08X%08X'", \ - CONST_DOUBLE_HIGH (XV), CONST_DOUBLE_LOW (XV)); \ - } \ - } \ - break; \ - case CONST: \ - if (GET_CODE (XEXP (XV, 0)) == PLUS \ - && GET_CODE (XEXP (XEXP (XV, 0), 0)) == SYMBOL_REF) \ - { \ - mvs_page_lit += 4; \ - if (SYMBOL_REF_EXTERNAL_P (XEXP (XEXP (XV, 0), 0))) \ - { \ - fprintf (FILE, "=V("); \ - ASM_OUTPUT_LABELREF (FILE, \ - XSTR (XEXP (XEXP (XV, 0), 0), 0)); \ - fprintf (FILE, ")\n\tA\t%s,=F'" HOST_WIDE_INT_PRINT_DEC "'", \ - curreg, INTVAL (XEXP (XEXP (XV, 0), 1))); \ - } \ - else \ - { \ - fprintf (FILE, "=A("); \ - output_addr_const (FILE, XV); \ - fprintf (FILE, ")"); \ - } \ - } \ - else \ - { \ - mvs_page_lit += 4; \ - fprintf (FILE, "=F'"); \ - output_addr_const (FILE, XV); \ - fprintf (FILE, "'"); \ - } \ - break; \ - default: \ - abort(); \ - } \ -} - -#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \ -{ \ - rtx breg, xreg, offset, plus; \ - \ - switch (GET_CODE (ADDR)) \ - { \ - case REG: \ - fprintf (FILE, "0(%s)", reg_names[REGNO (ADDR)]); \ - break; \ - case PLUS: \ - breg = 0; \ - xreg = 0; \ - offset = 0; \ - if (GET_CODE (XEXP (ADDR, 0)) == PLUS) \ - { \ - if (GET_CODE (XEXP (ADDR, 1)) == REG) \ - breg = XEXP (ADDR, 1); \ - else \ - offset = XEXP (ADDR, 1); \ - plus = XEXP (ADDR, 0); \ - } \ - else \ - { \ - if (GET_CODE (XEXP (ADDR, 0)) == REG) \ - breg = XEXP (ADDR, 0); \ - else \ - offset = XEXP (ADDR, 0); \ - plus = XEXP (ADDR, 1); \ - } \ - if (GET_CODE (plus) == PLUS) \ - { \ - if (GET_CODE (XEXP (plus, 0)) == REG) \ - { \ - if (breg) \ - xreg = XEXP (plus, 0); \ - else \ - breg = XEXP (plus, 0); \ - } \ - else \ - { \ - offset = XEXP (plus, 0); \ - } \ - if (GET_CODE (XEXP (plus, 1)) == REG) \ - { \ - if (breg) \ - xreg = XEXP (plus, 1); \ - else \ - breg = XEXP (plus, 1); \ - } \ - else \ - { \ - offset = XEXP (plus, 1); \ - } \ - } \ - else if (GET_CODE (plus) == REG) \ - { \ - if (breg) \ - xreg = plus; \ - else \ - breg = plus; \ - } \ - else \ - { \ - offset = plus; \ - } \ - if (offset) \ - { \ - if (GET_CODE (offset) == LABEL_REF) \ - fprintf (FILE, "L%d", \ - CODE_LABEL_NUMBER (XEXP (offset, 0))); \ - else \ - output_addr_const (FILE, offset); \ - } \ - else \ - fprintf (FILE, "0"); \ - if (xreg) \ - fprintf (FILE, "(%s,%s)", \ - reg_names[REGNO (xreg)], reg_names[REGNO (breg)]); \ - else \ - fprintf (FILE, "(%s)", reg_names[REGNO (breg)]); \ - break; \ - default: \ - mvs_page_lit += 4; \ - if (SYMBOL_REF_EXTERNAL_P (ADDR)) fprintf (FILE, "=V("); \ - else fprintf (FILE, "=A("); \ - output_addr_const (FILE, ADDR); \ - fprintf (FILE, ")"); \ - break; \ - } \ -} - -#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \ -{ \ - if (strlen (NAME) + 1 > mvs_function_name_length) \ - { \ - if (mvs_function_name) \ - free (mvs_function_name); \ - mvs_function_name = 0; \ - } \ - if (!mvs_function_name) \ - { \ - mvs_function_name_length = strlen (NAME) * 2 + 1; \ - mvs_function_name = (char *) xmalloc (mvs_function_name_length); \ - } \ - if (!strcmp (NAME, "main")) \ - strcpy (mvs_function_name, "gccmain"); \ - else \ - strcpy (mvs_function_name, NAME); \ - fprintf (FILE, "\tDS\t0F\n"); \ - assemble_name (FILE, mvs_function_name); \ - fputs ("\tRMODE\tANY\n", FILE); \ - assemble_name (FILE, mvs_function_name); \ - fputs ("\tCSECT\n", FILE); \ -} - -/* Output assembler code to FILE to increment profiler label # LABELNO - for profiling a function entry. */ - -#define FUNCTION_PROFILER(FILE, LABELNO) \ - fprintf (FILE, "Error: No profiling available.\n") - -#endif /* TARGET_HLASM */ - -/* ======================================================== */ - -#ifdef TARGET_ELF_ABI - -/* How to refer to registers in assembler output. This sequence is - indexed by compiler's hard-register-number (see above). */ - -#define REGISTER_NAMES \ -{ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \ - "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", \ - "f0", "f2", "f4", "f6" \ -} - -/* Print operand XV (an rtx) in assembler syntax to file FILE. - CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified. - For `%' followed by punctuation, CODE is the punctuation and XV is null. */ - -#define PRINT_OPERAND(FILE, XV, CODE) \ -{ \ - switch (GET_CODE (XV)) \ - { \ - static char curreg[4]; \ - case REG: \ - if (CODE == 'N') \ - strcpy (curreg, reg_names[REGNO (XV) + 1]); \ - else \ - strcpy (curreg, reg_names[REGNO (XV)]); \ - fprintf (FILE, "%s", curreg); \ - break; \ - case MEM: \ - { \ - rtx addr = XEXP (XV, 0); \ - if (CODE == 'O') \ - { \ - if (GET_CODE (addr) == PLUS) \ - fprintf (FILE, HOST_WIDE_INT_PRINT_DEC, INTVAL (XEXP (addr, 1))); \ - else \ - fprintf (FILE, "0"); \ - } \ - else if (CODE == 'R') \ - { \ - if (GET_CODE (addr) == PLUS) \ - fprintf (FILE, "%s", reg_names[REGNO (XEXP (addr, 0))]);\ - else \ - fprintf (FILE, "%s", reg_names[REGNO (addr)]); \ - } \ - else \ - output_address (XEXP (XV, 0)); \ - } \ - break; \ - case SYMBOL_REF: \ - case LABEL_REF: \ - mvs_page_lit += 4; \ - if (SYMBOL_REF_EXTERNAL_P (XV)) fprintf (FILE, "=V("); \ - else fprintf (FILE, "=A("); \ - output_addr_const (FILE, XV); \ - fprintf (FILE, ")"); \ - break; \ - case CONST_INT: \ - if (CODE == 'B') \ - fprintf (FILE, "%d", (int) (INTVAL (XV) & 0xff)); \ - else if (CODE == 'X') \ - fprintf (FILE, "%02X", (int) (INTVAL (XV) & 0xff)); \ - else if (CODE == 'h') \ - fprintf (FILE, HOST_WIDE_INT_PRINT_DEC, (INTVAL (XV) << 16) >> 16); \ - else if (CODE == 'H') \ - { \ - mvs_page_lit += 2; \ - fprintf (FILE, "=H'" HOST_WIDE_INT_PRINT_DEC "'", \ - (INTVAL (XV) << 16) >> 16); \ - } \ - else if (CODE == 'K') \ - { \ - /* auto sign-extension of signed 16-bit to signed 32-bit */ \ - mvs_page_lit += 4; \ - fprintf (FILE, "=F'" HOST_WIDE_INT_PRINT_DEC "'", \ - (INTVAL (XV) << 16) >> 16); \ - } \ - else if (CODE == 'W') \ - { \ - /* hand-built sign-extension of signed 32-bit to 64-bit */ \ - mvs_page_lit += 8; \ - if (0 <= INTVAL (XV)) { \ - fprintf (FILE, "=XL8'00000000"); \ - } else { \ - fprintf (FILE, "=XL8'FFFFFFFF"); \ - } \ - fprintf (FILE, "%08X'", INTVAL (XV)); \ - } \ - else \ - { \ - mvs_page_lit += 4; \ - fprintf (FILE, "=F'" HOST_WIDE_INT_PRINT_DEC "'", INTVAL (XV)); \ - } \ - break; \ - case CONST_DOUBLE: \ - if (GET_MODE (XV) == DImode) \ - { \ - if (CODE == 'M') \ - { \ - mvs_page_lit += 4; \ - fprintf (FILE, "=XL4'%08X'", CONST_DOUBLE_LOW (XV)); \ - } \ - else if (CODE == 'L') \ - { \ - mvs_page_lit += 4; \ - fprintf (FILE, "=XL4'%08X'", CONST_DOUBLE_HIGH (XV)); \ - } \ - else \ - { \ - mvs_page_lit += 8; \ - fprintf (FILE, "=yyyyXL8'%08X%08X'", \ - CONST_DOUBLE_HIGH (XV), CONST_DOUBLE_LOW (XV)); \ - } \ - } \ - else \ - { \ - char buf[50]; \ - if (GET_MODE (XV) == SFmode) \ - { \ - mvs_page_lit += 4; \ - real_to_decimal (buf, CONST_DOUBLE_REAL_VALUE (XV), \ - sizeof (buf), 0, 1); \ - fprintf (FILE, "=E'%s'", buf); \ - } \ - else if (GET_MODE (XV) == DFmode) \ - { \ - mvs_page_lit += 8; \ - real_to_decimal (buf, CONST_DOUBLE_REAL_VALUE (XV), \ - sizeof (buf), 0, 1); \ - fprintf (FILE, "=D'%s'", buf); \ - } \ - else /* VOIDmode */ \ - { \ - mvs_page_lit += 8; \ - fprintf (FILE, "=XL8'%08X%08X'", \ - CONST_DOUBLE_HIGH (XV), CONST_DOUBLE_LOW (XV)); \ - } \ - } \ - break; \ - case CONST: \ - if (GET_CODE (XEXP (XV, 0)) == PLUS \ - && GET_CODE (XEXP (XEXP (XV, 0), 0)) == SYMBOL_REF) \ - { \ - mvs_page_lit += 4; \ - if (SYMBOL_REF_EXTERNAL_P (XEXP (XEXP (XV, 0), 0))) \ - { \ - fprintf (FILE, "=V("); \ - ASM_OUTPUT_LABELREF (FILE, \ - XSTR (XEXP (XEXP (XV, 0), 0), 0)); \ - fprintf (FILE, ")\n\tA\t%s,=F'" HOST_WIDE_INT_PRINT_DEC "'", \ - curreg, INTVAL (XEXP (XEXP (XV, 0), 1))); \ - } \ - else \ - { \ - fprintf (FILE, "=A("); \ - output_addr_const (FILE, XV); \ - fprintf (FILE, ")"); \ - } \ - } \ - else \ - { \ - mvs_page_lit += 4; \ - fprintf (FILE, "=bogus_bad_F'"); \ - output_addr_const (FILE, XV); \ - fprintf (FILE, "'"); \ -/* XXX hack alert this gets gen'd in -fPIC code in relation to a tablejump */ \ -/* but its somehow fundamentally broken, I can't make any sense out of it */ \ -debug_rtx (XV); \ -abort(); \ - } \ - break; \ - default: \ - abort(); \ - } \ -} - -#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \ -{ \ - rtx breg, xreg, offset, plus; \ - \ - switch (GET_CODE (ADDR)) \ - { \ - case REG: \ - fprintf (FILE, "0(%s)", reg_names[REGNO (ADDR)]); \ - break; \ - case PLUS: \ - breg = 0; \ - xreg = 0; \ - offset = 0; \ - if (GET_CODE (XEXP (ADDR, 0)) == PLUS) \ - { \ - if (GET_CODE (XEXP (ADDR, 1)) == REG) \ - breg = XEXP (ADDR, 1); \ - else \ - offset = XEXP (ADDR, 1); \ - plus = XEXP (ADDR, 0); \ - } \ - else \ - { \ - if (GET_CODE (XEXP (ADDR, 0)) == REG) \ - breg = XEXP (ADDR, 0); \ - else \ - offset = XEXP (ADDR, 0); \ - plus = XEXP (ADDR, 1); \ - } \ - if (GET_CODE (plus) == PLUS) \ - { \ - if (GET_CODE (XEXP (plus, 0)) == REG) \ - { \ - if (breg) \ - xreg = XEXP (plus, 0); \ - else \ - breg = XEXP (plus, 0); \ - } \ - else \ - { \ - offset = XEXP (plus, 0); \ - } \ - if (GET_CODE (XEXP (plus, 1)) == REG) \ - { \ - if (breg) \ - xreg = XEXP (plus, 1); \ - else \ - breg = XEXP (plus, 1); \ - } \ - else \ - { \ - offset = XEXP (plus, 1); \ - } \ - } \ - else if (GET_CODE (plus) == REG) \ - { \ - if (breg) \ - xreg = plus; \ - else \ - breg = plus; \ - } \ - else \ - { \ - offset = plus; \ - } \ - if (offset) \ - { \ - if (GET_CODE (offset) == LABEL_REF) \ - fprintf (FILE, "L%d", \ - CODE_LABEL_NUMBER (XEXP (offset, 0))); \ - else \ - output_addr_const (FILE, offset); \ - } \ - else \ - fprintf (FILE, "0"); \ - if (xreg) \ - fprintf (FILE, "(%s,%s)", \ - reg_names[REGNO (xreg)], reg_names[REGNO (breg)]); \ - else \ - fprintf (FILE, "(%s)", reg_names[REGNO (breg)]); \ - break; \ - default: \ - mvs_page_lit += 4; \ - if (SYMBOL_REF_EXTERNAL_P (ADDR)) fprintf (FILE, "=V("); \ - else fprintf (FILE, "=A("); \ - output_addr_const (FILE, ADDR); \ - fprintf (FILE, ")"); \ - break; \ - } \ -} - -/* Output assembler code to FILE to increment profiler label # LABELNO - for profiling a function entry. */ -/* Make it a no-op for now, so we can at least compile glibc */ -#define FUNCTION_PROFILER(FILE, LABELNO) { \ - mvs_check_page (FILE, 24, 4); \ - fprintf (FILE, "\tSTM\tr1,r2,%d(sp)\n", STACK_POINTER_OFFSET-8); \ - fprintf (FILE, "\tLA\tr1,1(0,0)\n"); \ - fprintf (FILE, "\tL\tr2,=A(.LP%d)\n", LABELNO); \ - fprintf (FILE, "\tA\tr1,0(r2)\n"); \ - fprintf (FILE, "\tST\tr1,0(r2)\n"); \ - fprintf (FILE, "\tLM\tr1,r2,%d(sp)\n", STACK_POINTER_OFFSET-8); \ -} - -/* Don't bother to output .extern pseudo-ops. They are not needed by - ELF assemblers. */ - -#undef ASM_OUTPUT_EXTERNAL - -#define ASM_DOUBLE "\t.double" - -/* #define ASM_OUTPUT_LABELREF(FILE, NAME) */ /* use gas -- defaults.h */ - -/* let config/svr4.h define this ... - * #define ASM_OUTPUT_CASE_LABEL(FILE, PREFIX, NUM, TABLE) - * fprintf (FILE, "%s%d:\n", PREFIX, NUM) - */ - -/* This is how to output an element of a case-vector that is absolute. */ -#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ - mvs_check_page (FILE, 4, 0); \ - fprintf (FILE, "\t.long\t.L%d\n", VALUE) - -/* This is how to output an element of a case-vector that is relative. */ -#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ - mvs_check_page (FILE, 4, 0); \ - fprintf (FILE, "\t.long\t.L%d-.L%d\n", VALUE, REL) - -/* Right now, PUSH & POP are used only when profiling is enabled, - and then, only to push the static chain reg and the function struct - value reg, and only if those are used by the function being profiled. - We don't need this for profiling, so punt. */ -#define ASM_OUTPUT_REG_PUSH(FILE, REGNO) -#define ASM_OUTPUT_REG_POP(FILE, REGNO) - - -/* Indicate that jump tables go in the text section. This is - necessary when compiling PIC code. */ -#define JUMP_TABLES_IN_TEXT_SECTION 1 - -/* Define macro used to output shift-double opcodes when the shift - count is in %cl. Some assemblers require %cl as an argument; - some don't. - - GAS requires the %cl argument, so override i386/unix.h. */ - -#undef SHIFT_DOUBLE_OMITS_COUNT -#define SHIFT_DOUBLE_OMITS_COUNT 0 - -/* Implicit library calls should use memcpy, not bcopy, etc. */ -#define TARGET_MEM_FUNCTIONS - -/* Output before read-only data. */ -#define TEXT_SECTION_ASM_OP "\t.text" - -/* Output before writable (initialized) data. */ -#define DATA_SECTION_ASM_OP "\t.data" - -/* Output before writable (uninitialized) data. */ -#define BSS_SECTION_ASM_OP "\t.bss" - -/* In the past there was confusion as to what the argument to .align was - in GAS. For the last several years the rule has been this: for a.out - file formats that argument is LOG, and for all other file formats the - argument is 1< */ - rtx reg1 = gen_reg_rtx (DImode); - rtx reg2 = gen_reg_rtx (DImode); - rtx result = operands[0]; - rtx mem1 = operands[1]; - rtx mem2 = operands[2]; - rtx len = operands[3]; - if (!CONSTANT_P (len)) - len = force_reg (SImode, len); - - /* Load up the address+length pairs. */ - emit_insn (gen_rtx_CLOBBER (VOIDmode, reg1)); - emit_move_insn (gen_rtx_SUBREG (SImode, reg1, 0), - force_operand (XEXP (mem1, 0), NULL_RTX)); - emit_move_insn (gen_rtx_SUBREG (SImode, reg1, GET_MODE_SIZE (SImode)), len); - - emit_insn (gen_rtx_CLOBBER (VOIDmode, reg2)); - emit_move_insn (gen_rtx_SUBREG (SImode, reg2, 0), - force_operand (XEXP (mem2, 0), NULL_RTX)); - emit_move_insn (gen_rtx_SUBREG (SImode, reg2, GET_MODE_SIZE (SImode)), len); - - /* Compare! */ - emit_insn (gen_cmpmemsi_1 (result, reg1, reg2)); - } - DONE; -}") - -; Compare a block that is less than 256 bytes in length. - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d") - (compare (match_operand:BLK 1 "s_operand" "m") - (match_operand:BLK 2 "s_operand" "m"))) - (use (match_operand:QI 3 "immediate_operand" "I"))] - "((unsigned) INTVAL (operands[3]) < 256)" - "* -{ - check_label_emit (); - mvs_check_page (0, 22, 0); - return \"LA %0,%1\;CLC %O1(%c3,%R1),%2\;BH *+12\;BL *+6\;SLR %0,%0\;LNR %0,%0\"; -}" - [(set_attr "length" "22")] -) - -; Compare a block that is larger than 255 bytes in length. - -(define_insn "cmpmemsi_1" - [(set (match_operand:SI 0 "register_operand" "+d") - (compare - (mem:BLK (subreg:SI (match_operand:DI 1 "register_operand" "+d") 0)) - (mem:BLK (subreg:SI (match_operand:DI 2 "register_operand" "+d") 0)))) - (use (match_dup 1)) - (use (match_dup 2)) - (clobber (match_dup 1)) - (clobber (match_dup 2))] - "" - "* -{ - check_label_emit (); - mvs_check_page (0, 18, 0); - return \"LA %0,1(0,0)\;CLCL %1,%2\;BH *+12\;BL *+6\;SLR %0,%0\;LNR %0,%0\"; -}" - [(set_attr "length" "18")] -) - -;; -;;- Move instructions. -;; - -; -; movdi instruction pattern(s). -; - -(define_insn "" -;; [(set (match_operand:DI 0 "r_or_s_operand" "=dm") -;; (match_operand:DI 1 "r_or_s_operand" "dim*fF"))] - [(set (match_operand:DI 0 "r_or_s_operand" "=dS,m") - (match_operand:DI 1 "r_or_s_operand" "diS*fF,d*fF"))] - - "TARGET_CHAR_INSTRUCTIONS" - "* -{ - check_label_emit (); - if (REG_P (operands[0])) - { - if (FP_REG_P (operands[1])) - { - mvs_check_page (0, 8, 0); - return \"STD %1,140(,13)\;LM %0,%N0,140(13)\"; - } - if (REG_P (operands[1])) - { - mvs_check_page (0, 4, 0); - return \"LR %0,%1\;LR %N0,%N1\"; - } - if (operands[1] == const0_rtx) - { - CC_STATUS_INIT; - mvs_check_page (0, 4, 0); - return \"SLR %0,%0\;SLR %N0,%N0\"; - } - if (GET_CODE (operands[1]) == CONST_INT - && (unsigned) INTVAL (operands[1]) < 4096) - { - CC_STATUS_INIT; - mvs_check_page (0, 6, 0); - return \"SLR %0,%0\;LA %N0,%c1(0,0)\"; - } - if (GET_CODE (operands[1]) == CONST_INT) - { - CC_STATUS_SET (operands[0], operands[1]); - mvs_check_page (0, 8, 0); - return \"L %0,%1\;SRDA %0,32\"; - } - mvs_check_page (0, 4, 0); - return \"LM %0,%N0,%1\"; - } - else if (FP_REG_P (operands[1])) - { - mvs_check_page (0, 4, 0); - return \"STD %1,%0\"; - } - else if (REG_P (operands[1])) - { - mvs_check_page (0, 4, 0); - return \"STM %1,%N1,%0\"; - } - mvs_check_page (0, 6, 0); - return \"MVC %O0(8,%R0),%W1\"; -}" - [(set_attr "length" "8")] -) - -(define_insn "movdi" -;; [(set (match_operand:DI 0 "general_operand" "=d,dm") -;; (match_operand:DI 1 "general_operand" "dimF,*fd"))] - [(set (match_operand:DI 0 "general_operand" "=d,dm") - (match_operand:DI 1 "r_or_s_operand" "diSF,*fd"))] - "" - "* -{ - check_label_emit (); - if (REG_P (operands[0])) - { - if (FP_REG_P (operands[1])) - { - mvs_check_page (0, 8, 0); - return \"STD %1,140(,13)\;LM %0,%N0,140(13)\"; - } - if (REG_P (operands[1])) - { - mvs_check_page (0, 4, 0); - return \"LR %0,%1\;LR %N0,%N1\"; - } - if (operands[1] == const0_rtx) - { - CC_STATUS_INIT; - mvs_check_page (0, 4, 0); - return \"SLR %0,%0\;SLR %N0,%N0\"; - } - if (GET_CODE (operands[1]) == CONST_INT - && (unsigned) INTVAL (operands[1]) < 4096) - { - CC_STATUS_INIT; - mvs_check_page (0, 6, 0); - return \"SLR %0,%0\;LA %N0,%c1(0,0)\"; - } - if (GET_CODE (operands[1]) == CONST_INT) - { - CC_STATUS_SET (operands[0], operands[1]); - mvs_check_page (0, 8, 0); - return \"L %0,%1\;SRDA %0,32\"; - } - mvs_check_page (0, 4, 0); - return \"LM %0,%N0,%1\"; - } - else if (FP_REG_P (operands[1])) - { - mvs_check_page (0, 4, 0); - return \"STD %1,%0\"; - } - mvs_check_page (0, 4, 0); - return \"STM %1,%N1,%0\"; -}" - [(set_attr "length" "8")] -) - -;; we have got to provide a movdi alternative that will go from -;; register to memory & back in its full glory. However, we try to -;; discourage its use by listing this alternative last. -;; The problem is that the instructions above only provide -;; S-form style (base + displacement) mem access, while the -;; below provvides the full (base+index+displacement) RX-form. -;; These are rarely needed, but when needed they're needed. - -(define_insn "" - [(set (match_operand:DI 0 "general_operand" "=d,???m") - (match_operand:DI 1 "general_operand" "???m,d"))] - - "" - "* -{ - check_label_emit (); - if (REG_P (operands[0])) - { - mvs_check_page (0, 8, 0); - return \"LM %0,%N0,%1\"; - } - else if (REG_P (operands[1])) - { - mvs_check_page (0, 8, 0); - return \"STM %1,%N1,%0\"; - } - mvs_check_page (0, 6, 0); - return \"MVC %O0(8,%R0),%1\"; -}" - [(set_attr "length" "8")] -) - -; -; movsi instruction pattern(s). -; - -(define_insn "" -;; [(set (match_operand:SI 0 "r_or_s_operand" "=dm,d,dm") -;; (match_operand:SI 1 "r_or_s_operand" "diR,dim,*fF"))] - [(set (match_operand:SI 0 "r_or_s_operand" "=d,dS,dm") - (match_operand:SI 1 "general_operand" "dim,diS,di*fF"))] - - "TARGET_CHAR_INSTRUCTIONS" - "* -{ - check_label_emit (); - if (REG_P (operands[0])) - { - if (FP_REG_P (operands[1])) - { - mvs_check_page (0, 8, 0); - return \"STE %1,140(,13)\;L %0,140(,13)\"; - } - if (REG_P (operands[1])) - { - mvs_check_page (0, 2, 0); - return \"LR %0,%1\"; - } - if (operands[1] == const0_rtx) - { - CC_STATUS_INIT; - mvs_check_page (0, 2, 0); - return \"SLR %0,%0\"; - } - if (GET_CODE (operands[1]) == CONST_INT - && (unsigned) INTVAL (operands[1]) < 4096) - { - mvs_check_page (0, 4, 0); - return \"LA %0,%c1(0,0)\"; - } - mvs_check_page (0, 4, 0); - return \"L %0,%1\"; - } - else if (FP_REG_P (operands[1])) - { - mvs_check_page (0, 4, 0); - return \"STE %1,%0\"; - } - else if (REG_P (operands[1])) - { - mvs_check_page (0, 4, 0); - return \"ST %1,%0\"; - } - mvs_check_page (0, 6, 0); - return \"MVC %O0(4,%R0),%1\"; -}" - [(set_attr "length" "8")] -) - -(define_insn "movsi" - [(set (match_operand:SI 0 "general_operand" "=d,dm") - (match_operand:SI 1 "general_operand" "dimF,*fd"))] - "" - "* -{ - check_label_emit (); - if (REG_P (operands[0])) - { - if (FP_REG_P (operands[1])) - { - mvs_check_page (0, 8, 0); - return \"STE %1,140(,13)\;L %0,140(,13)\"; - } - if (REG_P (operands[1])) - { - mvs_check_page (0, 2, 0); - return \"LR %0,%1\"; - } - if (operands[1] == const0_rtx) - { - CC_STATUS_INIT; - mvs_check_page (0, 2, 0); - return \"SLR %0,%0\"; - } - if (GET_CODE (operands[1]) == CONST_INT - && (unsigned) INTVAL (operands[1]) < 4096) - { - mvs_check_page (0, 4, 0); - return \"LA %0,%c1(0,0)\"; - } - mvs_check_page (0, 4, 0); - return \"L %0,%1\"; - } - else if (FP_REG_P (operands[1])) - { - mvs_check_page (0, 4, 0); - return \"STE %1,%0\"; - } - mvs_check_page (0, 4, 0); - return \"ST %1,%0\"; -}" - [(set_attr "length" "8")] -) - -;(define_expand "movsi" -; [(set (match_operand:SI 0 "general_operand" "=d,dm") -; (match_operand:SI 1 "general_operand" "dimF,*fd"))] -; "" -; " -;{ -; rtx op0, op1; -; -; op0 = operands[0]; -; if (GET_CODE (op0) == CONST -; && GET_CODE (XEXP (XEXP (op0, 0), 0)) == SYMBOL_REF -; && SYMBOL_REF_EXTERNAL_P (XEXP (XEXP (op0, 0), 0))) -; { -; op0 = gen_rtx_MEM (SImode, copy_to_mode_reg (SImode, XEXP (op0, 0))); -; } -; -; op1 = operands[1]; -; if (GET_CODE (op1) == CONST -; && GET_CODE (XEXP (XEXP (op1, 0), 0)) == SYMBOL_REF -; && SYMBOL_REF_EXTERNAL_P (XEXP (XEXP (op1, 0), 0))) -; { -; op1 = gen_rtx_MEM (SImode, copy_to_mode_reg (SImode, XEXP (op1, 0))); -; } -; -; emit_insn (gen_rtx_SET (VOIDmode, op0, op1)); -; DONE; -;}") - -; -; movhi instruction pattern(s). -; - -(define_insn "" - [(set (match_operand:HI 0 "r_or_s_operand" "=g") - (match_operand:HI 1 "r_or_s_operand" "g"))] - "TARGET_CHAR_INSTRUCTIONS" - "* -{ - check_label_emit (); - if (REG_P (operands[0])) - { - if (REG_P (operands[1])) - { - mvs_check_page (0, 2, 0); - return \"LR %0,%1\"; - } - if (operands[1] == const0_rtx) - { - CC_STATUS_INIT; - mvs_check_page (0, 2, 0); - return \"SLR %0,%0\"; - } - if (GET_CODE (operands[1]) == CONST_INT - && (unsigned) INTVAL (operands[1]) < 4096) - { - mvs_check_page (0, 4, 0); - return \"LA %0,%c1(0,0)\"; - } - if (GET_CODE (operands[1]) == CONST_INT) - { - mvs_check_page (0, 4, 0); - return \"LH %0,%H1\"; - } - mvs_check_page (0, 4, 0); - return \"LH %0,%1\"; - } - else if (REG_P (operands[1])) - { - mvs_check_page (0, 4, 0); - return \"STH %1,%0\"; - } - if (GET_CODE (operands[1]) == CONST_INT) - { - mvs_check_page (0, 6, 0); - return \"MVC %O0(2,%R0),%H1\"; - } - mvs_check_page (0, 6, 0); - return \"MVC %O0(2,%R0),%1\"; -}" - [(set_attr "length" "6")] -) - -(define_insn "movhi" - [(set (match_operand:HI 0 "general_operand" "=d,m") - (match_operand:HI 1 "general_operand" "g,d"))] - "" - "* -{ - check_label_emit (); - if (REG_P (operands[0])) - { - if (REG_P (operands[1])) - { - mvs_check_page (0, 2, 0); - return \"LR %0,%1\"; - } - if (operands[1] == const0_rtx) - { - CC_STATUS_INIT; - mvs_check_page (0, 2, 0); - return \"SLR %0,%0\"; - } - if (GET_CODE (operands[1]) == CONST_INT - && (unsigned) INTVAL (operands[1]) < 4096) - { - mvs_check_page (0, 4, 0); - return \"LA %0,%c1(0,0)\"; - } - if (GET_CODE (operands[1]) == CONST_INT) - { - mvs_check_page (0, 4, 0); - return \"LH %0,%H1\"; - } - mvs_check_page (0, 4, 0); - return \"LH %0,%1\"; - } - mvs_check_page (0, 4, 0); - return \"STH %1,%0\"; -}" - [(set_attr "length" "4")] -) - -; -; movqi instruction pattern(s). -; - -(define_insn "" - [(set (match_operand:QI 0 "r_or_s_operand" "=g") - (match_operand:QI 1 "r_or_s_operand" "g"))] - "TARGET_CHAR_INSTRUCTIONS" - "* -{ - check_label_emit (); - if (REG_P (operands[0])) - { - if (REG_P (operands[1])) - { - mvs_check_page (0, 2, 0); - return \"LR %0,%1\"; - } - if (operands[1] == const0_rtx) - { - CC_STATUS_INIT; - mvs_check_page (0, 2, 0); - return \"SLR %0,%0\"; - } - if (GET_CODE (operands[1]) == CONST_INT) - { - if ((INTVAL (operands[1]) >= 0) - && (unsigned) INTVAL (operands[1]) < 4096) - { - mvs_check_page (0, 4, 0); - return \"LA %0,%c1(0,0)\"; - } - mvs_check_page (0, 4, 0); - return \"L %0,=F'%c1'\"; - } - mvs_check_page (0, 4, 0); - return \"IC %0,%1\"; - } - else if (REG_P (operands[1])) - { - mvs_check_page (0, 4, 0); - return \"STC %1,%0\"; - } - else if (GET_CODE (operands[1]) == CONST_INT) - { - mvs_check_page (0, 4, 0); - return \"MVI %0,%B1\"; - } - mvs_check_page (0, 6, 0); - return \"MVC %O0(1,%R0),%1\"; -}" - [(set_attr "length" "6")] -) - -(define_insn "movqi" - [(set (match_operand:QI 0 "general_operand" "=d,m") - (match_operand:QI 1 "general_operand" "g,d"))] - "" - "* -{ - check_label_emit (); - if (REG_P (operands[0])) - { - if (REG_P (operands[1])) - { - mvs_check_page (0, 2, 0); - return \"LR %0,%1\"; - } - if (operands[1] == const0_rtx) - { - CC_STATUS_INIT; - mvs_check_page (0, 2, 0); - return \"SLR %0,%0\"; - } - if (GET_CODE (operands[1]) == CONST_INT) - { - if ((INTVAL (operands[1]) >= 0) - && (unsigned) INTVAL (operands[1]) < 4096) - { - mvs_check_page (0, 4, 0); - return \"LA %0,%c1(0,0)\"; - } - mvs_check_page (0, 4, 0); - return \"L %0,=F'%c1'\"; - } - mvs_check_page (0, 4, 0); - return \"IC %0,%1\"; - } - mvs_check_page (0, 4, 0); - return \"STC %1,%0\"; -}" - [(set_attr "length" "4")] -) - -; -; movstrictqi instruction pattern(s). -; - -(define_insn "movstrictqi" - [(set (strict_low_part (match_operand:QI 0 "general_operand" "+d")) - (match_operand:QI 1 "general_operand" "g"))] - "" - "* -{ - check_label_emit (); - if (REG_P (operands[1])) - { - mvs_check_page (0, 8, 0); - return \"STC %1,140(,13)\;IC %0,140(,13)\"; - } - mvs_check_page (0, 4, 0); - return \"IC %0,%1\"; -}" - [(set_attr "length" "8")] -) - -; -; movstricthi instruction pattern(s). -; - -(define_insn "" - [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d")) - (match_operand:HI 1 "r_or_s_operand" "g"))] - "" - "* -{ - check_label_emit (); - if (REG_P (operands[1])) - { - mvs_check_page (0, 8, 0); - return \"STH %1,140(,13)\;ICM %0,3,140(13)\"; - } - else if (GET_CODE (operands[1]) == CONST_INT) - { - mvs_check_page (0, 4, 0); - return \"ICM %0,3,%H1\"; - } - mvs_check_page (0, 4, 0); - return \"ICM %0,3,%1\"; -}" - [(set_attr "length" "8")] -) - -(define_insn "movstricthi" - [(set (strict_low_part (match_operand:HI 0 "general_operand" "+dm")) - (match_operand:HI 1 "general_operand" "d"))] - "" - "* -{ - check_label_emit (); - if (REG_P (operands[0])) - { - mvs_check_page (0, 8, 0); - return \"STH %1,140(,13)\;ICM %0,3,140(13)\"; - } - mvs_check_page (0, 4, 0); - return \"STH %1,%0\"; -}" - [(set_attr "length" "8")] -) - -; -; movdf instruction pattern(s). -; - -(define_insn "" -;; [(set (match_operand:DF 0 "r_or_s_operand" "=fm,fm,*dm") -;; (match_operand:DF 1 "r_or_s_operand" "fmF,*dm,fmF"))] - [(set (match_operand:DF 0 "general_operand" "=f,m,fS,*dS,???d") - (match_operand:DF 1 "general_operand" "fmF,fF,*dS,fSF,???d"))] - - "TARGET_CHAR_INSTRUCTIONS" - "* -{ - check_label_emit (); - if (FP_REG_P (operands[0])) - { - if (FP_REG_P (operands[1])) - { - mvs_check_page (0, 2, 0); - return \"LDR %0,%1\"; - } - if (REG_P (operands[1])) - { - mvs_check_page (0, 8, 0); - return \"STM %1,%N1,140(13)\;LD %0,140(,13)\"; - } - if (operands[1] == const0_rtx) - { - CC_STATUS_SET (operands[0], operands[1]); - mvs_check_page (0, 2, 0); - return \"SDR %0,%0\"; - } - mvs_check_page (0, 4, 0); - return \"LD %0,%1\"; - } - if (REG_P (operands[0])) - { - if (FP_REG_P (operands[1])) - { - mvs_check_page (0, 12, 0); - return \"STD %1,140(,13)\;LM %0,%N0,140(13)\"; - } - if (REG_P (operands[1])) - { - mvs_check_page (0, 4, 0); - return \"LR %0,%1\;LR %N0,%N1\"; - } - mvs_check_page (0, 4, 0); - return \"LM %0,%N0,%1\"; - } - else if (FP_REG_P (operands[1])) - { - mvs_check_page (0, 4, 0); - return \"STD %1,%0\"; - } - else if (REG_P (operands[1])) - { - mvs_check_page (0, 4, 0); - return \"STM %1,%N1,%0\"; - } - mvs_check_page (0, 6, 0); - return \"MVC %O0(8,%R0),%1\"; -}" - [(set_attr "length" "12")] -) - -(define_insn "movdf" -;; [(set (match_operand:DF 0 "general_operand" "=f,fm,m,*d") -;; (match_operand:DF 1 "general_operand" "fmF,*d,f,fmF"))] - [(set (match_operand:DF 0 "general_operand" "=f,m,fS,*d,???d") - (match_operand:DF 1 "general_operand" "fmF,f,*d,SfF,???d"))] - - "" - "* -{ - check_label_emit (); - if (FP_REG_P (operands[0])) - { - if (FP_REG_P (operands[1])) - { - mvs_check_page (0, 2, 0); - return \"LDR %0,%1\"; - } - if (REG_P (operands[1])) - { - mvs_check_page (0, 8, 0); - return \"STM %1,%N1,140(13)\;LD %0,140(,13)\"; - } - if (operands[1] == const0_rtx) - { - CC_STATUS_SET (operands[0], operands[1]); - mvs_check_page (0, 2, 0); - return \"SDR %0,%0\"; - } - mvs_check_page (0, 4, 0); - return \"LD %0,%1\"; - } - else if (REG_P (operands[0])) - { - if (FP_REG_P (operands[1])) - { - mvs_check_page (0, 12, 0); - return \"STD %1,140(,13)\;LM %0,%N0,140(13)\"; - } - if (REG_P (operands[1])) - { - mvs_check_page (0, 4, 0); - return \"LR %0,%1\;LR %N0,%N1\"; - } - mvs_check_page (0, 4, 0); - return \"LM %0,%N0,%1\"; - } - else if (FP_REG_P (operands[1])) - { - mvs_check_page (0, 4, 0); - return \"STD %1,%0\"; - } - mvs_check_page (0, 4, 0); - return \"STM %1,%N1,%0\"; -}" - [(set_attr "length" "12")] -) - -; -; movsf instruction pattern(s). -; - -(define_insn "" -;; [(set (match_operand:SF 0 "r_or_s_operand" "=fm,fm,*dm") -;; (match_operand:SF 1 "r_or_s_operand" "fmF,*dm,fmF"))] -;; [(set (match_operand:SF 0 "general_operand" "=f,m,fm,*d,S") -;; (match_operand:SF 1 "general_operand" "fmF,fF,*d,fmF,S"))] - [(set (match_operand:SF 0 "general_operand" "=f*d,fm,S,???d") - (match_operand:SF 1 "general_operand" "fmF,fF*d,S,???d"))] - - "TARGET_CHAR_INSTRUCTIONS" - "* -{ - check_label_emit (); - if (FP_REG_P (operands[0])) - { - if (FP_REG_P (operands[1])) - { - mvs_check_page (0, 2, 0); - return \"LER %0,%1\"; - } - if (REG_P (operands[1])) - { - mvs_check_page (0, 8, 0); - return \"ST %1,140(,13)\;LE %0,140(,13)\"; - } - if (operands[1] == const0_rtx) - { - CC_STATUS_SET (operands[0], operands[1]); - mvs_check_page (0, 2, 0); - return \"SER %0,%0\"; - } - mvs_check_page (0, 4, 0); - return \"LE %0,%1\"; - } - else if (REG_P (operands[0])) - { - if (FP_REG_P (operands[1])) - { - mvs_check_page (0, 8, 0); - return \"STE %1,140(,13)\;L %0,140(,13)\"; - } - if (REG_P (operands[1])) - { - mvs_check_page (0, 2, 0); - return \"LR %0,%1\"; - } - mvs_check_page (0, 4, 0); - return \"L %0,%1\"; - } - else if (FP_REG_P (operands[1])) - { - mvs_check_page (0, 4, 0); - return \"STE %1,%0\"; - } - else if (REG_P (operands[1])) - { - mvs_check_page (0, 4, 0); - return \"ST %1,%0\"; - } - mvs_check_page (0, 6, 0); - return \"MVC %O0(4,%R0),%1\"; -}" - [(set_attr "length" "8")] -) - -(define_insn "movsf" - [(set (match_operand:SF 0 "general_operand" "=f,fm,m,*d") - (match_operand:SF 1 "general_operand" "fmF,*d,f,fmF"))] - "" - "* -{ - check_label_emit (); - if (FP_REG_P (operands[0])) - { - if (FP_REG_P (operands[1])) - { - mvs_check_page (0, 2, 0); - return \"LER %0,%1\"; - } - if (REG_P (operands[1])) - { - mvs_check_page (0, 8, 0); - return \"ST %1,140(,13)\;LE %0,140(,13)\"; - } - if (operands[1] == const0_rtx) - { - CC_STATUS_SET (operands[0], operands[1]); - mvs_check_page (0, 2, 0); - return \"SER %0,%0\"; - } - mvs_check_page (0, 4, 0); - return \"LE %0,%1\"; - } - else if (REG_P (operands[0])) - { - if (FP_REG_P (operands[1])) - { - mvs_check_page (0, 8, 0); - return \"STE %1,140(,13)\;L %0,140(,13)\"; - } - mvs_check_page (0, 4, 0); - return \"L %0,%1\"; - } - else if (FP_REG_P (operands[1])) - { - mvs_check_page (0, 4, 0); - return \"STE %1,%0\"; - } - mvs_check_page (0, 4, 0); - return \"ST %1,%0\"; -}" - [(set_attr "length" "8")] -) - -; -; clrstrsi instruction pattern(s). -; memset a block of bytes to zero. -; block must be less than 16M (24 bits) in length -; -(define_expand "clrstrsi" - [(set (match_operand:BLK 0 "general_operand" "g") - (const_int 0)) - (use (match_operand:SI 1 "general_operand" "")) - (match_operand 2 "" "")] - "" - " -{ - { - /* implementation suggested by Richard Henderson */ - rtx reg1 = gen_reg_rtx (DImode); - rtx reg2 = gen_reg_rtx (DImode); - rtx mem1 = operands[0]; - rtx zippo = gen_rtx_CONST_INT (SImode, 0); - rtx len = operands[1]; - if (!CONSTANT_P (len)) - len = force_reg (SImode, len); - - /* Load up the address+length pairs. */ - emit_insn (gen_rtx_CLOBBER (VOIDmode, reg1)); - emit_move_insn (gen_rtx_SUBREG (SImode, reg1, 0), - force_operand (XEXP (mem1, 0), NULL_RTX)); - emit_move_insn (gen_rtx_SUBREG (SImode, reg1, GET_MODE_SIZE (SImode)), len); - - emit_insn (gen_rtx_CLOBBER (VOIDmode, reg2)); - emit_move_insn (gen_rtx_SUBREG (SImode, reg2, 0), zippo); - emit_move_insn (gen_rtx_SUBREG (SImode, reg2, GET_MODE_SIZE (SImode)), zippo); - - /* Copy! */ - emit_insn (gen_movstrsi_1 (reg1, reg2)); - } - DONE; -}") - -; -; movstrsi instruction pattern(s). -; block must be less than 16M (24 bits) in length - -(define_expand "movstrsi" - [(set (match_operand:BLK 0 "general_operand" "") - (match_operand:BLK 1 "general_operand" "")) - (use (match_operand:SI 2 "general_operand" "")) - (match_operand 3 "" "")] - "" - " -{ - rtx op0, op1; - - op0 = XEXP (operands[0], 0); - if (GET_CODE (op0) == REG - || (GET_CODE (op0) == PLUS && GET_CODE (XEXP (op0, 0)) == REG - && GET_CODE (XEXP (op0, 1)) == CONST_INT - && (unsigned) INTVAL (XEXP (op0, 1)) < 4096)) - op0 = operands[0]; - else - op0 = replace_equiv_address (operands[0], copy_to_mode_reg (SImode, op0)); - - op1 = XEXP (operands[1], 0); - if (GET_CODE (op1) == REG - || (GET_CODE (op1) == PLUS && GET_CODE (XEXP (op1, 0)) == REG - && GET_CODE (XEXP (op1, 1)) == CONST_INT - && (unsigned) INTVAL (XEXP (op1, 1)) < 4096)) - op1 = operands[1]; - else - op1 = replace_equiv_address (operands[1], copy_to_mode_reg (SImode, op1)); - - if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 256) - emit_insn (gen_rtx_PARALLEL (VOIDmode, - gen_rtvec (2, - gen_rtx_SET (VOIDmode, op0, op1), - gen_rtx_USE (VOIDmode, operands[2])))); - - else - { - /* implementation provided by Richard Henderson */ - rtx reg1 = gen_reg_rtx (DImode); - rtx reg2 = gen_reg_rtx (DImode); - rtx mem1 = operands[0]; - rtx mem2 = operands[1]; - rtx len = operands[2]; - if (!CONSTANT_P (len)) - len = force_reg (SImode, len); - - /* Load up the address+length pairs. */ - emit_insn (gen_rtx_CLOBBER (VOIDmode, reg1)); - emit_move_insn (gen_rtx_SUBREG (SImode, reg1, 0), - force_operand (XEXP (mem1, 0), NULL_RTX)); - emit_move_insn (gen_rtx_SUBREG (SImode, reg1, GET_MODE_SIZE (SImode)), len); - - emit_insn (gen_rtx_CLOBBER (VOIDmode, reg2)); - emit_move_insn (gen_rtx_SUBREG (SImode, reg2, 0), - force_operand (XEXP (mem2, 0), NULL_RTX)); - emit_move_insn (gen_rtx_SUBREG (SImode, reg2, GET_MODE_SIZE (SImode)), len); - - /* Copy! */ - emit_insn (gen_movstrsi_1 (reg1, reg2)); - } - DONE; -}") - -; Move a block that is less than 256 bytes in length. - -(define_insn "" - [(set (match_operand:BLK 0 "s_operand" "=m") - (match_operand:BLK 1 "s_operand" "m")) - (use (match_operand 2 "immediate_operand" "I"))] - "((unsigned) INTVAL (operands[2]) < 256)" - "* -{ - check_label_emit (); - mvs_check_page (0, 6, 0); - return \"MVC %O0(%c2,%R0),%1\"; -}" - [(set_attr "length" "6")] -) - -; Move a block that is larger than 255 bytes in length. - -(define_insn "movstrsi_1" - [(set (mem:BLK (subreg:SI (match_operand:DI 0 "register_operand" "+d") 0)) - (mem:BLK (subreg:SI (match_operand:DI 1 "register_operand" "+d") 0))) - (use (match_dup 0)) - (use (match_dup 1)) - (clobber (match_dup 0)) - (clobber (match_dup 1))] - "" - "* -{ - check_label_emit (); - mvs_check_page (0, 2, 0); - return \"MVCL %0,%1\"; -}" - [(set_attr "length" "2")] -) - -;; -;;- Conversion instructions. -;; - -; -; extendsidi2 instruction pattern(s). -; - -(define_expand "extendsidi2" - [(set (match_operand:DI 0 "register_operand" "=d") - (sign_extend:DI (match_operand:SI 1 "general_operand" "")))] - "" - " -{ - if (GET_CODE (operands[1]) != CONST_INT) - { - emit_insn (gen_rtx_SET (VOIDmode, - operand_subword (operands[0], 0, 1, DImode), operands[1])); - emit_insn (gen_rtx_SET (VOIDmode, operands[0], - gen_rtx_ASHIFTRT (DImode, operands[0], - gen_rtx_CONST_INT (SImode, 32)))); - } - else - { - if (INTVAL (operands[1]) < 0) - { - emit_insn (gen_rtx_SET (VOIDmode, - operand_subword (operands[0], 0, 1, DImode), - gen_rtx_CONST_INT (SImode, -1))); - } - else - { - emit_insn (gen_rtx_SET (VOIDmode, - operand_subword (operands[0], 0, 1, DImode), - gen_rtx_CONST_INT (SImode, 0))); - } - emit_insn (gen_rtx_SET (VOIDmode, gen_lowpart (SImode, operands[0]), - operands[1])); - } - DONE; -}") - -; -; extendhisi2 instruction pattern(s). -; - -(define_insn "extendhisi2" - [(set (match_operand:SI 0 "general_operand" "=d,m") - (sign_extend:SI (match_operand:HI 1 "general_operand" "g,d")))] - "" - "* -{ - check_label_emit (); - if (REG_P (operands[0])) - { - if (REG_P (operands[1])) - { - if (REGNO (operands[0]) != REGNO (operands[1])) - { - mvs_check_page (0, 10, 0); - return \"LR %0,%1\;SLL %0,16\;SRA %0,16\"; - } - else - return \"\"; /* Should be empty. 16-bits regs are always 32-bits. */ - } - if (operands[1] == const0_rtx) - { - CC_STATUS_INIT; - mvs_check_page (0, 2, 0); - return \"SLR %0,%0\"; - } - if (GET_CODE (operands[1]) == CONST_INT - && (unsigned) INTVAL (operands[1]) < 4096) - { - mvs_check_page (0, 4, 0); - return \"LA %0,%c1(0,0)\"; - } - if (GET_CODE (operands[1]) == CONST_INT) - { - mvs_check_page (0, 4, 0); - return \"LH %0,%H1\"; - } - mvs_check_page (0, 4, 0); - return \"LH %0,%1\"; - } - mvs_check_page (0, 12, 0); - return \"SLL %1,16\;SRA %1,16\;ST %1,%0\"; -}" - [(set_attr "length" "12")] -) - -; -; extendqisi2 instruction pattern(s). -; - -(define_insn "extendqisi2" - [(set (match_operand:SI 0 "general_operand" "=d") - (sign_extend:SI (match_operand:QI 1 "general_operand" "0mi")))] - "" - "* -{ - check_label_emit (); - CC_STATUS_SET (operands[0], operands[1]); - if (REG_P (operands[1])) - { - mvs_check_page (0, 8, 0); - return \"SLL %0,24\;SRA %0,24\"; - } - if (s_operand (operands[1], GET_MODE (operands[1]))) - { - mvs_check_page (0, 8, 0); - return \"ICM %0,8,%1\;SRA %0,24\"; - } - mvs_check_page (0, 12, 0); - return \"IC %0,%1\;SLL %0,24\;SRA %0,24\"; -}" - [(set_attr "length" "12")] -) - -; -; extendqihi2 instruction pattern(s). -; - -(define_insn "extendqihi2" - [(set (match_operand:HI 0 "general_operand" "=d") - (sign_extend:HI (match_operand:QI 1 "general_operand" "0m")))] - "" - "* -{ - check_label_emit (); - CC_STATUS_SET (operands[0], operands[1]); - if (REG_P (operands[1])) - { - mvs_check_page (0, 8, 0); - return \"SLL %0,24\;SRA %0,24\"; - } - if (s_operand (operands[1], GET_MODE (operands[1]))) - { - mvs_check_page (0, 8, 0); - return \"ICM %0,8,%1\;SRA %0,24\"; - } - mvs_check_page (0, 12, 0); - return \"IC %0,%1\;SLL %0,24\;SRA %0,24\"; -}" - [(set_attr "length" "12")] -) - -; -; zero_extendsidi2 instruction pattern(s). -; - -(define_expand "zero_extendsidi2" - [(set (match_operand:DI 0 "register_operand" "=d") - (zero_extend:DI (match_operand:SI 1 "general_operand" "")))] - "" - " -{ - emit_insn (gen_rtx_SET (VOIDmode, - operand_subword (operands[0], 0, 1, DImode), operands[1])); - emit_insn (gen_rtx_SET (VOIDmode, operands[0], - gen_rtx_LSHIFTRT (DImode, operands[0], - gen_rtx_CONST_INT (SImode, 32)))); - DONE; -}") - -; -; zero_extendhisi2 instruction pattern(s). -; - -(define_insn "zero_extendhisi2" - [(set (match_operand:SI 0 "general_operand" "=d") - (zero_extend:SI (match_operand:HI 1 "general_operand" "0")))] - "" - "* -{ - check_label_emit (); - /* AND only sets zero/not-zero bits not the arithmetic bits ... */ - CC_STATUS_INIT; - mvs_check_page (0, 4, 4); - return \"N %1,=XL4'0000FFFF'\"; -}" - [(set_attr "length" "4")] -) - -; -; zero_extendqisi2 instruction pattern(s). -; - -(define_insn "zero_extendqisi2" - [(set (match_operand:SI 0 "general_operand" "=d,&d") - (zero_extend:SI (match_operand:QI 1 "general_operand" "0i,m")))] - "" - "* -{ - check_label_emit (); - if (REG_P (operands[1])) - { - /* AND only sets zero/not-zero bits not the arithmetic bits ... */ - CC_STATUS_INIT; - mvs_check_page (0, 4, 4); - return \"N %0,=XL4'000000FF'\"; - } - if (GET_CODE (operands[1]) == CONST_INT) - { - mvs_check_page (0, 4, 0); - return \"LA %0,%c1(0,0)\"; - } - CC_STATUS_INIT; - mvs_check_page (0, 8, 0); - return \"SLR %0,%0\;IC %0,%1\"; -}" - [(set_attr "length" "8")] -) - -; -; zero_extendqihi2 instruction pattern(s). -; - -(define_insn "zero_extendqihi2" - [(set (match_operand:HI 0 "general_operand" "=d,&d") - (zero_extend:HI (match_operand:QI 1 "general_operand" "0i,m")))] - "" - "* -{ - check_label_emit (); - if (REG_P (operands[1])) - { - /* AND only sets zero/not-zero bits not the arithmetic bits ... */ - CC_STATUS_INIT; - mvs_check_page (0, 4, 4); - return \"N %0,=XL4'000000FF'\"; - } - if (GET_CODE (operands[1]) == CONST_INT) - { - mvs_check_page (0, 4, 0); - return \"LA %0,%c1(0,0)\"; - } - CC_STATUS_INIT; - mvs_check_page (0, 8, 0); - return \"SLR %0,%0\;IC %0,%1\"; -}" - [(set_attr "length" "8")] -) - -; -; truncsihi2 instruction pattern(s). -; - -(define_insn "truncsihi2" - [(set (match_operand:HI 0 "general_operand" "=d,m") - (truncate:HI (match_operand:SI 1 "general_operand" "0,d")))] - "" - "* -{ - check_label_emit (); - if (REG_P (operands[0])) - { - CC_STATUS_SET (operands[0], operands[1]); - mvs_check_page (0, 8, 0); - return \"SLL %0,16\;SRA %0,16\"; - } - mvs_check_page (0, 4, 0); - return \"STH %1,%0\"; -}" - [(set_attr "length" "8")] -) - -; -; fix_truncdfsi2 instruction pattern(s). -; - -(define_insn "fix_truncdfsi2" - [(set (match_operand:SI 0 "general_operand" "=d") - (fix:SI (truncate:DF (match_operand:DF 1 "general_operand" "+f")))) - (clobber (reg:DF 16))] - "" - "* -{ - check_label_emit (); - CC_STATUS_INIT; - if (REGNO (operands[1]) == 16) - { - mvs_check_page (0, 12, 8); - return \"AD 0,=XL8'4F08000000000000'\;STD 0,140(,13)\;L %0,144(,13)\"; - } - mvs_check_page (0, 14, 8); - return \"LDR 0,%1\;AD 0,=XL8'4F08000000000000'\;STD 0,140(,13)\;L %0,144(,13)\"; -}" - [(set_attr "length" "14")] -) - -; -; floatsidf2 instruction pattern(s). -; -; LE/370 mode uses the float field of the TCA. -; - -(define_insn "floatsidf2" - [(set (match_operand:DF 0 "general_operand" "=f") - (float:DF (match_operand:SI 1 "general_operand" "d")))] - "" - "* -{ - check_label_emit (); - CC_STATUS_INIT; -#ifdef TARGET_ELF_ABI - mvs_check_page (0, 22, 12); - return \"MVC 140(4,13),=XL4'4E000000'\;ST %1,144(,13)\;XI 144(13),128\;LD %0,140(,13)\;SD %0,=XL8'4E00000080000000'\"; -#else - mvs_check_page (0, 16, 8); - return \"ST %1,508(,12)\;XI 508(12),128\;LD %0,504(,12)\;SD %0,=XL8'4E00000080000000'\"; -#endif -}" - [(set_attr "length" "22")] -) - -; -; truncdfsf2 instruction pattern(s). -; - -(define_insn "truncdfsf2" - [(set (match_operand:SF 0 "general_operand" "=f") - (float_truncate:SF (match_operand:DF 1 "general_operand" "f")))] - "" - "* -{ - check_label_emit (); - mvs_check_page (0, 2, 0); - return \"LRER %0,%1\"; -}" - [(set_attr "length" "2")] -) - -; -; extendsfdf2 instruction pattern(s). -; - -(define_insn "extendsfdf2" - [(set (match_operand:DF 0 "general_operand" "=f") - (float_extend:DF (match_operand:SF 1 "general_operand" "fmF")))] - "" - "* -{ - check_label_emit (); - CC_STATUS_SET (0, const0_rtx); - if (FP_REG_P (operands[1])) - { - if (REGNO (operands[0]) == REGNO (operands[1])) - { - mvs_check_page (0, 10, 0); - return \"STE %1,140(,13)\;SDR %0,%0\;LE %0,140(,13)\"; - } - mvs_check_page (0, 4, 0); - return \"SDR %0,%0\;LER %0,%1\"; - } - mvs_check_page (0, 6, 0); - return \"SDR %0,%0\;LE %0,%1\"; -}" - [(set_attr "length" "10")] -) - -;; -;;- Add instructions. -;; - -; -; adddi3 instruction pattern(s). -; -; -;(define_expand "adddi3" -; [(set (match_operand:DI 0 "general_operand" "") -; (plus:DI (match_operand:DI 1 "general_operand" "") -; (match_operand:DI 2 "general_operand" "")))] -; "" -; " -;{ -; rtx label = gen_label_rtx (); -; rtx op0_high = operand_subword (operands[0], 0, 1, DImode); -; rtx op0_low = gen_lowpart (SImode, operands[0]); -; -; emit_insn (gen_rtx_SET (VOIDmode, op0_high, -; gen_rtx_PLUS (SImode, -; operand_subword (operands[1], 0, 1, DImode), -; operand_subword (operands[2], 0, 1, DImode)))); -; emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, -; gen_rtx_SET (VOIDmode, op0_low, -; gen_rtx_PLUS (SImode, gen_lowpart (SImode, operands[1]), -; gen_lowpart (SImode, operands[2]))), -; gen_rtx_USE (VOIDmode, gen_rtx_LABEL_REF (VOIDmode, label))))); -; emit_insn (gen_rtx_SET (VOIDmode, op0_high, -; gen_rtx_PLUS (SImode, op0_high, -; gen_rtx_CONST_INT (SImode, 1)))); -; emit_label (label); -; DONE; -;}") - -(define_insn "" - [(set (match_operand:SI 0 "general_operand" "=d") - (plus:SI (match_operand:SI 1 "general_operand" "%0") - (match_operand:SI 2 "general_operand" "g"))) - (use (label_ref (match_operand 3 "" ""))) -; (clobber (reg:SI 14)) - ] - "" - "* -{ - int onpage; - - check_label_emit (); - onpage = mvs_check_label (CODE_LABEL_NUMBER (operands[3])); - if (REG_P (operands[2])) - { - if (!onpage) - { - mvs_check_page (0, 8, 4); - return \"ALR %0,%2\;L 14,=A(%l3)\;BCR 12,14\"; - } - if (mvs_check_page (0, 6, 0)) - { - mvs_check_page (0, 2, 4); - return \"ALR %0,%2\;L 14,=A(%l3)\;BCR 12,14\"; - } - return \"ALR %0,%2\;BC 12,%l3\"; - } - if (!onpage) - { - mvs_check_page (0, 10, 4); - return \"AL %0,%2\;L 14,=A(%l3)\;BCR 12,14\"; - } - if (mvs_check_page (0, 8 ,0)) - { - mvs_check_page (0, 2, 4); - return \"AL %0,%2\;L 14,=A(%l3)\;BCR 12,14\"; - } - return \"AL %0,%2\;BC 12,%l3\"; -}" - [(set_attr "length" "10")] -) - -; -; addsi3 instruction pattern(s). -; -; The following insn is used when it is known that operand one is an address, -; frame, stack or argument pointer, and operand two is a constant that is -; small enough to fit in the displacement field. -; Notice that we can't allow the frame pointer to used as a normal register -; because of this insn. -; - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d") - (plus:SI (match_operand:SI 1 "general_operand" "%a") - (match_operand:SI 2 "immediate_operand" "J")))] - "((REGNO (operands[1]) == FRAME_POINTER_REGNUM || REGNO (operands[1]) == ARG_POINTER_REGNUM || REGNO (operands[1]) == STACK_POINTER_REGNUM) && (unsigned) INTVAL (operands[2]) < 4096)" - "* -{ - check_label_emit (); - CC_STATUS_INIT; /* add assumes CC but LA doesn't set CC */ - mvs_check_page (0, 4, 0); - return \"LA %0,%c2(,%1)\"; -}" - [(set_attr "length" "4")] -) - -; This insn handles additions that are relative to the frame pointer. - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d") - (plus:SI (match_operand:SI 1 "register_operand" "%a") - (match_operand:SI 2 "immediate_operand" "i")))] - "REGNO (operands[1]) == FRAME_POINTER_REGNUM" - "* -{ - check_label_emit (); - if ((unsigned) INTVAL (operands[2]) < 4096) - { - CC_STATUS_INIT; /* add assumes CC but LA doesn't set CC */ - mvs_check_page (0, 4, 0); - return \"LA %0,%c2(,%1)\"; - } - if (REGNO (operands[1]) == REGNO (operands[0])) - { - CC_STATUS_INIT; - mvs_check_page (0, 4, 0); - return \"A %0,%2\"; - } - mvs_check_page (0, 6, 0); - return \"L %0,%2\;AR %0,%1\"; -}" - [(set_attr "length" "6")] -) - -;; -;; The CC status bits for the arithmetic instructions are handled -;; in the NOTICE_UPDATE_CC macro (yeah???) and so they do not need -;; to be set below. They only need to be invalidated if *not* set -;; (e.g. by BCTR) ... yeah I think that's right ... -;; - -(define_insn "addsi3" - [(set (match_operand:SI 0 "general_operand" "=d") - (plus:SI (match_operand:SI 1 "general_operand" "%0") - (match_operand:SI 2 "general_operand" "g")))] - "" - "* -{ - check_label_emit (); - if (REG_P (operands[2])) - { - mvs_check_page (0, 2, 0); - return \"AR %0,%2\"; - } - if (GET_CODE (operands[2]) == CONST_INT) - { - if (INTVAL (operands[2]) == -1) - { - CC_STATUS_INIT; /* add assumes CC but BCTR doesn't set CC */ - mvs_check_page (0, 2, 0); - return \"BCTR %0,0\"; - } - } - mvs_check_page (0, 4, 0); - return \"A %0,%2\"; -}" - [(set_attr "length" "4")] -) - -; -; addhi3 instruction pattern(s). -; - -(define_insn "addhi3" - [(set (match_operand:HI 0 "general_operand" "=d") - (plus:HI (match_operand:HI 1 "general_operand" "%0") - (match_operand:HI 2 "general_operand" "dmi")))] - "" - "* -{ - check_label_emit (); - if (REG_P (operands[2])) - { - mvs_check_page (0, 8, 0); - return \"STH %2,140(,13)\;AH %0,140(,13)\"; - } - if (GET_CODE (operands[2]) == CONST_INT) - { - if (INTVAL (operands[2]) == -1) - { - CC_STATUS_INIT; /* add assumes CC but BCTR doesn't set CC */ - mvs_check_page (0, 2, 0); - return \"BCTR %0,0\"; - } - mvs_check_page (0, 4, 0); - return \"AH %0,%H2\"; - } - mvs_check_page (0, 4, 0); - return \"AH %0,%2\"; -}" - [(set_attr "length" "8")] -) - -; -; addqi3 instruction pattern(s). -; - -(define_insn "addqi3" - [(set (match_operand:QI 0 "general_operand" "=d") - (plus:QI (match_operand:QI 1 "general_operand" "%a") - (match_operand:QI 2 "general_operand" "ai")))] - "" - "* -{ - check_label_emit (); - CC_STATUS_INIT; /* add assumes CC but LA doesn't set CC */ - mvs_check_page (0, 4, 0); - if (REG_P (operands[2])) - return \"LA %0,0(%1,%2)\"; - return \"LA %0,%B2(,%1)\"; -}" - [(set_attr "length" "4")] -) - -; -; adddf3 instruction pattern(s). -; - -(define_insn "adddf3" - [(set (match_operand:DF 0 "general_operand" "=f") - (plus:DF (match_operand:DF 1 "general_operand" "%0") - (match_operand:DF 2 "general_operand" "fmF")))] - "" - "* -{ - check_label_emit (); - if (FP_REG_P (operands[2])) - { - mvs_check_page (0, 2, 0); - return \"ADR %0,%2\"; - } - mvs_check_page (0, 4, 0); - return \"AD %0,%2\"; -}" - [(set_attr "length" "4")] -) - -; -; addsf3 instruction pattern(s). -; - -(define_insn "addsf3" - [(set (match_operand:SF 0 "general_operand" "=f") - (plus:SF (match_operand:SF 1 "general_operand" "%0") - (match_operand:SF 2 "general_operand" "fmF")))] - "" - "* -{ - check_label_emit (); - if (FP_REG_P (operands[2])) - { - mvs_check_page (0, 2, 0); - return \"AER %0,%2\"; - } - mvs_check_page (0, 4, 0); - return \"AE %0,%2\"; -}" - [(set_attr "length" "4")] -) - -;; -;;- Subtract instructions. -;; - -; -; subdi3 instruction pattern(s). -; -; -;(define_expand "subdi3" -; [(set (match_operand:DI 0 "general_operand" "") -; (minus:DI (match_operand:DI 1 "general_operand" "") -; (match_operand:DI 2 "general_operand" "")))] -; "" -; " -;{ -; rtx label = gen_label_rtx (); -; rtx op0_high = operand_subword (operands[0], 0, 1, DImode); -; rtx op0_low = gen_lowpart (SImode, operands[0]); -; -; emit_insn (gen_rtx_SET (VOIDmode, op0_high, -; gen_rtx_MINUS (SImode, -; operand_subword (operands[1], 0, 1, DImode), -; operand_subword (operands[2], 0, 1, DImode)))); -; emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, -; gen_rtx_SET (VOIDmode, op0_low, -; gen_rtx_MINUS (SImode, -; gen_lowpart (SImode, operands[1]), -; gen_lowpart (SImode, operands[2]))), -; gen_rtx_USE (VOIDmode, -; gen_rtx_LABEL_REF (VOIDmode, label))))); -; emit_insn (gen_rtx_SET (VOIDmode, op0_high, -; gen_rtx_MINUS (SImode, op0_high, -; gen_rtx_CONST_INT (SImode, 1)))); -; emit_label (label); -; DONE; -;}") - -(define_insn "" - [(set (match_operand:SI 0 "general_operand" "=d") - (minus:SI (match_operand:SI 1 "general_operand" "0") - (match_operand:SI 2 "general_operand" "g"))) - (use (label_ref (match_operand 3 "" ""))) -; (clobber (reg:SI 14)) - ] - "" - "* -{ - int onpage; - - check_label_emit (); - CC_STATUS_INIT; - onpage = mvs_check_label (CODE_LABEL_NUMBER (operands[3])); - if (REG_P (operands[2])) - { - if (!onpage) - { - mvs_check_page (0, 8, 4); - return \"SLR %0,%2\;L 14,=A(%l3)\;BCR 12,14\"; - } - if (mvs_check_page (0, 6, 0)) - { - mvs_check_page (0, 2, 4); - return \"SLR %0,%2\;L 14,=A(%l3)\;BCR 12,14\"; - } - return \"SLR %0,%2\;BC 12,%l3\"; - } - if (!onpage) - { - mvs_check_page (0, 10, 4); - return \"SL %0,%2\;L 14,=A(%l3)\;BCR 12,14\"; - } - if (mvs_check_page (0, 8, 0)) - { - mvs_check_page (0, 2, 4); - return \"SL %0,%2\;L 14,=A(%l3)\;BCR 12,14\"; - } - return \"SL %0,%2\;BC 12,%l3\"; -}" - [(set_attr "length" "10")] -) - -; -; subsi3 instruction pattern(s). -; - -(define_insn "subsi3" - [(set (match_operand:SI 0 "general_operand" "=d") - (minus:SI (match_operand:SI 1 "general_operand" "0") - (match_operand:SI 2 "general_operand" "g")))] - "" - "* -{ - check_label_emit (); - if (REG_P (operands[2])) - { - mvs_check_page (0, 2, 0); - return \"SR %0,%2\"; - } - if (operands[2] == const1_rtx) - { - CC_STATUS_INIT; /* subtract assumes CC but BCTR doesn't set CC */ - mvs_check_page (0, 2, 0); - return \"BCTR %0,0\"; - } - mvs_check_page (0, 4, 0); - return \"S %0,%2\"; -}" - [(set_attr "length" "4")] -) - -; -; subhi3 instruction pattern(s). -; - -(define_insn "subhi3" - [(set (match_operand:HI 0 "general_operand" "=d") - (minus:HI (match_operand:HI 1 "general_operand" "0") - (match_operand:HI 2 "general_operand" "g")))] - "" - "* -{ - check_label_emit (); - if (REG_P (operands[2])) - { - mvs_check_page (0, 8, 0); - return \"STH %2,140(,13)\;SH %0,140(,13)\"; - } - if (operands[2] == const1_rtx) - { - CC_STATUS_INIT; /* subtract assumes CC but BCTR doesn't set CC */ - mvs_check_page (0, 2, 0); - return \"BCTR %0,0\"; - } - if (GET_CODE (operands[2]) == CONST_INT) - { - mvs_check_page (0, 4, 0); - return \"SH %0,%H2\"; - } - mvs_check_page (0, 4, 0); - return \"SH %0,%2\"; -}" - [(set_attr "length" "8")] -) - -; -; subqi3 instruction pattern(s). -; - -(define_expand "subqi3" - [(set (match_operand:QI 0 "general_operand" "=d") - (minus:QI (match_operand:QI 1 "general_operand" "0") - (match_operand:QI 2 "general_operand" "di")))] - "" - " -{ - if (REG_P (operands[2])) - { - emit_insn (gen_rtx_SET (VOIDmode, operands[0], - gen_rtx_MINUS (QImode, operands[1], operands[2]))); - } - else - { - emit_insn (gen_rtx_SET (VOIDmode, operands[0], - gen_rtx_PLUS (QImode, operands[1], - negate_rtx (QImode, operands[2])))); - } - DONE; -}") - -(define_insn "" - [(set (match_operand:QI 0 "register_operand" "=d") - (minus:QI (match_operand:QI 1 "register_operand" "0") - (match_operand:QI 2 "register_operand" "d")))] - "" - "* -{ - check_label_emit (); - mvs_check_page (0, 2, 0); - return \"SR %0,%2\"; -}" - [(set_attr "length" "2")] -) - -; -; subdf3 instruction pattern(s). -; - -(define_insn "subdf3" - [(set (match_operand:DF 0 "general_operand" "=f") - (minus:DF (match_operand:DF 1 "general_operand" "0") - (match_operand:DF 2 "general_operand" "fmF")))] - "" - "* -{ - check_label_emit (); - if (FP_REG_P (operands[2])) - { - mvs_check_page (0, 2, 0); - return \"SDR %0,%2\"; - } - mvs_check_page (0, 4, 0); - return \"SD %0,%2\"; -}" - [(set_attr "length" "4")] -) - -; -; subsf3 instruction pattern(s). -; - -(define_insn "subsf3" - [(set (match_operand:SF 0 "general_operand" "=f") - (minus:SF (match_operand:SF 1 "general_operand" "0") - (match_operand:SF 2 "general_operand" "fmF")))] - "" - "* -{ - check_label_emit (); - if (FP_REG_P (operands[2])) - { - mvs_check_page (0, 2, 0); - return \"SER %0,%2\"; - } - mvs_check_page (0, 4, 0); - return \"SE %0,%2\"; -}" - [(set_attr "length" "4")] -) - -;; -;;- Multiply instructions. -;; - -; -; mulsi3 instruction pattern(s). -; - -(define_expand "mulsi3" - [(set (match_operand:SI 0 "general_operand" "") - (mult:SI (match_operand:SI 1 "general_operand" "") - (match_operand:SI 2 "general_operand" "")))] - "" - " -{ - if (GET_CODE (operands[1]) == CONST_INT - && CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'K')) - { - emit_insn (gen_rtx_SET (VOIDmode, operands[0], - gen_rtx_MULT (SImode, operands[2], operands[1]))); - } - else if (GET_CODE (operands[2]) == CONST_INT - && CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K')) - { - emit_insn (gen_rtx_SET (VOIDmode, operands[0], - gen_rtx_MULT (SImode, operands[1], operands[2]))); - } - else - { - rtx r = gen_reg_rtx (DImode); - - /* XXX trouble. Below we generate some rtx's that model what - * is really supposed to happen with multiply on the 370/390 - * hardware, and that is all well & good. However, during optimization - * it can happen that the two operands are exchanged (after all, - * multiplication is commutitive), in which case the doubleword - * ends up in memory and everything is hosed. The gen_reg_rtx - * should have kept it in a reg ... We hack around this - * below, in the M/MR isntruction pattern, and constrain it to - * \"di\" instead of \"g\". But this still ends up with lots & lots of - * movement between registers & memory and is an awful waste. - * Dunno how to untwist it elegantly; but it seems to work for now. - */ - emit_insn (gen_rtx_SET (VOIDmode, - gen_rtx_SUBREG (SImode, r, GET_MODE_SIZE (SImode)), - operands[1])); - emit_insn (gen_rtx_SET (VOIDmode, r, - gen_rtx_MULT (DImode, r, operands[2]))); - emit_insn (gen_rtx_SET (VOIDmode, operands[0], - gen_rtx_SUBREG (SImode, r, GET_MODE_SIZE (SImode)))); - } - DONE; -}") - -(define_insn "" - [(set (match_operand:SI 0 "general_operand" "=d") - (mult:SI (match_operand:SI 1 "general_operand" "%0") - (match_operand:SI 2 "immediate_operand" "K")))] - "" - "* -{ - check_label_emit (); - mvs_check_page (0, 4, 0); - return \"MH %0,%H2\"; -}" - [(set_attr "length" "4")] -) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=d") - (mult:DI (match_operand:DI 1 "general_operand" "%0") - (match_operand:SI 2 "general_operand" "di")))] - "" - "* -{ - check_label_emit (); - if (REG_P (operands[2])) - { - mvs_check_page (0, 2, 0); - return \"MR %0,%2\"; - } - mvs_check_page (0, 4, 0); - return \"M %0,%2\"; -}" - [(set_attr "length" "4")] -) - -; -; muldf3 instruction pattern(s). -; - -(define_insn "muldf3" - [(set (match_operand:DF 0 "general_operand" "=f") - (mult:DF (match_operand:DF 1 "general_operand" "%0") - (match_operand:DF 2 "general_operand" "fmF")))] - "" - "* -{ - check_label_emit (); - if (FP_REG_P (operands[2])) - { - mvs_check_page (0, 2, 0); - return \"MDR %0,%2\"; - } - mvs_check_page (0, 4, 0); - return \"MD %0,%2\"; -}" - [(set_attr "length" "4")] -) - -; -; mulsf3 instruction pattern(s). -; - -(define_insn "mulsf3" - [(set (match_operand:SF 0 "general_operand" "=f") - (mult:SF (match_operand:SF 1 "general_operand" "%0") - (match_operand:SF 2 "general_operand" "fmF")))] - "" - "* -{ - check_label_emit (); - if (FP_REG_P (operands[2])) - { - mvs_check_page (0, 2, 0); - return \"MER %0,%2\"; - } - mvs_check_page (0, 4, 0); - return \"ME %0,%2\"; -}" - [(set_attr "length" "4")] -) - -;; -;;- Divide instructions. -;; - -; -; divsi3 instruction pattern(s). -; - -(define_expand "divsi3" - [(set (match_operand:SI 0 "general_operand" "") - (div:SI (match_operand:SI 1 "general_operand" "") - (match_operand:SI 2 "general_operand" "")))] - "" - " -{ - rtx r = gen_reg_rtx (DImode); - - emit_insn (gen_extendsidi2 (r, operands[1])); - emit_insn (gen_rtx_SET (VOIDmode, r, - gen_rtx_DIV (DImode, r, operands[2]))); - emit_insn (gen_rtx_SET (VOIDmode, operands[0], - gen_rtx_SUBREG (SImode, r, GET_MODE_SIZE (SImode)))); - DONE; -}") - - -; -; udivsi3 instruction pattern(s). -; - -(define_expand "udivsi3" - [(set (match_operand:SI 0 "general_operand" "") - (udiv:SI (match_operand:SI 1 "general_operand" "") - (match_operand:SI 2 "general_operand" "")))] - "" - " -{ - rtx dr = gen_reg_rtx (DImode); - rtx dr_0 = gen_rtx_SUBREG (SImode, dr, 0); - rtx dr_1 = gen_rtx_SUBREG (SImode, dr, GET_MODE_SIZE (SImode)); - - - if (GET_CODE (operands[2]) == CONST_INT) - { - if (INTVAL (operands[2]) > 0) - { - emit_insn (gen_zero_extendsidi2 (dr, operands[1])); - emit_insn (gen_rtx_SET (VOIDmode, dr, - gen_rtx_DIV (DImode, dr, operands[2]))); - } - else - { - rtx label1 = gen_label_rtx (); - - emit_insn (gen_rtx_SET (VOIDmode, dr_0, operands[1])); - emit_insn (gen_rtx_SET (VOIDmode, dr_1, const0_rtx)); - emit_insn (gen_cmpsi (dr_0, operands[2])); - emit_jump_insn (gen_bltu (label1)); - emit_insn (gen_rtx_SET (VOIDmode, dr_1, const1_rtx)); - emit_label (label1); - } - } - else - { - rtx label1 = gen_label_rtx (); - rtx label2 = gen_label_rtx (); - rtx label3 = gen_label_rtx (); - rtx sr = gen_reg_rtx (SImode); - - emit_insn (gen_rtx_SET (VOIDmode, dr_0, operands[1])); - emit_insn (gen_rtx_SET (VOIDmode, sr, operands[2])); - emit_insn (gen_rtx_SET (VOIDmode, dr_1, const0_rtx)); - emit_insn (gen_cmpsi (sr, dr_0)); - emit_jump_insn (gen_bgtu (label3)); - emit_insn (gen_cmpsi (sr, const1_rtx)); - emit_jump_insn (gen_blt (label2)); - emit_insn (gen_cmpsi (sr, const1_rtx)); - emit_jump_insn (gen_beq (label1)); - emit_insn (gen_rtx_SET (VOIDmode, dr, - gen_rtx_LSHIFTRT (DImode, dr, - gen_rtx_CONST_INT (SImode, 32)))); - emit_insn (gen_rtx_SET (VOIDmode, dr, - gen_rtx_DIV (DImode, dr, sr))); - emit_jump_insn (gen_jump (label3)); - emit_label (label1); - emit_insn (gen_rtx_SET (VOIDmode, dr_1, dr_0)); - emit_jump_insn (gen_jump (label3)); - emit_label (label2); - emit_insn (gen_rtx_SET (VOIDmode, dr_1, const1_rtx)); - emit_label (label3); - } - emit_insn (gen_rtx_SET (VOIDmode, operands[0], dr_1)); - - DONE; -}") - -; This is used by divsi3 & udivsi3. - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=d") - (div:DI (match_operand:DI 1 "register_operand" "0") - (match_operand:SI 2 "general_operand" "dm")))] - "" - "* -{ - check_label_emit (); - if (REG_P (operands[2])) - { - mvs_check_page (0, 2, 0); - return \"DR %0,%2\"; - } - mvs_check_page (0, 4, 0); - return \"D %0,%2\"; -}" - [(set_attr "length" "4")] -) - -; -; divdf3 instruction pattern(s). -; - -(define_insn "divdf3" - [(set (match_operand:DF 0 "general_operand" "=f") - (div:DF (match_operand:DF 1 "general_operand" "0") - (match_operand:DF 2 "general_operand" "fmF")))] - "" - "* -{ - check_label_emit (); - if (FP_REG_P (operands[2])) - { - mvs_check_page (0, 2, 0); - return \"DDR %0,%2\"; - } - mvs_check_page (0, 4, 0); - return \"DD %0,%2\"; -}" - [(set_attr "length" "4")] -) - -; -; divsf3 instruction pattern(s). -; - -(define_insn "divsf3" - [(set (match_operand:SF 0 "general_operand" "=f") - (div:SF (match_operand:SF 1 "general_operand" "0") - (match_operand:SF 2 "general_operand" "fmF")))] - "" - "* -{ - check_label_emit (); - if (FP_REG_P (operands[2])) - { - mvs_check_page (0, 2, 0); - return \"DER %0,%2\"; - } - mvs_check_page (0, 4, 0); - return \"DE %0,%2\"; -}" - [(set_attr "length" "4")] -) - -;; -;;- Modulo instructions. -;; - -; -; modsi3 instruction pattern(s). -; - -(define_expand "modsi3" - [(set (match_operand:SI 0 "general_operand" "") - (mod:SI (match_operand:SI 1 "general_operand" "") - (match_operand:SI 2 "general_operand" "")))] - "" - " -{ - rtx r = gen_reg_rtx (DImode); - - emit_insn (gen_extendsidi2 (r, operands[1])); - emit_insn (gen_rtx_SET (VOIDmode, r, - gen_rtx_MOD (DImode, r, operands[2]))); - emit_insn (gen_rtx_SET (VOIDmode, operands[0], - gen_rtx_SUBREG (SImode, r, 0))); - DONE; -}") - -; -; umodsi3 instruction pattern(s). -; - -(define_expand "umodsi3" - [(set (match_operand:SI 0 "general_operand" "") - (umod:SI (match_operand:SI 1 "general_operand" "") - (match_operand:SI 2 "general_operand" "")))] - "" - " -{ - rtx dr = gen_reg_rtx (DImode); - rtx dr_0 = gen_rtx_SUBREG (SImode, dr, 0); - - emit_insn (gen_rtx_SET (VOIDmode, dr_0, operands[1])); - - if (GET_CODE (operands[2]) == CONST_INT) - { - if (INTVAL (operands[2]) > 0) - { - emit_insn (gen_rtx_SET (VOIDmode, dr, - gen_rtx_LSHIFTRT (DImode, dr, - gen_rtx_CONST_INT (SImode, 32)))); - emit_insn (gen_rtx_SET (VOIDmode, dr, - gen_rtx_MOD (DImode, dr, operands[2]))); - } - else - { - rtx label1 = gen_label_rtx (); - rtx sr = gen_reg_rtx (SImode); - - emit_insn (gen_rtx_SET (VOIDmode, sr, operands[2])); - emit_insn (gen_cmpsi (dr_0, sr)); - emit_jump_insn (gen_bltu (label1)); - emit_insn (gen_rtx_SET (VOIDmode, sr, gen_rtx_ABS (SImode, sr))); - emit_insn (gen_rtx_SET (VOIDmode, dr_0, - gen_rtx_PLUS (SImode, dr_0, sr))); - emit_label (label1); - } - } - else - { - rtx label1 = gen_label_rtx (); - rtx label2 = gen_label_rtx (); - rtx label3 = gen_label_rtx (); - rtx sr = gen_reg_rtx (SImode); - - emit_insn (gen_rtx_SET (VOIDmode, dr_0, operands[1])); - emit_insn (gen_rtx_SET (VOIDmode, sr, operands[2])); - emit_insn (gen_cmpsi (sr, dr_0)); - emit_jump_insn (gen_bgtu (label3)); - emit_insn (gen_cmpsi (sr, const1_rtx)); - emit_jump_insn (gen_blt (label2)); - emit_jump_insn (gen_beq (label1)); - emit_insn (gen_rtx_SET (VOIDmode, dr, - gen_rtx_LSHIFTRT (DImode, dr, - gen_rtx_CONST_INT (SImode, 32)))); - emit_insn (gen_rtx_SET (VOIDmode, dr, gen_rtx_MOD (DImode, dr, sr))); - emit_jump_insn (gen_jump (label3)); - emit_label (label1); - emit_insn (gen_rtx_SET (VOIDmode, dr_0, const0_rtx)); - emit_jump_insn (gen_jump (label3)); - emit_label (label2); - emit_insn (gen_rtx_SET (VOIDmode, dr_0, - gen_rtx_MINUS (SImode, dr_0, sr))); - emit_label (label3); - - } - emit_insn (gen_rtx_SET (VOIDmode, operands[0], dr_0)); - - DONE; -}") - -; This is used by modsi3 & umodsi3. - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=d") - (mod:DI (match_operand:DI 1 "register_operand" "0") - (match_operand:SI 2 "general_operand" "dm")))] - "" - "* -{ - check_label_emit (); - if (REG_P (operands[2])) - { - mvs_check_page (0, 2, 0); - return \"DR %0,%2\"; - } - mvs_check_page (0, 4, 0); - return \"D %0,%2\"; -}" - [(set_attr "length" "4")] -) - -;; -;;- And instructions. -;; - -; -; anddi3 instruction pattern(s). -; - -;(define_expand "anddi3" -; [(set (match_operand:DI 0 "general_operand" "") -; (and:DI (match_operand:DI 1 "general_operand" "") -; (match_operand:DI 2 "general_operand" "")))] -; "" -; " -;{ -; rtx gen_andsi3(); -; -; emit_insn (gen_andsi3 (operand_subword (operands[0], 0, 1, DImode), -; operand_subword (operands[1], 0, 1, DImode), -; operand_subword (operands[2], 0, 1, DImode))); -; emit_insn (gen_andsi3 (gen_lowpart (SImode, operands[0]), -; gen_lowpart (SImode, operands[1]), -; gen_lowpart (SImode, operands[2]))); -; DONE; -;}") - -; -; andsi3 instruction pattern(s). -; - -(define_insn "" - [(set (match_operand:SI 0 "r_or_s_operand" "=d,m") - (and:SI (match_operand:SI 1 "r_or_s_operand" "%0,0") - (match_operand:SI 2 "r_or_s_operand" "g,mi")))] - "TARGET_CHAR_INSTRUCTIONS" - "* -{ - check_label_emit (); - CC_STATUS_INIT; /* and sets CC but not how we want it */ - if (REG_P (operands[2])) - { - mvs_check_page (0, 2, 0); - return \"NR %0,%2\"; - } - if (REG_P (operands[0])) - { - mvs_check_page (0, 4, 0); - return \"N %0,%2\"; - } - mvs_check_page (0, 6, 0); - return \"NC %O0(4,%R0),%2\"; -}" - [(set_attr "length" "6")] -) - -(define_insn "andsi3" - [(set (match_operand:SI 0 "general_operand" "=d") - (and:SI (match_operand:SI 1 "general_operand" "%0") - (match_operand:SI 2 "general_operand" "g")))] - "" - "* -{ - check_label_emit (); - CC_STATUS_INIT; /* and sets CC but not how we want it */ - if (REG_P (operands[2])) - { - mvs_check_page (0, 2, 0); - return \"NR %0,%2\"; - } - mvs_check_page (0, 4, 0); - return \"N %0,%2\"; -}" - [(set_attr "length" "4")] -) - -; -; andhi3 instruction pattern(s). -; - -(define_insn "" - [(set (match_operand:HI 0 "r_or_s_operand" "=d,m") - (and:HI (match_operand:HI 1 "r_or_s_operand" "%0,0") - (match_operand:HI 2 "r_or_s_operand" "di,mi")))] - "TARGET_CHAR_INSTRUCTIONS" - "* -{ - check_label_emit (); - CC_STATUS_INIT; /* and sets CC but not how we want it */ - if (REG_P (operands[2])) - { - mvs_check_page (0, 2, 0); - return \"NR %0,%2\"; - } - if (REG_P (operands[0])) - { - /* %K2 == sign extend operand to 32 bits so that CH works */ - mvs_check_page (0, 4, 0); - if (GET_CODE (operands[2]) == CONST_INT) - return \"N %0,%K2\"; - return \"N %0,%2\"; - } - if (GET_CODE (operands[2]) == CONST_INT) - { - mvs_check_page (0, 6, 0); - return \"NC %O0(2,%R0),%H2\"; - } - mvs_check_page (0, 6, 0); - return \"NC %O0(2,%R0),%2\"; -}" - [(set_attr "length" "6")] -) - -(define_insn "andhi3" - [(set (match_operand:HI 0 "general_operand" "=d") - (and:HI (match_operand:HI 1 "general_operand" "%0") - (match_operand:HI 2 "general_operand" "di")))] - "" - "* -{ - check_label_emit (); - CC_STATUS_INIT; /* and sets CC but not how we want it */ - if (GET_CODE (operands[2]) == CONST_INT) - { - /* %K2 == sign extend operand to 32 bits so that CH works */ - mvs_check_page (0, 4, 0); - return \"N %0,%K2\"; - } - mvs_check_page (0, 2, 0); - return \"NR %0,%2\"; -}" - [(set_attr "length" "4")] -) - -; -; andqi3 instruction pattern(s). -; - -(define_insn "" - [(set (match_operand:QI 0 "r_or_s_operand" "=d,m") - (and:QI (match_operand:QI 1 "r_or_s_operand" "%0,0") - (match_operand:QI 2 "r_or_s_operand" "di,mi")))] - "TARGET_CHAR_INSTRUCTIONS" - "* -{ - check_label_emit (); - CC_STATUS_INIT; /* and sets CC but not how we want it */ - if (REG_P (operands[2])) - { - mvs_check_page (0, 2, 0); - return \"NR %0,%2\"; - } - if (REG_P (operands[0])) - { - mvs_check_page (0, 4, 0); - return \"N %0,%2\"; - } - if (GET_CODE (operands[2]) == CONST_INT) - { - mvs_check_page (0, 4, 0); - return \"NI %0,%B2\"; - } - mvs_check_page (0, 6, 0); - return \"NC %O0(1,%R0),%2\"; -}" - [(set_attr "length" "6")] -) - -(define_insn "andqi3" - [(set (match_operand:QI 0 "general_operand" "=d") - (and:QI (match_operand:QI 1 "general_operand" "%0") - (match_operand:QI 2 "general_operand" "di")))] - "" - "* -{ - check_label_emit (); - CC_STATUS_INIT; /* and sets CC but not how we want it */ - if (GET_CODE (operands[2]) == CONST_INT) - { - mvs_check_page (0, 4, 0); - return \"N %0,%2\"; - } - mvs_check_page (0, 2, 0); - return \"NR %0,%2\"; -}" - [(set_attr "length" "4")] -) - -;; -;;- Bit set (inclusive or) instructions. -;; - -; -; iordi3 instruction pattern(s). -; - -;(define_expand "iordi3" -; [(set (match_operand:DI 0 "general_operand" "") -; (ior:DI (match_operand:DI 1 "general_operand" "") -; (match_operand:DI 2 "general_operand" "")))] -; "" -; " -;{ -; rtx gen_iorsi3(); -; -; emit_insn (gen_iorsi3 (operand_subword (operands[0], 0, 1, DImode), -; operand_subword (operands[1], 0, 1, DImode), -; operand_subword (operands[2], 0, 1, DImode))); -; emit_insn (gen_iorsi3 (gen_lowpart (SImode, operands[0]), -; gen_lowpart (SImode, operands[1]), -; gen_lowpart (SImode, operands[2]))); -; DONE; -;}") - -; -; iorsi3 instruction pattern(s). -; - -(define_insn "" - [(set (match_operand:SI 0 "r_or_s_operand" "=d,m") - (ior:SI (match_operand:SI 1 "r_or_s_operand" "%0,0") - (match_operand:SI 2 "r_or_s_operand" "g,Si")))] - "TARGET_CHAR_INSTRUCTIONS" - "* -{ - check_label_emit (); - CC_STATUS_INIT; /* OR sets CC but not how we want it */ - if (REG_P (operands[2])) - { - mvs_check_page (0, 2, 0); - return \"OR %0,%2\"; - } - if (REG_P (operands[0])) - { - mvs_check_page (0, 4, 0); - return \"O %0,%2\"; - } - mvs_check_page (0, 6, 0); - return \"OC %O0(4,%R0),%2\"; -}" - [(set_attr "length" "6")] -) - -(define_insn "iorsi3" - [(set (match_operand:SI 0 "general_operand" "=d") - (ior:SI (match_operand:SI 1 "general_operand" "%0") - (match_operand:SI 2 "general_operand" "g")))] - "" - "* -{ - check_label_emit (); - CC_STATUS_INIT; /* OR sets CC but not how we want it */ - if (REG_P (operands[2])) - { - mvs_check_page (0, 2, 0); - return \"OR %0,%2\"; - } - mvs_check_page (0, 4, 0); - return \"O %0,%2\"; -}" - [(set_attr "length" "4")] -) - -; -; iorhi3 instruction pattern(s). -; - -(define_insn "" - [(set (match_operand:HI 0 "r_or_s_operand" "=d,m") - (ior:HI (match_operand:HI 1 "r_or_s_operand" "%0,0") - (match_operand:HI 2 "r_or_s_operand" "di,mi")))] - "TARGET_CHAR_INSTRUCTIONS" - "* -{ - check_label_emit (); - CC_STATUS_INIT; /* OR sets CC but not how we want it */ - if (REG_P (operands[2])) - { - mvs_check_page (0, 2, 0); - return \"OR %0,%2\"; - } - if (REG_P (operands[0])) - { - mvs_check_page (0, 4, 0); - return \"O %0,%2\"; - } - if (GET_CODE (operands[2]) == CONST_INT) - { - mvs_check_page (0, 6, 2); - return \"OC %O0(2,%R0),%H2\"; - } - mvs_check_page (0, 6, 0); - return \"OC %O0(2,%R0),%2\"; -}" - [(set_attr "length" "6")] -) - -(define_insn "iorhi3" - [(set (match_operand:HI 0 "general_operand" "=d") - (ior:HI (match_operand:HI 1 "general_operand" "%0") - (match_operand:HI 2 "general_operand" "di")))] - "" - "* -{ - check_label_emit (); - CC_STATUS_INIT; /* OR sets CC but not how we want it */ - if (GET_CODE (operands[2]) == CONST_INT) - { - mvs_check_page (0, 4, 0); - return \"O %0,%2\"; - } - mvs_check_page (0, 2, 0); - return \"OR %0,%2\"; -}" - [(set_attr "length" "4")] -) - -; -; iorqi3 instruction pattern(s). -; - -(define_insn "" - [(set (match_operand:QI 0 "r_or_s_operand" "=d,m") - (ior:QI (match_operand:QI 1 "r_or_s_operand" "%0,0") - (match_operand:QI 2 "r_or_s_operand" "di,mi")))] - "TARGET_CHAR_INSTRUCTIONS" - "* -{ - check_label_emit (); - CC_STATUS_INIT; /* OR sets CC but not how we want it */ - if (REG_P (operands[2])) - { - mvs_check_page (0, 2, 0); - return \"OR %0,%2\"; - } - if (REG_P (operands[0])) - { - mvs_check_page (0, 4, 0); - return \"O %0,%2\"; - } - if (GET_CODE (operands[2]) == CONST_INT) - { - mvs_check_page (0, 4, 0); - return \"OI %0,%B2\"; - } - mvs_check_page (0, 6, 0); - return \"OC %O0(1,%R0),%2\"; -}" - [(set_attr "length" "6")] -) - -(define_insn "iorqi3" - [(set (match_operand:QI 0 "general_operand" "=d") - (ior:QI (match_operand:QI 1 "general_operand" "%0") - (match_operand:QI 2 "general_operand" "di")))] - "" - "* -{ - check_label_emit (); - CC_STATUS_INIT; /* OR sets CC but not how we want it */ - if (GET_CODE (operands[2]) == CONST_INT) - { - mvs_check_page (0, 4, 0); - return \"O %0,%2\"; - } - mvs_check_page (0, 2, 0); - return \"OR %0,%2\"; -}" - [(set_attr "length" "4")] -) - -;; -;;- Xor instructions. -;; - -; -; xordi3 instruction pattern(s). -; - -;(define_expand "xordi3" -; [(set (match_operand:DI 0 "general_operand" "") -; (xor:DI (match_operand:DI 1 "general_operand" "") -; (match_operand:DI 2 "general_operand" "")))] -; "" -; " -;{ -; rtx gen_xorsi3(); -; -; emit_insn (gen_xorsi3 (operand_subword (operands[0], 0, 1, DImode), -; operand_subword (operands[1], 0, 1, DImode), -; operand_subword (operands[2], 0, 1, DImode))); -; emit_insn (gen_xorsi3 (gen_lowpart (SImode, operands[0]), -; gen_lowpart (SImode, operands[1]), -; gen_lowpart (SImode, operands[2]))); -; DONE; -;}") - -; -; xorsi3 instruction pattern(s). -; - -(define_insn "" - [(set (match_operand:SI 0 "r_or_s_operand" "=d,m") - (xor:SI (match_operand:SI 1 "r_or_s_operand" "%0,0") - (match_operand:SI 2 "r_or_s_operand" "g,mi")))] - "TARGET_CHAR_INSTRUCTIONS" - "* -{ - check_label_emit (); - CC_STATUS_INIT; /* XOR sets CC but not how we want it */ - if (REG_P (operands[2])) - { - mvs_check_page (0, 2, 0); - return \"XR %0,%2\"; - } - if (REG_P (operands[0])) - { - mvs_check_page (0, 4, 0); - return \"X %0,%2\"; - } - mvs_check_page (0, 6, 0); - return \"XC %O0(4,%R0),%2\"; -}" - [(set_attr "length" "6")] -) - -(define_insn "xorsi3" - [(set (match_operand:SI 0 "general_operand" "=d") - (xor:SI (match_operand:SI 1 "general_operand" "%0") - (match_operand:SI 2 "general_operand" "g")))] - "" - "* -{ - check_label_emit (); - CC_STATUS_INIT; /* XOR sets CC but not how we want it */ - if (REG_P (operands[2])) - { - mvs_check_page (0, 2, 0); - return \"XR %0,%2\"; - } - mvs_check_page (0, 4, 0); - return \"X %0,%2\"; -}" - [(set_attr "length" "4")] -) - -; -; xorhi3 instruction pattern(s). -; - -(define_insn "" - [(set (match_operand:HI 0 "r_or_s_operand" "=d,m") - (xor:HI (match_operand:HI 1 "r_or_s_operand" "%0,0") - (match_operand:HI 2 "r_or_s_operand" "di,mi")))] - "TARGET_CHAR_INSTRUCTIONS" - "* -{ - check_label_emit (); - CC_STATUS_INIT; /* XOR sets CC but not how we want it */ - if (REG_P (operands[2])) - { - mvs_check_page (0, 2, 0); - return \"XR %0,%2\"; - } - if (REG_P (operands[0])) - { - mvs_check_page (0, 4, 0); - return \"X %0,%H2\"; - } - if (GET_CODE (operands[2]) == CONST_INT) - { - mvs_check_page (0, 6, 0); - return \"XC %O0(2,%R0),%H2\"; - } - mvs_check_page (0, 6, 0); - return \"XC %O0(2,%R0),%2\"; -}" - [(set_attr "length" "6")] -) - -(define_insn "xorhi3" - [(set (match_operand:HI 0 "general_operand" "=d") - (xor:HI (match_operand:HI 1 "general_operand" "%0") - (match_operand:HI 2 "general_operand" "di")))] - "" - "* -{ - check_label_emit (); - CC_STATUS_INIT; /* XOR sets CC but not how we want it */ - if (GET_CODE (operands[2]) == CONST_INT) - { - mvs_check_page (0, 4, 0); - return \"X %0,%H2\"; - } - mvs_check_page (0, 2, 0); - return \"XR %0,%2\"; -}" - [(set_attr "length" "4")] -) - -; -; xorqi3 instruction pattern(s). -; - -(define_insn "" - [(set (match_operand:QI 0 "r_or_s_operand" "=d,m") - (xor:QI (match_operand:QI 1 "r_or_s_operand" "%0,0") - (match_operand:QI 2 "r_or_s_operand" "di,mi")))] - "TARGET_CHAR_INSTRUCTIONS" - "* -{ - check_label_emit (); - CC_STATUS_INIT; /* XOR sets CC but not how we want it */ - if (REG_P (operands[2])) - { - mvs_check_page (0, 2, 0); - return \"XR %0,%2\"; - } - if (REG_P (operands[0])) - { - mvs_check_page (0, 4, 0); - return \"X %0,%2\"; - } - if (GET_CODE (operands[2]) == CONST_INT) - { - mvs_check_page (0, 4, 0); - return \"XI %0,%B2\"; - } - mvs_check_page (0, 6, 0); - return \"XC %O0(1,%R0),%2\"; -}" - [(set_attr "length" "6")] -) - -(define_insn "xorqi3" - [(set (match_operand:QI 0 "general_operand" "=d") - (xor:QI (match_operand:QI 1 "general_operand" "%0") - (match_operand:QI 2 "general_operand" "di")))] - "" - "* -{ - check_label_emit (); - CC_STATUS_INIT; /* XOR sets CC but not how we want it */ - if (GET_CODE (operands[2]) == CONST_INT) - { - mvs_check_page (0, 4, 0); - return \"X %0,%2\"; - } - mvs_check_page (0, 2, 0); - return \"XR %0,%2\"; -}" - [(set_attr "length" "4")] -) - -;; -;;- Negate instructions. -;; - -; -; negsi2 instruction pattern(s). -; - -(define_insn "negsi2" - [(set (match_operand:SI 0 "general_operand" "=d") - (neg:SI (match_operand:SI 1 "general_operand" "d")))] - "" - "* -{ - check_label_emit (); - mvs_check_page (0, 2, 0); - return \"LCR %0,%1\"; -}" - [(set_attr "length" "2")] -) - -; -; neghi2 instruction pattern(s). -; - -(define_insn "neghi2" - [(set (match_operand:HI 0 "general_operand" "=d") - (neg:HI (match_operand:HI 1 "general_operand" "d")))] - "" - "* -{ - check_label_emit (); - mvs_check_page (0, 10, 0); - return \"SLL %1,16\;SRA %1,16\;LCR %0,%1\"; -}" - [(set_attr "length" "10")] -) - -; -; negdf2 instruction pattern(s). -; - -(define_insn "negdf2" - [(set (match_operand:DF 0 "general_operand" "=f") - (neg:DF (match_operand:DF 1 "general_operand" "f")))] - "" - "* -{ - check_label_emit (); - mvs_check_page (0, 2, 0); - return \"LCDR %0,%1\"; -}" - [(set_attr "length" "2")] -) - -; -; negsf2 instruction pattern(s). -; - -(define_insn "negsf2" - [(set (match_operand:SF 0 "general_operand" "=f") - (neg:SF (match_operand:SF 1 "general_operand" "f")))] - "" - "* -{ - check_label_emit (); - mvs_check_page (0, 2, 0); - return \"LCER %0,%1\"; -}" - [(set_attr "length" "2")] -) - -;; -;;- Absolute value instructions. -;; - -; -; abssi2 instruction pattern(s). -; - -(define_insn "abssi2" - [(set (match_operand:SI 0 "general_operand" "=d") - (abs:SI (match_operand:SI 1 "general_operand" "d")))] - "" - "* -{ - check_label_emit (); - mvs_check_page (0, 2, 0); - return \"LPR %0,%1\"; -}" - [(set_attr "length" "2")] -) - -; -; abshi2 instruction pattern(s). -; - -(define_insn "abshi2" - [(set (match_operand:HI 0 "general_operand" "=d") - (abs:HI (match_operand:HI 1 "general_operand" "d")))] - "" - "* -{ - check_label_emit (); - mvs_check_page (0, 10, 0); - return \"SLL %1,16\;SRA %1,16\;LPR %0,%1\"; -}" - [(set_attr "length" "10")] -) - -; -; absdf2 instruction pattern(s). -; - -(define_insn "absdf2" - [(set (match_operand:DF 0 "general_operand" "=f") - (abs:DF (match_operand:DF 1 "general_operand" "f")))] - "" - "* -{ - check_label_emit (); - mvs_check_page (0, 2, 0); - return \"LPDR %0,%1\"; -}" - [(set_attr "length" "2")] -) - -; -; abssf2 instruction pattern(s). -; - -(define_insn "abssf2" - [(set (match_operand:SF 0 "general_operand" "=f") - (abs:SF (match_operand:SF 1 "general_operand" "f")))] - "" - "* -{ - check_label_emit (); - mvs_check_page (0, 2, 0); - return \"LPER %0,%1\"; -}" - [(set_attr "length" "2")] -) - -;; -;;- One complement instructions. -;; - -; -; one_cmpldi2 instruction pattern(s). -; - -;(define_expand "one_cmpldi2" -; [(set (match_operand:DI 0 "general_operand" "") -; (not:DI (match_operand:DI 1 "general_operand" "")))] -; "" -; " -;{ -; rtx gen_one_cmplsi2(); -; -; emit_insn (gen_one_cmplsi2 (operand_subword (operands[0], 0, 1, DImode), -; operand_subword (operands[1], 0, 1, DImode))); -; emit_insn (gen_one_cmplsi2 (gen_lowpart (SImode, operands[0]), -; gen_lowpart (SImode, operands[1]))); -; DONE; -;}") - -; -; one_cmplsi2 instruction pattern(s). -; - -(define_insn "" - [(set (match_operand:SI 0 "r_or_s_operand" "=dm") - (not:SI (match_operand:SI 1 "r_or_s_operand" "0")))] - "TARGET_CHAR_INSTRUCTIONS" - "* -{ - check_label_emit (); - CC_STATUS_INIT; /* XOR sets CC but not how we want it */ - if (REG_P (operands[0])) - { - mvs_check_page (0, 4, 4); - return \"X %0,=F'-1'\"; - } - CC_STATUS_INIT; - mvs_check_page (0, 6, 4); - return \"XC %O0(4,%R0),=F'-1'\"; -}" - [(set_attr "length" "6")] -) - -(define_insn "one_cmplsi2" - [(set (match_operand:SI 0 "general_operand" "=d") - (not:SI (match_operand:SI 1 "general_operand" "0")))] - "" - "* -{ - check_label_emit (); - CC_STATUS_INIT; /* XOR sets CC but not how we want it */ - mvs_check_page (0, 4, 4); - return \"X %0,=F'-1'\"; -}" - [(set_attr "length" "4")] -) - -; -; one_cmplhi2 instruction pattern(s). -; - -(define_insn "" - [(set (match_operand:HI 0 "r_or_s_operand" "=dm") - (not:HI (match_operand:HI 1 "r_or_s_operand" "0")))] - "TARGET_CHAR_INSTRUCTIONS" - "* -{ - check_label_emit (); - CC_STATUS_INIT; /* XOR sets CC but not how we want it */ - if (REG_P (operands[0])) - { - mvs_check_page (0, 4, 4); - return \"X %0,=F'-1'\"; - } - mvs_check_page (0, 6, 4); - return \"XC %O0(2,%R0),=XL4'FFFF'\"; -}" - [(set_attr "length" "6")] -) - -(define_insn "one_cmplhi2" - [(set (match_operand:HI 0 "general_operand" "=d") - (not:HI (match_operand:HI 1 "general_operand" "0")))] - "" - "* -{ - check_label_emit (); - CC_STATUS_INIT; /* XOR sets CC but not how we want it */ - mvs_check_page (0, 4, 4); - return \"X %0,=F'-1'\"; -}" - [(set_attr "length" "4")] -) - -; -; one_cmplqi2 instruction pattern(s). -; - -(define_insn "" - [(set (match_operand:QI 0 "r_or_s_operand" "=dm") - (not:QI (match_operand:QI 1 "r_or_s_operand" "0")))] - "TARGET_CHAR_INSTRUCTIONS" - "* -{ - check_label_emit (); - CC_STATUS_INIT; /* XOR sets CC but not how we want it */ - if (REG_P (operands[0])) - { - mvs_check_page (0, 4, 4); - return \"X %0,=F'-1'\"; - } - mvs_check_page (0, 4, 0); - return \"XI %0,255\"; -}" - [(set_attr "length" "4")] -) - -(define_insn "one_cmplqi2" - [(set (match_operand:QI 0 "general_operand" "=d") - (not:QI (match_operand:QI 1 "general_operand" "0")))] - "" - "* -{ - check_label_emit (); - CC_STATUS_INIT; /* XOR sets CC but not how we want it */ - mvs_check_page (0, 4, 4); - return \"X %0,=F'-1'\"; -}" - [(set_attr "length" "4")] -) - -;; -;;- Arithmetic shift instructions. -;; - -; -; ashldi3 instruction pattern(s). -; - -(define_insn "ashldi3" - [(set (match_operand:DI 0 "general_operand" "=d") - (ashift:DI (match_operand:DI 1 "general_operand" "0") - (match_operand:SI 2 "general_operand" "Ja")))] - "" - "* -{ - check_label_emit (); - /* this status set seems not have the desired effect, - * proably because the 64-bit long-long test is emulated ?! */ - CC_STATUS_SET (operands[0], operands[1]); - mvs_check_page (0, 4, 0); - if (REG_P (operands[2])) - return \"SLDA %0,0(%2)\"; - return \"SLDA %0,%c2\"; -}" - [(set_attr "length" "4")] -) - -; -; ashrdi3 instruction pattern(s). -; - -(define_insn "ashrdi3" - [(set (match_operand:DI 0 "register_operand" "=d") - (ashiftrt:DI (match_operand:DI 1 "general_operand" "0") - (match_operand:SI 2 "general_operand" "Ja")))] - "" - "* -{ - check_label_emit (); - /* this status set seems not have the desired effect, - * proably because the 64-bit long-long test is emulated ?! */ - CC_STATUS_SET (operands[0], operands[1]); - mvs_check_page (0, 4, 0); - if (REG_P (operands[2])) - return \"SRDA %0,0(%2)\"; - return \"SRDA %0,%c2\"; -}" - [(set_attr "length" "4")] -) - -; -; ashlsi3 instruction pattern(s). -; - -(define_insn "ashlsi3" - [(set (match_operand:SI 0 "general_operand" "=d") - (ashift:SI (match_operand:SI 1 "general_operand" "0") - (match_operand:SI 2 "general_operand" "Ja")))] - "" - "* -{ - check_label_emit (); - mvs_check_page (0, 4, 0); - if (REG_P (operands[2])) - return \"SLL %0,0(%2)\"; - return \"SLL %0,%c2\"; -}" - [(set_attr "length" "4")] -) - -; -; ashrsi3 instruction pattern(s). -; - -(define_insn "ashrsi3" - [(set (match_operand:SI 0 "general_operand" "=d") - (ashiftrt:SI (match_operand:SI 1 "general_operand" "0") - (match_operand:SI 2 "general_operand" "Ja")))] - "" - "* -{ - check_label_emit (); - CC_STATUS_SET (operands[0], operands[1]); - mvs_check_page (0, 4, 0); - if (REG_P (operands[2])) - return \"SRA %0,0(%2)\"; - return \"SRA %0,%c2\"; -}" - [(set_attr "length" "4")] -) - -; -; ashlhi3 instruction pattern(s). -; - -(define_insn "ashlhi3" - [(set (match_operand:HI 0 "general_operand" "=d") - (ashift:HI (match_operand:HI 1 "general_operand" "0") - (match_operand:SI 2 "general_operand" "Ja")))] - "" - "* -{ - check_label_emit (); - mvs_check_page (0, 8, 0); - if (REG_P (operands[2])) - return \"SLL %0,16(%2)\;SRA %0,16\"; - return \"SLL %0,16+%c2\;SRA %0,16\"; -}" - [(set_attr "length" "8")] -) - -; -; ashrhi3 instruction pattern(s). -; - -(define_insn "ashrhi3" - [(set (match_operand:HI 0 "general_operand" "=d") - (ashiftrt:HI (match_operand:HI 1 "general_operand" "0") - (match_operand:SI 2 "general_operand" "Ja")))] - "" - "* -{ - check_label_emit (); - mvs_check_page (0, 8, 0); - if (REG_P (operands[2])) - return \"SLL %0,16\;SRA %0,16(%2)\"; - return \"SLL %0,16\;SRA %0,16+%c2\"; -}" - [(set_attr "length" "8")] -) - -; -; ashlqi3 instruction pattern(s). -; - -(define_insn "ashlqi3" - [(set (match_operand:QI 0 "general_operand" "=d") - (ashift:QI (match_operand:QI 1 "general_operand" "0") - (match_operand:SI 2 "general_operand" "Ja")))] - "" - "* -{ - check_label_emit (); - mvs_check_page (0, 4, 0); - if (REG_P (operands[2])) - return \"SLL %0,0(%2)\"; - return \"SLL %0,%c2\"; -}" - [(set_attr "length" "4")] -) - -; -; ashrqi3 instruction pattern(s). -; - -(define_insn "ashrqi3" - [(set (match_operand:QI 0 "general_operand" "=d") - (ashiftrt:QI (match_operand:QI 1 "general_operand" "0") - (match_operand:SI 2 "general_operand" "Ja")))] - "" - "* -{ - check_label_emit (); - mvs_check_page (0, 8, 0); - if (REG_P (operands[2])) - return \"SLL %0,24\;SRA %0,24(%2)\"; - return \"SLL %0,24\;SRA %0,24+%c2\"; -}" - [(set_attr "length" "8")] -) - -;; -;;- Logical shift instructions. -;; - -; -; lshrdi3 instruction pattern(s). -; - -(define_insn "lshrdi3" - [(set (match_operand:DI 0 "general_operand" "=d") - (lshiftrt:DI (match_operand:DI 1 "general_operand" "0") - (match_operand:SI 2 "general_operand" "Ja")))] - "" - "* -{ - check_label_emit (); - mvs_check_page (0, 4, 0); - if (REG_P (operands[2])) - return \"SRDL %0,0(%2)\"; - return \"SRDL %0,%c2\"; -}" - [(set_attr "length" "4")] -) - - -; -; lshrsi3 instruction pattern(s). -; - -(define_insn "lshrsi3" - [(set (match_operand:SI 0 "general_operand" "=d") - (lshiftrt:SI (match_operand:SI 1 "general_operand" "0") - (match_operand:SI 2 "general_operand" "Ja")))] - "" - "* -{ - check_label_emit (); - mvs_check_page (0, 4, 0); - if (REG_P (operands[2])) - return \"SRL %0,0(%2)\"; - return \"SRL %0,%c2\"; -}" - [(set_attr "length" "4")] -) - -; -; lshrhi3 instruction pattern(s). -; - -(define_insn "lshrhi3" - [(set (match_operand:HI 0 "general_operand" "=d") - (lshiftrt:HI (match_operand:HI 1 "general_operand" "0") - (match_operand:SI 2 "general_operand" "Ja")))] - "" - "* -{ - check_label_emit (); - CC_STATUS_INIT; /* AND sets the CC but not how we want it */ - if (REG_P (operands[2])) - { - mvs_check_page (0, 8, 4); - return \"N %0,=XL4'0000FFFF'\;SRL %0,0(%2)\"; - } - mvs_check_page (0, 8, 4); - return \"N %0,=XL4'0000FFFF'\;SRL %0,%c2\"; -}" - [(set_attr "length" "8")] -) - -; -; lshrqi3 instruction pattern(s). -; - -(define_insn "lshrqi3" - [(set (match_operand:QI 0 "general_operand" "=d") - (lshiftrt:QI (match_operand:QI 1 "general_operand" "0") - (match_operand:SI 2 "general_operand" "Ja")))] - "" - "* -{ - check_label_emit (); - CC_STATUS_INIT; /* AND sets the CC but not how we want it */ - mvs_check_page (0, 8, 4); - if (REG_P (operands[2])) - return \"N %0,=XL4'000000FF'\;SRL %0,0(%2)\"; - return \"N %0,=XL4'000000FF'\;SRL %0,%c2\"; -}" - [(set_attr "length" "8")] -) - -;; ======================================================================= -;;- Conditional jump instructions. -;; ======================================================================= - -; -; beq instruction pattern(s). -; - -(define_insn "beq" - [(set (pc) - (if_then_else (eq (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc))) -; (clobber (reg:SI 14)) - ] - "" - "* -{ - check_label_emit (); - mvs_check_page (0, 4, 0); - if (i370_short_branch(insn) || mvs_check_label (CODE_LABEL_NUMBER (operands[0]))) - { - return \"BE %l0\"; - } - mvs_check_page (0, 2, 4); - return \"L 14,=A(%l0)\;BER 14\"; -}" - [(set_attr "length" "6")] -) - -; -; bne instruction pattern(s). -; - -(define_insn "bne" - [(set (pc) - (if_then_else (ne (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc))) -; (clobber (reg:SI 14)) - ] - "" - "* -{ - check_label_emit (); - mvs_check_page (0, 4, 0); - if (i370_short_branch(insn) || mvs_check_label (CODE_LABEL_NUMBER (operands[0]))) - { - return \"BNE %l0\"; - } - mvs_check_page (0, 2, 4); - return \"L 14,=A(%l0)\;BNER 14\"; -}" - [(set_attr "length" "6")] -) - -; -; bgt instruction pattern(s). -; - -(define_insn "bgt" - [(set (pc) - (if_then_else (gt (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc))) -; (clobber (reg:SI 14)) - ] - "" - "* -{ - check_label_emit (); - mvs_check_page (0, 4, 0); - if (i370_short_branch(insn) || mvs_check_label (CODE_LABEL_NUMBER (operands[0]))) - { - return \"BH %l0\"; - } - mvs_check_page (0, 2, 4); - return \"L 14,=A(%l0)\;BHR 14\"; -}" - [(set_attr "length" "6")] -) - -; -; bgtu instruction pattern(s). -; - -(define_insn "bgtu" - [(set (pc) - (if_then_else (gtu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc))) -; (clobber (reg:SI 14)) - ] - "" - "* -{ - check_label_emit (); - mvs_check_page (0, 4, 0); - if (i370_short_branch(insn) || mvs_check_label (CODE_LABEL_NUMBER (operands[0]))) - { - return \"BH %l0\"; - } - mvs_check_page (0, 2, 4); - return \"L 14,=A(%l0)\;BHR 14\"; -}" - [(set_attr "length" "6")] -) - -; -; blt instruction pattern(s). -; - -(define_insn "blt" - [(set (pc) - (if_then_else (lt (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc))) -; (clobber (reg:SI 14)) - ] - "" - "* -{ - check_label_emit (); - mvs_check_page (0, 4, 0); - if (i370_short_branch(insn) || mvs_check_label (CODE_LABEL_NUMBER (operands[0]))) - { - return \"BL %l0\"; - } - mvs_check_page (0, 2, 4); - return \"L 14,=A(%l0)\;BLR 14\"; -}" - [(set_attr "length" "6")] -) - -; -; bltu instruction pattern(s). -; - -(define_insn "bltu" - [(set (pc) - (if_then_else (ltu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc))) -; (clobber (reg:SI 14)) - ] - "" - "* -{ - check_label_emit (); - mvs_check_page (0, 4, 0); - if (i370_short_branch(insn) || mvs_check_label (CODE_LABEL_NUMBER (operands[0]))) - { - return \"BL %l0\"; - } - mvs_check_page (0, 2, 4); - return \"L 14,=A(%l0)\;BLR 14\"; -}" - [(set_attr "length" "6")] -) - -; -; bge instruction pattern(s). -; - -(define_insn "bge" - [(set (pc) - (if_then_else (ge (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc))) -; (clobber (reg:SI 14)) - ] - "" - "* -{ - check_label_emit (); - mvs_check_page (0, 4, 0); - if (i370_short_branch(insn) || mvs_check_label (CODE_LABEL_NUMBER (operands[0]))) - { - return \"BNL %l0\"; - } - mvs_check_page (0, 2, 4); - return \"L 14,=A(%l0)\;BNLR 14\"; -}" - [(set_attr "length" "6")] -) - -; -; bgeu instruction pattern(s). -; - -(define_insn "bgeu" - [(set (pc) - (if_then_else (geu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc))) -; (clobber (reg:SI 14)) - ] - "" - "* -{ - check_label_emit (); - mvs_check_page (0, 4, 0); - if (i370_short_branch(insn) || mvs_check_label (CODE_LABEL_NUMBER (operands[0]))) - { - return \"BNL %l0\"; - } - mvs_check_page (0, 2, 4); - return \"L 14,=A(%l0)\;BNLR 14\"; -}" - [(set_attr "length" "6")] -) - -; -; ble instruction pattern(s). -; - -(define_insn "ble" - [(set (pc) - (if_then_else (le (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc))) -; (clobber (reg:SI 14)) - ] - "" - "* -{ - check_label_emit (); - mvs_check_page (0, 4, 0); - if (i370_short_branch(insn) || mvs_check_label (CODE_LABEL_NUMBER (operands[0]))) - { - return \"BNH %l0\"; - } - mvs_check_page (0, 2, 4); - return \"L 14,=A(%l0)\;BNHR 14\"; -}" - [(set_attr "length" "6")] -) - -; -; bleu instruction pattern(s). -; - -(define_insn "bleu" - [(set (pc) - (if_then_else (leu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc))) -; (clobber (reg:SI 14)) - ] - "" - "* -{ - check_label_emit (); - mvs_check_page (0, 4, 0); - if (i370_short_branch(insn) || mvs_check_label (CODE_LABEL_NUMBER (operands[0]))) - { - return \"BNH %l0\"; - } - mvs_check_page (0, 2, 4); - return \"L 14,=A(%l0)\;BNHR 14\"; -}" - [(set_attr "length" "6")] -) - -;; -;;- Negated conditional jump instructions. -;; - -(define_insn "" - [(set (pc) - (if_then_else (eq (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" "")))) -; (clobber (reg:SI 14)) - ] - "" - "* -{ - check_label_emit (); - mvs_check_page (0, 4, 0); - if (i370_short_branch(insn) || mvs_check_label (CODE_LABEL_NUMBER (operands[0]))) - { - return \"BNE %l0\"; - } - mvs_check_page (0, 2, 4); - return \"L 14,=A(%l0)\;BNER 14\"; -}" - [(set_attr "length" "6")] -) - -(define_insn "" - [(set (pc) - (if_then_else (ne (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" "")))) -; (clobber (reg:SI 14)) - ] - "" - "* -{ - check_label_emit (); - mvs_check_page (0, 4, 0); - if (i370_short_branch(insn) || mvs_check_label (CODE_LABEL_NUMBER (operands[0]))) - { - return \"BE %l0\"; - } - mvs_check_page (0, 2, 4); - return \"L 14,=A(%l0)\;BER 14\"; -}" - [(set_attr "length" "6")] -) - -(define_insn "" - [(set (pc) - (if_then_else (gt (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" "")))) -; (clobber (reg:SI 14)) - ] - "" - "* -{ - check_label_emit (); - mvs_check_page (0, 4, 0); - if (i370_short_branch(insn) || mvs_check_label (CODE_LABEL_NUMBER (operands[0]))) - { - return \"BNH %l0\"; - } - mvs_check_page (0, 2, 4); - return \"L 14,=A(%l0)\;BNHR 14\"; -}" - [(set_attr "length" "6")] -) - -(define_insn "" - [(set (pc) - (if_then_else (gtu (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" "")))) -; (clobber (reg:SI 14)) - ] - "" - "* -{ - check_label_emit (); - mvs_check_page (0, 4, 0); - if (i370_short_branch(insn) || mvs_check_label (CODE_LABEL_NUMBER (operands[0]))) - { - return \"BNH %l0\"; - } - mvs_check_page (0, 2, 4); - return \"L 14,=A(%l0)\;BNHR 14\"; -}" - [(set_attr "length" "6")] -) - -(define_insn "" - [(set (pc) - (if_then_else (lt (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" "")))) -; (clobber (reg:SI 14)) - ] - "" - "* -{ - check_label_emit (); - mvs_check_page (0, 4, 0); - if (i370_short_branch(insn) || mvs_check_label (CODE_LABEL_NUMBER (operands[0]))) - { - return \"BNL %l0\"; - } - mvs_check_page (0, 2, 4); - return \"L 14,=A(%l0)\;BNLR 14\"; -}" - [(set_attr "length" "6")] -) - -(define_insn "" - [(set (pc) - (if_then_else (ltu (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" "")))) -; (clobber (reg:SI 14)) - ] - "" - "* -{ - check_label_emit (); - mvs_check_page (0, 4, 0); - if (i370_short_branch(insn) || mvs_check_label (CODE_LABEL_NUMBER (operands[0]))) - { - return \"BNL %l0\"; - } - mvs_check_page (0, 2, 4); - return \"L 14,=A(%l0)\;BNLR 14\"; -}" - [(set_attr "length" "6")] -) - -(define_insn "" - [(set (pc) - (if_then_else (ge (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" "")))) -; (clobber (reg:SI 14)) - ] - "" - "* -{ - check_label_emit (); - mvs_check_page (0, 4, 0); - if (i370_short_branch(insn) || mvs_check_label (CODE_LABEL_NUMBER (operands[0]))) - { - return \"BL %l0\"; - } - mvs_check_page (0, 2, 4); - return \"L 14,=A(%l0)\;BLR 14\"; -}" - [(set_attr "length" "6")] -) - -(define_insn "" - [(set (pc) - (if_then_else (geu (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" "")))) -; (clobber (reg:SI 14)) - ] - "" - "* -{ - check_label_emit (); - mvs_check_page (0, 4, 0); - if (i370_short_branch(insn) || mvs_check_label (CODE_LABEL_NUMBER (operands[0]))) - { - return \"BL %l0\"; - } - mvs_check_page (0, 2, 4); - return \"L 14,=A(%l0)\;BLR 14\"; -}" - [(set_attr "length" "6")] -) - -(define_insn "" - [(set (pc) - (if_then_else (le (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" "")))) -; (clobber (reg:SI 14)) - ] - "" - "* -{ - check_label_emit (); - mvs_check_page (0, 4, 0); - if (i370_short_branch(insn) || mvs_check_label (CODE_LABEL_NUMBER (operands[0]))) - { - return \"BH %l0\"; - } - mvs_check_page (0, 2, 4); - return \"L 14,=A(%l0)\;BHR 14\"; -}" - [(set_attr "length" "6")] -) - -(define_insn "" - [(set (pc) - (if_then_else (leu (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" "")))) -; (clobber (reg:SI 14)) - ] - "" - "* -{ - check_label_emit (); - mvs_check_page (0, 4, 0); - if (i370_short_branch(insn) || mvs_check_label (CODE_LABEL_NUMBER (operands[0]))) - { - return \"BH %l0\"; - } - mvs_check_page (0, 2, 4); - return \"L 14,=A(%l0)\;BHR 14\"; -}" - [(set_attr "length" "6")] -) - -;; ============================================================== -;;- Subtract one and jump if not zero. -;; These insns seem to not be getting matched ... -;; XXX should fix this, as it would improve for loops - -(define_insn "" - [(set (pc) - (if_then_else - (ne (plus:SI (match_operand:SI 0 "register_operand" "+d") - (const_int -1)) - (const_int 0)) - (label_ref (match_operand 1 "" "")) - (pc))) - (set (match_dup 0) - (plus:SI (match_dup 0) - (const_int -1))) -; (clobber (reg:SI 14)) - ] - "" - "* -{ - check_label_emit (); - mvs_check_page (0, 4, 0); - if (mvs_check_label (CODE_LABEL_NUMBER (operands[1]))) - { - return \"BCT %0,%l1\"; - } - mvs_check_page (0, 2, 4); - return \"L 14,=A(%l1)\;BCTR %0,14\"; -}" - [(set_attr "length" "6")] -) - -(define_insn "" - [(set (pc) - (if_then_else - (eq (plus:SI (match_operand:SI 0 "register_operand" "+d") - (const_int -1)) - (const_int 0)) - (pc) - (label_ref (match_operand 1 "" "")))) - (set (match_dup 0) - (plus:SI (match_dup 0) - (const_int -1))) -; (clobber (reg:SI 14)) - ] - "" - "* -{ - check_label_emit (); - mvs_check_page (0, 4, 0); - if (mvs_check_label (CODE_LABEL_NUMBER (operands[1]))) - { - return \"BCT %0,%l1\"; - } - mvs_check_page (0, 2, 4); - return \"L 14,=A(%l1)\;BCTR %0,14\"; -}" - [(set_attr "length" "6")] -) - -;; ============================================================= -;;- Unconditional jump instructions. -;; - -; -; jump instruction pattern(s). -; - -(define_insn "jump" - [(set (pc) - (label_ref (match_operand 0 "" ""))) -; (clobber (reg:SI 14)) - ] - "" - "* -{ - check_label_emit (); - mvs_check_page (0, 4, 0); - if (i370_short_branch(insn) || mvs_check_label (CODE_LABEL_NUMBER (operands[0]))) - { - return \"B %l0\"; - } - mvs_check_page (0, 2, 4); - return \"L 14,=A(%l0)\;BR 14\"; -}" - [(set_attr "length" "6")] -) - -; -; indirect-jump instruction pattern(s). -; hack alert -- should check that displacement is < 4096 - -(define_insn "indirect_jump" - [(set (pc) (match_operand:SI 0 "general_operand" "rm"))] - "" - "* -{ - check_label_emit (); - if (REG_P (operands[0])) - { - mvs_check_page (0, 2, 0); - return \"BR %0\"; - } - mvs_check_page (0, 4, 0); - return \"B %0\"; -}" - [(set_attr "length" "4")] -) - -; -; tablejump instruction pattern(s). -; - -(define_insn "tablejump" - [(set (pc) - (match_operand:SI 0 "general_operand" "am")) - (use (label_ref (match_operand 1 "" ""))) -; (clobber (reg:SI 14)) - ] - "" - "* -{ - check_label_emit (); - if (REG_P (operands[0])) - { - mvs_check_page (0, 6, 0); - return \"BR %0\;DS 0F\"; - } - mvs_check_page (0, 10, 0); - return \"L 14,%0\;BR 14\;DS 0F\"; -}" - [(set_attr "length" "10")] -) - -;; -;;- Jump to subroutine. -;; -;; For the C/370 environment the internal functions, ie. sqrt, are called with -;; a non-standard form. So, we must fix it here. There's no BM like IBM. -;; -;; The ELF ABI is different from the C/370 ABI because we have a simpler, -;; more powerful way of dealing with structure-value returns. Basically, -;; we use R1 to point at structure returns (64-bit and larger returns) -;; and R11 to point at the args. Note that this handles double-precision -;; (64-bit) values just fine, in a less-kludged manner than the C/370 ABI. -;; Since R1 is used, we use R2 to pass the argument pointer to the routine. - -; -; call instruction pattern(s). -; -; We define four call instruction patterns below. The first two patterns, -; although general, end up matching (only?) calls through function pointers. -; The last two, which require a symbol-ref to match, get used for all -; ordinary subroutine calls. - -(define_insn "call" - [(call (match_operand:QI 0 "memory_operand" "m") - (match_operand:SI 1 "immediate_operand" "i")) - (clobber (reg:SI 2)) - ] - "" - "* -{ - static char temp[128]; - int i = STACK_POINTER_OFFSET; - CC_STATUS_INIT; - - check_label_emit (); -#ifdef TARGET_ELF_ABI - mvs_check_page (0, 10, 4); - sprintf ( temp, \"LA r2,%d(,sp)\;LA 15,%%0\;BASR 14,15\", i ); - return temp; -#else - if (mvs_function_check (XSTR (operands[0], 0))) - { - mvs_check_page (0, 22, 4); - sprintf ( temp, \"LA 1,136(,13)\;ST 1,%d(,13)\;LA 1,%d(,13)\;LA 15,%%0\;BALR 14,15\;LD 0,136(,13)\", - i - 4, i - 4 ); - } - else - { - mvs_check_page (0, 10, 4); - sprintf ( temp, \"LA 1,%d(,13)\;LA 15,%%0\;BALR 14,15\", i ); - } - return temp; -#endif -}" - [(set_attr "length" "22")] -) - -; -; call_value instruction pattern(s). -; - -(define_insn "call_value" - [(set (match_operand 0 "" "=rf") - (call (match_operand:QI 1 "memory_operand" "m") - (match_operand:SI 2 "general_operand" "i"))) - (clobber (reg:SI 2)) - ] - "" - "* -{ - static char temp[128]; - int i = STACK_POINTER_OFFSET; - CC_STATUS_INIT; - - check_label_emit (); -#ifdef TARGET_ELF_ABI - mvs_check_page (0, 10, 4); - sprintf ( temp, \"LA r2,%d(,sp)\;LA 15,%%1\;BASR 14,15\", i ); - return temp; -#else - if (mvs_function_check (XSTR (operands[1], 0))) - { - mvs_check_page (0, 22, 4); - sprintf ( temp, \"LA 1,136(,13)\;ST 1,%d(,13)\;LA 1,%d(,13)\;LA 15,%%1\;BALR 14,15\;LD 0,136(,13)\", - i - 4, i - 4 ); - } - else - { - mvs_check_page (0, 10, 4); - sprintf ( temp, \"LA 1,%d(,13)\;LA 15,%%1\;BALR 14,15\", i ); - } - return temp; -#endif -}" - [(set_attr "length" "22")] -) - -(define_insn "" - [(call (mem:QI (match_operand:SI 0 "" "i")) - (match_operand:SI 1 "general_operand" "g")) - (clobber (reg:SI 2)) - ] - "GET_CODE (operands[0]) == SYMBOL_REF" - "* -{ - static char temp[128]; - int i = STACK_POINTER_OFFSET; - CC_STATUS_INIT; - - check_label_emit (); -#ifdef TARGET_ELF_ABI - mvs_check_page (0, 10, 4); - sprintf ( temp, \"LA r2,%d(,sp)\;L 15,%%0\;BASR 14,15\", i ); - return temp; -#else - if (mvs_function_check (XSTR (operands[0], 0))) - { - mvs_check_page (0, 22, 4); - sprintf ( temp, \"LA 1,136(,13)\;ST 1,%d(,13)\;LA 1,%d(,13)\;L 15,%%0\;BALR 14,15\;LD 0,136(,13)\", - i - 4, i - 4 ); - } - else - { - mvs_check_page (0, 10, 4); - sprintf ( temp, \"LA 1,%d(,13)\;L 15,%%0\;BALR 14,15\", i ); - } - return temp; -#endif -}" - [(set_attr "length" "22")] -) - -(define_insn "" - [(set (match_operand 0 "" "=rf") - (call (mem:QI (match_operand:SI 1 "" "i")) - (match_operand:SI 2 "general_operand" "g"))) - (clobber (reg:SI 2)) - ] - "GET_CODE (operands[1]) == SYMBOL_REF" - "* -{ - static char temp[128]; - int i = STACK_POINTER_OFFSET; - CC_STATUS_INIT; - - check_label_emit (); -#ifdef TARGET_ELF_ABI - mvs_check_page (0, 10, 4); - sprintf ( temp, \"LA r2,%d(,sp)\;L 15,%%1\;BASR 14,15\", i ); - return temp; -#else - if (mvs_function_check (XSTR (operands[1], 0))) - { - mvs_check_page (0, 22, 4); - sprintf ( temp, \"LA 1,136(,13)\;ST 1,%d(,13)\;LA 1,%d(,13)\;L 15,%%1\;BALR 14,15\;LD 0,136(,13)\", - i - 4, i - 4 ); - } - else - { - mvs_check_page (0, 10, 4); - sprintf ( temp, \"LA 1,%d(,13)\;L 15,%%1\;BALR 14,15\", i ); - } - return temp; -#endif -}" - [(set_attr "length" "22")] -) - -;; -;; Call subroutine returning any type. -;; This instruction pattern appears to be used only by the -;; expand_builtin_apply definition for __builtin_apply. It is needed -;; since call_value might return an int in r15 or a float in fpr0 (r16) -;; and the builtin code calls abort since the reg is ambiguous. Well, -;; the below is probably broken anyway, we just want to go for now. -;; -(define_expand "untyped_call" -[(parallel [(call (match_operand 0 "" "") - (const_int 0)) - (match_operand 1 "" "") - (match_operand 2 "" "")])] - "" - " -{ - int i; - - emit_call_insn (GEN_CALL (operands[0], const0_rtx, const0_rtx, const0_rtx)); - - for (i = 0; i < XVECLEN (operands[2], 0); i++) - { - rtx set = XVECEXP (operands[2], 0, i); - emit_move_insn (SET_DEST (set), SET_SRC (set)); - } - - /* The optimizer does not know that the call sets the function value - registers we stored in the result block. We avoid problems by - claiming that all hard registers are used and clobbered at this - point. */ - /* emit_insn (gen_blockage ()); */ - - DONE; -}") - - -;; -;;- Miscellaneous instructions. -;; - -; -; nop instruction pattern(s). -; - -(define_insn "nop" - [(const_int 0)] - "" - "* -{ - check_label_emit (); - mvs_check_page (0, 2, 0); - return \"LR 0,0\"; -}" - [(set_attr "length" "2")] -) diff --git a/gcc/config/i370/linux.h b/gcc/config/i370/linux.h deleted file mode 100644 index f402fbde9f3..00000000000 --- a/gcc/config/i370/linux.h +++ /dev/null @@ -1,113 +0,0 @@ -/* Definitions of target machine for GNU compiler. System/370 version. - Copyright (C) 1989, 1993, 1995, 1996, 1997, 2003 - Free Software Foundation, Inc. - Contributed by Jan Stein (jan@cd.chalmers.se). - Modified for Linux/390 by Linas Vepstas (linas@linas.org) - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GCC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - - -#define TARGET_VERSION fprintf (stderr, " (i370 GNU/Linux with ELF)"); - -/* Specify that we're generating code for a Linux port to 370 */ - -#define TARGET_ELF_ABI - -/* Target OS preprocessor built-ins. */ -#define TARGET_OS_CPP_BUILTINS() LINUX_TARGET_OS_CPP_BUILTINS() - -/* Options for this target machine. */ - -#define LIBGCC_SPEC "libgcc.a%s" - -#ifdef SOME_FUTURE_DAY - -#define CPP_SPEC "%{posix: -D_POSIX_SOURCE} %(cpp_sysv) %(cpp_endian_big) \ -%{mcall-linux: %(cpp_os_linux) } \ -%{!mcall-linux: %(cpp_os_default) }" - -#define LIB_SPEC "\ -%{mcall-linux: %(lib_linux) } \ -%{!mcall-linux:%(lib_default) }" - -#define STARTFILE_SPEC "\ -%{mcall-linux: %(startfile_linux) } \ -%{!mcall-linux: %(startfile_default) }" - -#define ENDFILE_SPEC "\ -%{mcall-linux: %(endfile_linux) } \ -%{!mcall-linux: %(endfile_default) }" - -/* GNU/Linux support. */ -#ifndef LIB_LINUX_SPEC -#define LIB_LINUX_SPEC "%{mnewlib: --start-group -llinux -lc --end-group } %{!mnewlib: -lc }" -#endif - -#ifndef STARTFILE_LINUX_SPEC -#define STARTFILE_LINUX_SPEC "\ -%{!shared: %{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} %{!p:crt1.o%s}}} \ -%{mnewlib: ecrti.o%s} \ -%{!mnewlib: crti.o%s %{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}}" -#endif - -#ifndef ENDFILE_LINUX_SPEC -#define ENDFILE_LINUX_SPEC "\ -%{mnewlib: ecrtn.o%s} \ -%{!mnewlib: %{!shared:crtend.o%s} %{shared:crtendS.o%s} crtn.o%s}" -#endif - -#ifndef LINK_START_LINUX_SPEC -#define LINK_START_LINUX_SPEC "-Ttext 0x10000" -#endif - -#ifndef LINK_OS_LINUX_SPEC -#define LINK_OS_LINUX_SPEC "" -#endif - -#ifndef CPP_OS_LINUX_SPEC -#define CPP_OS_LINUX_SPEC "-D__unix__ -D__gnu_linux__ -D__linux__ \ -%{!ansi: -Dunix -Dlinux } \ --Asystem=unix -Asystem=linux" -#endif - -#ifndef CPP_OS_LINUX_SPEC -#define CPP_OS_LINUX_SPEC "" -#endif - - -/* Define any extra SPECS that the compiler needs to generate. */ -#undef SUBTARGET_EXTRA_SPECS -#define SUBTARGET_EXTRA_SPECS \ - { "lib_linux", LIB_LINUX_SPEC }, \ - { "lib_default", LIB_DEFAULT_SPEC }, \ - { "startfile_linux", STARTFILE_LINUX_SPEC }, \ - { "startfile_default", STARTFILE_DEFAULT_SPEC }, \ - { "endfile_linux", ENDFILE_LINUX_SPEC }, \ - { "endfile_default", ENDFILE_DEFAULT_SPEC }, \ - { "link_shlib", LINK_SHLIB_SPEC }, \ - { "link_target", LINK_TARGET_SPEC }, \ - { "link_start", LINK_START_SPEC }, \ - { "link_start_linux", LINK_START_LINUX_SPEC }, \ - { "link_os", LINK_OS_SPEC }, \ - { "link_os_linux", LINK_OS_LINUX_SPEC }, \ - { "link_os_default", LINK_OS_DEFAULT_SPEC }, \ - { "cpp_endian_big", CPP_ENDIAN_BIG_SPEC }, \ - { "cpp_os_linux", CPP_OS_LINUX_SPEC }, \ - { "cpp_os_default", CPP_OS_DEFAULT_SPEC }, - -#endif /* SOME_FUTURE_DAY */ diff --git a/gcc/config/i370/mvs.h b/gcc/config/i370/mvs.h deleted file mode 100644 index dfb4cba188a..00000000000 --- a/gcc/config/i370/mvs.h +++ /dev/null @@ -1,49 +0,0 @@ -/* Definitions of target machine for GNU compiler. System/370 version. - Copyright (C) 1989, 1993, 1995, 1996, 1997, 2003 - Free Software Foundation, Inc. - Contributed by Jan Stein (jan@cd.chalmers.se). - Modified for OS/390 LanguageEnvironment C by Dave Pitts (dpitts@cozx.com) - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GCC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -#define TARGET_VERSION printf (" (370/MVS)"); - -/* Specify that we're generating code for the Language Environment */ - -#define LE370 1 -#define TARGET_EBCDIC 1 -#define TARGET_HLASM 1 - -/* Options for the preprocessor for this target machine. */ - -#define CPP_SPEC "-trigraphs" - -/* Target OS preprocessor built-ins. */ -#define TARGET_OS_CPP_BUILTINS() \ - do { \ - builtin_define_std ("MVS"); \ - builtin_define_std ("mvs"); \ - MAYBE_LE370_MACROS(); \ - builtin_assert ("system=mvs"); \ - } while (0) - -#if defined(LE370) -# define MAYBE_LE370_MACROS() do {builtin_define_std ("LE370");} while (0) -#else -# define MAYBE_LE370_MACROS() -#endif diff --git a/gcc/config/i370/oe.h b/gcc/config/i370/oe.h deleted file mode 100644 index 088c043530e..00000000000 --- a/gcc/config/i370/oe.h +++ /dev/null @@ -1,53 +0,0 @@ -/* Definitions of target machine for GNU compiler. System/370 version. - Copyright (C) 1989, 1993, 1995, 1996, 1997, 2003 - Free Software Foundation, Inc. - Contributed by Jan Stein (jan@cd.chalmers.se). - Modified for OS/390 OpenEdition by Dave Pitts (dpitts@cozx.com) - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GCC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -#define TARGET_VERSION printf (" (370/OpenEdition)"); - -/* Specify that we're generating code for the Language Environment */ - -#define LE370 1 -#define LONGEXTERNAL 1 -#define TARGET_EBCDIC 1 -#define TARGET_HLASM 1 - -/* Options for the preprocessor for this target machine. */ - -#define CPP_SPEC "-trigraphs" - -/* Options for this target machine. */ - -#define LIB_SPEC "" -#define LIBGCC_SPEC "" -#define STARTFILE_SPEC "/usr/local/lib/gccmain.o" - -/* Target OS preprocessor built-ins. */ -#define TARGET_OS_CPP_BUILTINS() \ - do { \ - builtin_define_std ("unix"); \ - builtin_define_std ("UNIX"); \ - builtin_define_std ("openedition"); \ - builtin_define ("__i370__"); \ - builtin_assert ("system=openedition"); \ - builtin_assert ("system=unix"); \ - } while (0) - diff --git a/gcc/config/i370/t-i370 b/gcc/config/i370/t-i370 deleted file mode 100644 index fccd1632fde..00000000000 --- a/gcc/config/i370/t-i370 +++ /dev/null @@ -1,3 +0,0 @@ -i370-c.o: $(srcdir)/config/i370/i370-c.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ - $(TM_H) $(TREE_H) toplev.h $(CPPLIB_H) c-pragma.h $(TM_P_H) - $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/i370/i370-c.c diff --git a/gcc/config/i386/freebsd-aout.h b/gcc/config/i386/freebsd-aout.h deleted file mode 100644 index 663ed8dac09..00000000000 --- a/gcc/config/i386/freebsd-aout.h +++ /dev/null @@ -1,230 +0,0 @@ -/* Definitions of target machine for GNU compiler for Intel 80386 - running FreeBSD. - Copyright (C) 1988, 1992, 1994, 1996, 1997, 1999, 2000, 2002, 2003 - Free Software Foundation, Inc. - Contributed by Poul-Henning Kamp - Continued development by David O'Brien - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GCC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/* Don't assume anything about the header files. */ -#define NO_IMPLICIT_EXTERN_C - -/* This goes away when the math-emulator is fixed */ -#undef TARGET_SUBTARGET_DEFAULT -#define TARGET_SUBTARGET_DEFAULT \ - (MASK_80387 | MASK_IEEE_FP | MASK_FLOAT_RETURNS | MASK_NO_FANCY_MATH_387) - -/* The macro defined in i386.h doesn't work with the old gas of - FreeBSD 2.x. The definition in sco.h and sol2.h appears to work, - but it turns out that, even though the assembler doesn't complain, - we get incorrect results. Fortunately, the definition in - defaults.h works. */ -#undef ASM_PREFERRED_EH_DATA_FORMAT - -#define TARGET_OS_CPP_BUILTINS() \ - do \ - { \ - builtin_define_std ("unix"); \ - builtin_define ("__FreeBSD__"); \ - builtin_assert ("system=unix"); \ - builtin_assert ("system=bsd"); \ - builtin_assert ("system=FreeBSD"); \ - } \ - while (0) - -/* Like the default, except no -lg. */ -#define LIB_SPEC "%{!shared:%{!pg:-lc}%{pg:-lc_p}}" - -#undef SIZE_TYPE -#define SIZE_TYPE "unsigned int" - -#undef PTRDIFF_TYPE -#define PTRDIFF_TYPE "int" - -#undef WCHAR_TYPE -#define WCHAR_TYPE "int" - -#undef WCHAR_TYPE_SIZE -#define WCHAR_TYPE_SIZE BITS_PER_WORD - -/* Override the default comment-starter of "/". */ - -#undef ASM_COMMENT_START -#define ASM_COMMENT_START "#" - -#undef ASM_APP_ON -#define ASM_APP_ON "#APP\n" - -#undef ASM_APP_OFF -#define ASM_APP_OFF "#NO_APP\n" - -/* FreeBSD using a.out does not support DWARF2 unwinding mechanisms. */ -#define DWARF2_UNWIND_INFO 0 - -/* Don't default to pcc-struct-return, because in FreeBSD we prefer the - superior nature of the older gcc way. */ -#define DEFAULT_PCC_STRUCT_RETURN 0 - -/* Ensure we the configuration knows our system correctly so we can link with - libraries compiled with the native cc. */ -#undef NO_DOLLAR_IN_LABEL - -/* i386 freebsd still uses old binutils that don't insert nops by default - when the .align directive demands to insert extra space in the text - segment. */ -#undef ASM_OUTPUT_ALIGN -#define ASM_OUTPUT_ALIGN(FILE,LOG) \ - if ((LOG)!=0) fprintf ((FILE), "\t.align %d,0x90\n", (LOG)) - -/* Profiling routines, partially copied from i386/osfrose.h. */ - -/* Tell final.c that we don't need a label passed to mcount. */ -#define NO_PROFILE_COUNTERS 1 - -#undef MCOUNT_NAME -#define MCOUNT_NAME "mcount" -#undef PROFILE_COUNT_REGISTER -#define PROFILE_COUNT_REGISTER "eax" - -/* - * Some imports from svr4.h in support of shared libraries. - * Currently, we need the DECLARE_OBJECT_SIZE stuff. - */ - -/* Define the strings used for the special svr4 .type and .size directives. - These strings generally do not vary from one system running svr4 to - another, but if a given system (e.g. m88k running svr) needs to use - different pseudo-op names for these, they may be overridden in the - file which includes this one. */ - -#define TYPE_ASM_OP "\t.type\t" -#define SIZE_ASM_OP "\t.size\t" -#define SET_ASM_OP "\t.set\t" - -/* The following macro defines the format used to output the second - operand of the .type assembler directive. Different svr4 assemblers - expect various different forms for this operand. The one given here - is just a default. You may need to override it in your machine- - specific tm.h file (depending upon the particulars of your assembler). */ - -#define TYPE_OPERAND_FMT "@%s" - -#define HANDLE_SYSV_PRAGMA 1 - -#define ASM_WEAKEN_LABEL(FILE,NAME) \ - do { fputs ("\t.weak\t", FILE); assemble_name (FILE, NAME); \ - fputc ('\n', FILE); } while (0) - -/* Write the extra assembler code needed to declare a function's result. - Most svr4 assemblers don't require any special declaration of the - result value, but there are exceptions. */ - -#ifndef ASM_DECLARE_RESULT -#define ASM_DECLARE_RESULT(FILE, RESULT) -#endif - -/* These macros generate the special .type and .size directives which - are used to set the corresponding fields of the linker symbol table - entries in an ELF object file under SVR4. These macros also output - the starting labels for the relevant functions/objects. */ - -/* Write the extra assembler code needed to declare a function properly. - Some svr4 assemblers need to also have something extra said about the - function's return value. We allow for that here. */ - -#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \ - do \ - { \ - ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "function"); \ - ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL)); \ - ASM_OUTPUT_LABEL (FILE, NAME); \ - } \ - while (0) - -/* Write the extra assembler code needed to declare an object properly. */ - -#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL) \ - do \ - { \ - HOST_WIDE_INT size; \ - \ - ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "object"); \ - \ - size_directive_output = 0; \ - if (!flag_inhibit_size_directive \ - && (DECL) && DECL_SIZE (DECL)) \ - { \ - size_directive_output = 1; \ - size = int_size_in_bytes (TREE_TYPE (DECL)); \ - ASM_OUTPUT_SIZE_DIRECTIVE (FILE, NAME, size); \ - } \ - \ - ASM_OUTPUT_LABEL (FILE, NAME); \ - } \ - while (0) - -/* Output the size directive for a decl in rest_of_decl_compilation - in the case where we did not do so before the initializer. - Once we find the error_mark_node, we know that the value of - size_directive_output was set - by ASM_DECLARE_OBJECT_NAME when it was run for the same decl. */ - -#undef ASM_FINISH_DECLARE_OBJECT -#define ASM_FINISH_DECLARE_OBJECT(FILE, DECL, TOP_LEVEL, AT_END) \ -do { \ - const char *name = XSTR (XEXP (DECL_RTL (DECL), 0), 0); \ - HOST_WIDE_INT size; \ - if (!flag_inhibit_size_directive && DECL_SIZE (DECL) \ - && ! AT_END && TOP_LEVEL \ - && DECL_INITIAL (DECL) == error_mark_node \ - && !size_directive_output) \ - { \ - size_directive_output = 1; \ - size = int_size_in_bytes (TREE_TYPE (DECL)); \ - ASM_OUTPUT_SIZE_DIRECTIVE (FILE, name, size); \ - } \ - } while (0) - -/* This is how to declare the size of a function. */ - -#define ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL) \ - do { \ - if (!flag_inhibit_size_directive) \ - ASM_OUTPUT_MEASURED_SIZE (FILE, FNAME); \ - } while (0) - -#define AS_NEEDS_DASH_FOR_PIPED_INPUT -#define ASM_SPEC "%{fpic|fpie|fPIC|fPIE:-k}" -#define LINK_SPEC \ - "%{p:%e`-p' not supported; use `-pg' and gprof(1)} \ - %{shared:-Bshareable} \ - %{!shared:%{!nostdlib:%{!r:%{!e*:-e start}}} -dc -dp %{static:-Bstatic} \ - %{pg:-Bstatic} %{Z}} \ - %{assert*} %{R*}" - -#define STARTFILE_SPEC \ - "%{shared:c++rt0.o%s} \ - %{!shared:%{pg:gcrt0.o%s}%{!pg:%{static:scrt0.o%s}%{!static:crt0.o%s}}}" - -/* Define this so we can compile MS code for use with WINE. */ -#define HANDLE_PRAGMA_PACK_PUSH_POP - -/* FreeBSD 2.2.7's assembler does not support .quad properly. Do not - use it. */ -#undef ASM_QUAD diff --git a/gcc/config/i386/linux-aout.h b/gcc/config/i386/linux-aout.h deleted file mode 100644 index d7be93c7312..00000000000 --- a/gcc/config/i386/linux-aout.h +++ /dev/null @@ -1,73 +0,0 @@ -/* Definitions for Intel 386 running Linux-based GNU systems using a.out. - Copyright (C) 1992, 1994, 1995, 1997, 1998, 2002 - Free Software Foundation, Inc. - Contributed by H.J. Lu (hjl@nynexst.com) - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GCC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -#undef ASM_COMMENT_START -#define ASM_COMMENT_START "#" - -#define TARGET_OS_CPP_BUILTINS() \ - do \ - { \ - LINUX_TARGET_OS_CPP_BUILTINS(); \ - if (flag_pic) \ - { \ - builtin_define ("__PIC__"); \ - builtin_define ("__pic__"); \ - } \ - } \ - while (0) - -#undef CPP_SPEC -#define CPP_SPEC "%{posix:-D_POSIX_SOURCE}" - -#undef SIZE_TYPE -#define SIZE_TYPE "unsigned int" - -#undef PTRDIFF_TYPE -#define PTRDIFF_TYPE "int" - -#undef WCHAR_TYPE -#define WCHAR_TYPE "long int" - -#undef WCHAR_TYPE_SIZE -#define WCHAR_TYPE_SIZE BITS_PER_WORD - -/* Don't default to pcc-struct-return, because gcc is the only compiler, - and we want to retain compatibility with older gcc versions. */ -#define DEFAULT_PCC_STRUCT_RETURN 0 - -#undef LIB_SPEC - -#if 1 -/* We no longer link with libc_p.a or libg.a by default. If you - want to profile or debug the GNU/Linux C library, please add - -lc_p or -ggdb to LDFLAGS at the link time, respectively. */ -#define LIB_SPEC \ -"%{mieee-fp:-lieee} %{p:-lgmon} %{pg:-lgmon} %{!ggdb:-lc} %{ggdb:-lg}" -#else -#define LIB_SPEC \ -"%{mieee-fp:-lieee} %{p:-lgmon -lc_p} %{pg:-lgmon -lc_p} \ - %{!p:%{!pg:%{!g*:-lc} %{g*:-lg -static}}}" -#endif - - -#undef LINK_SPEC -#define LINK_SPEC "-m i386linux" diff --git a/gcc/config/i386/moss.h b/gcc/config/i386/moss.h deleted file mode 100644 index 3b748cfe1d9..00000000000 --- a/gcc/config/i386/moss.h +++ /dev/null @@ -1,43 +0,0 @@ -/* Definitions for Intel 386 running MOSS - Copyright (C) 1996, 2001 Free Software Foundation, Inc. - Contributed by Bryan Ford - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GCC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -#undef TARGET_OS_CPP_BUILTINS /* config.gcc includes i386/linux.h. */ -#define TARGET_OS_CPP_BUILTINS() \ - do \ - { \ - builtin_define_std ("moss"); \ - builtin_assert ("system=posix"); \ - if (flag_pic) \ - { \ - builtin_define ("__PIC__"); \ - builtin_define ("__pic__"); \ - } \ - } \ - while (0) - -#undef STARTFILE_SPEC -#define STARTFILE_SPEC "crt0.o%s" - -#undef ENDFILE_SPEC -#define ENDFILE_SPEC "crtn.o%s" - -#undef LINK_SPEC - diff --git a/gcc/config/i386/netware.h b/gcc/config/i386/netware.h deleted file mode 100644 index 28adf7256c5..00000000000 --- a/gcc/config/i386/netware.h +++ /dev/null @@ -1,40 +0,0 @@ -/* Core target definitions for GCC for Intel 80386 running Netware 4. - and using stabs-in-elf for the debugging format. - Copyright (C) 1993, 1994 Free Software Foundation, Inc. - - Written by David V. Henkel-Wallace (gumby@cygnus.com) - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GCC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -#undef TARGET_VERSION -#define TARGET_VERSION fprintf (stderr, " (i386 Netware 4)"); - -#define TARGET_OS_CPP_BUILTINS() \ - do \ - { \ - builtin_define_std ("APX386"); \ - builtin_define ("__netware__"); \ - builtin_assert ("system=netware"); \ - } \ - while (0) - -#undef WCHAR_TYPE -#define WCHAR_TYPE "short unsigned int" - -#undef WCHAR_TYPE_SIZE -#define WCHAR_TYPE_SIZE 16 diff --git a/gcc/config/i386/svr3.ifile b/gcc/config/i386/svr3.ifile deleted file mode 100644 index 32b3ddc2bf3..00000000000 --- a/gcc/config/i386/svr3.ifile +++ /dev/null @@ -1,48 +0,0 @@ -/* - * svr3.ifile - for collectless G++ on i386 System V. - * Leaves memory configured at address 0. - * - * Install this file as $prefix/gcc-lib/TARGET/VERSION/gcc.ifile - * - * BLOCK to an offset that leaves room for many headers ( the value - * here allows for a file header, an outheader, and up to 11 section - * headers on most systems. - * BIND to an address that includes page 0 in mapped memory. The value - * used for BLOCK should be or'd into this value. Here I'm setting BLOCK - * to 0x200 and BIND to ( value_used_for(BLOCK) ) - * If you are using shared libraries, watch that you don't overlap the - * address ranges assigned for shared libs. - * - * GROUP BIND to a location in the next segment. Here, the only value - * that you should change (I think) is that within NEXT, which I've set - * to my hardware segment size. You can always use a larger size, but not - * a smaller one. - */ -SECTIONS -{ - .text BIND(0x000200) BLOCK (0x200) : - { - /* plenty for room for headers */ - *(.init) - *(.text) - vfork = fork; /* I got tired of editing peoples sloppy code */ - *(.fini) - } - .stab BIND(ADDR(.text) + SIZEOF(.text)): { } - .stabstr BIND(ADDR(.stab) + SIZEOF(.stab)): { } - GROUP BIND( NEXT(0x400000) + - (ADDR(.stabstr) + (SIZEOF(.stabstr)) % 0x1000)): - { - .data : { - __CTOR_LIST__ = . ; - . += 4 ; /* leading NULL */ - *(.ctor) - . += 4 ; /* trailing NULL */ - __DTOR_LIST__ = . ; - . += 4 ; /* leading NULL */ - *(.dtor) - . += 4 ; /* trailing NULL */ - } - .bss : { } - } -} diff --git a/gcc/config/i386/svr3dbx.h b/gcc/config/i386/svr3dbx.h deleted file mode 100644 index d06d9117d41..00000000000 --- a/gcc/config/i386/svr3dbx.h +++ /dev/null @@ -1,81 +0,0 @@ -/* Definitions for Intel 386 running system V, using dbx-in-coff encapsulation. - Copyright (C) 1992, 1995, 2002 Free Software Foundation, Inc. - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GCC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/* We do not want to output SDB debugging information. */ - -#undef SDB_DEBUGGING_INFO - -/* We want to output DBX debugging information. */ - -#define DBX_DEBUGGING_INFO 1 - -/* Compensate for botch in dbxout_init/dbxout_source_file which - unconditionally drops the first character from ltext_label_name */ - -#undef ASM_GENERATE_INTERNAL_LABEL -#define ASM_GENERATE_INTERNAL_LABEL(BUF,PREFIX,NUMBER) \ - sprintf ((BUF), "*.%s%ld", (PREFIX), (long)(NUMBER)) - -/* With the current gas, .align N aligns to an N-byte boundary. - This is done to be compatible with the system assembler. - You must specify -DOTHER_ALIGN when building gas-1.38.1. */ - -#undef ASM_OUTPUT_ALIGN -#define ASM_OUTPUT_ALIGN(FILE,LOG) \ - if ((LOG)!=0) fprintf ((FILE), "\t.align %d\n", 1<<(LOG)) - -/* Align labels, etc. at 4-byte boundaries. - For the 486, align to 16-byte boundary for sake of cache. */ - -#undef LABEL_ALIGN_AFTER_BARRIER -#define LABEL_ALIGN_AFTER_BARRIER(LABEL) (i386_align_jumps) - -/* Align start of loop at 4-byte boundary. */ - -#undef LOOP_ALIGN -#define LOOP_ALIGN(LABEL) (i386_align_loops) - - -/* Additional overrides needed for dbx-in-coff gas, mostly taken from pbb.h */ - -/* Although the gas we use can create .ctor and .dtor sections from N_SETT - stabs, it does not support section directives, so we need to have the loader - define the lists. - */ -#define CTOR_LISTS_DEFINED_EXTERNALLY - -/* Use crt1.o as a startup file and crtn.o as a closing file. */ -/* - * The loader directive file svr3.ifile defines how to merge the constructor - * sections into the data section. Also, since gas only puts out those - * sections in response to N_SETT stabs, and does not (yet) have a - * ".sections" directive, svr3.ifile also defines the list symbols - * __DTOR_LIST__ and __CTOR_LIST__. - */ -#undef STARTFILE_SPEC -#define STARTFILE_SPEC \ - "%{!r:%{!z:svr3.ifile%s}%{z:svr3z.ifile%s}}\ - %{pg:gcrt1.o%s}%{!pg:%{posix:%{p:mcrtp1.o%s}%{!p:crtp1.o%s}}%{!posix:%{p:mcrt1.o%s}%{!p:crt1.o%s}}} \ - %{p:-L/usr/lib/libp}%{pg:-L/usr/lib/libp}" - -#define ENDFILE_SPEC "crtn.o%s" - -#undef LIB_SPEC -#define LIB_SPEC "%{posix:-lcposix} %{shlib:-lc_s} -lc -lg" diff --git a/gcc/config/i386/svr3gas.h b/gcc/config/i386/svr3gas.h deleted file mode 100644 index 81428aeb9e4..00000000000 --- a/gcc/config/i386/svr3gas.h +++ /dev/null @@ -1,141 +0,0 @@ -/* Definitions for Intel 386 running system V, using gas. - Copyright (C) 1992, 1996, 2000, 2002 Free Software Foundation, Inc. - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GCC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -#define TARGET_VERSION fprintf (stderr, " (80386, ATT syntax)"); - -/* Add stuff that normally comes from i386/sysv3.h */ - -/* longjmp may fail to restore the registers if called from the same - function that called setjmp. To compensate, the compiler avoids - putting variables in registers in functions that use both setjmp - and longjmp. */ - -#define NON_SAVING_SETJMP \ - (current_function_calls_setjmp && current_function_calls_longjmp) - -/* longjmp may fail to restore the stack pointer if the saved frame - pointer is the same as the caller's frame pointer. Requiring a frame - pointer in any function that calls setjmp or longjmp avoids this - problem, unless setjmp and longjmp are called from the same function. - Since a frame pointer will be required in such a function, it is OK - that the stack pointer is not restored. */ - -#undef SUBTARGET_FRAME_POINTER_REQUIRED -#define SUBTARGET_FRAME_POINTER_REQUIRED \ - (current_function_calls_setjmp || current_function_calls_longjmp) - -/* Modify ASM_OUTPUT_LOCAL slightly to test -msvr3-shlib, adapted to gas */ -#undef ASM_OUTPUT_LOCAL -#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \ - do { \ - int align = exact_log2 (ROUNDED); \ - if (align > 2) align = 2; \ - if (TARGET_SVR3_SHLIB) \ - { \ - data_section (); \ - ASM_OUTPUT_ALIGN ((FILE), align == -1 ? 2 : align); \ - ASM_OUTPUT_LABEL ((FILE), (NAME)); \ - fprintf ((FILE), "\t.set .,.+%u\n", (int)(ROUNDED)); \ - } \ - else \ - { \ - fputs (".lcomm ", (FILE)); \ - assemble_name ((FILE), (NAME)); \ - fprintf ((FILE), ",%u\n", (int)(ROUNDED)); \ - } \ - } while (0) - -/* Add stuff that normally comes from i386/sysv3.h via svr3.h */ - -/* Define the actual types of some ANSI-mandated types. These - definitions should work for most SVR3 systems. */ - -#undef SIZE_TYPE -#define SIZE_TYPE "unsigned int" - -#undef PTRDIFF_TYPE -#define PTRDIFF_TYPE "int" - -#undef WCHAR_TYPE -#define WCHAR_TYPE "long int" - -#undef WCHAR_TYPE_SIZE -#define WCHAR_TYPE_SIZE BITS_PER_WORD - -/* ??? This stuff is copied from config/svr3.h. In the future, - this file should be rewritten to include config/svr3.h - and override what isn't right. */ - -#define INIT_SECTION_ASM_OP "\t.section\t.init" -#define FINI_SECTION_ASM_OP "\t.section .fini,\"x\"" -#define CTORS_SECTION_ASM_OP INIT_SECTION_ASM_OP -#define DTORS_SECTION_ASM_OP FINI_SECTION_ASM_OP - -/* CTOR_LIST_BEGIN and CTOR_LIST_END are machine-dependent - because they push on the stack. */ -/* This is copied from i386/sysv3.h. */ - -#define CTOR_LIST_BEGIN \ - asm (INIT_SECTION_ASM_OP); \ - asm ("pushl $0") -#define CTOR_LIST_END CTOR_LIST_BEGIN - -/* Constructor list on stack is in reverse order. Go to the end of the - list and go backwards to call constructors in the right order. */ -#define DO_GLOBAL_CTORS_BODY \ -do { \ - func_ptr *p, *beg = alloca (0); \ - for (p = beg; *p; p++) \ - ; \ - while (p != beg) \ - (*--p) (); \ -} while (0) - -#undef EXTRA_SECTIONS -#define EXTRA_SECTIONS in_init, in_fini - -#undef EXTRA_SECTION_FUNCTIONS -#define EXTRA_SECTION_FUNCTIONS \ - INIT_SECTION_FUNCTION \ - FINI_SECTION_FUNCTION - -#define INIT_SECTION_FUNCTION \ -void \ -init_section () \ -{ \ - if (in_section != in_init) \ - { \ - fprintf (asm_out_file, "%s\n", INIT_SECTION_ASM_OP); \ - in_section = in_init; \ - } \ -} - -#define FINI_SECTION_FUNCTION \ -void \ -fini_section () \ -{ \ - if (in_section != in_fini) \ - { \ - fprintf (asm_out_file, "%s\n", FINI_SECTION_ASM_OP); \ - in_section = in_fini; \ - } \ -} - -#define TARGET_ASM_CONSTRUCTOR ix86_svr3_asm_out_constructor diff --git a/gcc/config/i386/svr3z.ifile b/gcc/config/i386/svr3z.ifile deleted file mode 100644 index 4946051235e..00000000000 --- a/gcc/config/i386/svr3z.ifile +++ /dev/null @@ -1,48 +0,0 @@ -/* - * svr3z.ifile - for collectless G++ on i386 System V. - * Leaves memory unconfigured at address 0. - * - * Install this file as $prefix/gcc-lib/TARGET/VERSION/gccz.ifile - * - * BLOCK to an offset that leaves room for many headers ( the value - * here allows for a file header, an outheader, and up to 11 section - * headers on most systems. - * BIND to an address that excludes page 0 from being mapped. The value - * used for BLOCK should be or'd into this value. Here I'm setting BLOCK - * to 0x200 and BIND to ( 0x400000 | value_used_for(BLOCK) ) - * If you are using shared libraries, watch that you don't overlap the - * address ranges assigned for shared libs. - * - * GROUP BIND to a location in the next segment. Here, the only value - * that you should change (I think) is that within NEXT, which I've set - * to my hardware segment size. You can always use a larger size, but not - * a smaller one. - */ -SECTIONS -{ - .text BIND(0x400200) BLOCK (0x200) : - { - /* plenty for room for headers */ - *(.init) - *(.text) - vfork = fork; /* I got tired of editing peoples sloppy code */ - *(.fini) - } - .stab BIND(ADDR(.text) + SIZEOF(.text)): { } - .stabstr BIND(ADDR(.stab) + SIZEOF(.stab)): { } - GROUP BIND( NEXT(0x400000) + - (ADDR(.stabstr) + (SIZEOF(.stabstr)) % 0x1000)): - { - .data : { - __CTOR_LIST__ = . ; - . += 4 ; /* leading NULL */ - *(.ctor) - . += 4 ; /* trailing NULL */ - __DTOR_LIST__ = . ; - . += 4 ; /* leading NULL */ - *(.dtor) - . += 4 ; /* trailing NULL */ - } - .bss : { } - } -} diff --git a/gcc/config/i386/t-udk b/gcc/config/i386/t-udk deleted file mode 100644 index 96e18643979..00000000000 --- a/gcc/config/i386/t-udk +++ /dev/null @@ -1,2 +0,0 @@ -# Tell fixincludes to work on this set of headers -SYSTEM_HEADER_DIR = /udk/usr/include diff --git a/gcc/config/i386/udk.h b/gcc/config/i386/udk.h deleted file mode 100644 index 66f5b87067e..00000000000 --- a/gcc/config/i386/udk.h +++ /dev/null @@ -1,28 +0,0 @@ -/* Configuration for i386 interfacing with SCO's Universal Development Kit - probably running on OpenServer 5, Unixware 2, or Unixware 5 - */ - - -/* We're very much the SVR4 target with "/udk" prepended to everything that's - interesting */ - -#undef MD_EXEC_PREFIX -#define MD_EXEC_PREFIX "/udk/usr/ccs/bin/" - -#undef MD_STARTFILE_PREFIX -#define MD_STARTFILE_PREFIX "/udk/usr/ccs/lib/" - -#define STANDARD_INCLUDE_DIR "/udk/usr/include" - -#undef LINK_SPEC -#define LINK_SPEC "%{h*} %{v:-V} \ - %{b} %{Wl,*:%*} \ - %{static:-dn -Bstatic} \ - %{shared:-G -dy -z text} \ - %{symbolic:-Bsymbolic -G -dy -z text} \ - %{G:-G} \ - %{YP,*} \ - %{!YP,*:%{p:-Y P,/udk/usr/ccs/lib/libp:/udk/usr/lib/libp:/udk/usr/ccs/lib:/udk/usr/lib} \ - %{!p:-Y P,/udk/usr/ccs/lib:/udk/usr/lib}} \ - %{Qy:} %{!Qn:-Qy}" - diff --git a/gcc/config/i386/vsta.h b/gcc/config/i386/vsta.h deleted file mode 100644 index f9c4710c6ff..00000000000 --- a/gcc/config/i386/vsta.h +++ /dev/null @@ -1,32 +0,0 @@ -/* Configuration for an i386 running VSTa micro-kernel. - Copyright (C) 1994, 2002 Free Software Foundation, Inc. - Contributed by Rob Savoye (rob@cygnus.com). - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GCC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -#define TARGET_VERSION fprintf (stderr, " (80386, BSD syntax)"); - -#define TARGET_OS_CPP_BUILTINS() \ - do \ - { \ - builtin_define_std ("unix"); \ - builtin_define ("VSTA"); \ - builtin_assert ("system=unix"); \ - builtin_assert ("system=vsta"); \ - } \ - while (0) diff --git a/gcc/config/i960/i960-c.c b/gcc/config/i960/i960-c.c deleted file mode 100644 index 6c1199e352e..00000000000 --- a/gcc/config/i960/i960-c.c +++ /dev/null @@ -1,117 +0,0 @@ -/* Intel 80960 specific, C compiler specific functions. - Copyright (C) 1992, 1995, 1996, 1997, 1998, 1999, 2000 - Free Software Foundation, Inc. - Contributed by Steven McGeady, Intel Corp. - Additional Work by Glenn Colon-Bonet, Jonathan Shapiro, Andy Wilson - Converted to GCC 2.0 by Jim Wilson and Michael Tiemann, Cygnus Support. - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GCC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -#include "config.h" -#include "system.h" -#include "coretypes.h" -#include "tm.h" -#include "cpplib.h" -#include "tree.h" -#include "c-pragma.h" -#include "toplev.h" -#include "ggc.h" -#include "tm_p.h" - -/* Handle pragmas for compatibility with Intel's compilers. */ - -/* NOTE: ic960 R3.0 pragma align definition: - - #pragma align [(size)] | (identifier=size[,...]) - #pragma noalign [(identifier)[,...]] - - (all parens are optional) - - - size is [1,2,4,8,16] - - noalign means size==1 - - applies only to component elements of a struct (and union?) - - identifier applies to structure tag (only) - - missing identifier means next struct - - - alignment rules for bitfields need more investigation. - - This implementation only handles the case of no identifiers. */ - -void -i960_pr_align (pfile) - cpp_reader *pfile ATTRIBUTE_UNUSED; -{ - tree number; - enum cpp_ttype type; - int align; - - type = c_lex (&number); - if (type == CPP_OPEN_PAREN) - type = c_lex (&number); - if (type == CPP_NAME) - { - warning ("sorry, not implemented: #pragma align NAME=SIZE"); - return; - } - if (type != CPP_NUMBER) - { - warning ("malformed #pragma align - ignored"); - return; - } - - align = TREE_INT_CST_LOW (number); - switch (align) - { - case 0: - /* Return to last alignment. */ - align = i960_last_maxbitalignment / 8; - /* Fall through. */ - case 16: - case 8: - case 4: - case 2: - case 1: - i960_last_maxbitalignment = i960_maxbitalignment; - i960_maxbitalignment = align * 8; - break; - - default: - /* Silently ignore bad values. */ - break; - } -} - -void -i960_pr_noalign (pfile) - cpp_reader *pfile ATTRIBUTE_UNUSED; -{ - enum cpp_ttype type; - tree number; - - type = c_lex (&number); - if (type == CPP_OPEN_PAREN) - type = c_lex (&number); - if (type == CPP_NAME) - { - warning ("sorry, not implemented: #pragma noalign NAME"); - return; - } - - i960_last_maxbitalignment = i960_maxbitalignment; - i960_maxbitalignment = 8; -} diff --git a/gcc/config/i960/i960-coff.h b/gcc/config/i960/i960-coff.h deleted file mode 100644 index 465ea33cc3e..00000000000 --- a/gcc/config/i960/i960-coff.h +++ /dev/null @@ -1,43 +0,0 @@ -/* Definitions of target machine for GNU compiler, for "naked" Intel - 80960 using coff object format and coff debugging symbols. - Copyright (C) 1988, 1989, 1991, 1996, 2000 Free Software Foundation. - Contributed by Steven McGeady (mcg@omepd.intel.com) - Additional work by Glenn Colon-Bonet, Jonathan Shapiro, Andy Wilson - Converted to GCC 2.0 by Michael Tiemann, Cygnus Support. - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GCC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/* Support -gstabs using stabs in COFF sections. */ - -/* Generate SDB_DEBUGGING_INFO by default. */ -#undef PREFERRED_DEBUGGING_TYPE -#define PREFERRED_DEBUGGING_TYPE SDB_DEBUG - -/* This is intended to be used with Cygnus's newlib library, so we want to - use the standard definition of LIB_SPEC. */ -#undef LIB_SPEC - -/* Emit a .file directive. */ -#define TARGET_ASM_FILE_START_FILE_DIRECTIVE true - -/* Support the ctors and dtors sections for g++. */ - -#define CTORS_SECTION_ASM_OP "\t.section\t.ctors,\"x\"" -#define DTORS_SECTION_ASM_OP "\t.section\t.dtors,\"x\"" - -/* end of i960-coff.h */ diff --git a/gcc/config/i960/i960-modes.def b/gcc/config/i960/i960-modes.def deleted file mode 100644 index e99939049c6..00000000000 --- a/gcc/config/i960/i960-modes.def +++ /dev/null @@ -1,33 +0,0 @@ -/* Definitions of target machine for GNU compiler, for Intel 80960 - Copyright (C) 2002 Free Software Foundation, Inc. - Contributed by Steven McGeady, Intel Corp. - Additional Work by Glenn Colon-Bonet, Jonathan Shapiro, Andy Wilson - Converted to GCC 2.0 by Jim Wilson and Michael Tiemann, Cygnus Support. - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GCC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/* long double */ -FLOAT_MODE (TF, 16, ieee_extended_intel_128_format); - -/* Add any extra modes needed to represent the condition code. - - Also, signed and unsigned comparisons are distinguished, as - are operations which are compatible with chkbit insns. */ - -CC_MODE (CC_UNS); -CC_MODE (CC_CHK); diff --git a/gcc/config/i960/i960-protos.h b/gcc/config/i960/i960-protos.h deleted file mode 100644 index 269a40be19c..00000000000 --- a/gcc/config/i960/i960-protos.h +++ /dev/null @@ -1,102 +0,0 @@ -/* Definitions of target machine for GNU compiler, for Intel 80960 - Copyright (C) 2000 - Free Software Foundation, Inc. - Contributed by Steven McGeady, Intel Corp. - Additional Work by Glenn Colon-Bonet, Jonathan Shapiro, Andy Wilson - Converted to GCC 2.0 by Jim Wilson and Michael Tiemann, Cygnus Support. - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GCC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -#ifndef GCC_I960_PROTOS_H -#define GCC_I960_PROTOS_H - -#ifdef RTX_CODE -extern struct rtx_def *legitimize_address (rtx, rtx, enum machine_mode); -/* Define the function that build the compare insn for scc and bcc. */ - -extern struct rtx_def *gen_compare_reg (enum rtx_code, rtx, rtx); - -/* Define functions in i960.c and used in insn-output.c. */ - -extern const char *i960_output_ldconst (rtx, rtx); -extern const char *i960_output_call_insn (rtx, rtx, rtx, rtx); -extern const char *i960_output_ret_insn (rtx); -extern const char *i960_output_move_double (rtx, rtx); -extern const char *i960_output_move_double_zero (rtx); -extern const char *i960_output_move_quad (rtx, rtx); -extern const char *i960_output_move_quad_zero (rtx); - -extern int literal (rtx, enum machine_mode); -extern int hard_regno_mode_ok (int, enum machine_mode); -extern int fp_literal (rtx, enum machine_mode); -extern int signed_literal (rtx, enum machine_mode); -extern int legitimate_address_p (enum machine_mode, rtx, int); -extern void i960_print_operand (FILE *, rtx, int); -extern int fpmove_src_operand (rtx, enum machine_mode); -extern int arith_operand (rtx, enum machine_mode); -extern int logic_operand (rtx, enum machine_mode); -extern int fp_arith_operand (rtx, enum machine_mode); -extern int signed_arith_operand (rtx, enum machine_mode); -extern int fp_literal_one (rtx, enum machine_mode); -extern int fp_literal_zero (rtx, enum machine_mode); -extern int symbolic_memory_operand (rtx, enum machine_mode); -extern int eq_or_neq (rtx, enum machine_mode); -extern int arith32_operand (rtx, enum machine_mode); -extern int power2_operand (rtx, enum machine_mode); -extern int cmplpower2_operand (rtx, enum machine_mode); -extern enum machine_mode select_cc_mode (RTX_CODE, rtx); -extern int emit_move_sequence (rtx *, enum machine_mode); -extern int i960_bypass (rtx, rtx, rtx, int); -extern void i960_print_operand_addr (FILE *, rtx); -extern int i960_expr_alignment (rtx, int); -extern int i960_improve_align (rtx, rtx, int); -extern int i960_si_ti (rtx, rtx); -extern int i960_si_di (rtx, rtx); -#ifdef TREE_CODE -extern struct rtx_def *i960_function_arg (CUMULATIVE_ARGS *, - enum machine_mode, - tree, int); -extern rtx i960_va_arg (tree, tree); -extern void i960_va_start (tree, rtx); -#endif /* TREE_CODE */ -extern enum reg_class secondary_reload_class (enum reg_class, enum machine_mode, rtx); -#endif /* RTX_CODE */ - -#ifdef TREE_CODE -extern void i960_function_name_declare (FILE *, const char *, tree); -extern void i960_function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode, tree, int); -extern int i960_round_align (int, tree); -extern void i960_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode, tree, int *, int); -extern int i960_final_reg_parm_stack_space (int, tree); -extern int i960_reg_parm_stack_space (tree); -#endif /* TREE_CODE */ - -extern int process_pragma (int(*)(void), void(*)(int), const char *); -extern int i960_object_bytes_bitalign (int); -extern void i960_initialize (void); -extern int bitpos (unsigned int); -extern int is_mask (unsigned int); -extern int bitstr (unsigned int, int *, int *); -extern int compute_frame_size (int); -extern void output_function_profiler (FILE *, int); -extern void i960_scan_opcode (const char *); - -extern void i960_pr_align (struct cpp_reader *); -extern void i960_pr_noalign (struct cpp_reader *); - -#endif /* ! GCC_I960_PROTOS_H */ diff --git a/gcc/config/i960/i960.c b/gcc/config/i960/i960.c deleted file mode 100644 index 3d976b65fd4..00000000000 --- a/gcc/config/i960/i960.c +++ /dev/null @@ -1,2917 +0,0 @@ -/* Subroutines used for code generation on intel 80960. - Copyright (C) 1992, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 - Free Software Foundation, Inc. - Contributed by Steven McGeady, Intel Corp. - Additional Work by Glenn Colon-Bonet, Jonathan Shapiro, Andy Wilson - Converted to GCC 2.0 by Jim Wilson and Michael Tiemann, Cygnus Support. - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GCC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -#include "config.h" -#include "system.h" -#include "coretypes.h" -#include "tm.h" -#include -#include "rtl.h" -#include "regs.h" -#include "hard-reg-set.h" -#include "real.h" -#include "insn-config.h" -#include "conditions.h" -#include "output.h" -#include "insn-attr.h" -#include "flags.h" -#include "tree.h" -#include "expr.h" -#include "except.h" -#include "function.h" -#include "recog.h" -#include "toplev.h" -#include "tm_p.h" -#include "target.h" -#include "target-def.h" - -static void i960_output_function_prologue (FILE *, HOST_WIDE_INT); -static void i960_output_function_epilogue (FILE *, HOST_WIDE_INT); -static void i960_output_mi_thunk (FILE *, tree, HOST_WIDE_INT, - HOST_WIDE_INT, tree); -static bool i960_rtx_costs (rtx, int, int, int *); -static int i960_address_cost (rtx); -static tree i960_build_builtin_va_list (void); - -/* Save the operands last given to a compare for use when we - generate a scc or bcc insn. */ - -rtx i960_compare_op0, i960_compare_op1; - -/* Used to implement #pragma align/noalign. Initialized by OVERRIDE_OPTIONS - macro in i960.h. */ - -int i960_maxbitalignment; -int i960_last_maxbitalignment; - -/* Used to implement switching between MEM and ALU insn types, for better - C series performance. */ - -enum insn_types i960_last_insn_type; - -/* The leaf-procedure return register. Set only if this is a leaf routine. */ - -static int i960_leaf_ret_reg; - -/* True if replacing tail calls with jumps is OK. */ - -static int tail_call_ok; - -/* A string containing a list of insns to emit in the epilogue so as to - restore all registers saved by the prologue. Created by the prologue - code as it saves registers away. */ - -char epilogue_string[1000]; - -/* A unique number (per function) for return labels. */ - -static int ret_label = 0; - -/* This is true if FNDECL is either a varargs or a stdarg function. - This is used to help identify functions that use an argument block. */ - -#define VARARGS_STDARG_FUNCTION(FNDECL) \ -(TYPE_ARG_TYPES (TREE_TYPE (FNDECL)) != 0 \ - && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (TREE_TYPE (FNDECL))))) \ - != void_type_node) - -/* Initialize the GCC target structure. */ -#undef TARGET_ASM_ALIGNED_SI_OP -#define TARGET_ASM_ALIGNED_SI_OP "\t.word\t" - -#undef TARGET_ASM_FUNCTION_PROLOGUE -#define TARGET_ASM_FUNCTION_PROLOGUE i960_output_function_prologue -#undef TARGET_ASM_FUNCTION_EPILOGUE -#define TARGET_ASM_FUNCTION_EPILOGUE i960_output_function_epilogue - -#undef TARGET_ASM_OUTPUT_MI_THUNK -#define TARGET_ASM_OUTPUT_MI_THUNK i960_output_mi_thunk -#undef TARGET_CAN_ASM_OUTPUT_MI_THUNK -#define TARGET_CAN_ASM_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall - -#undef TARGET_RTX_COSTS -#define TARGET_RTX_COSTS i960_rtx_costs -#undef TARGET_ADDRESS_COST -#define TARGET_ADDRESS_COST i960_address_cost - -#undef TARGET_BUILD_BUILTIN_VA_LIST -#define TARGET_BUILD_BUILTIN_VA_LIST i960_build_builtin_va_list - -struct gcc_target targetm = TARGET_INITIALIZER; - -/* Override conflicting target switch options. - Doesn't actually detect if more than one -mARCH option is given, but - does handle the case of two blatantly conflicting -mARCH options. - - Also initialize variables before compiling any files. */ - -void -i960_initialize () -{ - if (TARGET_K_SERIES && TARGET_C_SERIES) - { - warning ("conflicting architectures defined - using C series"); - target_flags &= ~TARGET_FLAG_K_SERIES; - } - if (TARGET_K_SERIES && TARGET_MC) - { - warning ("conflicting architectures defined - using K series"); - target_flags &= ~TARGET_FLAG_MC; - } - if (TARGET_C_SERIES && TARGET_MC) - { - warning ("conflicting architectures defined - using C series"); - target_flags &= ~TARGET_FLAG_MC; - } - if (TARGET_IC_COMPAT3_0) - { - flag_short_enums = 1; - flag_signed_char = 1; - target_flags |= TARGET_FLAG_CLEAN_LINKAGE; - if (TARGET_IC_COMPAT2_0) - { - warning ("iC2.0 and iC3.0 are incompatible - using iC3.0"); - target_flags &= ~TARGET_FLAG_IC_COMPAT2_0; - } - } - if (TARGET_IC_COMPAT2_0) - { - flag_signed_char = 1; - target_flags |= TARGET_FLAG_CLEAN_LINKAGE; - } - - if (TARGET_IC_COMPAT2_0) - { - i960_maxbitalignment = 8; - i960_last_maxbitalignment = 128; - } - else - { - i960_maxbitalignment = 128; - i960_last_maxbitalignment = 8; - } -} - -/* Return true if OP can be used as the source of an fp move insn. */ - -int -fpmove_src_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return (GET_CODE (op) == CONST_DOUBLE || general_operand (op, mode)); -} - -#if 0 -/* Return true if OP is a register or zero. */ - -int -reg_or_zero_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return register_operand (op, mode) || op == const0_rtx; -} -#endif - -/* Return truth value of whether OP can be used as an operands in a three - address arithmetic insn (such as add %o1,7,%l2) of mode MODE. */ - -int -arith_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return (register_operand (op, mode) || literal (op, mode)); -} - -/* Return truth value of whether OP can be used as an operands in a three - address logic insn, possibly complementing OP, of mode MODE. */ - -int -logic_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return (register_operand (op, mode) - || (GET_CODE (op) == CONST_INT - && INTVAL(op) >= -32 && INTVAL(op) < 32)); -} - -/* Return true if OP is a register or a valid floating point literal. */ - -int -fp_arith_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return (register_operand (op, mode) || fp_literal (op, mode)); -} - -/* Return true if OP is a register or a valid signed integer literal. */ - -int -signed_arith_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return (register_operand (op, mode) || signed_literal (op, mode)); -} - -/* Return truth value of whether OP is an integer which fits the - range constraining immediate operands in three-address insns. */ - -int -literal (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - return ((GET_CODE (op) == CONST_INT) && INTVAL(op) >= 0 && INTVAL(op) < 32); -} - -/* Return true if OP is a float constant of 1. */ - -int -fp_literal_one (op, mode) - rtx op; - enum machine_mode mode; -{ - return (TARGET_NUMERICS && mode == GET_MODE (op) && op == CONST1_RTX (mode)); -} - -/* Return true if OP is a float constant of 0. */ - -int -fp_literal_zero (op, mode) - rtx op; - enum machine_mode mode; -{ - return (TARGET_NUMERICS && mode == GET_MODE (op) && op == CONST0_RTX (mode)); -} - -/* Return true if OP is a valid floating point literal. */ - -int -fp_literal(op, mode) - rtx op; - enum machine_mode mode; -{ - return fp_literal_zero (op, mode) || fp_literal_one (op, mode); -} - -/* Return true if OP is a valid signed immediate constant. */ - -int -signed_literal(op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - return ((GET_CODE (op) == CONST_INT) && INTVAL(op) > -32 && INTVAL(op) < 32); -} - -/* Return truth value of statement that OP is a symbolic memory - operand of mode MODE. */ - -int -symbolic_memory_operand (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - if (GET_CODE (op) != MEM) - return 0; - op = XEXP (op, 0); - return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == CONST - || GET_CODE (op) == HIGH || GET_CODE (op) == LABEL_REF); -} - -/* Return truth value of whether OP is EQ or NE. */ - -int -eq_or_neq (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - return (GET_CODE (op) == EQ || GET_CODE (op) == NE); -} - -/* OP is an integer register or a constant. */ - -int -arith32_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if (register_operand (op, mode)) - return 1; - return (CONSTANT_P (op)); -} - -/* Return true if OP is an integer constant which is a power of 2. */ - -int -power2_operand (op,mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - if (GET_CODE (op) != CONST_INT) - return 0; - - return exact_log2 (INTVAL (op)) >= 0; -} - -/* Return true if OP is an integer constant which is the complement of a - power of 2. */ - -int -cmplpower2_operand (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - if (GET_CODE (op) != CONST_INT) - return 0; - - return exact_log2 (~ INTVAL (op)) >= 0; -} - -/* If VAL has only one bit set, return the index of that bit. Otherwise - return -1. */ - -int -bitpos (val) - unsigned int val; -{ - register int i; - - for (i = 0; val != 0; i++, val >>= 1) - { - if (val & 1) - { - if (val != 1) - return -1; - return i; - } - } - return -1; -} - -/* Return nonzero if OP is a mask, i.e. all one bits are consecutive. - The return value indicates how many consecutive nonzero bits exist - if this is a mask. This is the same as the next function, except that - it does not indicate what the start and stop bit positions are. */ - -int -is_mask (val) - unsigned int val; -{ - register int start, end = 0, i; - - start = -1; - for (i = 0; val != 0; val >>= 1, i++) - { - if (val & 1) - { - if (start < 0) - start = i; - - end = i; - continue; - } - /* Still looking for the first bit. */ - if (start < 0) - continue; - - /* We've seen the start of a bit sequence, and now a zero. There - must be more one bits, otherwise we would have exited the loop. - Therefore, it is not a mask. */ - if (val) - return 0; - } - - /* The bit string has ones from START to END bit positions only. */ - return end - start + 1; -} - -/* If VAL is a mask, then return nonzero, with S set to the starting bit - position and E set to the ending bit position of the mask. The return - value indicates how many consecutive bits exist in the mask. This is - the same as the previous function, except that it also indicates the - start and end bit positions of the mask. */ - -int -bitstr (val, s, e) - unsigned int val; - int *s, *e; -{ - register int start, end, i; - - start = -1; - end = -1; - for (i = 0; val != 0; val >>= 1, i++) - { - if (val & 1) - { - if (start < 0) - start = i; - - end = i; - continue; - } - - /* Still looking for the first bit. */ - if (start < 0) - continue; - - /* We've seen the start of a bit sequence, and now a zero. There - must be more one bits, otherwise we would have exited the loop. - Therefor, it is not a mask. */ - if (val) - { - start = -1; - end = -1; - break; - } - } - - /* The bit string has ones from START to END bit positions only. */ - *s = start; - *e = end; - return ((start < 0) ? 0 : end - start + 1); -} - -/* Return the machine mode to use for a comparison. */ - -enum machine_mode -select_cc_mode (op, x) - RTX_CODE op; - rtx x ATTRIBUTE_UNUSED; -{ - if (op == GTU || op == LTU || op == GEU || op == LEU) - return CC_UNSmode; - return CCmode; -} - -/* X and Y are two things to compare using CODE. Emit the compare insn and - return the rtx for register 36 in the proper mode. */ - -rtx -gen_compare_reg (code, x, y) - enum rtx_code code; - rtx x, y; -{ - rtx cc_reg; - enum machine_mode ccmode = SELECT_CC_MODE (code, x, y); - enum machine_mode mode - = GET_MODE (x) == VOIDmode ? GET_MODE (y) : GET_MODE (x); - - if (mode == SImode) - { - if (! arith_operand (x, mode)) - x = force_reg (SImode, x); - if (! arith_operand (y, mode)) - y = force_reg (SImode, y); - } - - cc_reg = gen_rtx_REG (ccmode, 36); - emit_insn (gen_rtx_SET (VOIDmode, cc_reg, - gen_rtx_COMPARE (ccmode, x, y))); - - return cc_reg; -} - -/* For the i960, REG is cost 1, REG+immed CONST is cost 2, REG+REG is cost 2, - REG+nonimmed CONST is cost 4. REG+SYMBOL_REF, SYMBOL_REF, and similar - are 4. Indexed addresses are cost 6. */ - -/* ??? Try using just RTX_COST, i.e. not defining ADDRESS_COST. */ - -static int -i960_address_cost (x) - rtx x; -{ - if (GET_CODE (x) == REG) - return 1; - - /* This is a MEMA operand -- it's free. */ - if (GET_CODE (x) == CONST_INT - && INTVAL (x) >= 0 - && INTVAL (x) < 4096) - return 0; - - if (GET_CODE (x) == PLUS) - { - rtx base = XEXP (x, 0); - rtx offset = XEXP (x, 1); - - if (GET_CODE (base) == SUBREG) - base = SUBREG_REG (base); - if (GET_CODE (offset) == SUBREG) - offset = SUBREG_REG (offset); - - if (GET_CODE (base) == REG) - { - if (GET_CODE (offset) == REG) - return 2; - if (GET_CODE (offset) == CONST_INT) - { - if ((unsigned)INTVAL (offset) < 2047) - return 2; - return 4; - } - if (CONSTANT_P (offset)) - return 4; - } - if (GET_CODE (base) == PLUS || GET_CODE (base) == MULT) - return 6; - - /* This is an invalid address. The return value doesn't matter, but - for convenience we make this more expensive than anything else. */ - return 12; - } - if (GET_CODE (x) == MULT) - return 6; - - /* Symbol_refs and other unrecognized addresses are cost 4. */ - return 4; -} - -/* Emit insns to move operands[1] into operands[0]. - - Return 1 if we have written out everything that needs to be done to - do the move. Otherwise, return 0 and the caller will emit the move - normally. */ - -int -emit_move_sequence (operands, mode) - rtx *operands; - enum machine_mode mode; -{ - /* We can only store registers to memory. */ - - if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) != REG - && (operands[1] != const0_rtx || current_function_args_size - || current_function_stdarg - || rtx_equal_function_value_matters)) - /* Here we use the same test as movsi+1 pattern -- see i960.md. */ - operands[1] = force_reg (mode, operands[1]); - - /* Storing multi-word values in unaligned hard registers to memory may - require a scratch since we have to store them a register at a time and - adding 4 to the memory address may not yield a valid insn. */ - /* ??? We don't always need the scratch, but that would complicate things. - Maybe later. */ - /* ??? We must also handle stores to pseudos here, because the pseudo may be - replaced with a MEM later. This would be cleaner if we didn't have - a separate pattern for unaligned DImode/TImode stores. */ - if (GET_MODE_SIZE (mode) > UNITS_PER_WORD - && (GET_CODE (operands[0]) == MEM - || (GET_CODE (operands[0]) == REG - && REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER)) - && GET_CODE (operands[1]) == REG - && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER - && ! HARD_REGNO_MODE_OK (REGNO (operands[1]), mode)) - { - emit_insn (gen_rtx_PARALLEL - (VOIDmode, - gen_rtvec (2, - gen_rtx_SET (VOIDmode, operands[0], operands[1]), - gen_rtx_CLOBBER (VOIDmode, - gen_rtx_SCRATCH (Pmode))))); - return 1; - } - - return 0; -} - -/* Output assembler to move a double word value. */ - -const char * -i960_output_move_double (dst, src) - rtx dst, src; -{ - rtx operands[5]; - - if (GET_CODE (dst) == REG - && GET_CODE (src) == REG) - { - if ((REGNO (src) & 1) - || (REGNO (dst) & 1)) - { - /* We normally copy the low-numbered register first. However, if - the second source register is the same as the first destination - register, we must copy in the opposite order. */ - if (REGNO (src) + 1 == REGNO (dst)) - return "mov %D1,%D0\n\tmov %1,%0"; - else - return "mov %1,%0\n\tmov %D1,%D0"; - } - else - return "movl %1,%0"; - } - else if (GET_CODE (dst) == REG - && GET_CODE (src) == CONST_INT - && CONST_OK_FOR_LETTER_P (INTVAL (src), 'I')) - { - if (REGNO (dst) & 1) - return "mov %1,%0\n\tmov 0,%D0"; - else - return "movl %1,%0"; - } - else if (GET_CODE (dst) == REG - && GET_CODE (src) == MEM) - { - if (REGNO (dst) & 1) - { - /* One can optimize a few cases here, but you have to be - careful of clobbering registers used in the address and - edge conditions. */ - operands[0] = dst; - operands[1] = src; - operands[2] = gen_rtx_REG (Pmode, REGNO (dst) + 1); - operands[3] = gen_rtx_MEM (word_mode, operands[2]); - operands[4] = adjust_address (operands[3], word_mode, - UNITS_PER_WORD); - output_asm_insn - ("lda %1,%2\n\tld %3,%0\n\tld %4,%D0", operands); - return ""; - } - else - return "ldl %1,%0"; - } - else if (GET_CODE (dst) == MEM - && GET_CODE (src) == REG) - { - if (REGNO (src) & 1) - { - operands[0] = dst; - operands[1] = adjust_address (dst, word_mode, UNITS_PER_WORD); - if (! memory_address_p (word_mode, XEXP (operands[1], 0))) - abort (); - operands[2] = src; - output_asm_insn ("st %2,%0\n\tst %D2,%1", operands); - return ""; - } - return "stl %1,%0"; - } - else - abort (); -} - -/* Output assembler to move a double word zero. */ - -const char * -i960_output_move_double_zero (dst) - rtx dst; -{ - rtx operands[2]; - - operands[0] = dst; - { - operands[1] = adjust_address (dst, word_mode, 4); - output_asm_insn ("st g14,%0\n\tst g14,%1", operands); - } - return ""; -} - -/* Output assembler to move a quad word value. */ - -const char * -i960_output_move_quad (dst, src) - rtx dst, src; -{ - rtx operands[7]; - - if (GET_CODE (dst) == REG - && GET_CODE (src) == REG) - { - if ((REGNO (src) & 3) - || (REGNO (dst) & 3)) - { - /* We normally copy starting with the low numbered register. - However, if there is an overlap such that the first dest reg - is <= the last source reg but not < the first source reg, we - must copy in the opposite order. */ - if (REGNO (dst) <= REGNO (src) + 3 - && REGNO (dst) >= REGNO (src)) - return "mov %F1,%F0\n\tmov %E1,%E0\n\tmov %D1,%D0\n\tmov %1,%0"; - else - return "mov %1,%0\n\tmov %D1,%D0\n\tmov %E1,%E0\n\tmov %F1,%F0"; - } - else - return "movq %1,%0"; - } - else if (GET_CODE (dst) == REG - && GET_CODE (src) == CONST_INT - && CONST_OK_FOR_LETTER_P (INTVAL (src), 'I')) - { - if (REGNO (dst) & 3) - return "mov %1,%0\n\tmov 0,%D0\n\tmov 0,%E0\n\tmov 0,%F0"; - else - return "movq %1,%0"; - } - else if (GET_CODE (dst) == REG - && GET_CODE (src) == MEM) - { - if (REGNO (dst) & 3) - { - /* One can optimize a few cases here, but you have to be - careful of clobbering registers used in the address and - edge conditions. */ - operands[0] = dst; - operands[1] = src; - operands[2] = gen_rtx_REG (Pmode, REGNO (dst) + 3); - operands[3] = gen_rtx_MEM (word_mode, operands[2]); - operands[4] - = adjust_address (operands[3], word_mode, UNITS_PER_WORD); - operands[5] - = adjust_address (operands[4], word_mode, UNITS_PER_WORD); - operands[6] - = adjust_address (operands[5], word_mode, UNITS_PER_WORD); - output_asm_insn ("lda %1,%2\n\tld %3,%0\n\tld %4,%D0\n\tld %5,%E0\n\tld %6,%F0", operands); - return ""; - } - else - return "ldq %1,%0"; - } - else if (GET_CODE (dst) == MEM - && GET_CODE (src) == REG) - { - if (REGNO (src) & 3) - { - operands[0] = dst; - operands[1] = adjust_address (dst, word_mode, UNITS_PER_WORD); - operands[2] = adjust_address (dst, word_mode, 2 * UNITS_PER_WORD); - operands[3] = adjust_address (dst, word_mode, 3 * UNITS_PER_WORD); - if (! memory_address_p (word_mode, XEXP (operands[3], 0))) - abort (); - operands[4] = src; - output_asm_insn ("st %4,%0\n\tst %D4,%1\n\tst %E4,%2\n\tst %F4,%3", operands); - return ""; - } - return "stq %1,%0"; - } - else - abort (); -} - -/* Output assembler to move a quad word zero. */ - -const char * -i960_output_move_quad_zero (dst) - rtx dst; -{ - rtx operands[4]; - - operands[0] = dst; - { - operands[1] = adjust_address (dst, word_mode, 4); - operands[2] = adjust_address (dst, word_mode, 8); - operands[3] = adjust_address (dst, word_mode, 12); - output_asm_insn ("st g14,%0\n\tst g14,%1\n\tst g14,%2\n\tst g14,%3", operands); - } - return ""; -} - - -/* Emit insns to load a constant to non-floating point registers. - Uses several strategies to try to use as few insns as possible. */ - -const char * -i960_output_ldconst (dst, src) - register rtx dst, src; -{ - register int rsrc1; - register unsigned rsrc2; - enum machine_mode mode = GET_MODE (dst); - rtx operands[4]; - - operands[0] = operands[2] = dst; - operands[1] = operands[3] = src; - - /* Anything that isn't a compile time constant, such as a SYMBOL_REF, - must be a ldconst insn. */ - - if (GET_CODE (src) != CONST_INT && GET_CODE (src) != CONST_DOUBLE) - { - output_asm_insn ("ldconst %1,%0", operands); - return ""; - } - else if (mode == TFmode) - { - REAL_VALUE_TYPE d; - long value_long[3]; - int i; - - if (fp_literal_zero (src, TFmode)) - return "movt 0,%0"; - - REAL_VALUE_FROM_CONST_DOUBLE (d, src); - REAL_VALUE_TO_TARGET_LONG_DOUBLE (d, value_long); - - output_asm_insn ("# ldconst %1,%0",operands); - - for (i = 0; i < 3; i++) - { - operands[0] = gen_rtx_REG (SImode, REGNO (dst) + i); - operands[1] = GEN_INT (value_long[i]); - output_asm_insn (i960_output_ldconst (operands[0], operands[1]), - operands); - } - - return ""; - } - else if (mode == DFmode) - { - rtx first, second; - - if (fp_literal_zero (src, DFmode)) - return "movl 0,%0"; - - split_double (src, &first, &second); - - output_asm_insn ("# ldconst %1,%0",operands); - - operands[0] = gen_rtx_REG (SImode, REGNO (dst)); - operands[1] = first; - output_asm_insn (i960_output_ldconst (operands[0], operands[1]), - operands); - operands[0] = gen_rtx_REG (SImode, REGNO (dst) + 1); - operands[1] = second; - output_asm_insn (i960_output_ldconst (operands[0], operands[1]), - operands); - return ""; - } - else if (mode == SFmode) - { - REAL_VALUE_TYPE d; - long value; - - REAL_VALUE_FROM_CONST_DOUBLE (d, src); - REAL_VALUE_TO_TARGET_SINGLE (d, value); - - output_asm_insn ("# ldconst %1,%0",operands); - operands[0] = gen_rtx_REG (SImode, REGNO (dst)); - operands[1] = GEN_INT (value); - output_asm_insn (i960_output_ldconst (operands[0], operands[1]), - operands); - return ""; - } - else if (mode == TImode) - { - /* ??? This is currently not handled at all. */ - abort (); - - /* Note: lowest order word goes in lowest numbered reg. */ - rsrc1 = INTVAL (src); - if (rsrc1 >= 0 && rsrc1 < 32) - return "movq %1,%0"; - else - output_asm_insn ("movq\t0,%0\t# ldconstq %1,%0",operands); - /* Go pick up the low-order word. */ - } - else if (mode == DImode) - { - rtx upperhalf, lowerhalf, xoperands[2]; - - if (GET_CODE (src) == CONST_DOUBLE || GET_CODE (src) == CONST_INT) - split_double (src, &lowerhalf, &upperhalf); - - else - abort (); - - /* Note: lowest order word goes in lowest numbered reg. */ - /* Numbers from 0 to 31 can be handled with a single insn. */ - rsrc1 = INTVAL (lowerhalf); - if (upperhalf == const0_rtx && rsrc1 >= 0 && rsrc1 < 32) - return "movl %1,%0"; - - /* Output the upper half with a recursive call. */ - xoperands[0] = gen_rtx_REG (SImode, REGNO (dst) + 1); - xoperands[1] = upperhalf; - output_asm_insn (i960_output_ldconst (xoperands[0], xoperands[1]), - xoperands); - /* The lower word is emitted as normally. */ - } - else - { - rsrc1 = INTVAL (src); - if (mode == QImode) - { - if (rsrc1 > 0xff) - rsrc1 &= 0xff; - } - else if (mode == HImode) - { - if (rsrc1 > 0xffff) - rsrc1 &= 0xffff; - } - } - - if (rsrc1 >= 0) - { - /* ldconst 0..31,X -> mov 0..31,X */ - if (rsrc1 < 32) - { - if (i960_last_insn_type == I_TYPE_REG && TARGET_C_SERIES) - return "lda %1,%0"; - return "mov %1,%0"; - } - - /* ldconst 32..63,X -> add 31,nn,X */ - if (rsrc1 < 63) - { - if (i960_last_insn_type == I_TYPE_REG && TARGET_C_SERIES) - return "lda %1,%0"; - operands[1] = GEN_INT (rsrc1 - 31); - output_asm_insn ("addo\t31,%1,%0\t# ldconst %3,%0", operands); - return ""; - } - } - else if (rsrc1 < 0) - { - /* ldconst -1..-31 -> sub 0,0..31,X */ - if (rsrc1 >= -31) - { - /* return 'sub -(%1),0,%0' */ - operands[1] = GEN_INT (- rsrc1); - output_asm_insn ("subo\t%1,0,%0\t# ldconst %3,%0", operands); - return ""; - } - - /* ldconst -32 -> not 31,X */ - if (rsrc1 == -32) - { - operands[1] = GEN_INT (~rsrc1); - output_asm_insn ("not\t%1,%0 # ldconst %3,%0", operands); - return ""; - } - } - - /* If const is a single bit. */ - if (bitpos (rsrc1) >= 0) - { - operands[1] = GEN_INT (bitpos (rsrc1)); - output_asm_insn ("setbit\t%1,0,%0\t# ldconst %3,%0", operands); - return ""; - } - - /* If const is a bit string of less than 6 bits (1..31 shifted). */ - if (is_mask (rsrc1)) - { - int s, e; - - if (bitstr (rsrc1, &s, &e) < 6) - { - rsrc2 = ((unsigned int) rsrc1) >> s; - operands[1] = GEN_INT (rsrc2); - operands[2] = GEN_INT (s); - output_asm_insn ("shlo\t%2,%1,%0\t# ldconst %3,%0", operands); - return ""; - } - } - - /* Unimplemented cases: - const is in range 0..31 but rotated around end of word: - ror 31,3,g0 -> ldconst 0xe0000003,g0 - - and any 2 instruction cases that might be worthwhile */ - - output_asm_insn ("ldconst %1,%0", operands); - return ""; -} - -/* Determine if there is an opportunity for a bypass optimization. - Bypass succeeds on the 960K* if the destination of the previous - instruction is the second operand of the current instruction. - Bypass always succeeds on the C*. - - Return 1 if the pattern should interchange the operands. - - CMPBR_FLAG is true if this is for a compare-and-branch insn. - OP1 and OP2 are the two source operands of a 3 operand insn. */ - -int -i960_bypass (insn, op1, op2, cmpbr_flag) - register rtx insn, op1, op2; - int cmpbr_flag; -{ - register rtx prev_insn, prev_dest; - - if (TARGET_C_SERIES) - return 0; - - /* Can't do this if op1 isn't a register. */ - if (! REG_P (op1)) - return 0; - - /* Can't do this for a compare-and-branch if both ops aren't regs. */ - if (cmpbr_flag && ! REG_P (op2)) - return 0; - - prev_insn = prev_real_insn (insn); - - if (prev_insn && GET_CODE (prev_insn) == INSN - && GET_CODE (PATTERN (prev_insn)) == SET) - { - prev_dest = SET_DEST (PATTERN (prev_insn)); - if ((GET_CODE (prev_dest) == REG && REGNO (prev_dest) == REGNO (op1)) - || (GET_CODE (prev_dest) == SUBREG - && GET_CODE (SUBREG_REG (prev_dest)) == REG - && REGNO (SUBREG_REG (prev_dest)) == REGNO (op1))) - return 1; - } - return 0; -} - -/* Output the code which declares the function name. This also handles - leaf routines, which have special requirements, and initializes some - global variables. */ - -void -i960_function_name_declare (file, name, fndecl) - FILE *file; - const char *name; - tree fndecl; -{ - register int i, j; - int leaf_proc_ok; - rtx insn; - - /* Increment global return label. */ - - ret_label++; - - /* Compute whether tail calls and leaf routine optimizations can be performed - for this function. */ - - if (TARGET_TAILCALL) - tail_call_ok = 1; - else - tail_call_ok = 0; - - if (TARGET_LEAFPROC) - leaf_proc_ok = 1; - else - leaf_proc_ok = 0; - - /* Even if nobody uses extra parms, can't have leafproc or tail calls if - argblock, because argblock uses g14 implicitly. */ - - if (current_function_args_size != 0 || VARARGS_STDARG_FUNCTION (fndecl)) - { - tail_call_ok = 0; - leaf_proc_ok = 0; - } - - /* See if caller passes in an address to return value. */ - - if (aggregate_value_p (DECL_RESULT (fndecl), fndecl)) - { - tail_call_ok = 0; - leaf_proc_ok = 0; - } - - /* Can not use tail calls or make this a leaf routine if there is a non - zero frame size. */ - - if (get_frame_size () != 0) - leaf_proc_ok = 0; - - /* I don't understand this condition, and do not think that it is correct. - Apparently this is just checking whether the frame pointer is used, and - we can't trust regs_ever_live[fp] since it is (almost?) always set. */ - - if (tail_call_ok) - for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) - if (GET_CODE (insn) == INSN - && reg_mentioned_p (frame_pointer_rtx, insn)) - { - tail_call_ok = 0; - break; - } - - /* Check for CALL insns. Can not be a leaf routine if there are any. */ - - if (leaf_proc_ok) - for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) - if (GET_CODE (insn) == CALL_INSN) - { - leaf_proc_ok = 0; - break; - } - - /* Can not be a leaf routine if any non-call clobbered registers are - used in this function. */ - - if (leaf_proc_ok) - for (i = 0, j = 0; i < FIRST_PSEUDO_REGISTER; i++) - if (regs_ever_live[i] - && ((! call_used_regs[i]) || (i > 7 && i < 12))) - { - /* Global registers. */ - if (i < 16 && i > 7 && i != 13) - leaf_proc_ok = 0; - /* Local registers. */ - else if (i < 32) - leaf_proc_ok = 0; - } - - /* Now choose a leaf return register, if we can find one, and if it is - OK for this to be a leaf routine. */ - - i960_leaf_ret_reg = -1; - - if (optimize && leaf_proc_ok) - { - for (i960_leaf_ret_reg = -1, i = 0; i < 8; i++) - if (regs_ever_live[i] == 0) - { - i960_leaf_ret_reg = i; - regs_ever_live[i] = 1; - break; - } - } - - /* Do this after choosing the leaf return register, so it will be listed - if one was chosen. */ - - fprintf (file, "\t# Function '%s'\n", (name[0] == '*' ? &name[1] : name)); - fprintf (file, "\t# Registers used: "); - - for (i = 0, j = 0; i < FIRST_PSEUDO_REGISTER; i++) - { - if (regs_ever_live[i]) - { - fprintf (file, "%s%s ", reg_names[i], call_used_regs[i] ? "" : "*"); - - if (i > 15 && j == 0) - { - fprintf (file,"\n\t#\t\t "); - j++; - } - } - } - - fprintf (file, "\n"); - - if (i960_leaf_ret_reg >= 0) - { - /* Make it a leaf procedure. */ - - if (TREE_PUBLIC (fndecl)) - fprintf (file,"\t.globl\t%s.lf\n", (name[0] == '*' ? &name[1] : name)); - - fprintf (file, "\t.leafproc\t"); - assemble_name (file, name); - fprintf (file, ",%s.lf\n", (name[0] == '*' ? &name[1] : name)); - ASM_OUTPUT_LABEL (file, name); - fprintf (file, "\tlda Li960R%d,g14\n", ret_label); - fprintf (file, "%s.lf:\n", (name[0] == '*' ? &name[1] : name)); - fprintf (file, "\tmov g14,g%d\n", i960_leaf_ret_reg); - - if (TARGET_C_SERIES) - { - fprintf (file, "\tlda 0,g14\n"); - i960_last_insn_type = I_TYPE_MEM; - } - else - { - fprintf (file, "\tmov 0,g14\n"); - i960_last_insn_type = I_TYPE_REG; - } - } - else - { - ASM_OUTPUT_LABEL (file, name); - i960_last_insn_type = I_TYPE_CTRL; - } -} - -/* Compute and return the frame size. */ - -int -compute_frame_size (size) - int size; -{ - int actual_fsize; - int outgoing_args_size = current_function_outgoing_args_size; - - /* The STARTING_FRAME_OFFSET is totally hidden to us as far - as size is concerned. */ - actual_fsize = (size + 15) & -16; - actual_fsize += (outgoing_args_size + 15) & -16; - - return actual_fsize; -} - -/* Here register group is range of registers which can be moved by - one i960 instruction. */ - -struct reg_group -{ - char start_reg; - char length; -}; - -static int i960_form_reg_groups (int, int, int *, int, struct reg_group *); -static int i960_reg_group_compare (const void *, const void *); -static int i960_split_reg_group (struct reg_group *, int, int); -static void i960_arg_size_and_align (enum machine_mode, tree, int *, int *); - -/* The following functions forms the biggest as possible register - groups with registers in STATE. REGS contain states of the - registers in range [start, finish_reg). The function returns the - number of groups formed. */ -static int -i960_form_reg_groups (start_reg, finish_reg, regs, state, reg_groups) - int start_reg; - int finish_reg; - int *regs; - int state; - struct reg_group *reg_groups; -{ - int i; - int nw = 0; - - for (i = start_reg; i < finish_reg; ) - { - if (regs [i] != state) - { - i++; - continue; - } - else if (i % 2 != 0 || regs [i + 1] != state) - reg_groups [nw].length = 1; - else if (i % 4 != 0 || regs [i + 2] != state) - reg_groups [nw].length = 2; - else if (regs [i + 3] != state) - reg_groups [nw].length = 3; - else - reg_groups [nw].length = 4; - reg_groups [nw].start_reg = i; - i += reg_groups [nw].length; - nw++; - } - return nw; -} - -/* We sort register winodws in descending order by length. */ -static int -i960_reg_group_compare (group1, group2) - const void *group1; - const void *group2; -{ - const struct reg_group *w1 = group1; - const struct reg_group *w2 = group2; - - if (w1->length > w2->length) - return -1; - else if (w1->length < w2->length) - return 1; - else - return 0; -} - -/* Split the first register group in REG_GROUPS on subgroups one of - which will contain SUBGROUP_LENGTH registers. The function - returns new number of winodws. */ -static int -i960_split_reg_group (reg_groups, nw, subgroup_length) - struct reg_group *reg_groups; - int nw; - int subgroup_length; -{ - if (subgroup_length < reg_groups->length - subgroup_length) - /* This guarantees correct alignments of the two subgroups for - i960 (see spliting for the group length 2, 3, 4). More - generalized algorithm would require splitting the group more - two subgroups. */ - subgroup_length = reg_groups->length - subgroup_length; - /* More generalized algorithm would require to try merging - subgroups here. But in case i960 it always results in failure - because of register group alignment. */ - reg_groups[nw].length = reg_groups->length - subgroup_length; - reg_groups[nw].start_reg = reg_groups->start_reg + subgroup_length; - nw++; - reg_groups->length = subgroup_length; - qsort (reg_groups, nw, sizeof (struct reg_group), i960_reg_group_compare); - return nw; -} - -/* Output code for the function prologue. */ - -static void -i960_output_function_prologue (file, size) - FILE *file; - HOST_WIDE_INT size; -{ - register int i, j, nr; - int n_saved_regs = 0; - int n_remaining_saved_regs; - HOST_WIDE_INT lvar_size; - HOST_WIDE_INT actual_fsize, offset; - int gnw, lnw; - struct reg_group *g, *l; - char tmpstr[1000]; - /* -1 if reg must be saved on proc entry, 0 if available, 1 if saved - somewhere. */ - int regs[FIRST_PSEUDO_REGISTER]; - /* All global registers (which must be saved) divided by groups. */ - struct reg_group global_reg_groups [16]; - /* All local registers (which are available) divided by groups. */ - struct reg_group local_reg_groups [16]; - - - for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) - if (regs_ever_live[i] - && ((! call_used_regs[i]) || (i > 7 && i < 12)) - /* No need to save the static chain pointer. */ - && ! (i == STATIC_CHAIN_REGNUM && current_function_needs_context)) - { - regs[i] = -1; - /* Count global registers that need saving. */ - if (i < 16) - n_saved_regs++; - } - else - regs[i] = 0; - - n_remaining_saved_regs = n_saved_regs; - - epilogue_string[0] = '\0'; - - if (current_function_profile) - { - /* When profiling, we may use registers 20 to 27 to save arguments, so - they can't be used here for saving globals. J is the number of - argument registers the mcount call will save. */ - for (j = 7; j >= 0 && ! regs_ever_live[j]; j--) - ; - - for (i = 20; i <= j + 20; i++) - regs[i] = -1; - } - - gnw = i960_form_reg_groups (0, 16, regs, -1, global_reg_groups); - lnw = i960_form_reg_groups (19, 32, regs, 0, local_reg_groups); - qsort (global_reg_groups, gnw, sizeof (struct reg_group), - i960_reg_group_compare); - qsort (local_reg_groups, lnw, sizeof (struct reg_group), - i960_reg_group_compare); - for (g = global_reg_groups, l = local_reg_groups; lnw != 0 && gnw != 0;) - { - if (g->length == l->length) - { - fprintf (file, "\tmov%s %s,%s\n", - ((g->length == 4) ? "q" : - (g->length == 3) ? "t" : - (g->length == 2) ? "l" : ""), - reg_names[(unsigned char) g->start_reg], - reg_names[(unsigned char) l->start_reg]); - sprintf (tmpstr, "\tmov%s %s,%s\n", - ((g->length == 4) ? "q" : - (g->length == 3) ? "t" : - (g->length == 2) ? "l" : ""), - reg_names[(unsigned char) l->start_reg], - reg_names[(unsigned char) g->start_reg]); - strcat (epilogue_string, tmpstr); - n_remaining_saved_regs -= g->length; - for (i = 0; i < g->length; i++) - { - regs [i + g->start_reg] = 1; - regs [i + l->start_reg] = -1; - regs_ever_live [i + l->start_reg] = 1; - } - g++; - l++; - gnw--; - lnw--; - } - else if (g->length > l->length) - gnw = i960_split_reg_group (g, gnw, l->length); - else - lnw = i960_split_reg_group (l, lnw, g->length); - } - - actual_fsize = compute_frame_size (size) + 4 * n_remaining_saved_regs; -#if 0 - /* ??? The 1.2.1 compiler does this also. This is meant to round the frame - size up to the nearest multiple of 16. I don't know whether this is - necessary, or even desirable. - - The frame pointer must be aligned, but the call instruction takes care of - that. If we leave the stack pointer unaligned, we may save a little on - dynamic stack allocation. And we don't lose, at least according to the - i960CA manual. */ - actual_fsize = (actual_fsize + 15) & ~0xF; -#endif - - /* Check stack limit if necessary. */ - if (current_function_limit_stack) - { - rtx min_stack = stack_limit_rtx; - if (actual_fsize != 0) - min_stack = plus_constant (stack_limit_rtx, -actual_fsize); - - /* Now, emulate a little bit of reload. We want to turn 'min_stack' - into an arith_operand. Use register 20 as the temporary. */ - if (legitimate_address_p (Pmode, min_stack, 1) - && !arith_operand (min_stack, Pmode)) - { - rtx tmp = gen_rtx_MEM (Pmode, min_stack); - fputs ("\tlda\t", file); - i960_print_operand (file, tmp, 0); - fputs (",r4\n", file); - min_stack = gen_rtx_REG (Pmode, 20); - } - if (arith_operand (min_stack, Pmode)) - { - fputs ("\tcmpo\tsp,", file); - i960_print_operand (file, min_stack, 0); - fputs ("\n\tfaultge.f\n", file); - } - else - warning ("stack limit expression is not supported"); - } - - /* Allocate space for register save and locals. */ - if (actual_fsize > 0) - { - if (actual_fsize < 32) - fprintf (file, "\taddo " HOST_WIDE_INT_PRINT_DEC ",sp,sp\n", - actual_fsize); - else - fprintf (file, "\tlda\t" HOST_WIDE_INT_PRINT_DEC "(sp),sp\n", - actual_fsize); - } - - /* Take hardware register save area created by the call instruction - into account, but store them before the argument block area. */ - lvar_size = actual_fsize - compute_frame_size (0) - n_remaining_saved_regs * 4; - offset = STARTING_FRAME_OFFSET + lvar_size; - /* Save registers on stack if needed. */ - /* ??? Is it worth to use the same algorithm as one for saving - global registers in local registers? */ - for (i = 0, j = n_remaining_saved_regs; j > 0 && i < 16; i++) - { - if (regs[i] != -1) - continue; - - nr = 1; - - if (i <= 14 && i % 2 == 0 && regs[i+1] == -1 && offset % 2 == 0) - nr = 2; - - if (nr == 2 && i <= 12 && i % 4 == 0 && regs[i+2] == -1 - && offset % 4 == 0) - nr = 3; - - if (nr == 3 && regs[i+3] == -1) - nr = 4; - - fprintf (file,"\tst%s %s," HOST_WIDE_INT_PRINT_DEC "(fp)\n", - ((nr == 4) ? "q" : - (nr == 3) ? "t" : - (nr == 2) ? "l" : ""), - reg_names[i], offset); - sprintf (tmpstr,"\tld%s " HOST_WIDE_INT_PRINT_DEC "(fp),%s\n", - ((nr == 4) ? "q" : - (nr == 3) ? "t" : - (nr == 2) ? "l" : ""), - offset, reg_names[i]); - strcat (epilogue_string, tmpstr); - i += nr-1; - j -= nr; - offset += nr * 4; - } - - if (actual_fsize == 0) - return; - - fprintf (file, "\t#Prologue stats:\n"); - fprintf (file, "\t# Total Frame Size: " HOST_WIDE_INT_PRINT_DEC " bytes\n", - actual_fsize); - - if (lvar_size) - fprintf (file, "\t# Local Variable Size: " HOST_WIDE_INT_PRINT_DEC - " bytes\n", lvar_size); - if (n_saved_regs) - fprintf (file, "\t# Register Save Size: %d regs, %d bytes\n", - n_saved_regs, n_saved_regs * 4); - fprintf (file, "\t#End Prologue#\n"); -} - -/* Output code for the function profiler. */ - -void -output_function_profiler (file, labelno) - FILE *file; - int labelno; -{ - /* The last used parameter register. */ - int last_parm_reg; - int i, j, increment; - int varargs_stdarg_function - = VARARGS_STDARG_FUNCTION (current_function_decl); - - /* Figure out the last used parameter register. The proper thing to do - is to walk incoming args of the function. A function might have live - parameter registers even if it has no incoming args. Note that we - don't have to save parameter registers g8 to g11 because they are - call preserved. */ - - /* See also output_function_prologue, which tries to use local registers - for preserved call-saved global registers. */ - - for (last_parm_reg = 7; - last_parm_reg >= 0 && ! regs_ever_live[last_parm_reg]; - last_parm_reg--) - ; - - /* Save parameter registers in regs r4 (20) to r11 (27). */ - - for (i = 0, j = 4; i <= last_parm_reg; i += increment, j += increment) - { - if (i % 4 == 0 && (last_parm_reg - i) >= 3) - increment = 4; - else if (i % 4 == 0 && (last_parm_reg - i) >= 2) - increment = 3; - else if (i % 2 == 0 && (last_parm_reg - i) >= 1) - increment = 2; - else - increment = 1; - - fprintf (file, "\tmov%s g%d,r%d\n", - (increment == 4 ? "q" : increment == 3 ? "t" - : increment == 2 ? "l": ""), i, j); - } - - /* If this function uses the arg pointer, then save it in r3 and then - set it to zero. */ - - if (current_function_args_size != 0 || varargs_stdarg_function) - fprintf (file, "\tmov g14,r3\n\tmov 0,g14\n"); - - /* Load location address into g0 and call mcount. */ - - fprintf (file, "\tlda\tLP%d,g0\n\tcallx\tmcount\n", labelno); - - /* If this function uses the arg pointer, restore it. */ - - if (current_function_args_size != 0 || varargs_stdarg_function) - fprintf (file, "\tmov r3,g14\n"); - - /* Restore parameter registers. */ - - for (i = 0, j = 4; i <= last_parm_reg; i += increment, j += increment) - { - if (i % 4 == 0 && (last_parm_reg - i) >= 3) - increment = 4; - else if (i % 4 == 0 && (last_parm_reg - i) >= 2) - increment = 3; - else if (i % 2 == 0 && (last_parm_reg - i) >= 1) - increment = 2; - else - increment = 1; - - fprintf (file, "\tmov%s r%d,g%d\n", - (increment == 4 ? "q" : increment == 3 ? "t" - : increment == 2 ? "l": ""), j, i); - } -} - -/* Output code for the function epilogue. */ - -static void -i960_output_function_epilogue (file, size) - FILE *file; - HOST_WIDE_INT size ATTRIBUTE_UNUSED; -{ - if (i960_leaf_ret_reg >= 0) - { - fprintf (file, "Li960R%d: ret\n", ret_label); - return; - } - - if (*epilogue_string == 0) - { - register rtx tmp; - - /* Emit a return insn, but only if control can fall through to here. */ - - tmp = get_last_insn (); - while (tmp) - { - if (GET_CODE (tmp) == BARRIER) - return; - if (GET_CODE (tmp) == CODE_LABEL) - break; - if (GET_CODE (tmp) == JUMP_INSN) - { - if (GET_CODE (PATTERN (tmp)) == RETURN) - return; - break; - } - if (GET_CODE (tmp) == NOTE) - { - tmp = PREV_INSN (tmp); - continue; - } - break; - } - fprintf (file, "Li960R%d: ret\n", ret_label); - return; - } - - fprintf (file, "Li960R%d:\n", ret_label); - - fprintf (file, "\t#EPILOGUE#\n"); - - /* Output the string created by the prologue which will restore all - registers saved by the prologue. */ - - if (epilogue_string[0] != '\0') - fprintf (file, "%s", epilogue_string); - - /* Must clear g14 on return if this function set it. - Only varargs/stdarg functions modify g14. */ - - if (VARARGS_STDARG_FUNCTION (current_function_decl)) - fprintf (file, "\tmov 0,g14\n"); - - fprintf (file, "\tret\n"); - fprintf (file, "\t#End Epilogue#\n"); -} - -/* Output code for a call insn. */ - -const char * -i960_output_call_insn (target, argsize_rtx, arg_pointer, insn) - register rtx target, argsize_rtx, arg_pointer, insn; -{ - int argsize = INTVAL (argsize_rtx); - rtx nexti = next_real_insn (insn); - rtx operands[2]; - int varargs_stdarg_function - = VARARGS_STDARG_FUNCTION (current_function_decl); - - operands[0] = target; - operands[1] = arg_pointer; - - if (current_function_args_size != 0 || varargs_stdarg_function) - output_asm_insn ("mov g14,r3", operands); - - if (argsize > 48) - output_asm_insn ("lda %a1,g14", operands); - else if (current_function_args_size != 0 || varargs_stdarg_function) - output_asm_insn ("mov 0,g14", operands); - - /* The code used to assume that calls to SYMBOL_REFs could not be more - than 24 bits away (b vs bx, callj vs callx). This is not true. This - feature is now implemented by relaxing in the GNU linker. It can convert - bx to b if in range, and callx to calls/call/balx/bal as appropriate. */ - - /* Nexti could be zero if the called routine is volatile. */ - if (optimize && (*epilogue_string == 0) && argsize == 0 && tail_call_ok - && (nexti == 0 || GET_CODE (PATTERN (nexti)) == RETURN)) - { - /* Delete following return insn. */ - if (nexti && no_labels_between_p (insn, nexti)) - delete_insn (nexti); - output_asm_insn ("bx %0", operands); - return "# notreached"; - } - - output_asm_insn ("callx %0", operands); - - /* If the caller sets g14 to the address of the argblock, then the caller - must clear it after the return. */ - - if (current_function_args_size != 0 || varargs_stdarg_function) - output_asm_insn ("mov r3,g14", operands); - else if (argsize > 48) - output_asm_insn ("mov 0,g14", operands); - - return ""; -} - -/* Output code for a return insn. */ - -const char * -i960_output_ret_insn (insn) - register rtx insn; -{ - static char lbuf[20]; - - if (*epilogue_string != 0) - { - if (! TARGET_CODE_ALIGN && next_real_insn (insn) == 0) - return ""; - - sprintf (lbuf, "b Li960R%d", ret_label); - return lbuf; - } - - /* Must clear g14 on return if this function set it. - Only varargs/stdarg functions modify g14. */ - - if (VARARGS_STDARG_FUNCTION (current_function_decl)) - output_asm_insn ("mov 0,g14", 0); - - if (i960_leaf_ret_reg >= 0) - { - sprintf (lbuf, "bx (%s)", reg_names[i960_leaf_ret_reg]); - return lbuf; - } - return "ret"; -} - -/* Print the operand represented by rtx X formatted by code CODE. */ - -void -i960_print_operand (file, x, code) - FILE *file; - rtx x; - int code; -{ - enum rtx_code rtxcode = x ? GET_CODE (x) : NIL; - - if (rtxcode == REG) - { - switch (code) - { - case 'D': - /* Second reg of a double or quad. */ - fprintf (file, "%s", reg_names[REGNO (x)+1]); - break; - - case 'E': - /* Third reg of a quad. */ - fprintf (file, "%s", reg_names[REGNO (x)+2]); - break; - - case 'F': - /* Fourth reg of a quad. */ - fprintf (file, "%s", reg_names[REGNO (x)+3]); - break; - - case 0: - fprintf (file, "%s", reg_names[REGNO (x)]); - break; - - default: - abort (); - } - return; - } - else if (rtxcode == MEM) - { - output_address (XEXP (x, 0)); - return; - } - else if (rtxcode == CONST_INT) - { - HOST_WIDE_INT val = INTVAL (x); - if (code == 'C') - val = ~val; - if (val > 9999 || val < -999) - fprintf (file, HOST_WIDE_INT_PRINT_HEX, val); - else - fprintf (file, HOST_WIDE_INT_PRINT_DEC, val); - return; - } - else if (rtxcode == CONST_DOUBLE) - { - char dstr[30]; - - if (x == CONST0_RTX (GET_MODE (x))) - { - fprintf (file, "0f0.0"); - return; - } - else if (x == CONST1_RTX (GET_MODE (x))) - { - fprintf (file, "0f1.0"); - return; - } - - real_to_decimal (dstr, CONST_DOUBLE_REAL_VALUE (x), sizeof (dstr), 0, 1); - fprintf (file, "0f%s", dstr); - return; - } - - switch(code) - { - case 'B': - /* Branch or jump, depending on assembler. */ - if (TARGET_ASM_COMPAT) - fputs ("j", file); - else - fputs ("b", file); - break; - - case 'S': - /* Sign of condition. */ - if ((rtxcode == EQ) || (rtxcode == NE) || (rtxcode == GTU) - || (rtxcode == LTU) || (rtxcode == GEU) || (rtxcode == LEU)) - fputs ("o", file); - else if ((rtxcode == GT) || (rtxcode == LT) - || (rtxcode == GE) || (rtxcode == LE)) - fputs ("i", file); - else - abort(); - break; - - case 'I': - /* Inverted condition. */ - rtxcode = reverse_condition (rtxcode); - goto normal; - - case 'X': - /* Inverted condition w/ reversed operands. */ - rtxcode = reverse_condition (rtxcode); - /* Fallthrough. */ - - case 'R': - /* Reversed operand condition. */ - rtxcode = swap_condition (rtxcode); - /* Fallthrough. */ - - case 'C': - /* Normal condition. */ - normal: - if (rtxcode == EQ) { fputs ("e", file); return; } - else if (rtxcode == NE) { fputs ("ne", file); return; } - else if (rtxcode == GT) { fputs ("g", file); return; } - else if (rtxcode == GTU) { fputs ("g", file); return; } - else if (rtxcode == LT) { fputs ("l", file); return; } - else if (rtxcode == LTU) { fputs ("l", file); return; } - else if (rtxcode == GE) { fputs ("ge", file); return; } - else if (rtxcode == GEU) { fputs ("ge", file); return; } - else if (rtxcode == LE) { fputs ("le", file); return; } - else if (rtxcode == LEU) { fputs ("le", file); return; } - else abort (); - break; - - case '+': - /* For conditional branches, substitute ".t" or ".f". */ - if (TARGET_BRANCH_PREDICT) - { - x = find_reg_note (current_output_insn, REG_BR_PROB, 0); - if (x) - { - int pred_val = INTVAL (XEXP (x, 0)); - fputs ((pred_val < REG_BR_PROB_BASE / 2 ? ".f" : ".t"), file); - } - } - break; - - case 0: - output_addr_const (file, x); - break; - - default: - abort (); - } - - return; -} - -/* Print a memory address as an operand to reference that memory location. - - This is exactly the same as legitimate_address_p, except that it the prints - addresses instead of recognizing them. */ - -void -i960_print_operand_addr (file, addr) - FILE *file; - register rtx addr; -{ - rtx breg, ireg; - rtx scale, offset; - - ireg = 0; - breg = 0; - offset = 0; - scale = const1_rtx; - - if (GET_CODE (addr) == REG) - breg = addr; - else if (CONSTANT_P (addr)) - offset = addr; - else if (GET_CODE (addr) == PLUS) - { - rtx op0, op1; - - op0 = XEXP (addr, 0); - op1 = XEXP (addr, 1); - - if (GET_CODE (op0) == REG) - { - breg = op0; - if (GET_CODE (op1) == REG) - ireg = op1; - else if (CONSTANT_P (op1)) - offset = op1; - else - abort (); - } - else if (GET_CODE (op0) == PLUS) - { - if (GET_CODE (XEXP (op0, 0)) == MULT) - { - ireg = XEXP (XEXP (op0, 0), 0); - scale = XEXP (XEXP (op0, 0), 1); - if (GET_CODE (XEXP (op0, 1)) == REG) - { - breg = XEXP (op0, 1); - offset = op1; - } - else - abort (); - } - else if (GET_CODE (XEXP (op0, 0)) == REG) - { - breg = XEXP (op0, 0); - if (GET_CODE (XEXP (op0, 1)) == REG) - { - ireg = XEXP (op0, 1); - offset = op1; - } - else - abort (); - } - else - abort (); - } - else if (GET_CODE (op0) == MULT) - { - ireg = XEXP (op0, 0); - scale = XEXP (op0, 1); - if (GET_CODE (op1) == REG) - breg = op1; - else if (CONSTANT_P (op1)) - offset = op1; - else - abort (); - } - else - abort (); - } - else if (GET_CODE (addr) == MULT) - { - ireg = XEXP (addr, 0); - scale = XEXP (addr, 1); - } - else - abort (); - - if (offset) - output_addr_const (file, offset); - if (breg) - fprintf (file, "(%s)", reg_names[REGNO (breg)]); - if (ireg) - fprintf (file, "[%s*" HOST_WIDE_INT_PRINT_DEC "]", - reg_names[REGNO (ireg)], INTVAL (scale)); -} - -/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression - that is a valid memory address for an instruction. - The MODE argument is the machine mode for the MEM expression - that wants to use this address. - - On 80960, legitimate addresses are: - base ld (g0),r0 - disp (12 or 32 bit) ld foo,r0 - base + index ld (g0)[g1*1],r0 - base + displ ld 0xf00(g0),r0 - base + index*scale + displ ld 0xf00(g0)[g1*4],r0 - index*scale + base ld (g0)[g1*4],r0 - index*scale + displ ld 0xf00[g1*4],r0 - index*scale ld [g1*4],r0 - index + base + displ ld 0xf00(g0)[g1*1],r0 - - In each case, scale can be 1, 2, 4, 8, or 16. */ - -/* This is exactly the same as i960_print_operand_addr, except that - it recognizes addresses instead of printing them. - - It only recognizes address in canonical form. LEGITIMIZE_ADDRESS should - convert common non-canonical forms to canonical form so that they will - be recognized. */ - -/* These two macros allow us to accept either a REG or a SUBREG anyplace - where a register is valid. */ - -#define RTX_OK_FOR_BASE_P(X, STRICT) \ - ((GET_CODE (X) == REG \ - && (STRICT ? REG_OK_FOR_BASE_P_STRICT (X) : REG_OK_FOR_BASE_P (X))) \ - || (GET_CODE (X) == SUBREG \ - && GET_CODE (SUBREG_REG (X)) == REG \ - && (STRICT ? REG_OK_FOR_BASE_P_STRICT (SUBREG_REG (X)) \ - : REG_OK_FOR_BASE_P (SUBREG_REG (X))))) - -#define RTX_OK_FOR_INDEX_P(X, STRICT) \ - ((GET_CODE (X) == REG \ - && (STRICT ? REG_OK_FOR_INDEX_P_STRICT (X) : REG_OK_FOR_INDEX_P (X)))\ - || (GET_CODE (X) == SUBREG \ - && GET_CODE (SUBREG_REG (X)) == REG \ - && (STRICT ? REG_OK_FOR_INDEX_P_STRICT (SUBREG_REG (X)) \ - : REG_OK_FOR_INDEX_P (SUBREG_REG (X))))) - -int -legitimate_address_p (mode, addr, strict) - enum machine_mode mode ATTRIBUTE_UNUSED; - register rtx addr; - int strict; -{ - if (RTX_OK_FOR_BASE_P (addr, strict)) - return 1; - else if (CONSTANT_P (addr)) - return 1; - else if (GET_CODE (addr) == PLUS) - { - rtx op0, op1; - - if (! TARGET_COMPLEX_ADDR && ! reload_completed) - return 0; - - op0 = XEXP (addr, 0); - op1 = XEXP (addr, 1); - - if (RTX_OK_FOR_BASE_P (op0, strict)) - { - if (RTX_OK_FOR_INDEX_P (op1, strict)) - return 1; - else if (CONSTANT_P (op1)) - return 1; - else - return 0; - } - else if (GET_CODE (op0) == PLUS) - { - if (GET_CODE (XEXP (op0, 0)) == MULT) - { - if (! (RTX_OK_FOR_INDEX_P (XEXP (XEXP (op0, 0), 0), strict) - && SCALE_TERM_P (XEXP (XEXP (op0, 0), 1)))) - return 0; - - if (RTX_OK_FOR_BASE_P (XEXP (op0, 1), strict) - && CONSTANT_P (op1)) - return 1; - else - return 0; - } - else if (RTX_OK_FOR_BASE_P (XEXP (op0, 0), strict)) - { - if (RTX_OK_FOR_INDEX_P (XEXP (op0, 1), strict) - && CONSTANT_P (op1)) - return 1; - else - return 0; - } - else - return 0; - } - else if (GET_CODE (op0) == MULT) - { - if (! (RTX_OK_FOR_INDEX_P (XEXP (op0, 0), strict) - && SCALE_TERM_P (XEXP (op0, 1)))) - return 0; - - if (RTX_OK_FOR_BASE_P (op1, strict)) - return 1; - else if (CONSTANT_P (op1)) - return 1; - else - return 0; - } - else - return 0; - } - else if (GET_CODE (addr) == MULT) - { - if (! TARGET_COMPLEX_ADDR && ! reload_completed) - return 0; - - return (RTX_OK_FOR_INDEX_P (XEXP (addr, 0), strict) - && SCALE_TERM_P (XEXP (addr, 1))); - } - else - return 0; -} - -/* Try machine-dependent ways of modifying an illegitimate address - to be legitimate. If we find one, return the new, valid address. - This macro is used in only one place: `memory_address' in explow.c. - - This converts some non-canonical addresses to canonical form so they - can be recognized. */ - -rtx -legitimize_address (x, oldx, mode) - register rtx x; - register rtx oldx ATTRIBUTE_UNUSED; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - if (GET_CODE (x) == SYMBOL_REF) - { - abort (); - x = copy_to_reg (x); - } - - if (! TARGET_COMPLEX_ADDR && ! reload_completed) - return x; - - /* Canonicalize (plus (mult (reg) (const)) (plus (reg) (const))) - into (plus (plus (mult (reg) (const)) (reg)) (const)). This can be - created by virtual register instantiation, register elimination, and - similar optimizations. */ - if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == MULT - && GET_CODE (XEXP (x, 1)) == PLUS) - x = gen_rtx_PLUS (Pmode, - gen_rtx_PLUS (Pmode, XEXP (x, 0), XEXP (XEXP (x, 1), 0)), - XEXP (XEXP (x, 1), 1)); - - /* Canonicalize (plus (plus (mult (reg) (const)) (plus (reg) (const))) const) - into (plus (plus (mult (reg) (const)) (reg)) (const)). */ - else if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == PLUS - && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT - && GET_CODE (XEXP (XEXP (x, 0), 1)) == PLUS - && CONSTANT_P (XEXP (x, 1))) - { - rtx constant, other; - - if (GET_CODE (XEXP (x, 1)) == CONST_INT) - { - constant = XEXP (x, 1); - other = XEXP (XEXP (XEXP (x, 0), 1), 1); - } - else if (GET_CODE (XEXP (XEXP (XEXP (x, 0), 1), 1)) == CONST_INT) - { - constant = XEXP (XEXP (XEXP (x, 0), 1), 1); - other = XEXP (x, 1); - } - else - constant = 0, other = 0; - - if (constant) - x = gen_rtx_PLUS (Pmode, - gen_rtx_PLUS (Pmode, XEXP (XEXP (x, 0), 0), - XEXP (XEXP (XEXP (x, 0), 1), 0)), - plus_constant (other, INTVAL (constant))); - } - - return x; -} - -#if 0 -/* Return the most stringent alignment that we are willing to consider - objects of size SIZE and known alignment ALIGN as having. */ - -int -i960_alignment (size, align) - int size; - int align; -{ - int i; - - if (! TARGET_STRICT_ALIGN) - if (TARGET_IC_COMPAT2_0 || align >= 4) - { - i = i960_object_bytes_bitalign (size) / BITS_PER_UNIT; - if (i > align) - align = i; - } - - return align; -} -#endif - - -int -hard_regno_mode_ok (regno, mode) - int regno; - enum machine_mode mode; -{ - if (regno < 32) - { - switch (mode) - { - case CCmode: case CC_UNSmode: case CC_CHKmode: - return 0; - - case DImode: case DFmode: - return (regno & 1) == 0; - - case TImode: case TFmode: - return (regno & 3) == 0; - - default: - return 1; - } - } - else if (regno >= 32 && regno < 36) - { - switch (mode) - { - case SFmode: case DFmode: case TFmode: - case SCmode: case DCmode: - return 1; - - default: - return 0; - } - } - else if (regno == 36) - { - switch (mode) - { - case CCmode: case CC_UNSmode: case CC_CHKmode: - return 1; - - default: - return 0; - } - } - else if (regno == 37) - return 0; - - abort (); -} - - -/* Return the minimum alignment of an expression rtx X in bytes. This takes - advantage of machine specific facts, such as knowing that the frame pointer - is always 16 byte aligned. */ - -int -i960_expr_alignment (x, size) - rtx x; - int size; -{ - int align = 1; - - if (x == 0) - return 1; - - switch (GET_CODE(x)) - { - case CONST_INT: - align = INTVAL(x); - - if ((align & 0xf) == 0) - align = 16; - else if ((align & 0x7) == 0) - align = 8; - else if ((align & 0x3) == 0) - align = 4; - else if ((align & 0x1) == 0) - align = 2; - else - align = 1; - break; - - case PLUS: - align = MIN (i960_expr_alignment (XEXP (x, 0), size), - i960_expr_alignment (XEXP (x, 1), size)); - break; - - case SYMBOL_REF: - /* If this is a valid program, objects are guaranteed to be - correctly aligned for whatever size the reference actually is. */ - align = i960_object_bytes_bitalign (size) / BITS_PER_UNIT; - break; - - case REG: - if (REGNO (x) == FRAME_POINTER_REGNUM) - align = 16; - break; - - case ASHIFT: - align = i960_expr_alignment (XEXP (x, 0), size); - - if (GET_CODE (XEXP (x, 1)) == CONST_INT) - { - align = align << INTVAL (XEXP (x, 1)); - align = MIN (align, 16); - } - break; - - case MULT: - align = (i960_expr_alignment (XEXP (x, 0), size) * - i960_expr_alignment (XEXP (x, 1), size)); - - align = MIN (align, 16); - break; - default: - break; - } - - return align; -} - -/* Return true if it is possible to reference both BASE and OFFSET, which - have alignment at least as great as 4 byte, as if they had alignment valid - for an object of size SIZE. */ - -int -i960_improve_align (base, offset, size) - rtx base; - rtx offset; - int size; -{ - int i, j; - - /* We have at least a word reference to the object, so we know it has to - be aligned at least to 4 bytes. */ - - i = MIN (i960_expr_alignment (base, 4), - i960_expr_alignment (offset, 4)); - - i = MAX (i, 4); - - /* We know the size of the request. If strict align is not enabled, we - can guess that the alignment is OK for the requested size. */ - - if (! TARGET_STRICT_ALIGN) - if ((j = (i960_object_bytes_bitalign (size) / BITS_PER_UNIT)) > i) - i = j; - - return (i >= size); -} - -/* Return true if it is possible to access BASE and OFFSET, which have 4 byte - (SImode) alignment as if they had 16 byte (TImode) alignment. */ - -int -i960_si_ti (base, offset) - rtx base; - rtx offset; -{ - return i960_improve_align (base, offset, 16); -} - -/* Return true if it is possible to access BASE and OFFSET, which have 4 byte - (SImode) alignment as if they had 8 byte (DImode) alignment. */ - -int -i960_si_di (base, offset) - rtx base; - rtx offset; -{ - return i960_improve_align (base, offset, 8); -} - -/* Return raw values of size and alignment (in words) for the data - type being accessed. These values will be rounded by the caller. */ - -static void -i960_arg_size_and_align (mode, type, size_out, align_out) - enum machine_mode mode; - tree type; - int *size_out; - int *align_out; -{ - int size, align; - - /* Use formal alignment requirements of type being passed, except make - it at least a word. If we don't have a type, this is a library call, - and the parm has to be of scalar type. In this case, consider its - formal alignment requirement to be its size in words. */ - - if (mode == BLKmode) - size = (int_size_in_bytes (type) + UNITS_PER_WORD - 1) / UNITS_PER_WORD; - else if (mode == VOIDmode) - { - /* End of parm list. */ - if (type == 0 || TYPE_MODE (type) != VOIDmode) - abort (); - size = 1; - } - else - size = (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD; - - if (type == 0) - align = size; - else if (TYPE_ALIGN (type) >= BITS_PER_WORD) - align = TYPE_ALIGN (type) / BITS_PER_WORD; - else - align = 1; - - *size_out = size; - *align_out = align; -} - -/* On the 80960 the first 12 args are in registers and the rest are pushed. - Any arg that is bigger than 4 words is placed on the stack and all - subsequent arguments are placed on the stack. - - Additionally, parameters with an alignment requirement stronger than - a word must be aligned appropriately. Note that this means that a - 64 bit object with a 32 bit alignment is not 64 bit aligned and may be - passed in an odd/even register pair. */ - -/* Update CUM to advance past an argument described by MODE and TYPE. */ - -void -i960_function_arg_advance (cum, mode, type, named) - CUMULATIVE_ARGS *cum; - enum machine_mode mode; - tree type; - int named ATTRIBUTE_UNUSED; -{ - int size, align; - - i960_arg_size_and_align (mode, type, &size, &align); - - if (size > 4 || cum->ca_nstackparms != 0 - || (size + ROUND_PARM (cum->ca_nregparms, align)) > NPARM_REGS - || MUST_PASS_IN_STACK (mode, type)) - { - /* Indicate that all the registers are in use, even if all are not, - so va_start will compute the right value. */ - cum->ca_nregparms = NPARM_REGS; - cum->ca_nstackparms = ROUND_PARM (cum->ca_nstackparms, align) + size; - } - else - cum->ca_nregparms = ROUND_PARM (cum->ca_nregparms, align) + size; -} - -/* Return the register that the argument described by MODE and TYPE is - passed in, or else return 0 if it is passed on the stack. */ - -rtx -i960_function_arg (cum, mode, type, named) - CUMULATIVE_ARGS *cum; - enum machine_mode mode; - tree type; - int named ATTRIBUTE_UNUSED; -{ - rtx ret; - int size, align; - - if (mode == VOIDmode) - return 0; - - i960_arg_size_and_align (mode, type, &size, &align); - - if (size > 4 || cum->ca_nstackparms != 0 - || (size + ROUND_PARM (cum->ca_nregparms, align)) > NPARM_REGS - || MUST_PASS_IN_STACK (mode, type)) - { - cum->ca_nstackparms = ROUND_PARM (cum->ca_nstackparms, align); - ret = 0; - } - else - { - cum->ca_nregparms = ROUND_PARM (cum->ca_nregparms, align); - ret = gen_rtx_REG (mode, cum->ca_nregparms); - } - - return ret; -} - -/* Return the number of bits that an object of size N bytes is aligned to. */ - -int -i960_object_bytes_bitalign (n) - int n; -{ - if (n > 8) n = 128; - else if (n > 4) n = 64; - else if (n > 2) n = 32; - else if (n > 1) n = 16; - else n = 8; - - return n; -} - -/* Compute the alignment for an aggregate type TSIZE. - Alignment is MAX (greatest member alignment, - MIN (pragma align, structure size alignment)). */ - -int -i960_round_align (align, type) - int align; - tree type; -{ - int new_align; - tree tsize; - - if (TARGET_OLD_ALIGN || TYPE_PACKED (type)) - return align; - if (TREE_CODE (type) != RECORD_TYPE) - return align; - tsize = TYPE_SIZE (type); - - if (! tsize || TREE_CODE (tsize) != INTEGER_CST) - return align; - - new_align = i960_object_bytes_bitalign (TREE_INT_CST_LOW (tsize) - / BITS_PER_UNIT); - /* Handle #pragma align. */ - if (new_align > i960_maxbitalignment) - new_align = i960_maxbitalignment; - - if (align < new_align) - align = new_align; - - return align; -} - -/* Do any needed setup for a varargs function. For the i960, we must - create a register parameter block if one doesn't exist, and then copy - all register parameters to memory. */ - -void -i960_setup_incoming_varargs (cum, mode, type, pretend_size, no_rtl) - CUMULATIVE_ARGS *cum; - enum machine_mode mode ATTRIBUTE_UNUSED; - tree type ATTRIBUTE_UNUSED; - int *pretend_size ATTRIBUTE_UNUSED; - int no_rtl; -{ - /* Note: for a varargs fn with only a va_alist argument, this is 0. */ - int first_reg = cum->ca_nregparms; - - /* Copy only unnamed register arguments to memory. If there are - any stack parms, there are no unnamed arguments in registers, and - an argument block was already allocated by the caller. - Remember that any arg bigger than 4 words is passed on the stack as - are all subsequent args. - - If there are no stack arguments but there are exactly NPARM_REGS - registers, either there were no extra arguments or the caller - allocated an argument block. */ - - if (cum->ca_nstackparms == 0 && first_reg < NPARM_REGS && !no_rtl) - { - rtx label = gen_label_rtx (); - rtx regblock, fake_arg_pointer_rtx; - - /* Use a different rtx than arg_pointer_rtx so that cse and friends - can go on believing that the argument pointer can never be zero. */ - fake_arg_pointer_rtx = gen_raw_REG (Pmode, ARG_POINTER_REGNUM); - - /* If the argument pointer is 0, no arguments were passed on the stack - and we need to allocate a chunk to save the registers (if any - arguments were passed on the stack the caller would allocate the - 48 bytes as well). We must allocate all 48 bytes (12*4) because - va_start assumes it. */ - emit_insn (gen_cmpsi (fake_arg_pointer_rtx, const0_rtx)); - emit_jump_insn (gen_bne (label)); - emit_insn (gen_rtx_SET (VOIDmode, fake_arg_pointer_rtx, - stack_pointer_rtx)); - emit_insn (gen_rtx_SET (VOIDmode, stack_pointer_rtx, - memory_address (SImode, - plus_constant (stack_pointer_rtx, - 48)))); - emit_label (label); - - /* ??? Note that we unnecessarily store one extra register for stdarg - fns. We could optimize this, but it's kept as for now. */ - regblock = gen_rtx_MEM (BLKmode, - plus_constant (arg_pointer_rtx, first_reg * 4)); - set_mem_alias_set (regblock, get_varargs_alias_set ()); - set_mem_align (regblock, BITS_PER_WORD); - move_block_from_reg (first_reg, regblock, - NPARM_REGS - first_reg); - } -} - -/* Define the `__builtin_va_list' type for the ABI. */ - -static tree -i960_build_builtin_va_list () -{ - return build_array_type (unsigned_type_node, - build_index_type (size_one_node)); -} - -/* Implement `va_start' for varargs and stdarg. */ - -void -i960_va_start (valist, nextarg) - tree valist; - rtx nextarg ATTRIBUTE_UNUSED; -{ - tree s, t, base, num; - rtx fake_arg_pointer_rtx; - - /* The array type always decays to a pointer before we get here, so we - can't use ARRAY_REF. */ - base = build1 (INDIRECT_REF, unsigned_type_node, valist); - num = build1 (INDIRECT_REF, unsigned_type_node, - build (PLUS_EXPR, unsigned_type_node, valist, - TYPE_SIZE_UNIT (TREE_TYPE (valist)))); - - /* Use a different rtx than arg_pointer_rtx so that cse and friends - can go on believing that the argument pointer can never be zero. */ - fake_arg_pointer_rtx = gen_raw_REG (Pmode, ARG_POINTER_REGNUM); - s = make_tree (unsigned_type_node, fake_arg_pointer_rtx); - t = build (MODIFY_EXPR, unsigned_type_node, base, s); - TREE_SIDE_EFFECTS (t) = 1; - expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); - - s = build_int_2 ((current_function_args_info.ca_nregparms - + current_function_args_info.ca_nstackparms) * 4, 0); - t = build (MODIFY_EXPR, unsigned_type_node, num, s); - TREE_SIDE_EFFECTS (t) = 1; - expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); -} - -/* Implement `va_arg'. */ - -rtx -i960_va_arg (valist, type) - tree valist, type; -{ - HOST_WIDE_INT siz, ali; - tree base, num, pad, next, this, t1, t2, int48; - rtx addr_rtx; - - /* The array type always decays to a pointer before we get here, so we - can't use ARRAY_REF. */ - base = build1 (INDIRECT_REF, unsigned_type_node, valist); - num = build1 (INDIRECT_REF, unsigned_type_node, - build (PLUS_EXPR, unsigned_type_node, valist, - TYPE_SIZE_UNIT (TREE_TYPE (valist)))); - - /* Round up sizeof(type) to a word. */ - siz = (int_size_in_bytes (type) + UNITS_PER_WORD - 1) & -UNITS_PER_WORD; - - /* Round up alignment to a word. */ - ali = TYPE_ALIGN (type); - if (ali < BITS_PER_WORD) - ali = BITS_PER_WORD; - ali /= BITS_PER_UNIT; - - /* Align NUM appropriate for the argument. */ - pad = fold (build (PLUS_EXPR, unsigned_type_node, num, - build_int_2 (ali - 1, 0))); - pad = fold (build (BIT_AND_EXPR, unsigned_type_node, pad, - build_int_2 (-ali, -1))); - pad = save_expr (pad); - - /* Increment VPAD past this argument. */ - next = fold (build (PLUS_EXPR, unsigned_type_node, pad, - build_int_2 (siz, 0))); - next = save_expr (next); - - /* Find the offset for the current argument. Mind peculiar overflow - from registers to stack. */ - int48 = build_int_2 (48, 0); - if (siz > 16) - t2 = integer_one_node; - else - t2 = fold (build (GT_EXPR, integer_type_node, next, int48)); - t1 = fold (build (LE_EXPR, integer_type_node, num, int48)); - t1 = fold (build (TRUTH_AND_EXPR, integer_type_node, t1, t2)); - this = fold (build (COND_EXPR, unsigned_type_node, t1, int48, pad)); - - /* Find the address for the current argument. */ - t1 = fold (build (PLUS_EXPR, unsigned_type_node, base, this)); - t1 = build1 (NOP_EXPR, ptr_type_node, t1); - addr_rtx = expand_expr (t1, NULL_RTX, Pmode, EXPAND_NORMAL); - - /* Increment NUM. */ - t1 = build (MODIFY_EXPR, unsigned_type_node, num, next); - TREE_SIDE_EFFECTS (t1) = 1; - expand_expr (t1, const0_rtx, VOIDmode, EXPAND_NORMAL); - - return addr_rtx; -} - -/* Calculate the final size of the reg parm stack space for the current - function, based on how many bytes would be allocated on the stack. */ - -int -i960_final_reg_parm_stack_space (const_size, var_size) - int const_size; - tree var_size; -{ - if (var_size || const_size > 48) - return 48; - else - return 0; -} - -/* Calculate the size of the reg parm stack space. This is a bit complicated - on the i960. */ - -int -i960_reg_parm_stack_space (fndecl) - tree fndecl; -{ - /* In this case, we are called from emit_library_call, and we don't need - to pretend we have more space for parameters than what's apparent. */ - if (fndecl == 0) - return 0; - - /* In this case, we are called from locate_and_pad_parms when we're - not IN_REGS, so we have an arg block. */ - if (fndecl != current_function_decl) - return 48; - - /* Otherwise, we have an arg block if the current function has more than - 48 bytes of parameters. */ - if (current_function_args_size != 0 || VARARGS_STDARG_FUNCTION (fndecl)) - return 48; - else - return 0; -} - -/* Return the register class of a scratch register needed to copy IN into - or out of a register in CLASS in MODE. If it can be done directly, - NO_REGS is returned. */ - -enum reg_class -secondary_reload_class (class, mode, in) - enum reg_class class; - enum machine_mode mode; - rtx in; -{ - int regno = -1; - - if (GET_CODE (in) == REG || GET_CODE (in) == SUBREG) - regno = true_regnum (in); - - /* We can place anything into LOCAL_OR_GLOBAL_REGS and can put - LOCAL_OR_GLOBAL_REGS into anything. */ - if (class == LOCAL_OR_GLOBAL_REGS || class == LOCAL_REGS - || class == GLOBAL_REGS || (regno >= 0 && regno < 32)) - return NO_REGS; - - /* We can place any hard register, 0.0, and 1.0 into FP_REGS. */ - if (class == FP_REGS - && ((regno >= 0 && regno < FIRST_PSEUDO_REGISTER) - || in == CONST0_RTX (mode) || in == CONST1_RTX (mode))) - return NO_REGS; - - return LOCAL_OR_GLOBAL_REGS; -} - -/* Look at the opcode P, and set i96_last_insn_type to indicate which - function unit it executed on. */ - -/* ??? This would make more sense as an attribute. */ - -void -i960_scan_opcode (p) - const char *p; -{ - switch (*p) - { - case 'a': - case 'd': - case 'e': - case 'm': - case 'n': - case 'o': - case 'r': - /* Ret is not actually of type REG, but it won't matter, because no - insn will ever follow it. */ - case 'u': - case 'x': - i960_last_insn_type = I_TYPE_REG; - break; - - case 'b': - if (p[1] == 'x' || p[3] == 'x') - i960_last_insn_type = I_TYPE_MEM; - i960_last_insn_type = I_TYPE_CTRL; - break; - - case 'f': - case 't': - i960_last_insn_type = I_TYPE_CTRL; - break; - - case 'c': - if (p[1] == 'a') - { - if (p[4] == 'x') - i960_last_insn_type = I_TYPE_MEM; - else - i960_last_insn_type = I_TYPE_CTRL; - } - else if (p[1] == 'm') - { - if (p[3] == 'd') - i960_last_insn_type = I_TYPE_REG; - else if (p[4] == 'b' || p[4] == 'j') - i960_last_insn_type = I_TYPE_CTRL; - else - i960_last_insn_type = I_TYPE_REG; - } - else - i960_last_insn_type = I_TYPE_REG; - break; - - case 'l': - i960_last_insn_type = I_TYPE_MEM; - break; - - case 's': - if (p[1] == 't') - i960_last_insn_type = I_TYPE_MEM; - else - i960_last_insn_type = I_TYPE_REG; - break; - } -} - -static void -i960_output_mi_thunk (file, thunk, delta, vcall_offset, function) - FILE *file; - tree thunk ATTRIBUTE_UNUSED; - HOST_WIDE_INT delta; - HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED; - tree function; -{ - int d = delta; - if (d < 0 && d > -32) - fprintf (file, "\tsubo %d,g0,g0\n", -d); - else if (d > 0 && d < 32) - fprintf (file, "\taddo %d,g0,g0\n", d); - else - { - fprintf (file, "\tldconst %d,r5\n", d); - fprintf (file, "\taddo r5,g0,g0\n"); - } - fprintf (file, "\tbx "); - assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0)); - fprintf (file, "\n"); -} - -static bool -i960_rtx_costs (x, code, outer_code, total) - rtx x; - int code, outer_code; - int *total; -{ - switch (code) - { - /* Constants that can be (non-ldconst) insn operands are cost 0. - Constants that can be non-ldconst operands in rare cases are cost 1. - Other constants have higher costs. - - Must check for OUTER_CODE of SET for power2_operand, because - reload_cse_move2add calls us with OUTER_CODE of PLUS to decide - when to replace set with add. */ - - case CONST_INT: - if ((INTVAL (x) >= 0 && INTVAL (x) < 32) - || (outer_code == SET && power2_operand (x, VOIDmode))) - { - *total = 0; - return true; - } - else if (INTVAL (x) >= -31 && INTVAL (x) < 0) - { - *total = 1; - return true; - } - /* FALLTHRU */ - - case CONST: - case LABEL_REF: - case SYMBOL_REF: - *total = (TARGET_C_SERIES ? 6 : 8); - return true; - - case CONST_DOUBLE: - if (x == CONST0_RTX (DFmode) || x == CONST0_RTX (SFmode) - || x == CONST1_RTX (DFmode) || x == CONST1_RTX (SFmode)) - *total = 1; - else - *total = 12; - return true; - - default: - return false; - } -} diff --git a/gcc/config/i960/i960.h b/gcc/config/i960/i960.h deleted file mode 100644 index ad86dba003b..00000000000 --- a/gcc/config/i960/i960.h +++ /dev/null @@ -1,1404 +0,0 @@ -/* Definitions of target machine for GNU compiler, for Intel 80960 - Copyright (C) 1992, 1993, 1995, 1996, 1998, 1999, 2000, 2001, 2002 - Free Software Foundation, Inc. - Contributed by Steven McGeady, Intel Corp. - Additional Work by Glenn Colon-Bonet, Jonathan Shapiro, Andy Wilson - Converted to GCC 2.0 by Jim Wilson and Michael Tiemann, Cygnus Support. - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GCC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/* Note that some other tm.h files may include this one and then override - many of the definitions that relate to assembler syntax. */ - -/* Target CPU builtins. */ -#define TARGET_CPU_CPP_BUILTINS() \ - do \ - { \ - builtin_define_std ("i960"); \ - builtin_define_std ("I960"); \ - builtin_define_std ("i80960"); \ - builtin_define_std ("I80960"); \ - builtin_assert ("cpu=i960"); \ - builtin_assert ("machine=i960"); \ - } \ - while (0) - -#define MULTILIB_DEFAULTS { "mnumerics" } - -/* Name to predefine in the preprocessor for processor variations. - -mic* options make characters signed by default. */ -#define CPP_SPEC "%{mic*:-D__i960 -fsigned-char\ - %{mka:-D__i960KA}%{mkb:-D__i960KB}\ - %{mja:-D__i960JA}%{mjd:-D__i960JD}%{mjf:-D__i960JF}\ - %{mrp:-D__i960RP}\ - %{msa:-D__i960SA}%{msb:-D__i960SB}\ - %{mmc:-D__i960MC}\ - %{mca:-D__i960CA}%{mcc:-D__i960CC}\ - %{mcf:-D__i960CF}}\ - %{msoft-float:-D_SOFT_FLOAT}\ - %{mka:-D__i960KA__ -D__i960_KA__}\ - %{mkb:-D__i960KB__ -D__i960_KB__}\ - %{msa:-D__i960SA__ -D__i960_SA__}\ - %{msb:-D__i960SB__ -D__i960_SB__}\ - %{mmc:-D__i960MC__ -D__i960_MC__}\ - %{mca:-D__i960CA__ -D__i960_CA__}\ - %{mcc:-D__i960CC__ -D__i960_CC__}\ - %{mcf:-D__i960CF__ -D__i960_CF__}\ - %{!mka:%{!mkb:%{!msa:%{!msb:%{!mmc:%{!mca:\ - %{!mcc:%{!mcf:-D__i960_KB -D__i960KB__ %{mic*:-D__i960KB}}}}}}}}}\ - %{mlong-double-64:-D__LONG_DOUBLE_64__}" - -/* Specs for the compiler, to handle processor variations. - If the user gives an explicit -gstabs or -gcoff option, then do not - try to add an implicit one, as this will fail. - -mic* options make characters signed by default. */ -#define CC1_SPEC \ - "%{mic*:-fsigned-char}\ -%{!mka:%{!mkb:%{!msa:%{!msb:%{!mmc:%{!mca:%{!mcc:%{!mcf:%{!mja:%{!mjd:%{!mjf:%{!mrp:-mka}}}}}}}}}}}}\ - %{!gs*:%{!gc*:%{mbout:%{g*:-gstabs}}\ - %{mcoff:%{g*:-gcoff}}\ - %{!mbout:%{!mcoff:%{g*:-gstabs}}}}}" - -/* Specs for the assembler, to handle processor variations. - For compatibility with Intel's gnu960 tool chain, pass -A options to - the assembler. */ -#define ASM_SPEC \ - "%{mka:-AKA}%{mkb:-AKB}%{msa:-ASA}%{msb:-ASB}\ - %{mmc:-AMC}%{mca:-ACA}%{mcc:-ACC}%{mcf:-ACF}\ - %{mja:-AJX}%{mjd:-AJX}%{mjf:-AJX}%{mrp:-AJX}\ - %{!mka:%{!mkb:%{!msa:%{!msb:%{!mmc:%{!mca:%{!mcc:%{!mcf:%{!mja:%{!mjd:%{!mjf:%{!mrp:-AKB}}}}}}}}}}}}\ - %{mlink-relax:-linkrelax}" - -/* Specs for the linker, to handle processor variations. - For compatibility with Intel's gnu960 tool chain, pass -F and -A options - to the linker. */ -#define LINK_SPEC \ - "%{mka:-AKA}%{mkb:-AKB}%{msa:-ASA}%{msb:-ASB}\ - %{mmc:-AMC}%{mca:-ACA}%{mcc:-ACC}%{mcf:-ACF}\ - %{mja:-AJX}%{mjd:-AJX}%{mjf:-AJX}%{mrp:-AJX}\ - %{mbout:-Fbout}%{mcoff:-Fcoff}\ - %{mlink-relax:-relax}" - -/* Specs for the libraries to link with, to handle processor variations. - Compatible with Intel's gnu960 tool chain. */ -#define LIB_SPEC "%{!nostdlib:-lcg %{p:-lprof}%{pg:-lgprof}\ - %{mka:-lfpg}%{msa:-lfpg}%{mca:-lfpg}%{mcf:-lfpg} -lgnu}" - -/* Defining the macro shows we can debug even without a frame pointer. - Actually, we can debug without FP. But defining the macro results in - that -O means FP elimination. Addressing through sp requires - negative offset and more one word addressing in the most cases - (offsets except for 0-4095 require one more word). Therefore we've - not defined the macro. */ -/*#define CAN_DEBUG_WITHOUT_FP*/ - -/* Do leaf procedure and tail call optimizations for -O2 and higher. */ -#define OPTIMIZATION_OPTIONS(LEVEL,SIZE) \ -{ \ - if ((LEVEL) >= 2) \ - { \ - target_flags |= TARGET_FLAG_LEAFPROC; \ - target_flags |= TARGET_FLAG_TAILCALL; \ - } \ -} - -/* Print subsidiary information on the compiler version in use. */ -#define TARGET_VERSION fprintf (stderr," (intel 80960)"); - -/* Generate DBX debugging information. */ -#define DBX_DEBUGGING_INFO 1 - -/* Generate SDB style debugging information. */ -#define SDB_DEBUGGING_INFO 1 -#define EXTENDED_SDB_BASIC_TYPES - -/* Generate DBX_DEBUGGING_INFO by default. */ -#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG - -/* Redefine this to print in hex. No value adjustment is necessary - anymore. */ -#define PUT_SDB_TYPE(A) \ - fprintf (asm_out_file, "\t.type\t0x%x;", A) - -/* Handle pragmas for compatibility with Intel's compilers. */ - -extern int i960_maxbitalignment; -extern int i960_last_maxbitalignment; - -#define REGISTER_TARGET_PRAGMAS() do { \ - c_register_pragma (0, "align", i960_pr_align); \ - c_register_pragma (0, "noalign", i960_pr_noalign); \ -} while (0) - -/* Run-time compilation parameters selecting different hardware subsets. */ - -/* 960 architecture with floating-point. */ -#define TARGET_FLAG_NUMERICS 0x01 -#define TARGET_NUMERICS (target_flags & TARGET_FLAG_NUMERICS) - -/* 960 architecture with memory management. */ -/* ??? Not used currently. */ -#define TARGET_FLAG_PROTECTED 0x02 -#define TARGET_PROTECTED (target_flags & TARGET_FLAG_PROTECTED) - -/* The following three are mainly used to provide a little sanity checking - against the -mARCH flags given. The Jx series, for the purposes of - gcc, is a Kx with a data cache. */ - -/* Nonzero if we should generate code for the KA and similar processors. - No FPU, no microcode instructions. */ -#define TARGET_FLAG_K_SERIES 0x04 -#define TARGET_K_SERIES (target_flags & TARGET_FLAG_K_SERIES) - -/* Nonzero if we should generate code for the MC processor. - Not really different from KB for our purposes. */ -#define TARGET_FLAG_MC 0x08 -#define TARGET_MC (target_flags & TARGET_FLAG_MC) - -/* Nonzero if we should generate code for the CA processor. - Enables different optimization strategies. */ -#define TARGET_FLAG_C_SERIES 0x10 -#define TARGET_C_SERIES (target_flags & TARGET_FLAG_C_SERIES) - -/* Nonzero if we should generate leaf-procedures when we find them. - You may not want to do this because leaf-proc entries are - slower when not entered via BAL - this would be true when - a linker not supporting the optimization is used. */ -#define TARGET_FLAG_LEAFPROC 0x20 -#define TARGET_LEAFPROC (target_flags & TARGET_FLAG_LEAFPROC) - -/* Nonzero if we should perform tail-call optimizations when we find them. - You may not want to do this because the detection of cases where - this is not valid is not totally complete. */ -#define TARGET_FLAG_TAILCALL 0x40 -#define TARGET_TAILCALL (target_flags & TARGET_FLAG_TAILCALL) - -/* Nonzero if use of a complex addressing mode is a win on this implementation. - Complex addressing modes are probably not worthwhile on the K-series, - but they definitely are on the C-series. */ -#define TARGET_FLAG_COMPLEX_ADDR 0x80 -#define TARGET_COMPLEX_ADDR (target_flags & TARGET_FLAG_COMPLEX_ADDR) - -/* Align code to 8 byte boundaries for faster fetching. */ -#define TARGET_FLAG_CODE_ALIGN 0x100 -#define TARGET_CODE_ALIGN (target_flags & TARGET_FLAG_CODE_ALIGN) - -/* Append branch prediction suffixes to branch opcodes. */ -/* ??? Not used currently. */ -#define TARGET_FLAG_BRANCH_PREDICT 0x200 -#define TARGET_BRANCH_PREDICT (target_flags & TARGET_FLAG_BRANCH_PREDICT) - -/* Forces prototype and return promotions. */ -/* ??? This does not work. */ -#define TARGET_FLAG_CLEAN_LINKAGE 0x400 -#define TARGET_CLEAN_LINKAGE (target_flags & TARGET_FLAG_CLEAN_LINKAGE) - -/* For compatibility with iC960 v3.0. */ -#define TARGET_FLAG_IC_COMPAT3_0 0x800 -#define TARGET_IC_COMPAT3_0 (target_flags & TARGET_FLAG_IC_COMPAT3_0) - -/* For compatibility with iC960 v2.0. */ -#define TARGET_FLAG_IC_COMPAT2_0 0x1000 -#define TARGET_IC_COMPAT2_0 (target_flags & TARGET_FLAG_IC_COMPAT2_0) - -/* If no unaligned accesses are to be permitted. */ -#define TARGET_FLAG_STRICT_ALIGN 0x2000 -#define TARGET_STRICT_ALIGN (target_flags & TARGET_FLAG_STRICT_ALIGN) - -/* For compatibility with iC960 assembler. */ -#define TARGET_FLAG_ASM_COMPAT 0x4000 -#define TARGET_ASM_COMPAT (target_flags & TARGET_FLAG_ASM_COMPAT) - -/* For compatibility with the gcc960 v1.2 compiler. Use the old structure - alignment rules. Also, turns on STRICT_ALIGNMENT. */ -#define TARGET_FLAG_OLD_ALIGN 0x8000 -#define TARGET_OLD_ALIGN (target_flags & TARGET_FLAG_OLD_ALIGN) - -/* Nonzero if long doubles are to be 64 bits. Useful for soft-float targets - if 80 bit long double support is missing. */ -#define TARGET_FLAG_LONG_DOUBLE_64 0x10000 -#define TARGET_LONG_DOUBLE_64 (target_flags & TARGET_FLAG_LONG_DOUBLE_64) - -extern int target_flags; - -/* Macro to define tables used to set the flags. - This is a list in braces of pairs in braces, - each pair being { "NAME", VALUE } - where VALUE is the bits to set or minus the bits to clear. - An empty string NAME is used to identify the default VALUE. */ - -/* ??? Not all ten of these architecture variations actually exist, but I - am not sure which are real and which aren't. */ - -#define TARGET_SWITCHES \ - { {"sa", (TARGET_FLAG_K_SERIES|TARGET_FLAG_COMPLEX_ADDR), \ - N_("Generate SA code")}, \ - {"sb", (TARGET_FLAG_NUMERICS|TARGET_FLAG_K_SERIES| \ - TARGET_FLAG_COMPLEX_ADDR), \ - N_("Generate SB code")}, \ -/* {"sc", (TARGET_FLAG_NUMERICS|TARGET_FLAG_PROTECTED| \ - TARGET_FLAG_MC|TARGET_FLAG_COMPLEX_ADDR), \ - N_("Generate SC code")}, */ \ - {"ka", (TARGET_FLAG_K_SERIES|TARGET_FLAG_COMPLEX_ADDR), \ - N_("Generate KA code")}, \ - {"kb", (TARGET_FLAG_NUMERICS|TARGET_FLAG_K_SERIES| \ - TARGET_FLAG_COMPLEX_ADDR), \ - N_("Generate KB code")}, \ -/* {"kc", (TARGET_FLAG_NUMERICS|TARGET_FLAG_PROTECTED| \ - TARGET_FLAG_MC|TARGET_FLAG_COMPLEX_ADDR), \ - N_("Generate KC code")}, */ \ - {"ja", (TARGET_FLAG_K_SERIES|TARGET_FLAG_COMPLEX_ADDR), \ - N_("Generate JA code")}, \ - {"jd", (TARGET_FLAG_K_SERIES|TARGET_FLAG_COMPLEX_ADDR), \ - N_("Generate JD code")}, \ - {"jf", (TARGET_FLAG_NUMERICS|TARGET_FLAG_K_SERIES| \ - TARGET_FLAG_COMPLEX_ADDR), \ - N_("Generate JF code")}, \ - {"rp", (TARGET_FLAG_K_SERIES|TARGET_FLAG_COMPLEX_ADDR), \ - N_("generate RP code")}, \ - {"mc", (TARGET_FLAG_NUMERICS|TARGET_FLAG_PROTECTED| \ - TARGET_FLAG_MC|TARGET_FLAG_COMPLEX_ADDR), \ - N_("Generate MC code")}, \ - {"ca", (TARGET_FLAG_C_SERIES|TARGET_FLAG_BRANCH_PREDICT| \ - TARGET_FLAG_CODE_ALIGN|TARGET_FLAG_COMPLEX_ADDR),\ - N_("Generate CA code")}, \ -/* {"cb", (TARGET_FLAG_NUMERICS|TARGET_FLAG_C_SERIES| \ - TARGET_FLAG_BRANCH_PREDICT|TARGET_FLAG_CODE_ALIGN),\ - N_("Generate CB code")}, \ - {"cc", (TARGET_FLAG_NUMERICS|TARGET_FLAG_PROTECTED| \ - TARGET_FLAG_C_SERIES|TARGET_FLAG_BRANCH_PREDICT|\ - TARGET_FLAG_CODE_ALIGN), \ - N_("Generate CC code")}, */ \ - {"cf", (TARGET_FLAG_C_SERIES|TARGET_FLAG_BRANCH_PREDICT| \ - TARGET_FLAG_CODE_ALIGN|TARGET_FLAG_COMPLEX_ADDR),\ - N_("Generate CF code")}, \ - {"numerics", (TARGET_FLAG_NUMERICS), \ - N_("Use hardware floating point instructions")}, \ - {"soft-float", -(TARGET_FLAG_NUMERICS), \ - N_("Use software floating point")}, \ - {"leaf-procedures", TARGET_FLAG_LEAFPROC, \ - N_("Use alternate leaf function entries")}, \ - {"no-leaf-procedures", -(TARGET_FLAG_LEAFPROC), \ - N_("Do not use alternate leaf function entries")}, \ - {"tail-call", TARGET_FLAG_TAILCALL, \ - N_("Perform tail call optimization")}, \ - {"no-tail-call", -(TARGET_FLAG_TAILCALL), \ - N_("Do not perform tail call optimization")}, \ - {"complex-addr", TARGET_FLAG_COMPLEX_ADDR, \ - N_("Use complex addressing modes")}, \ - {"no-complex-addr", -(TARGET_FLAG_COMPLEX_ADDR), \ - N_("Do not use complex addressing modes")}, \ - {"code-align", TARGET_FLAG_CODE_ALIGN, \ - N_("Align code to 8 byte boundary")}, \ - {"no-code-align", -(TARGET_FLAG_CODE_ALIGN), \ - N_("Do not align code to 8 byte boundary")}, \ -/* {"clean-linkage", (TARGET_FLAG_CLEAN_LINKAGE), \ - N_("Force use of prototypes")}, \ - {"no-clean-linkage", -(TARGET_FLAG_CLEAN_LINKAGE), \ - N_("Do not force use of prototypes")}, */ \ - {"ic-compat", TARGET_FLAG_IC_COMPAT2_0, \ - N_("Enable compatibility with iC960 v2.0")}, \ - {"ic2.0-compat", TARGET_FLAG_IC_COMPAT2_0, \ - N_("Enable compatibility with iC960 v2.0")}, \ - {"ic3.0-compat", TARGET_FLAG_IC_COMPAT3_0, \ - N_("Enable compatibility with iC960 v3.0")}, \ - {"asm-compat", TARGET_FLAG_ASM_COMPAT, \ - N_("Enable compatibility with ic960 assembler")}, \ - {"intel-asm", TARGET_FLAG_ASM_COMPAT, \ - N_("Enable compatibility with ic960 assembler")}, \ - {"strict-align", TARGET_FLAG_STRICT_ALIGN, \ - N_("Do not permit unaligned accesses")}, \ - {"no-strict-align", -(TARGET_FLAG_STRICT_ALIGN), \ - N_("Permit unaligned accesses")}, \ - {"old-align", (TARGET_FLAG_OLD_ALIGN|TARGET_FLAG_STRICT_ALIGN), \ - N_("Layout types like Intel's v1.3 gcc")}, \ - {"no-old-align", -(TARGET_FLAG_OLD_ALIGN|TARGET_FLAG_STRICT_ALIGN), \ - N_("Do not layout types like Intel's v1.3 gcc")}, \ - {"long-double-64", TARGET_FLAG_LONG_DOUBLE_64, \ - N_("Use 64 bit long doubles")}, \ - {"link-relax", 0, \ - N_("Enable linker relaxation")}, \ - {"no-link-relax", 0, \ - N_("Do not enable linker relaxation")}, \ - SUBTARGET_SWITCHES \ - { "", TARGET_DEFAULT, \ - NULL}} - -/* This are meant to be redefined in the host dependent files */ -#define SUBTARGET_SWITCHES - -/* Override conflicting target switch options. - Doesn't actually detect if more than one -mARCH option is given, but - does handle the case of two blatantly conflicting -mARCH options. */ -#define OVERRIDE_OPTIONS i960_initialize () - -/* Don't enable anything by default. The user is expected to supply a -mARCH - option. If none is given, then -mka is added by CC1_SPEC. */ -#define TARGET_DEFAULT 0 - -/* Target machine storage layout. */ - -/* Define this if most significant bit is lowest numbered - in instructions that operate on numbered bit-fields. */ -#define BITS_BIG_ENDIAN 0 - -/* Define this if most significant byte of a word is the lowest numbered. - The i960 case be either big endian or little endian. We only support - little endian, which is the most common. */ -#define BYTES_BIG_ENDIAN 0 - -/* Define this if most significant word of a multiword number is lowest - numbered. */ -#define WORDS_BIG_ENDIAN 0 - -/* Bitfields cannot cross word boundaries. */ -#define BITFIELD_NBYTES_LIMITED 1 - -/* Width of a word, in units (bytes). */ -#define UNITS_PER_WORD 4 - -/* Width in bits of a long double. */ -#define LONG_DOUBLE_TYPE_SIZE (TARGET_LONG_DOUBLE_64 ? 64 : 128) -#define MAX_LONG_DOUBLE_TYPE_SIZE 128 - -/* Define this to set long double type size to use in libgcc2.c, which can - not depend on target_flags. */ -#if defined(__LONG_DOUBLE_64__) -#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 64 -#else -#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 128 -#endif - -/* Allocation boundary (in *bits*) for storing pointers in memory. */ -#define POINTER_BOUNDARY 32 - -/* Allocation boundary (in *bits*) for storing arguments in argument list. */ -#define PARM_BOUNDARY 32 - -/* Boundary (in *bits*) on which stack pointer should be aligned. */ -#define STACK_BOUNDARY 128 - -/* Allocation boundary (in *bits*) for the code of a function. */ -#define FUNCTION_BOUNDARY 128 - -/* Alignment of field after `int : 0' in a structure. */ -#define EMPTY_FIELD_BOUNDARY 32 - -/* This makes zero-length anonymous fields lay the next field - at a word boundary. It also makes the whole struct have - at least word alignment if there are any bitfields at all. */ -#define PCC_BITFIELD_TYPE_MATTERS 1 - -/* Every structure's size must be a multiple of this. */ -#define STRUCTURE_SIZE_BOUNDARY 8 - -/* No data type wants to be aligned rounder than this. - Extended precision floats gets 4-word alignment. */ -#define BIGGEST_ALIGNMENT 128 - -/* Define this if move instructions will actually fail to work - when given unaligned data. - 80960 will work even with unaligned data, but it is slow. */ -#define STRICT_ALIGNMENT TARGET_STRICT_ALIGN - -/* Specify alignment for string literals (which might be higher than the - base type's minimal alignment requirement. This allows strings to be - aligned on word boundaries, and optimizes calls to the str* and mem* - library functions. */ -#define CONSTANT_ALIGNMENT(EXP, ALIGN) \ - (TREE_CODE (EXP) == STRING_CST \ - && i960_object_bytes_bitalign (int_size_in_bytes (TREE_TYPE (EXP))) > (int)(ALIGN) \ - ? i960_object_bytes_bitalign (int_size_in_bytes (TREE_TYPE (EXP))) \ - : (int)(ALIGN)) - -/* Macros to determine size of aggregates (structures and unions - in C). Normally, these may be defined to simply return the maximum - alignment and simple rounded-up size, but on some machines (like - the i960), the total size of a structure is based on a non-trivial - rounding method. */ - -#define ROUND_TYPE_ALIGN(TYPE, COMPUTED, SPECIFIED) \ - i960_round_align (MAX ((COMPUTED), (SPECIFIED)), TYPE) - -/* Standard register usage. */ - -/* Number of actual hardware registers. - The hardware registers are assigned numbers for the compiler - from 0 to just below FIRST_PSEUDO_REGISTER. - All registers that the compiler knows about must be given numbers, - even those that are not normally considered general registers. - - Registers 0-15 are the global registers (g0-g15). - Registers 16-31 are the local registers (r0-r15). - Register 32-35 are the fp registers (fp0-fp3). - Register 36 is the condition code register. - Register 37 is unused. */ - -#define FIRST_PSEUDO_REGISTER 38 - -/* 1 for registers that have pervasive standard uses and are not available - for the register allocator. On 80960, this includes the frame pointer - (g15), the previous FP (r0), the stack pointer (r1), the return - instruction pointer (r2), and the argument pointer (g14). */ -#define FIXED_REGISTERS \ - {0, 0, 0, 0, 0, 0, 0, 0, \ - 0, 0, 0, 0, 0, 0, 1, 1, \ - 1, 1, 1, 0, 0, 0, 0, 0, \ - 0, 0, 0, 0, 0, 0, 0, 0, \ - 0, 0, 0, 0, 1, 1} - -/* 1 for registers not available across function calls. - These must include the FIXED_REGISTERS and also any - registers that can be used without being saved. - The latter must include the registers where values are returned - and the register where structure-value addresses are passed. - Aside from that, you can include as many other registers as you like. */ - -/* On the 80960, note that: - g0..g3 are used for return values, - g0..g7 may always be used for parameters, - g8..g11 may be used for parameters, but are preserved if they aren't, - g12 is the static chain if needed, otherwise is preserved - g13 is the struct return ptr if used, or temp, but may be trashed, - g14 is the leaf return ptr or the arg block ptr otherwise zero, - must be reset to zero before returning if it was used, - g15 is the frame pointer, - r0 is the previous FP, - r1 is the stack pointer, - r2 is the return instruction pointer, - r3-r15 are always available, - r3 is clobbered by calls in functions that use the arg pointer - r4-r11 may be clobbered by the mcount call when profiling - r4-r15 if otherwise unused may be used for preserving global registers - fp0..fp3 are never available. */ -#define CALL_USED_REGISTERS \ - {1, 1, 1, 1, 1, 1, 1, 1, \ - 0, 0, 0, 0, 0, 1, 1, 1, \ - 1, 1, 1, 0, 0, 0, 0, 0, \ - 0, 0, 0, 0, 0, 0, 0, 0, \ - 1, 1, 1, 1, 1, 1} - -/* If no fp unit, make all of the fp registers fixed so that they can't - be used. */ -#define CONDITIONAL_REGISTER_USAGE \ - if (! TARGET_NUMERICS) { \ - fixed_regs[32] = fixed_regs[33] = fixed_regs[34] = fixed_regs[35] = 1;\ - } \ - -/* Return number of consecutive hard regs needed starting at reg REGNO - to hold something of mode MODE. - This is ordinarily the length in words of a value of mode MODE - but can be less for certain modes in special long registers. - - On 80960, ordinary registers hold 32 bits worth, but can be ganged - together to hold double or extended precision floating point numbers, - and the floating point registers hold any size floating point number */ -#define HARD_REGNO_NREGS(REGNO, MODE) \ - ((REGNO) < 32 \ - ? (((MODE) == VOIDmode) \ - ? 1 : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)) \ - : ((REGNO) < FIRST_PSEUDO_REGISTER) ? 1 : 0) - -/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. - On 80960, the cpu registers can hold any mode but the float registers - can only hold SFmode, DFmode, or TFmode. */ -#define HARD_REGNO_MODE_OK(REGNO, MODE) hard_regno_mode_ok ((REGNO), (MODE)) - -/* Value is 1 if it is a good idea to tie two pseudo registers - when one has mode MODE1 and one has mode MODE2. - If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2, - for any hard reg, then this must be 0 for correct output. */ - -#define MODES_TIEABLE_P(MODE1, MODE2) \ - ((MODE1) == (MODE2) || GET_MODE_CLASS (MODE1) == GET_MODE_CLASS (MODE2)) - -/* Specify the registers used for certain standard purposes. - The values of these macros are register numbers. */ - -/* 80960 pc isn't overloaded on a register that the compiler knows about. */ -/* #define PC_REGNUM */ - -/* Register to use for pushing function arguments. */ -#define STACK_POINTER_REGNUM 17 - -/* Actual top-of-stack address is same as - the contents of the stack pointer register. */ -#define STACK_POINTER_OFFSET (-current_function_outgoing_args_size) - -/* Base register for access to local variables of the function. */ -#define FRAME_POINTER_REGNUM 15 - -/* Value should be nonzero if functions must have frame pointers. - Zero means the frame pointer need not be set up (and parms - may be accessed via the stack pointer) in functions that seem suitable. - This is computed in `reload', in reload1.c. */ -/* ??? It isn't clear to me why this is here. Perhaps because of a bug (since - fixed) in the definition of INITIAL_FRAME_POINTER_OFFSET which would have - caused this to fail. */ -/* ??? Must check current_function_has_nonlocal_goto, otherwise frame pointer - elimination messes up nonlocal goto sequences. I think this works for other - targets because they use indirect jumps for the return which disables fp - elimination. */ -#define FRAME_POINTER_REQUIRED \ - (! leaf_function_p () || current_function_has_nonlocal_goto) - -/* Definitions for register eliminations. - - This is an array of structures. Each structure initializes one pair - of eliminable registers. The "from" register number is given first, - followed by "to". Eliminations of the same "from" register are listed - in order of preference.. */ - -#define ELIMINABLE_REGS {{FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}} - -/* Given FROM and TO register numbers, say whether this elimination is allowed. - Frame pointer elimination is automatically handled. */ -#define CAN_ELIMINATE(FROM, TO) 1 - -/* Define the offset between two registers, one to be eliminated, and - the other its replacement, at the start of a routine. - - Since the stack grows upward on the i960, this must be a negative number. - This includes the 64 byte hardware register save area and the size of - the frame. */ - -#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \ - do { (OFFSET) = - (64 + compute_frame_size (get_frame_size ())); } while (0) - -/* Base register for access to arguments of the function. */ -#define ARG_POINTER_REGNUM 14 - -/* Register in which static-chain is passed to a function. - On i960, we use g12. We can't use any local register, because we need - a register that can be set before a call or before a jump. */ -#define STATIC_CHAIN_REGNUM 12 - -/* Functions which return large structures get the address - to place the wanted value at in g13. */ - -#define STRUCT_VALUE_REGNUM 13 - -/* The order in which to allocate registers. */ - -#define REG_ALLOC_ORDER \ -{ 4, 5, 6, 7, 0, 1, 2, 3, 13, /* g4, g5, g6, g7, g0, g1, g2, g3, g13 */ \ - 20, 21, 22, 23, 24, 25, 26, 27,/* r4, r5, r6, r7, r8, r9, r10, r11 */ \ - 28, 29, 30, 31, 19, 8, 9, 10, /* r12, r13, r14, r15, r3, g8, g9, g10 */ \ - 11, 12, /* g11, g12 */ \ - 32, 33, 34, 35, /* fp0, fp1, fp2, fp3 */ \ - /* We can't actually allocate these. */ \ - 16, 17, 18, 14, 15, 36, 37} /* r0, r1, r2, g14, g15, cc */ - -/* Define the classes of registers for register constraints in the - machine description. Also define ranges of constants. - - One of the classes must always be named ALL_REGS and include all hard regs. - If there is more than one class, another class must be named NO_REGS - and contain no registers. - - The name GENERAL_REGS must be the name of a class (or an alias for - another name such as ALL_REGS). This is the class of registers - that is allowed by "g" or "r" in a register constraint. - Also, registers outside this class are allocated only when - instructions express preferences for them. - - The classes must be numbered in nondecreasing order; that is, - a larger-numbered class must never be contained completely - in a smaller-numbered class. - - For any two classes, it is very desirable that there be another - class that represents their union. */ - -/* The 80960 has four kinds of registers, global, local, floating point, - and condition code. The cc register is never allocated, so no class - needs to be defined for it. */ - -enum reg_class { NO_REGS, GLOBAL_REGS, LOCAL_REGS, LOCAL_OR_GLOBAL_REGS, - FP_REGS, ALL_REGS, LIM_REG_CLASSES }; - -/* 'r' includes floating point registers if TARGET_NUMERICS. 'd' never - does. */ -#define GENERAL_REGS ((TARGET_NUMERICS) ? ALL_REGS : LOCAL_OR_GLOBAL_REGS) - -#define N_REG_CLASSES (int) LIM_REG_CLASSES - -/* Give names of register classes as strings for dump file. */ - -#define REG_CLASS_NAMES \ -{ "NO_REGS", "GLOBAL_REGS", "LOCAL_REGS", "LOCAL_OR_GLOBAL_REGS", \ - "FP_REGS", "ALL_REGS" } - -/* Define which registers fit in which classes. - This is an initializer for a vector of HARD_REG_SET - of length N_REG_CLASSES. */ - -#define REG_CLASS_CONTENTS \ -{ {0, 0}, {0x0ffff, 0}, {0xffff0000, 0}, {-1,0}, {0, -1}, {-1,-1}} - -/* The same information, inverted: - Return the class number of the smallest class containing - reg number REGNO. This could be a conditional expression - or could index an array. */ - -#define REGNO_REG_CLASS(REGNO) \ - ((REGNO) < 16 ? GLOBAL_REGS \ - : (REGNO) < 32 ? LOCAL_REGS \ - : (REGNO) < 36 ? FP_REGS \ - : NO_REGS) - -/* The class value for index registers, and the one for base regs. - There is currently no difference between base and index registers on the - i960, but this distinction may one day be useful. */ -#define INDEX_REG_CLASS LOCAL_OR_GLOBAL_REGS -#define BASE_REG_CLASS LOCAL_OR_GLOBAL_REGS - -/* Get reg_class from a letter such as appears in the machine description. - 'f' is a floating point register (fp0..fp3) - 'l' is a local register (r0-r15) - 'b' is a global register (g0-g15) - 'd' is any local or global register - 'r' or 'g' are pre-defined to the class GENERAL_REGS. */ -/* 'l' and 'b' are probably never used. Note that 'd' and 'r' are *not* - the same thing, since 'r' may include the fp registers. */ -#define REG_CLASS_FROM_LETTER(C) \ - (((C) == 'f') && (TARGET_NUMERICS) ? FP_REGS : ((C) == 'l' ? LOCAL_REGS : \ - (C) == 'b' ? GLOBAL_REGS : ((C) == 'd' ? LOCAL_OR_GLOBAL_REGS : NO_REGS))) - -/* The letters I, J, K, L and M in a register constraint string - can be used to stand for particular ranges of immediate operands. - This macro defines what the ranges are. - C is the letter, and VALUE is a constant value. - Return 1 if VALUE is in the range specified by C. - - For 80960: - 'I' is used for literal values 0..31 - 'J' means literal 0 - 'K' means 0..-31. */ - -#define CONST_OK_FOR_LETTER_P(VALUE, C) \ - ((C) == 'I' ? (((unsigned) (VALUE)) <= 31) \ - : (C) == 'J' ? ((VALUE) == 0) \ - : (C) == 'K' ? ((VALUE) >= -31 && (VALUE) <= 0) \ - : (C) == 'M' ? ((VALUE) >= -32 && (VALUE) <= 0) \ - : 0) - -/* Similar, but for floating constants, and defining letters G and H. - Here VALUE is the CONST_DOUBLE rtx itself. - For the 80960, G is 0.0 and H is 1.0. */ - -#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \ - ((TARGET_NUMERICS) && \ - (((C) == 'G' && (VALUE) == CONST0_RTX (GET_MODE (VALUE))) \ - || ((C) == 'H' && ((VALUE) == CONST1_RTX (GET_MODE (VALUE)))))) - -/* Given an rtx X being reloaded into a reg required to be - in class CLASS, return the class of reg to actually use. - In general this is just CLASS; but on some machines - in some cases it is preferable to use a more restrictive class. */ - -/* On 960, can't load constant into floating-point reg except - 0.0 or 1.0. - - Any hard reg is ok as a src operand of a reload insn. */ - -#define PREFERRED_RELOAD_CLASS(X,CLASS) \ - (GET_CODE (X) == REG && REGNO (X) < FIRST_PSEUDO_REGISTER \ - ? (CLASS) \ - : ((CLASS) == FP_REGS && CONSTANT_P (X) \ - && (X) != CONST0_RTX (DFmode) && (X) != CONST1_RTX (DFmode)\ - && (X) != CONST0_RTX (SFmode) && (X) != CONST1_RTX (SFmode)\ - ? NO_REGS \ - : (CLASS) == ALL_REGS ? LOCAL_OR_GLOBAL_REGS : (CLASS))) - -#define SECONDARY_RELOAD_CLASS(CLASS,MODE,IN) \ - secondary_reload_class (CLASS, MODE, IN) - -/* Return the maximum number of consecutive registers - needed to represent mode MODE in a register of class CLASS. */ -/* On 80960, this is the size of MODE in words, - except in the FP regs, where a single reg is always enough. */ -#define CLASS_MAX_NREGS(CLASS, MODE) \ - ((CLASS) == FP_REGS ? 1 : HARD_REGNO_NREGS (0, (MODE))) - -/* Stack layout; function entry, exit and calling. */ - -/* Define this if pushing a word on the stack - makes the stack pointer a smaller address. */ -/* #define STACK_GROWS_DOWNWARD */ - -/* Define this if the nominal address of the stack frame - is at the high-address end of the local variables; - that is, each additional local variable allocated - goes at a more negative offset in the frame. */ -/* #define FRAME_GROWS_DOWNWARD */ - -/* Offset within stack frame to start allocating local variables at. - If FRAME_GROWS_DOWNWARD, this is the offset to the END of the - first local allocated. Otherwise, it is the offset to the BEGINNING - of the first local allocated. - - The i960 has a 64 byte register save area, plus possibly some extra - bytes allocated for varargs functions. */ -#define STARTING_FRAME_OFFSET 64 - -/* If we generate an insn to push BYTES bytes, - this says how many the stack pointer really advances by. - On 80960, don't define this because there are no push insns. */ -/* #define PUSH_ROUNDING(BYTES) BYTES */ - -/* Offset of first parameter from the argument pointer register value. */ -#define FIRST_PARM_OFFSET(FNDECL) 0 - -/* When a parameter is passed in a register, no stack space is - allocated for it. However, when args are passed in the - stack, space is allocated for every register parameter. */ -#define MAYBE_REG_PARM_STACK_SPACE 48 -#define FINAL_REG_PARM_STACK_SPACE(CONST_SIZE, VAR_SIZE) \ - i960_final_reg_parm_stack_space (CONST_SIZE, VAR_SIZE); -#define REG_PARM_STACK_SPACE(DECL) i960_reg_parm_stack_space (DECL) -#define OUTGOING_REG_PARM_STACK_SPACE - -/* Keep the stack pointer constant throughout the function. */ -#define ACCUMULATE_OUTGOING_ARGS 1 - -/* Value is 1 if returning from a function call automatically - pops the arguments described by the number-of-args field in the call. - FUNDECL is the declaration node of the function (as a tree), - FUNTYPE is the data type of the function (as a tree), - or for a library call it is an identifier node for the subroutine name. */ - -#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) 0 - -/* Define how to find the value returned by a library function - assuming the value has mode MODE. */ - -#define LIBCALL_VALUE(MODE) gen_rtx_REG ((MODE), 0) - -/* 1 if N is a possible register number for a function value - as seen by the caller. - On 80960, returns are in g0..g3 */ - -#define FUNCTION_VALUE_REGNO_P(N) ((N) == 0) - -/* 1 if N is a possible register number for function argument passing. - On 80960, parameters are passed in g0..g11 */ - -#define FUNCTION_ARG_REGNO_P(N) ((N) < 12) - -/* Perform any needed actions needed for a function that is receiving a - variable number of arguments. - - CUM is as above. - - MODE and TYPE are the mode and type of the current parameter. - - PRETEND_SIZE is a variable that should be set to the amount of stack - that must be pushed by the prolog to pretend that our caller pushed - it. - - Normally, this macro will push all remaining incoming registers on the - stack and set PRETEND_SIZE to the length of the registers pushed. */ - -#define SETUP_INCOMING_VARARGS(CUM,MODE,TYPE,PRETEND_SIZE,NO_RTL) \ - i960_setup_incoming_varargs(&CUM,MODE,TYPE,&PRETEND_SIZE,NO_RTL) - -/* Implement `va_start' for varargs and stdarg. */ -#define EXPAND_BUILTIN_VA_START(valist, nextarg) \ - i960_va_start (valist, nextarg) - -/* Implement `va_arg'. */ -#define EXPAND_BUILTIN_VA_ARG(valist, type) \ - i960_va_arg (valist, type) - -/* Define a data type for recording info about an argument list - during the scan of that argument list. This data type should - hold all necessary information about the function itself - and about the args processed so far, enough to enable macros - such as FUNCTION_ARG to determine where the next arg should go. - - On 80960, this is two integers, which count the number of register - parameters and the number of stack parameters seen so far. */ - -struct cum_args { int ca_nregparms; int ca_nstackparms; }; - -#define CUMULATIVE_ARGS struct cum_args - -/* Define the number of registers that can hold parameters. - This macro is used only in macro definitions below and/or i960.c. */ -#define NPARM_REGS 12 - -/* Define how to round to the next parameter boundary. - This macro is used only in macro definitions below and/or i960.c. */ -#define ROUND_PARM(X, MULTIPLE_OF) \ - ((((X) + (MULTIPLE_OF) - 1) / (MULTIPLE_OF)) * MULTIPLE_OF) - -/* Initialize a variable CUM of type CUMULATIVE_ARGS - for a call to a function whose data type is FNTYPE. - For a library call, FNTYPE is 0. - - On 80960, the offset always starts at 0; the first parm reg is g0. */ - -#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) \ - ((CUM).ca_nregparms = 0, (CUM).ca_nstackparms = 0) - -/* Update the data in CUM to advance over an argument - of mode MODE and data type TYPE. - CUM should be advanced to align with the data type accessed and - also the size of that data type in # of regs. - (TYPE is null for libcalls where that information may not be available.) */ - -#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ - i960_function_arg_advance(&CUM, MODE, TYPE, NAMED) - -/* Indicate the alignment boundary for an argument of the specified mode and - type. */ -#define FUNCTION_ARG_BOUNDARY(MODE, TYPE) \ - (((TYPE) != 0) \ - ? ((TYPE_ALIGN (TYPE) <= PARM_BOUNDARY) \ - ? PARM_BOUNDARY \ - : TYPE_ALIGN (TYPE)) \ - : ((GET_MODE_ALIGNMENT (MODE) <= PARM_BOUNDARY) \ - ? PARM_BOUNDARY \ - : GET_MODE_ALIGNMENT (MODE))) - -/* Determine where to put an argument to a function. - Value is zero to push the argument on the stack, - or a hard register in which to store the argument. - - MODE is the argument's machine mode. - TYPE is the data type of the argument (as a tree). - This is null for libcalls where that information may - not be available. - CUM is a variable of type CUMULATIVE_ARGS which gives info about - the preceding args and about the function being called. - NAMED is nonzero if this argument is a named parameter - (otherwise it is an extra parameter matching an ellipsis). */ - -#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ - i960_function_arg(&CUM, MODE, TYPE, NAMED) - -/* Define how to find the value returned by a function. - VALTYPE is the data type of the value (as a tree). - If the precise function being called is known, FUNC is its FUNCTION_DECL; - otherwise, FUNC is 0. */ - -#define FUNCTION_VALUE(TYPE, FUNC) \ - gen_rtx_REG (TYPE_MODE (TYPE), 0) - -/* Force aggregates and objects larger than 16 bytes to be returned in memory, - since we only have 4 registers available for return values. */ - -#define RETURN_IN_MEMORY(TYPE) \ - (TYPE_MODE (TYPE) == BLKmode || int_size_in_bytes (TYPE) > 16) - -/* 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 - -/* For an arg passed partly in registers and partly in memory, - this is the number of registers used. - This never happens on 80960. */ - -#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) 0 - -/* Output the label for a function definition. - This handles leaf functions and a few other things for the i960. */ - -#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \ - i960_function_name_declare (FILE, NAME, DECL) - -/* Output assembler code to FILE to increment profiler label # LABELNO - for profiling a function entry. */ - -#define FUNCTION_PROFILER(FILE, LABELNO) \ - output_function_profiler ((FILE), (LABELNO)); - -/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function, - the stack pointer does not matter. The value is tested only in - functions that have frame pointers. - No definition is equivalent to always zero. */ - -#define EXIT_IGNORE_STACK 1 - -/* Addressing modes, and classification of registers for them. */ - -/* Macros to check register numbers against specific register classes. */ - -/* These assume that REGNO is a hard or pseudo reg number. - They give nonzero only if REGNO is a hard reg of the suitable class - or a pseudo reg currently allocated to a suitable hard reg. - Since they use reg_renumber, they are safe only once reg_renumber - has been allocated, which happens in local-alloc.c. */ - -#define REGNO_OK_FOR_INDEX_P(REGNO) \ - ((REGNO) < 32 || (unsigned) reg_renumber[REGNO] < 32) -#define REGNO_OK_FOR_BASE_P(REGNO) \ - ((REGNO) < 32 || (unsigned) reg_renumber[REGNO] < 32) -#define REGNO_OK_FOR_FP_P(REGNO) \ - ((REGNO) < 36 || (unsigned) reg_renumber[REGNO] < 36) - -/* Now macros that check whether X is a register and also, - strictly, whether it is in a specified class. - - These macros are specific to the 960, and may be used only - in code for printing assembler insns and in conditions for - define_optimization. */ - -/* 1 if X is an fp register. */ - -#define FP_REG_P(X) (REGNO (X) >= 32 && REGNO (X) < 36) - -/* Maximum number of registers that can appear in a valid memory address. */ -#define MAX_REGS_PER_ADDRESS 2 - -#define CONSTANT_ADDRESS_P(X) \ - (GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \ - || GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST \ - || GET_CODE (X) == HIGH) - -/* LEGITIMATE_CONSTANT_P is nonzero if the constant value X - is a legitimate general operand. - It is given that X satisfies CONSTANT_P. - - Anything but a CONST_DOUBLE can be made to work, excepting 0.0 and 1.0. - - ??? This probably should be defined to 1. */ - -#define LEGITIMATE_CONSTANT_P(X) \ - ((GET_CODE (X) != CONST_DOUBLE) || fp_literal ((X), GET_MODE (X))) - -/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx - and check its validity for a certain class. - We have two alternate definitions for each of them. - The usual definition accepts all pseudo regs; the other rejects - them unless they have been allocated suitable hard regs. - The symbol REG_OK_STRICT causes the latter definition to be used. - - Most source files want to accept pseudo regs in the hope that - they will get allocated to the class that the insn wants them to be in. - Source files for reload pass need to be strict. - After reload, it makes no difference, since pseudo regs have - been eliminated by then. */ - -#ifndef REG_OK_STRICT - -/* 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) < 32 || REGNO (X) >= FIRST_PSEUDO_REGISTER) -/* Nonzero if X is a hard reg that can be used as a base reg - or if it is a pseudo reg. */ -#define REG_OK_FOR_BASE_P(X) \ - (REGNO (X) < 32 || REGNO (X) >= FIRST_PSEUDO_REGISTER) - -#define REG_OK_FOR_INDEX_P_STRICT(X) REGNO_OK_FOR_INDEX_P (REGNO (X)) -#define REG_OK_FOR_BASE_P_STRICT(X) REGNO_OK_FOR_BASE_P (REGNO (X)) - -#else - -/* Nonzero if X is a hard reg that can be used as an index. */ -#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X)) -/* Nonzero if X is a hard reg that can be used as a base reg. */ -#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X)) - -#endif - -/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression - that is a valid memory address for an instruction. - The MODE argument is the machine mode for the MEM expression - that wants to use this address. - - On 80960, legitimate addresses are: - base ld (g0),r0 - disp (12 or 32 bit) ld foo,r0 - base + index ld (g0)[g1*1],r0 - base + displ ld 0xf00(g0),r0 - base + index*scale + displ ld 0xf00(g0)[g1*4],r0 - index*scale + base ld (g0)[g1*4],r0 - index*scale + displ ld 0xf00[g1*4],r0 - index*scale ld [g1*4],r0 - index + base + displ ld 0xf00(g0)[g1*1],r0 - - In each case, scale can be 1, 2, 4, 8, or 16. */ - -/* Returns 1 if the scale factor of an index term is valid. */ -#define SCALE_TERM_P(X) \ - (GET_CODE (X) == CONST_INT \ - && (INTVAL (X) == 1 || INTVAL (X) == 2 || INTVAL (X) == 4 \ - || INTVAL(X) == 8 || INTVAL (X) == 16)) - - -#ifdef REG_OK_STRICT -#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ - { if (legitimate_address_p (MODE, X, 1)) goto ADDR; } -#else -#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ - { if (legitimate_address_p (MODE, X, 0)) goto ADDR; } -#endif - -/* Try machine-dependent ways of modifying an illegitimate address - to be legitimate. If we find one, return the new, valid address. - This macro is used in only one place: `memory_address' in explow.c. - - OLDX is the address as it was before break_out_memory_refs was called. - In some cases it is useful to look at this to decide what needs to be done. - - MODE and WIN are passed so that this macro can use - GO_IF_LEGITIMATE_ADDRESS. - - It is always safe for this macro to do nothing. It exists to recognize - opportunities to optimize the output. */ - -/* On 80960, convert non-canonical addresses to canonical form. */ - -#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \ -{ rtx orig_x = (X); \ - (X) = legitimize_address (X, OLDX, MODE); \ - if ((X) != orig_x && memory_address_p (MODE, X)) \ - goto WIN; } - -/* Go to LABEL if ADDR (a legitimate address expression) - has an effect that depends on the machine mode it is used for. - On the 960 this is never true. */ - -#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) - -/* Specify the machine mode that this machine uses - for the index in the tablejump instruction. */ -#define CASE_VECTOR_MODE SImode - -/* Define as C expression which evaluates to nonzero if the tablejump - instruction expects the table to contain offsets from the address of the - table. - Do not define this if the table should contain absolute addresses. */ -/* #define CASE_VECTOR_PC_RELATIVE 1 */ - -/* Define this as 1 if `char' should by default be signed; else as 0. */ -#define DEFAULT_SIGNED_CHAR 0 - -/* Max number of bytes we can move from memory to memory - in one reasonably fast instruction. */ -#define MOVE_MAX 16 - -/* Define if operations between registers always perform the operation - on the full register even if a narrower mode is specified. */ -#define WORD_REGISTER_OPERATIONS - -/* Define if loading in MODE, an integral mode narrower than BITS_PER_WORD - will either zero-extend or sign-extend. The value of this macro should - be the code that says which one of the two operations is implicitly - done, NIL if none. */ -#define LOAD_EXTEND_OP(MODE) ZERO_EXTEND - -/* Nonzero if access to memory by bytes is no faster than for words. - Value changed to 1 after reports of poor bit-field code with g++. - Indications are that code is usually as good, sometimes better. */ - -#define SLOW_BYTE_ACCESS 1 - -/* Define this to be nonzero if shift instructions ignore all but the low-order - few bits. */ -#define SHIFT_COUNT_TRUNCATED 0 - -/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits - is done just by pretending it is already truncated. */ -#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1 - -/* Specify the machine mode that pointers have. - After generation of rtl, the compiler makes no further distinction - between pointers and any other objects of this machine mode. */ -#define Pmode SImode - -/* Specify the widest mode that BLKmode objects can be promoted to */ -#define MAX_FIXED_MODE_SIZE GET_MODE_BITSIZE (TImode) - -/* These global variables are used to pass information between - cc setter and cc user at insn emit time. */ - -extern struct rtx_def *i960_compare_op0, *i960_compare_op1; - -/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE, - return the mode to be used for the comparison. For floating-point, CCFPmode - should be used. CC_NOOVmode should be used when the first operand is a - PLUS, MINUS, or NEG. CCmode should be used when no special processing is - needed. */ -#define SELECT_CC_MODE(OP,X,Y) select_cc_mode (OP, X) - -/* A function address in a call instruction is a byte address - (for indexing purposes) so give the MEM rtx a byte's mode. */ -#define FUNCTION_MODE SImode - -/* Define this if addresses of constant functions - shouldn't be put through pseudo regs where they can be cse'd. - Desirable on machines where ordinary constants are expensive - but a CALL with constant address is cheap. */ -#define NO_FUNCTION_CSE - -/* Use memcpy, etc. instead of bcopy. */ - -#ifndef WIND_RIVER -#define TARGET_MEM_FUNCTIONS 1 -#endif - -/* Control the assembler format that we output. */ - -/* Output to assembler file text saying following lines - may contain character constants, extra white space, comments, etc. */ - -#define ASM_APP_ON "" - -/* Output to assembler file text saying following lines - no longer contain unusual constructs. */ - -#define ASM_APP_OFF "" - -/* Output before read-only data. */ - -#define TEXT_SECTION_ASM_OP "\t.text" - -/* Output before writable data. */ - -#define DATA_SECTION_ASM_OP "\t.data" - -/* How to refer to registers in assembler output. - This sequence is indexed by compiler's hard-register-number (see above). */ - -#define REGISTER_NAMES { \ - "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7", \ - "g8", "g9", "g10", "g11", "g12", "g13", "g14", "fp", \ - "pfp","sp", "rip", "r3", "r4", "r5", "r6", "r7", \ - "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", \ - "fp0","fp1","fp2", "fp3", "cc", "fake" } - -/* How to renumber registers for dbx and gdb. - In the 960 encoding, g0..g15 are registers 16..31. */ - -#define DBX_REGISTER_NUMBER(REGNO) \ - (((REGNO) < 16) ? (REGNO) + 16 \ - : (((REGNO) > 31) ? (REGNO) : (REGNO) - 16)) - -/* Don't emit dbx records longer than this. This is an arbitrary value. */ -#define DBX_CONTIN_LENGTH 1500 - -/* This is how to output a note to DBX telling it the line number - to which the following sequence of instructions corresponds. */ - -#define ASM_OUTPUT_SOURCE_LINE(FILE, LINE, COUNTER) \ -{ if (write_symbols == SDB_DEBUG) { \ - fprintf ((FILE), "\t.ln %d\n", \ - (sdb_begin_function_line \ - ? (LINE) - sdb_begin_function_line : 1)); \ - } else if (write_symbols == DBX_DEBUG) { \ - fprintf((FILE),"\t.stabd 68,0,%d\n",(LINE)); \ - } } - -/* Globalizing directive for a label. */ -#define GLOBAL_ASM_OP "\t.globl " - -/* The prefix to add to user-visible assembler symbols. */ - -#define USER_LABEL_PREFIX "_" - -/* This is how to store into the string LABEL - the symbol_ref name of an internal numbered label where - PREFIX is the class of label and NUM is the number within the class. - This is suitable for output with `assemble_name'. */ - -#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \ - sprintf (LABEL, "*%s%lu", PREFIX, (unsigned long)(NUM)) - -#define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \ - fprintf (FILE, "\tst\t%s,(sp)\n\taddo\t4,sp,sp\n", reg_names[REGNO]) - -/* This is how to output an insn to pop a register from the stack. - It need not be very fast code. */ - -#define ASM_OUTPUT_REG_POP(FILE,REGNO) \ - fprintf (FILE, "\tsubo\t4,sp,sp\n\tld\t(sp),%s\n", reg_names[REGNO]) - -/* This is how to output an element of a case-vector that is absolute. */ - -#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ - fprintf (FILE, "\t.word L%d\n", VALUE) - -/* This is how to output an element of a case-vector that is relative. */ - -#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ - fprintf (FILE, "\t.word L%d-L%d\n", VALUE, REL) - -/* This is how to output an assembler line that says to advance the - location counter to a multiple of 2**LOG bytes. */ - -#define ASM_OUTPUT_ALIGN(FILE,LOG) \ - fprintf (FILE, "\t.align %d\n", (LOG)) - -#define ASM_OUTPUT_SKIP(FILE,SIZE) \ - fprintf (FILE, "\t.space %d\n", (int)(SIZE)) - -/* This says how to output an assembler line - to define a global common symbol. */ - -/* For common objects, output unpadded size... gld960 & lnk960 both - have code to align each common object at link time. Also, if size - is 0, treat this as a declaration, not a definition - i.e., - do nothing at all. */ - -#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \ -{ if ((SIZE) != 0) \ - { \ - fputs (".globl ", (FILE)), \ - assemble_name ((FILE), (NAME)), \ - fputs ("\n.comm ", (FILE)), \ - assemble_name ((FILE), (NAME)), \ - fprintf ((FILE), ",%d\n", (int)(SIZE)); \ - } \ -} - -/* This says how to output an assembler line to define a local common symbol. - Output unpadded size, with request to linker to align as requested. - 0 size should not be possible here. */ - -#define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \ -( fputs (".bss\t", (FILE)), \ - assemble_name ((FILE), (NAME)), \ - fprintf ((FILE), ",%d,%d\n", (int)(SIZE), \ - (floor_log2 ((ALIGN) / BITS_PER_UNIT)))) - -/* A C statement (sans semicolon) to output to the stdio stream - FILE the assembler definition of uninitialized global DECL named - NAME whose size is SIZE bytes and alignment is ALIGN bytes. - Try to use asm_output_aligned_bss to implement this macro. */ - -#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \ - do { \ - ASM_OUTPUT_ALIGNED_LOCAL (FILE, NAME, SIZE, ALIGN); \ - } while (0) - -/* Output text for an #ident directive. */ -#define ASM_OUTPUT_IDENT(FILE, STR) fprintf(FILE, "\t# %s\n", STR); - -/* Align code to 8 byte boundary if TARGET_CODE_ALIGN is true. */ - -#define LABEL_ALIGN_AFTER_BARRIER(LABEL) (TARGET_CODE_ALIGN ? 3 : 0) - - -/* Print operand X (an rtx) in assembler syntax to file FILE. - CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified. - For `%' followed by punctuation, CODE is the punctuation and X is null. */ - -#define PRINT_OPERAND(FILE, X, CODE) \ - i960_print_operand (FILE, X, CODE); - -/* Print a memory address as an operand to reference that memory location. */ - -#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \ - i960_print_operand_addr (FILE, ADDR) - -/* Determine which codes are valid without a following integer. These must - not be alphabetic (the characters are chosen so that - PRINT_OPERAND_PUNCT_VALID_P translates into a simple range change when - using ASCII). */ - -#define PRINT_OPERAND_PUNCT_VALID_P(CODE) ((CODE) == '+') - -/* Output assembler code for a block containing the constant parts - of a trampoline, leaving space for the variable parts. */ - -/* On the i960, the trampoline contains three instructions: - ldconst _function, r4 - ldconst static addr, g12 - jump (r4) */ - -#define TRAMPOLINE_TEMPLATE(FILE) \ -{ \ - assemble_aligned_integer (UNITS_PER_WORD, GEN_INT (0x8C203000)); \ - assemble_aligned_integer (UNITS_PER_WORD, GEN_INT (0x00000000)); \ - assemble_aligned_integer (UNITS_PER_WORD, GEN_INT (0x8CE03000)); \ - assemble_aligned_integer (UNITS_PER_WORD, GEN_INT (0x00000000)); \ - assemble_aligned_integer (UNITS_PER_WORD, GEN_INT (0x84212000)); \ -} - -/* Length in units of the trampoline for entering a nested function. */ - -#define TRAMPOLINE_SIZE 20 - -/* Emit RTL insns to initialize the variable parts of a trampoline. - FNADDR is an RTX for the address of the function's pure code. - CXT is an RTX for the static chain value for the function. */ - -#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \ -{ \ - emit_move_insn (gen_rtx_MEM (SImode, plus_constant (TRAMP, 4)), FNADDR); \ - emit_move_insn (gen_rtx_MEM (SImode, plus_constant (TRAMP, 12)), CXT); \ -} - -/* Generate RTL to flush the register windows so as to make arbitrary frames - available. */ -#define SETUP_FRAME_ADDRESSES() \ - emit_insn (gen_flush_register_windows ()) - -#define BUILTIN_SETJMP_FRAME_VALUE hard_frame_pointer_rtx - -#if 0 -/* Promote char and short arguments to ints, when want compatibility with - the iC960 compilers. */ - -/* ??? In order for this to work, all users would need to be changed - to test the value of the macro at run time. */ -#define PROMOTE_PROTOTYPES TARGET_CLEAN_LINKAGE -/* ??? This does not exist. */ -#define PROMOTE_RETURN TARGET_CLEAN_LINKAGE -#endif - -/* Instruction type definitions. Used to alternate instructions types for - better performance on the C series chips. */ - -enum insn_types { I_TYPE_REG, I_TYPE_MEM, I_TYPE_CTRL }; - -/* Holds the insn type of the last insn output to the assembly file. */ - -extern enum insn_types i960_last_insn_type; - -/* Parse opcodes, and set the insn last insn type based on them. */ - -#define ASM_OUTPUT_OPCODE(FILE, INSN) i960_scan_opcode (INSN) - -/* Table listing what rtl codes each predicate in i960.c will accept. */ - -#define PREDICATE_CODES \ - {"fpmove_src_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF, \ - LABEL_REF, SUBREG, REG, MEM}}, \ - {"arith_operand", {SUBREG, REG, CONST_INT}}, \ - {"logic_operand", {SUBREG, REG, CONST_INT}}, \ - {"fp_arith_operand", {SUBREG, REG, CONST_DOUBLE}}, \ - {"signed_arith_operand", {SUBREG, REG, CONST_INT}}, \ - {"literal", {CONST_INT}}, \ - {"fp_literal_one", {CONST_DOUBLE}}, \ - {"fp_literal_double", {CONST_DOUBLE}}, \ - {"fp_literal", {CONST_DOUBLE}}, \ - {"signed_literal", {CONST_INT}}, \ - {"symbolic_memory_operand", {SUBREG, MEM}}, \ - {"eq_or_neq", {EQ, NE}}, \ - {"arith32_operand", {SUBREG, REG, LABEL_REF, SYMBOL_REF, CONST_INT, \ - CONST_DOUBLE, CONST}}, \ - {"power2_operand", {CONST_INT}}, \ - {"cmplpower2_operand", {CONST_INT}}, - -/* Defined in reload.c, and used in insn-recog.c. */ - -extern int rtx_equal_function_value_matters; diff --git a/gcc/config/i960/i960.md b/gcc/config/i960/i960.md deleted file mode 100644 index ad1678a7077..00000000000 --- a/gcc/config/i960/i960.md +++ /dev/null @@ -1,2818 +0,0 @@ -;;- Machine description for Intel 80960 chip for GNU C compiler -;; Copyright (C) 1992, 1995, 1998, 2001 Free Software Foundation, Inc. -;; Contributed by Steven McGeady, Intel Corp. -;; Additional work by Glenn Colon-Bonet, Jonathan Shapiro, Andy Wilson -;; Converted to GCC 2.0 by Jim Wilson and Michael Tiemann, Cygnus Support. - -;; This file is part of GCC. - -;; GCC is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; GCC is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GCC; see the file COPYING. If not, write to -;; the Free Software Foundation, 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - -;;- See file "rtl.def" for documentation on define_insn, match_*, et. al. - -;; There are very few (4) 'f' registers, they can't be loaded/stored from/to -;; memory, and some instructions explicitly require them, so we get better -;; code by discouraging pseudo-registers from being allocated to them. -;; However, we do want to allow all patterns which can store to them to -;; include them in their constraints, so we always use '*f' in a destination -;; constraint except when 'f' is the only alternative. - -;; Insn attributes which describe the i960. - -;; Modscan is not used, since the compiler never emits any of these insns. -(define_attr "type" - "move,arith,alu2,mult,div,modscan,load,store,branch,call,address,compare,fpload,fpstore,fpmove,fpcvt,fpcc,fpadd,fpmul,fpdiv,multi,misc" - (const_string "arith")) - -;; Length (in # of insns). -(define_attr "length" "" - (cond [(eq_attr "type" "load,fpload") - (if_then_else (match_operand 1 "symbolic_memory_operand" "") - (const_int 2) - (const_int 1)) - (eq_attr "type" "store,fpstore") - (if_then_else (match_operand 0 "symbolic_memory_operand" "") - (const_int 2) - (const_int 1)) - (eq_attr "type" "address") - (const_int 2)] - (const_int 1))) - -(define_asm_attributes - [(set_attr "length" "1") - (set_attr "type" "multi")]) - -;; (define_function_unit {name} {num-units} {n-users} {test} -;; {ready-delay} {issue-delay} [{conflict-list}]) - -;; The integer ALU -(define_function_unit "alu" 2 0 (eq_attr "type" "arith,compare,move,address") 1 0) -(define_function_unit "alu" 2 0 (eq_attr "type" "alu2") 2 0) -(define_function_unit "alu" 2 0 (eq_attr "type" "mult") 5 0) -(define_function_unit "alu" 2 0 (eq_attr "type" "div") 35 0) -(define_function_unit "alu" 2 0 (eq_attr "type" "modscan") 3 0) - -;; Memory with load-delay of 1 (i.e., 2 cycle load). -(define_function_unit "memory" 1 0 (eq_attr "type" "load,fpload") 2 0) - -;; Floating point operations. -(define_function_unit "fp" 1 2 (eq_attr "type" "fpmove") 5 0) -(define_function_unit "fp" 1 2 (eq_attr "type" "fpcvt") 35 0) -(define_function_unit "fp" 1 2 (eq_attr "type" "fpcc") 10 0) -(define_function_unit "fp" 1 2 (eq_attr "type" "fpadd") 10 0) -(define_function_unit "fp" 1 2 (eq_attr "type" "fpmul") 20 0) -(define_function_unit "fp" 1 2 (eq_attr "type" "fpdiv") 35 0) - -;; Compare instructions. -;; This controls RTL generation and register allocation. - -;; We generate RTL for comparisons and branches by having the cmpxx -;; patterns store away the operands. Then, the scc and bcc patterns -;; emit RTL for both the compare and the branch. -;; -;; We start with the DEFINE_EXPANDs, then DEFINE_INSNs to match -;; the patterns. Finally, we have the DEFINE_SPLITs for some of the scc -;; insns that actually require more than one machine instruction. - -;; Put cmpsi first because it is expected to be the most common. - -(define_expand "cmpsi" - [(set (reg:CC 36) - (compare:CC (match_operand:SI 0 "nonimmediate_operand" "") - (match_operand:SI 1 "general_operand" "")))] - "" - " -{ - i960_compare_op0 = operands[0]; - i960_compare_op1 = operands[1]; - DONE; -}") - -(define_expand "cmpdf" - [(set (reg:CC 36) - (compare:CC (match_operand:DF 0 "register_operand" "r") - (match_operand:DF 1 "nonmemory_operand" "rGH")))] - "TARGET_NUMERICS" - " -{ - i960_compare_op0 = operands[0]; - i960_compare_op1 = operands[1]; - DONE; -}") - -(define_expand "cmpsf" - [(set (reg:CC 36) - (compare:CC (match_operand:SF 0 "register_operand" "r") - (match_operand:SF 1 "nonmemory_operand" "rGH")))] - "TARGET_NUMERICS" - " -{ - i960_compare_op0 = operands[0]; - i960_compare_op1 = operands[1]; - DONE; -}") - -;; Now the DEFINE_INSNs for the compare and scc cases. First the compares. - -(define_insn "" - [(set (reg:CC 36) - (compare:CC (match_operand:SI 0 "register_operand" "d") - (match_operand:SI 1 "arith_operand" "dI")))] - "" - "cmpi %0,%1" - [(set_attr "type" "compare")]) - -(define_insn "" - [(set (reg:CC_UNS 36) - (compare:CC_UNS (match_operand:SI 0 "register_operand" "d") - (match_operand:SI 1 "arith_operand" "dI")))] - "" - "cmpo %0,%1" - [(set_attr "type" "compare")]) - -(define_insn "" - [(set (reg:CC 36) - (compare:CC (match_operand:DF 0 "register_operand" "r") - (match_operand:DF 1 "nonmemory_operand" "rGH")))] - "TARGET_NUMERICS" - "cmprl %0,%1" - [(set_attr "type" "fpcc")]) - -(define_insn "" - [(set (reg:CC 36) - (compare:CC (match_operand:SF 0 "register_operand" "r") - (match_operand:SF 1 "nonmemory_operand" "rGH")))] - "TARGET_NUMERICS" - "cmpr %0,%1" - [(set_attr "type" "fpcc")]) - -;; Instruction definitions for branch-on-bit-set and clear insns. - -(define_insn "" - [(set (pc) - (if_then_else - (ne (sign_extract:SI (match_operand:SI 0 "register_operand" "d") - (const_int 1) - (match_operand:SI 1 "arith_operand" "dI")) - (const_int 0)) - (label_ref (match_operand 2 "" "")) - (pc)))] - "" - "bbs%+ %1,%0,%l2" - [(set_attr "type" "branch")]) - -(define_insn "" - [(set (pc) - (if_then_else - (eq (sign_extract:SI (match_operand:SI 0 "register_operand" "d") - (const_int 1) - (match_operand:SI 1 "arith_operand" "dI")) - (const_int 0)) - (label_ref (match_operand 2 "" "")) - (pc)))] - "" - "bbc%+ %1,%0,%l2" - [(set_attr "type" "branch")]) - -(define_insn "" - [(set (pc) - (if_then_else - (ne (zero_extract:SI (match_operand:SI 0 "register_operand" "d") - (const_int 1) - (match_operand:SI 1 "arith_operand" "dI")) - (const_int 0)) - (label_ref (match_operand 2 "" "")) - (pc)))] - "" - "bbs%+ %1,%0,%l2" - [(set_attr "type" "branch")]) - -(define_insn "" - [(set (pc) - (if_then_else - (eq (zero_extract:SI (match_operand:SI 0 "register_operand" "d") - (const_int 1) - (match_operand:SI 1 "arith_operand" "dI")) - (const_int 0)) - (label_ref (match_operand 2 "" "")) - (pc)))] - "" - "bbc%+ %1,%0,%l2" - [(set_attr "type" "branch")]) - -;; ??? These will never match. The LOG_LINKs necessary to make these match -;; are not created by flow. These remain as a reminder to make this work -;; some day. - -(define_insn "" - [(set (reg:CC 36) - (compare (match_operand:SI 0 "arith_operand" "d") - (match_operand:SI 1 "arith_operand" "+d"))) - (set (match_dup 1) (plus:SI (match_dup 1) (const_int 1)))] - "0" - "cmpinci %0,%1" - [(set_attr "type" "compare")]) - -(define_insn "" - [(set (reg:CC_UNS 36) - (compare (match_operand:SI 0 "arith_operand" "d") - (match_operand:SI 1 "arith_operand" "+d"))) - (set (match_dup 1) (plus:SI (match_dup 1) (const_int 1)))] - "0" - "cmpinco %0,%1" - [(set_attr "type" "compare")]) - -(define_insn "" - [(set (reg:CC 36) - (compare (match_operand:SI 0 "arith_operand" "d") - (match_operand:SI 1 "arith_operand" "+d"))) - (set (match_dup 1) (minus:SI (match_dup 1) (const_int 1)))] - "0" - "cmpdeci %0,%1" - [(set_attr "type" "compare")]) - -(define_insn "" - [(set (reg:CC_UNS 36) - (compare (match_operand:SI 0 "arith_operand" "d") - (match_operand:SI 1 "arith_operand" "+d"))) - (set (match_dup 1) (minus:SI (match_dup 1) (const_int 1)))] - "0" - "cmpdeco %0,%1" - [(set_attr "type" "compare")]) - -;; Templates to store result of condition. -;; '1' is stored if condition is true. -;; '0' is stored if condition is false. -;; These should use predicate "general_operand", since -;; gcc seems to be creating mem references which use these -;; templates. - -(define_expand "seq" - [(set (match_operand:SI 0 "general_operand" "=d") - (eq:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_compare_reg (EQ, i960_compare_op0, i960_compare_op1); -}") - -(define_expand "sne" - [(set (match_operand:SI 0 "general_operand" "=d") - (ne:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_compare_reg (NE, i960_compare_op0, i960_compare_op1); -}") - -(define_expand "sgt" - [(set (match_operand:SI 0 "general_operand" "=d") - (gt:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_compare_reg (GT, i960_compare_op0, i960_compare_op1); -}") - -(define_expand "sgtu" - [(set (match_operand:SI 0 "general_operand" "=d") - (gtu:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_compare_reg (GTU, i960_compare_op0, i960_compare_op1); -}") - -(define_expand "slt" - [(set (match_operand:SI 0 "general_operand" "=d") - (lt:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_compare_reg (LT, i960_compare_op0, i960_compare_op1); -}") - -(define_expand "sltu" - [(set (match_operand:SI 0 "general_operand" "=d") - (ltu:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_compare_reg (LTU, i960_compare_op0, i960_compare_op1); -}") - -(define_expand "sge" - [(set (match_operand:SI 0 "general_operand" "=d") - (ge:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_compare_reg (GE, i960_compare_op0, i960_compare_op1); -}") - -(define_expand "sgeu" - [(set (match_operand:SI 0 "general_operand" "=d") - (geu:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_compare_reg (GEU, i960_compare_op0, i960_compare_op1); -}") - -(define_expand "sle" - [(set (match_operand:SI 0 "general_operand" "=d") - (le:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_compare_reg (LE, i960_compare_op0, i960_compare_op1); -}") - -(define_expand "sleu" - [(set (match_operand:SI 0 "general_operand" "=d") - (leu:SI (match_dup 1) (const_int 0)))] - "" - " -{ - operands[1] = gen_compare_reg (LEU, i960_compare_op0, i960_compare_op1); -}") - -(define_insn "" - [(set (match_operand:SI 0 "general_operand" "=d") - (eq:SI (match_operand:SI 1 "register_operand" "d") (const_int 0)))] - "" - "shro %1,1,%0" - [(set_attr "type" "alu2")]) - -(define_insn "" - [(set (match_operand:SI 0 "general_operand" "=d") - (match_operator:SI 1 "comparison_operator" [(reg:CC 36) (const_int 0)]))] - "" - "test%C1 %0" - [(set_attr "type" "compare")]) - -(define_insn "" - [(set (match_operand:SI 0 "general_operand" "=d") - (match_operator:SI 1 "comparison_operator" [(reg:CC_UNS 36) (const_int 0)]))] - "" - "test%C1 %0" - [(set_attr "type" "compare")]) - -;; These control RTL generation for conditional jump insns -;; and match them for register allocation. - -(define_expand "beq" - [(set (pc) - (if_then_else (eq (match_dup 1) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ operands[1] = gen_compare_reg (EQ, i960_compare_op0, i960_compare_op1); }") - -(define_expand "bne" - [(set (pc) - (if_then_else (ne (match_dup 1) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ operands[1] = gen_compare_reg (NE, i960_compare_op0, i960_compare_op1); }") - -(define_expand "bgt" - [(set (pc) - (if_then_else (gt (match_dup 1) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ operands[1] = gen_compare_reg (GT, i960_compare_op0, i960_compare_op1); }") - -(define_expand "bgtu" - [(set (pc) - (if_then_else (gtu (match_dup 1) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ operands[1] = gen_compare_reg (GTU, i960_compare_op0, i960_compare_op1); }") - -(define_expand "blt" - [(set (pc) - (if_then_else (lt (match_dup 1) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ operands[1] = gen_compare_reg (LT, i960_compare_op0, i960_compare_op1); }") - -(define_expand "bltu" - [(set (pc) - (if_then_else (ltu (match_dup 1) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ operands[1] = gen_compare_reg (LTU, i960_compare_op0, i960_compare_op1); }") - -(define_expand "bge" - [(set (pc) - (if_then_else (ge (match_dup 1) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ operands[1] = gen_compare_reg (GE, i960_compare_op0, i960_compare_op1); }") - -(define_expand "bgeu" - [(set (pc) - (if_then_else (geu (match_dup 1) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ operands[1] = gen_compare_reg (GEU, i960_compare_op0, i960_compare_op1); }") - -(define_expand "ble" - [(set (pc) - (if_then_else (le (match_dup 1) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ operands[1] = gen_compare_reg (LE, i960_compare_op0, i960_compare_op1); }") - -(define_expand "bleu" - [(set (pc) - (if_then_else (leu (match_dup 1) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ operands[1] = gen_compare_reg (LEU, i960_compare_op0, i960_compare_op1); }") - -;; Now the normal branch insns (forward and reverse). - -(define_insn "" - [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" - [(reg:CC 36) (const_int 0)]) - (label_ref (match_operand 1 "" "")) - (pc)))] - "" - "b%C0%+ %l1" - [(set_attr "type" "branch")]) - -(define_insn "" - [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" - [(reg:CC 36) (const_int 0)]) - (pc) - (label_ref (match_operand 1 "" ""))))] - "" - "b%I0%+ %l1" - [(set_attr "type" "branch")]) - -(define_insn "" - [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" - [(reg:CC_UNS 36) (const_int 0)]) - (label_ref (match_operand 1 "" "")) - (pc)))] - "" - "b%C0%+ %l1" - [(set_attr "type" "branch")]) - -(define_insn "" - [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" - [(reg:CC_UNS 36) (const_int 0)]) - (pc) - (label_ref (match_operand 1 "" ""))))] - "" - "b%I0%+ %l1" - [(set_attr "type" "branch")]) - -(define_insn "" - [(set (pc) - (if_then_else - (match_operator 0 "comparison_operator" - [(match_operand:SI 1 "arith_operand" "d") - (match_operand:SI 2 "arith_operand" "dI")]) - (label_ref (match_operand 3 "" "")) - (pc)))] - "" - "cmp%S0%B0%R0%+ %2,%1,%l3" - [(set_attr "type" "branch")]) - -(define_insn "" - [(set (pc) - (if_then_else - (match_operator 0 "comparison_operator" - [(match_operand:SI 1 "arith_operand" "d") - (match_operand:SI 2 "arith_operand" "dI")]) - (pc) - (label_ref (match_operand 3 "" ""))))] - "" - "cmp%S0%B0%X0%+ %2,%1,%l3" - [(set_attr "type" "branch")]) - -;; Now the trap instructions. The i960 appears to only have conditional -;; traps... - -(define_insn ("trap") - [(trap_if (const_int 1) (const_int 0))] - "" - "cmpo g0,g0 ; faulte.t") - -(define_expand "conditional_trap" - [(trap_if (match_operator 0 "comparison_operator" - [(match_dup 2) (const_int 0)]) - (match_operand 1 "const_int_operand" "i"))] - "" - " -{ - operands[2] = gen_compare_reg (GET_CODE (operands[0]), - i960_compare_op0, i960_compare_op1); -}") - -(define_insn "" - [(trap_if (match_operator 0 "comparison_operator" - [(reg:CC 36) (const_int 0)]) - (match_operand 1 "const_int_operand" "i"))] - "" - "fault%C0.f") - -(define_insn "" - [(trap_if (match_operator 0 "comparison_operator" - [(reg:CC_UNS 36) (const_int 0)]) - (match_operand 1 "const_int_operand" "i"))] - "" - "fault%C0.f") - -;; Normal move instructions. -;; This code is based on the sparc machine description. - -(define_expand "movsi" - [(set (match_operand:SI 0 "general_operand" "") - (match_operand:SI 1 "general_operand" ""))] - "" - " -{ - if (emit_move_sequence (operands, SImode)) - DONE; -}") - -;; The store case can not be separate, because reload may convert a register -;; to register move insn to a store (or load) insn without rerecognizing -;; the insn. - -;; The i960 does not have any store constant to memory instruction. However, -;; the calling convention is defined so that the arg pointer when it is not -;; overwise being used is zero. Thus, we can handle store zero to memory -;; by storing an unused arg pointer. The arg pointer will be unused if -;; current_function_args_size is zero and this is not a stdarg -;; function. This value of the former variable is not valid until after -;; all rtl generation is complete, including function inlining (because a -;; function that doesn't need an arg pointer may be inlined into a function -;; that does need an arg pointer), so we must also check that -;; rtx_equal_function_value_matters is zero. - -(define_insn "" - [(set (match_operand:SI 0 "general_operand" "=d,d,d,m") - (match_operand:SI 1 "general_operand" "dI,i,m,dJ"))] - "(current_function_args_size == 0 - && current_function_stdarg == 0 - && rtx_equal_function_value_matters == 0) - && (register_operand (operands[0], SImode) - || register_operand (operands[1], SImode) - || operands[1] == const0_rtx)" - "* -{ - switch (which_alternative) - { - case 0: - if (i960_last_insn_type == I_TYPE_REG && TARGET_C_SERIES) - { - if (GET_CODE (operands[1]) == REG) - return \"lda (%1),%0\"; - else - return \"lda %1,%0\"; - } - return \"mov %1,%0\"; - case 1: - return i960_output_ldconst (operands[0], operands[1]); - case 2: - return \"ld %1,%0\"; - case 3: - if (operands[1] == const0_rtx) - return \"st g14,%0\"; - return \"st %1,%0\"; - default: - abort(); - } -}" - [(set_attr "type" "move,address,load,store") - (set_attr "length" "*,3,*,*")]) - -(define_insn "" - [(set (match_operand:SI 0 "general_operand" "=d,d,d,m") - (match_operand:SI 1 "general_operand" "dI,i,m,d"))] - "(current_function_args_size != 0 - || current_function_stdarg != 0 - || rtx_equal_function_value_matters != 0) - && (register_operand (operands[0], SImode) - || register_operand (operands[1], SImode))" - "* -{ - switch (which_alternative) - { - case 0: - if (i960_last_insn_type == I_TYPE_REG && TARGET_C_SERIES) - { - if (GET_CODE (operands[1]) == REG) - return \"lda (%1),%0\"; - else - return \"lda %1,%0\"; - } - return \"mov %1,%0\"; - case 1: - return i960_output_ldconst (operands[0], operands[1]); - case 2: - return \"ld %1,%0\"; - case 3: - return \"st %1,%0\"; - default: - abort(); - } -}" - [(set_attr "type" "move,address,load,store") - (set_attr "length" "*,3,*,*")]) - -(define_expand "movhi" - [(set (match_operand:HI 0 "general_operand" "") - (match_operand:HI 1 "general_operand" ""))] - "" - " -{ - if (emit_move_sequence (operands, HImode)) - DONE; -}") - -;; Special pattern for zero stores to memory for functions which don't use -;; the arg pointer. - -;; The store case can not be separate. See above. -(define_insn "" - [(set (match_operand:HI 0 "general_operand" "=d,d,d,m") - (match_operand:HI 1 "general_operand" "dI,i,m,dJ"))] - "(current_function_args_size == 0 - && current_function_stdarg == 0 - && rtx_equal_function_value_matters == 0) - && (register_operand (operands[0], HImode) - || register_operand (operands[1], HImode) - || operands[1] == const0_rtx)" - "* -{ - switch (which_alternative) - { - case 0: - if (i960_last_insn_type == I_TYPE_REG && TARGET_C_SERIES) - { - if (GET_CODE (operands[1]) == REG) - return \"lda (%1),%0\"; - else - return \"lda %1,%0\"; - } - return \"mov %1,%0\"; - case 1: - return i960_output_ldconst (operands[0], operands[1]); - case 2: - return \"ldos %1,%0\"; - case 3: - if (operands[1] == const0_rtx) - return \"stos g14,%0\"; - return \"stos %1,%0\"; - default: - abort(); - } -}" - [(set_attr "type" "move,misc,load,store") - (set_attr "length" "*,3,*,*")]) - -;; The store case can not be separate. See above. -(define_insn "" - [(set (match_operand:HI 0 "general_operand" "=d,d,d,m") - (match_operand:HI 1 "general_operand" "dI,i,m,d"))] - "(current_function_args_size != 0 - || current_function_stdarg != 0 - || rtx_equal_function_value_matters != 0) - && (register_operand (operands[0], HImode) - || register_operand (operands[1], HImode))" - "* -{ - switch (which_alternative) - { - case 0: - if (i960_last_insn_type == I_TYPE_REG && TARGET_C_SERIES) - { - if (GET_CODE (operands[1]) == REG) - return \"lda (%1),%0\"; - else - return \"lda %1,%0\"; - } - return \"mov %1,%0\"; - case 1: - return i960_output_ldconst (operands[0], operands[1]); - case 2: - return \"ldos %1,%0\"; - case 3: - return \"stos %1,%0\"; - default: - abort(); - } -}" - [(set_attr "type" "move,misc,load,store") - (set_attr "length" "*,3,*,*")]) - -(define_expand "movqi" - [(set (match_operand:QI 0 "general_operand" "") - (match_operand:QI 1 "general_operand" ""))] - "" - " -{ - if (emit_move_sequence (operands, QImode)) - DONE; -}") - -;; The store case can not be separate. See comment above. -(define_insn "" - [(set (match_operand:QI 0 "general_operand" "=d,d,d,m") - (match_operand:QI 1 "general_operand" "dI,i,m,dJ"))] - "(current_function_args_size == 0 - && current_function_stdarg == 0 - && rtx_equal_function_value_matters == 0) - && (register_operand (operands[0], QImode) - || register_operand (operands[1], QImode) - || operands[1] == const0_rtx)" - "* -{ - switch (which_alternative) - { - case 0: - if (i960_last_insn_type == I_TYPE_REG && TARGET_C_SERIES) - { - if (GET_CODE (operands[1]) == REG) - return \"lda (%1),%0\"; - else - return \"lda %1,%0\"; - } - return \"mov %1,%0\"; - case 1: - return i960_output_ldconst (operands[0], operands[1]); - case 2: - return \"ldob %1,%0\"; - case 3: - if (operands[1] == const0_rtx) - return \"stob g14,%0\"; - return \"stob %1,%0\"; - default: - abort(); - } -}" - [(set_attr "type" "move,misc,load,store") - (set_attr "length" "*,3,*,*")]) - -;; The store case can not be separate. See comment above. -(define_insn "" - [(set (match_operand:QI 0 "general_operand" "=d,d,d,m") - (match_operand:QI 1 "general_operand" "dI,i,m,d"))] - "(current_function_args_size != 0 - || current_function_stdarg != 0 - || rtx_equal_function_value_matters != 0) - && (register_operand (operands[0], QImode) - || register_operand (operands[1], QImode))" - "* -{ - switch (which_alternative) - { - case 0: - if (i960_last_insn_type == I_TYPE_REG && TARGET_C_SERIES) - { - if (GET_CODE (operands[1]) == REG) - return \"lda (%1),%0\"; - else - return \"lda %1,%0\"; - } - return \"mov %1,%0\"; - case 1: - return i960_output_ldconst (operands[0], operands[1]); - case 2: - return \"ldob %1,%0\"; - case 3: - return \"stob %1,%0\"; - default: - abort(); - } -}" - [(set_attr "type" "move,misc,load,store") - (set_attr "length" "*,3,*,*")]) - -(define_expand "movdi" - [(set (match_operand:DI 0 "general_operand" "") - (match_operand:DI 1 "general_operand" ""))] - "" - " -{ - if (emit_move_sequence (operands, DImode)) - DONE; -}") - -;; The store case can not be separate. See comment above. -(define_insn "" - [(set (match_operand:DI 0 "general_operand" "=d,d,d,d,m,o") - (match_operand:DI 1 "general_operand" "d,I,i,m,d,J"))] - "(current_function_args_size == 0 - && current_function_stdarg == 0 - && rtx_equal_function_value_matters == 0) - && (register_operand (operands[0], DImode) - || register_operand (operands[1], DImode) - || operands[1] == const0_rtx)" - "* -{ - switch (which_alternative) - { - case 0: - case 1: - case 3: - case 4: - return i960_output_move_double (operands[0], operands[1]); - case 2: - return i960_output_ldconst (operands[0], operands[1]); - case 5: - return i960_output_move_double_zero (operands[0]); - default: - abort(); - } -}" - [(set_attr "type" "move,move,load,load,store,store")]) - -;; The store case can not be separate. See comment above. -(define_insn "" - [(set (match_operand:DI 0 "general_operand" "=d,d,d,d,m") - (match_operand:DI 1 "general_operand" "d,I,i,m,d"))] - "(current_function_args_size != 0 - || current_function_stdarg != 0 - || rtx_equal_function_value_matters != 0) - && (register_operand (operands[0], DImode) - || register_operand (operands[1], DImode))" - "* -{ - switch (which_alternative) - { - case 0: - case 1: - case 3: - case 4: - return i960_output_move_double (operands[0], operands[1]); - case 2: - return i960_output_ldconst (operands[0], operands[1]); - default: - abort(); - } -}" - [(set_attr "type" "move,move,load,load,store")]) - -(define_insn "*store_unaligned_di_reg" - [(set (match_operand:DI 0 "general_operand" "=d,m") - (match_operand:DI 1 "register_operand" "d,d")) - (clobber (match_scratch:SI 2 "=X,&d"))] - "" - "* -{ - if (which_alternative == 0) - return i960_output_move_double (operands[0], operands[1]); - - operands[3] = gen_rtx_MEM (word_mode, operands[2]); - operands[4] = adjust_address (operands[3], word_mode, UNITS_PER_WORD); - return \"lda %0,%2\;st %1,%3\;st %D1,%4\"; -}" - [(set_attr "type" "move,store")]) - -(define_expand "movti" - [(set (match_operand:TI 0 "general_operand" "") - (match_operand:TI 1 "general_operand" ""))] - "" - " -{ - if (emit_move_sequence (operands, TImode)) - DONE; -}") - -;; The store case can not be separate. See comment above. -(define_insn "" - [(set (match_operand:TI 0 "general_operand" "=d,d,d,d,m,o") - (match_operand:TI 1 "general_operand" "d,I,i,m,d,J"))] - "(current_function_args_size == 0 - && current_function_stdarg == 0 - && rtx_equal_function_value_matters == 0) - && (register_operand (operands[0], TImode) - || register_operand (operands[1], TImode) - || operands[1] == const0_rtx)" - "* -{ - switch (which_alternative) - { - case 0: - case 1: - case 3: - case 4: - return i960_output_move_quad (operands[0], operands[1]); - case 2: - return i960_output_ldconst (operands[0], operands[1]); - case 5: - return i960_output_move_quad_zero (operands[0]); - default: - abort(); - } -}" - [(set_attr "type" "move,move,load,load,store,store")]) - -;; The store case can not be separate. See comment above. -(define_insn "" - [(set (match_operand:TI 0 "general_operand" "=d,d,d,d,m") - (match_operand:TI 1 "general_operand" "d,I,i,m,d"))] - "(current_function_args_size != 0 - || current_function_stdarg != 0 - || rtx_equal_function_value_matters != 0) - && (register_operand (operands[0], TImode) - || register_operand (operands[1], TImode))" - "* -{ - switch (which_alternative) - { - case 0: - case 1: - case 3: - case 4: - return i960_output_move_quad (operands[0], operands[1]); - case 2: - return i960_output_ldconst (operands[0], operands[1]); - default: - abort(); - } -}" - [(set_attr "type" "move,move,load,load,store")]) - -(define_insn "*store_unaligned_ti_reg" - [(set (match_operand:TI 0 "general_operand" "=d,m") - (match_operand:TI 1 "register_operand" "d,d")) - (clobber (match_scratch:SI 2 "=X,&d"))] - "" - "* -{ - if (which_alternative == 0) - return i960_output_move_quad (operands[0], operands[1]); - - operands[3] = gen_rtx_MEM (word_mode, operands[2]); - operands[4] = adjust_address (operands[3], word_mode, UNITS_PER_WORD); - operands[5] = adjust_address (operands[4], word_mode, UNITS_PER_WORD); - operands[6] = adjust_address (operands[5], word_mode, UNITS_PER_WORD); - return \"lda %0,%2\;st %1,%3\;st %D1,%4\;st %E1,%5\;st %F1,%6\"; -}" - [(set_attr "type" "move,store")]) - -(define_expand "store_multiple" - [(set (match_operand:SI 0 "" "") ;;- dest - (match_operand:SI 1 "" "")) ;;- src - (use (match_operand:SI 2 "" ""))] ;;- nregs - "" - " -{ - int regno; - int count; - int offset = 0; - - if (GET_CODE (operands[0]) != MEM - || GET_CODE (operands[1]) != REG - || GET_CODE (operands[2]) != CONST_INT) - FAIL; - - count = INTVAL (operands[2]); - if (count > 12) - FAIL; - - regno = REGNO (operands[1]); - while (count >= 4 && ((regno & 3) == 0)) - { - emit_move_insn (adjust_address (operands[0], TImode, offset), - gen_rtx_REG (TImode, regno)); - count -= 4; - regno += 4; - offset += 16; - } - while (count >= 2 && ((regno & 1) == 0)) - { - emit_move_insn (adjust_address (operands[0], DImode, offset), - gen_rtx_REG (DImode, regno)); - count -= 2; - regno += 2; - offset += 8; - } - while (count > 0) - { - emit_move_insn (adjust_address (operands[0], SImode, offset), - gen_rtx_REG (SImode, regno)); - count -= 1; - regno += 1; - offset += 4; - } - DONE; -}") - -;; Floating point move insns - -(define_expand "movdf" - [(set (match_operand:DF 0 "general_operand" "") - (match_operand:DF 1 "fpmove_src_operand" ""))] - "" - " -{ - if (emit_move_sequence (operands, DFmode)) - DONE; -}") - -(define_insn "" - [(set (match_operand:DF 0 "general_operand" "=r,*f,d,d,m,o") - (match_operand:DF 1 "fpmove_src_operand" "r,GH,F,m,d,G"))] - "(current_function_args_size == 0 - && current_function_stdarg == 0 - && rtx_equal_function_value_matters == 0) - && (register_operand (operands[0], DFmode) - || register_operand (operands[1], DFmode) - || operands[1] == CONST0_RTX (DFmode))" - "* -{ - switch (which_alternative) - { - case 0: - if (FP_REG_P (operands[0]) || FP_REG_P (operands[1])) - return \"movrl %1,%0\"; - else - return \"movl %1,%0\"; - case 1: - return \"movrl %1,%0\"; - case 2: - return i960_output_ldconst (operands[0], operands[1]); - case 3: - return \"ldl %1,%0\"; - case 4: - return \"stl %1,%0\"; - case 5: - operands[1] = adjust_address (operands[0], VOIDmode, 4); - return \"st g14,%0\;st g14,%1\"; - default: - abort(); - } -}" - [(set_attr "type" "move,move,load,fpload,fpstore,fpstore")]) - -(define_insn "" - [(set (match_operand:DF 0 "general_operand" "=r,*f,d,d,m") - (match_operand:DF 1 "fpmove_src_operand" "r,GH,F,m,d"))] - "(current_function_args_size != 0 - || current_function_stdarg != 0 - || rtx_equal_function_value_matters != 0) - && (register_operand (operands[0], DFmode) - || register_operand (operands[1], DFmode))" - "* -{ - switch (which_alternative) - { - case 0: - if (FP_REG_P (operands[0]) || FP_REG_P (operands[1])) - return \"movrl %1,%0\"; - else - return \"movl %1,%0\"; - case 1: - return \"movrl %1,%0\"; - case 2: - return i960_output_ldconst (operands[0], operands[1]); - case 3: - return \"ldl %1,%0\"; - case 4: - return \"stl %1,%0\"; - default: - abort(); - } -}" - [(set_attr "type" "move,move,load,fpload,fpstore")]) - -(define_expand "movsf" - [(set (match_operand:SF 0 "general_operand" "") - (match_operand:SF 1 "fpmove_src_operand" ""))] - "" - " -{ - if (emit_move_sequence (operands, SFmode)) - DONE; -}") - -(define_insn "" - [(set (match_operand:SF 0 "general_operand" "=r,*f,d,d,m") - (match_operand:SF 1 "fpmove_src_operand" "r,GH,F,m,dG"))] - "(current_function_args_size == 0 - && current_function_stdarg == 0 - && rtx_equal_function_value_matters == 0) - && (register_operand (operands[0], SFmode) - || register_operand (operands[1], SFmode) - || operands[1] == CONST0_RTX (SFmode))" - "* -{ - switch (which_alternative) - { - case 0: - if (FP_REG_P (operands[0]) || FP_REG_P (operands[1])) - return \"movr %1,%0\"; - else - return \"mov %1,%0\"; - case 1: - return \"movr %1,%0\"; - case 2: - return i960_output_ldconst (operands[0], operands[1]); - case 3: - return \"ld %1,%0\"; - case 4: - if (operands[1] == CONST0_RTX (SFmode)) - return \"st g14,%0\"; - return \"st %1,%0\"; - default: - abort(); - } -}" - [(set_attr "type" "move,move,load,fpload,fpstore")]) - -(define_insn "" - [(set (match_operand:SF 0 "general_operand" "=r,*f,d,d,m") - (match_operand:SF 1 "fpmove_src_operand" "r,GH,F,m,d"))] - "(current_function_args_size != 0 - || current_function_stdarg != 0 - || rtx_equal_function_value_matters != 0) - && (register_operand (operands[0], SFmode) - || register_operand (operands[1], SFmode))" - "* -{ - switch (which_alternative) - { - case 0: - if (FP_REG_P (operands[0]) || FP_REG_P (operands[1])) - return \"movr %1,%0\"; - else - return \"mov %1,%0\"; - case 1: - return \"movr %1,%0\"; - case 2: - return i960_output_ldconst (operands[0], operands[1]); - case 3: - return \"ld %1,%0\"; - case 4: - return \"st %1,%0\"; - default: - abort(); - } -}" - [(set_attr "type" "move,move,load,fpload,fpstore")]) - -;; Mixed-mode moves with sign and zero-extension. - -;; Note that the one starting from HImode comes before those for QImode -;; so that a constant operand will match HImode, not QImode. - -(define_expand "extendhisi2" - [(set (match_operand:SI 0 "register_operand" "") - (sign_extend:SI - (match_operand:HI 1 "nonimmediate_operand" "")))] - "" - " -{ - if (GET_CODE (operand1) == REG - || (GET_CODE (operand1) == SUBREG - && GET_CODE (XEXP (operand1, 0)) == REG)) - { - rtx temp = gen_reg_rtx (SImode); - rtx shift_16 = GEN_INT (16); - int op1_subreg_byte = 0; - - if (GET_CODE (operand1) == SUBREG) - { - op1_subreg_byte = SUBREG_BYTE (operand1); - op1_subreg_byte /= GET_MODE_SIZE (SImode); - op1_subreg_byte *= GET_MODE_SIZE (SImode); - operand1 = SUBREG_REG (operand1); - } - if (GET_MODE (operand1) != SImode) - operand1 = gen_rtx (SUBREG, SImode, operand1, op1_subreg_byte); - - emit_insn (gen_ashlsi3 (temp, operand1, shift_16)); - emit_insn (gen_ashrsi3 (operand0, temp, shift_16)); - DONE; - } -}") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d") - (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))] - "" - "ldis %1,%0" - [(set_attr "type" "load")]) - -(define_expand "extendqisi2" - [(set (match_operand:SI 0 "register_operand" "") - (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))] - "" - " -{ - if (GET_CODE (operand1) == REG - || (GET_CODE (operand1) == SUBREG - && GET_CODE (XEXP (operand1, 0)) == REG)) - { - rtx temp = gen_reg_rtx (SImode); - rtx shift_24 = GEN_INT (24); - int op1_subreg_byte = 0; - - if (GET_CODE (operand1) == SUBREG) - { - op1_subreg_byte = SUBREG_BYTE (operand1); - op1_subreg_byte /= GET_MODE_SIZE (SImode); - op1_subreg_byte *= GET_MODE_SIZE (SImode); - operand1 = SUBREG_REG (operand1); - } - if (GET_MODE (operand1) != SImode) - operand1 = gen_rtx (SUBREG, SImode, operand1, op1_subreg_byte); - - emit_insn (gen_ashlsi3 (temp, operand1, shift_24)); - emit_insn (gen_ashrsi3 (operand0, temp, shift_24)); - DONE; - } -}") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d") - (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))] - "" - "ldib %1,%0" - [(set_attr "type" "load")]) - -(define_expand "extendqihi2" - [(set (match_operand:HI 0 "register_operand" "") - (sign_extend:HI - (match_operand:QI 1 "nonimmediate_operand" "")))] - "" - " -{ - if (GET_CODE (operand1) == REG - || (GET_CODE (operand1) == SUBREG - && GET_CODE (XEXP (operand1, 0)) == REG)) - { - rtx temp = gen_reg_rtx (SImode); - rtx shift_24 = GEN_INT (24); - int op0_subreg_byte = 0; - int op1_subreg_byte = 0; - - if (GET_CODE (operand1) == SUBREG) - { - op1_subreg_byte = SUBREG_BYTE (operand1); - op1_subreg_byte /= GET_MODE_SIZE (SImode); - op1_subreg_byte *= GET_MODE_SIZE (SImode); - operand1 = SUBREG_REG (operand1); - } - if (GET_MODE (operand1) != SImode) - operand1 = gen_rtx (SUBREG, SImode, operand1, op1_subreg_byte); - - if (GET_CODE (operand0) == SUBREG) - { - op0_subreg_byte = SUBREG_BYTE (operand0); - op0_subreg_byte /= GET_MODE_SIZE (SImode); - op0_subreg_byte *= GET_MODE_SIZE (SImode); - operand0 = SUBREG_REG (operand0); - } - if (GET_MODE (operand0) != SImode) - operand0 = gen_rtx_SUBREG (SImode, operand0, op0_subreg_byte); - - emit_insn (gen_ashlsi3 (temp, operand1, shift_24)); - emit_insn (gen_ashrsi3 (operand0, temp, shift_24)); - DONE; - } -}") - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=d") - (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))] - "" - "ldib %1,%0" - [(set_attr "type" "load")]) - -(define_expand "zero_extendhisi2" - [(set (match_operand:SI 0 "register_operand" "") - (zero_extend:SI - (match_operand:HI 1 "nonimmediate_operand" "")))] - "" - " -{ - if (GET_CODE (operand1) == REG - || (GET_CODE (operand1) == SUBREG - && GET_CODE (XEXP (operand1, 0)) == REG)) - { - rtx temp = gen_reg_rtx (SImode); - rtx shift_16 = GEN_INT (16); - int op1_subreg_byte = 0; - - if (GET_CODE (operand1) == SUBREG) - { - op1_subreg_byte = SUBREG_BYTE (operand1); - op1_subreg_byte /= GET_MODE_SIZE (SImode); - op1_subreg_byte *= GET_MODE_SIZE (SImode); - operand1 = SUBREG_REG (operand1); - } - if (GET_MODE (operand1) != SImode) - operand1 = gen_rtx (SUBREG, SImode, operand1, op1_subreg_byte); - - emit_insn (gen_ashlsi3 (temp, operand1, shift_16)); - emit_insn (gen_lshrsi3 (operand0, temp, shift_16)); - DONE; - } -}") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d") - (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))] - "" - "ldos %1,%0" - [(set_attr "type" "load")]) - -;; Using shifts here generates much better code than doing an `and 255'. -;; This is mainly because the `and' requires loading the constant separately, -;; the constant is likely to get optimized, and then the compiler can't -;; optimize the `and' because it doesn't know that one operand is a constant. - -(define_expand "zero_extendqisi2" - [(set (match_operand:SI 0 "register_operand" "") - (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))] - "" - " -{ - if (GET_CODE (operand1) == REG - || (GET_CODE (operand1) == SUBREG - && GET_CODE (XEXP (operand1, 0)) == REG)) - { - rtx temp = gen_reg_rtx (SImode); - rtx shift_24 = GEN_INT (24); - int op1_subreg_byte = 0; - - if (GET_CODE (operand1) == SUBREG) - { - op1_subreg_byte = SUBREG_BYTE (operand1); - op1_subreg_byte /= GET_MODE_SIZE (SImode); - op1_subreg_byte *= GET_MODE_SIZE (SImode); - operand1 = SUBREG_REG (operand1); - } - if (GET_MODE (operand1) != SImode) - operand1 = gen_rtx (SUBREG, SImode, operand1, op1_subreg_byte); - - emit_insn (gen_ashlsi3 (temp, operand1, shift_24)); - emit_insn (gen_lshrsi3 (operand0, temp, shift_24)); - DONE; - } -}") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d") - (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))] - "" - "ldob %1,%0" - [(set_attr "type" "load")]) - -(define_expand "zero_extendqihi2" - [(set (match_operand:HI 0 "register_operand" "") - (zero_extend:HI - (match_operand:QI 1 "nonimmediate_operand" "")))] - "" - " -{ - if (GET_CODE (operand1) == REG - || (GET_CODE (operand1) == SUBREG - && GET_CODE (XEXP (operand1, 0)) == REG)) - { - rtx temp = gen_reg_rtx (SImode); - rtx shift_24 = GEN_INT (24); - int op0_subreg_byte = 0; - int op1_subreg_byte = 0; - - if (GET_CODE (operand1) == SUBREG) - { - op1_subreg_byte = SUBREG_BYTE (operand1); - operand1 = SUBREG_REG (operand1); - } - if (GET_MODE (operand1) != SImode) - operand1 = gen_rtx (SUBREG, SImode, operand1, op1_subreg_byte); - - if (GET_CODE (operand0) == SUBREG) - { - op0_subreg_byte = SUBREG_BYTE (operand0); - operand0 = SUBREG_REG (operand0); - } - if (GET_MODE (operand0) != SImode) - operand0 = gen_rtx_SUBREG (SImode, operand0, op0_subreg_byte); - - emit_insn (gen_ashlsi3 (temp, operand1, shift_24)); - emit_insn (gen_lshrsi3 (operand0, temp, shift_24)); - DONE; - } -}") - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=d") - (zero_extend:HI (match_operand:QI 1 "memory_operand" "m")))] - "" - "ldob %1,%0" - [(set_attr "type" "load")]) - -;; Conversions between float and double. - -(define_insn "extendsfdf2" - [(set (match_operand:DF 0 "register_operand" "=*f,d") - (float_extend:DF (match_operand:SF 1 "fp_arith_operand" "dGH,fGH")))] - "TARGET_NUMERICS" - "@ - movr %1,%0 - movrl %1,%0" - [(set_attr "type" "fpmove")]) - -(define_insn "truncdfsf2" - [(set (match_operand:SF 0 "register_operand" "=d") - (float_truncate:SF - (match_operand:DF 1 "fp_arith_operand" "fGH")))] - "TARGET_NUMERICS" - "movr %1,%0" - [(set_attr "type" "fpmove")]) - -;; Conversion between fixed point and floating point. - -(define_insn "floatsidf2" - [(set (match_operand:DF 0 "register_operand" "=f") - (float:DF (match_operand:SI 1 "register_operand" "d")))] - "TARGET_NUMERICS" - "cvtir %1,%0" - [(set_attr "type" "fpcvt")]) - -(define_insn "floatsisf2" - [(set (match_operand:SF 0 "register_operand" "=d*f") - (float:SF (match_operand:SI 1 "register_operand" "d")))] - "TARGET_NUMERICS" - "cvtir %1,%0" - [(set_attr "type" "fpcvt")]) - -;; Convert a float to an actual integer. -;; Truncation is performed as part of the conversion. -;; The i960 requires conversion from DFmode to DImode to make -;; unsigned conversions work properly. - -(define_insn "fixuns_truncdfdi2" - [(set (match_operand:DI 0 "register_operand" "=d") - (unsigned_fix:DI (fix:DF (match_operand:DF 1 "fp_arith_operand" "fGH"))))] - "TARGET_NUMERICS" - "cvtzril %1,%0" - [(set_attr "type" "fpcvt")]) - -(define_insn "fixuns_truncsfdi2" - [(set (match_operand:DI 0 "register_operand" "=d") - (unsigned_fix:DI (fix:SF (match_operand:SF 1 "fp_arith_operand" "fGH"))))] - "TARGET_NUMERICS" - "cvtzril %1,%0" - [(set_attr "type" "fpcvt")]) - -(define_insn "fix_truncdfsi2" - [(set (match_operand:SI 0 "register_operand" "=d") - (fix:SI (fix:DF (match_operand:DF 1 "fp_arith_operand" "fGH"))))] - "TARGET_NUMERICS" - "cvtzri %1,%0" - [(set_attr "type" "fpcvt")]) - -(define_expand "fixuns_truncdfsi2" - [(set (match_operand:SI 0 "register_operand" "") - (unsigned_fix:SI (fix:DF (match_operand:DF 1 "fp_arith_operand" ""))))] - "TARGET_NUMERICS" - " -{ - rtx temp = gen_reg_rtx (DImode); - emit_insn (gen_rtx_SET (VOIDmode, temp, - gen_rtx_UNSIGNED_FIX (DImode, - gen_rtx_FIX (DFmode, - operands[1])))); - emit_insn (gen_rtx_SET (VOIDmode, operands[0], - gen_rtx_SUBREG (SImode, temp, 0))); - DONE; -}") - -(define_insn "fix_truncsfsi2" - [(set (match_operand:SI 0 "register_operand" "=d") - (fix:SI (fix:SF (match_operand:SF 1 "fp_arith_operand" "dfGH"))))] - "TARGET_NUMERICS" - "cvtzri %1,%0" - [(set_attr "type" "fpcvt")]) - -(define_expand "fixuns_truncsfsi2" - [(set (match_operand:SI 0 "register_operand" "") - (unsigned_fix:SI (fix:SF (match_operand:SF 1 "fp_arith_operand" ""))))] - "TARGET_NUMERICS" - " -{ - rtx temp = gen_reg_rtx (DImode); - emit_insn (gen_rtx_SET (VOIDmode, temp, - gen_rtx_UNSIGNED_FIX (DImode, - gen_rtx_FIX (SFmode, - operands[1])))); - emit_insn (gen_rtx_SET (VOIDmode, operands[0], - gen_rtx_SUBREG (SImode, temp, 0))); - DONE; -}") - -;; Arithmetic instructions. - -(define_insn "subsi3" - [(set (match_operand:SI 0 "register_operand" "=d") - (minus:SI (match_operand:SI 1 "arith_operand" "dI") - (match_operand:SI 2 "arith_operand" "dI")))] - "" - "subo %2,%1,%0") - -;; Try to generate an lda instruction when it would be faster than an -;; add instruction. -;; Some assemblers apparently won't accept two addresses added together. - -;; ??? The condition should be improved to reject the case of two -;; symbolic constants. - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d,d,d") - (plus:SI (match_operand:SI 1 "arith32_operand" "%dn,i,dn") - (match_operand:SI 2 "arith32_operand" "dn,dn,i")))] - "(TARGET_C_SERIES) && (CONSTANT_P (operands[1]) || CONSTANT_P (operands[2]))" - "* -{ - if (GET_CODE (operands[1]) == CONST_INT) - { - rtx tmp = operands[1]; - operands[1] = operands[2]; - operands[2] = tmp; - } - if (GET_CODE (operands[2]) == CONST_INT - && GET_CODE (operands[1]) == REG - && i960_last_insn_type != I_TYPE_REG) - { - if (INTVAL (operands[2]) < 0 && INTVAL (operands[2]) > -32) - return \"subo %n2,%1,%0\"; - else if (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32) - return \"addo %1,%2,%0\"; - } - /* Non-canonical results (op1 == const, op2 != const) have been seen - in reload output when both operands were symbols before reload, so - we deal with it here. This may be a fault of the constraints above. */ - if (CONSTANT_P (operands[1])) - { - if (CONSTANT_P (operands[2])) - return \"lda %1+%2,%0\"; - else - return \"lda %1(%2),%0\"; - } - return \"lda %2(%1),%0\"; -}") - -(define_insn "addsi3" - [(set (match_operand:SI 0 "register_operand" "=d") - (plus:SI (match_operand:SI 1 "signed_arith_operand" "%dI") - (match_operand:SI 2 "signed_arith_operand" "dIK")))] - "" - "* -{ - if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0) - return \"subo %n2,%1,%0\"; - if (i960_bypass (insn, operands[1], operands[2], 0)) - return \"addo %2,%1,%0\"; - return \"addo %1,%2,%0\"; -}") - -(define_insn "mulsi3" - [(set (match_operand:SI 0 "register_operand" "=d") - (mult:SI (match_operand:SI 1 "arith_operand" "%dI") - (match_operand:SI 2 "arith_operand" "dI")))] - "" - "* -{ - if (i960_bypass (insn, operands[1], operands[2], 0)) - return \"mulo %2,%1,%0\"; - return \"mulo %1,%2,%0\"; -}" - [(set_attr "type" "mult")]) - -(define_insn "umulsidi3" - [(set (match_operand:DI 0 "register_operand" "=d") - (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "d")) - (zero_extend:DI (match_operand:SI 2 "register_operand" "d"))))] - "" - "* -{ - if (i960_bypass (insn, operands[1], operands[2], 0)) - return \"emul %2,%1,%0\"; - return \"emul %1,%2,%0\"; -}" - [(set_attr "type" "mult")]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=d") - (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%d")) - (match_operand:SI 2 "literal" "I")))] - "" - "* -{ - if (i960_bypass (insn, operands[1], operands[2], 0)) - return \"emul %2,%1,%0\"; - return \"emul %1,%2,%0\"; -}" - [(set_attr "type" "mult")]) - -;; This goes after the move/add/sub/mul instructions -;; because those instructions are better when they apply. - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d") - (match_operand:SI 1 "address_operand" "p"))] - "" - "lda %a1,%0" - [(set_attr "type" "load")]) - -;; This will never be selected because of an "optimization" that GCC does. -;; It always converts divides by a power of 2 into a sequence of instructions -;; that does a right shift, and then corrects the result if it was negative. - -;; (define_insn "" -;; [(set (match_operand:SI 0 "register_operand" "=d") -;; (div:SI (match_operand:SI 1 "arith_operand" "dI") -;; (match_operand:SI 2 "power2_operand" "nI")))] -;; "" -;; "*{ -;; operands[2] = GEN_INT (bitpos (INTVAL (operands[2]))); -;; return \"shrdi %2,%1,%0\"; -;; }" - -(define_insn "divsi3" - [(set (match_operand:SI 0 "register_operand" "=d") - (div:SI (match_operand:SI 1 "arith_operand" "dI") - (match_operand:SI 2 "arith_operand" "dI")))] - "" - "divi %2,%1,%0" - [(set_attr "type" "div")]) - -(define_insn "udivsi3" - [(set (match_operand:SI 0 "register_operand" "=d") - (udiv:SI (match_operand:SI 1 "arith_operand" "dI") - (match_operand:SI 2 "arith_operand" "dI")))] - "" - "divo %2,%1,%0" - [(set_attr "type" "div")]) - -;; We must use `remi' not `modi' here, to ensure that `%' has the effects -;; specified by the ANSI C standard. - -(define_insn "modsi3" - [(set (match_operand:SI 0 "register_operand" "=d") - (mod:SI (match_operand:SI 1 "arith_operand" "dI") - (match_operand:SI 2 "arith_operand" "dI")))] - "" - "remi %2,%1,%0" - [(set_attr "type" "div")]) - -(define_insn "umodsi3" - [(set (match_operand:SI 0 "register_operand" "=d") - (umod:SI (match_operand:SI 1 "arith_operand" "dI") - (match_operand:SI 2 "arith_operand" "dI")))] - "" - "remo %2,%1,%0" - [(set_attr "type" "div")]) - -;; And instructions (with complement also). - -(define_insn "andsi3" - [(set (match_operand:SI 0 "register_operand" "=d") - (and:SI (match_operand:SI 1 "register_operand" "%d") - (match_operand:SI 2 "logic_operand" "dIM")))] - "" - "* -{ - if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0) - return \"andnot %C2,%1,%0\"; - if (i960_bypass (insn, operands[1], operands[2], 0)) - return \"and %2,%1,%0\"; - return \"and %1,%2,%0\"; -}") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d") - (and:SI (match_operand:SI 1 "arith_operand" "dI") - (match_operand:SI 2 "cmplpower2_operand" "n")))] - "" - "* -{ - operands[2] = GEN_INT (bitpos (~INTVAL (operands[2]))); - return \"clrbit %2,%1,%0\"; -}") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d") - (and:SI (not:SI (match_operand:SI 1 "register_operand" "d")) - (match_operand:SI 2 "logic_operand" "dIM")))] - "" - "* -{ - if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0) - return \"nor %C2,%1,%0\"; - if (i960_bypass (insn, operands[1], operands[2], 0)) - return \"notand %2,%1,%0\"; - return \"andnot %1,%2,%0\"; -}") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d") - (ior:SI (not:SI (match_operand:SI 1 "register_operand" "%d")) - (not:SI (match_operand:SI 2 "register_operand" "d"))))] - "" - "* -{ - if (i960_bypass (insn, operands[1], operands[2], 0)) - return \"nand %2,%1,%0\"; - return \"nand %1,%2,%0\"; -}") - -(define_insn "iorsi3" - [(set (match_operand:SI 0 "register_operand" "=d") - (ior:SI (match_operand:SI 1 "register_operand" "%d") - (match_operand:SI 2 "logic_operand" "dIM")))] - "" - "* -{ - if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0) - return \"ornot %C2,%1,%0\"; - if (i960_bypass (insn, operands[1], operands[2], 0)) - return \"or %2,%1,%0\"; - return \"or %1,%2,%0\"; -}") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d") - (ior:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "power2_operand" "n")))] - "" - "* -{ - operands[2] = GEN_INT (bitpos (INTVAL (operands[2]))); - return \"setbit %2,%1,%0\"; -}") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d") - (ior:SI (not:SI (match_operand:SI 1 "register_operand" "d")) - (match_operand:SI 2 "logic_operand" "dIM")))] - "" - "* -{ - if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0) - return \"nand %C2,%1,%0\"; - if (i960_bypass (insn, operands[1], operands[2], 0)) - return \"notor %2,%1,%0\"; - return \"ornot %1,%2,%0\"; -}") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d") - (and:SI (not:SI (match_operand:SI 1 "register_operand" "%d")) - (not:SI (match_operand:SI 2 "register_operand" "d"))))] - "" - "* -{ - if (i960_bypass (insn, operands[1], operands[2], 0)) - return \"nor %2,%1,%0\"; - return \"nor %1,%2,%0\"; -}") - -(define_insn "xorsi3" - [(set (match_operand:SI 0 "register_operand" "=d") - (xor:SI (match_operand:SI 1 "register_operand" "%d") - (match_operand:SI 2 "logic_operand" "dIM")))] - "" - "* -{ - if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0) - return \"xnor %C2,%1,%0\"; - if (i960_bypass (insn, operands[1], operands[2], 0)) - return \"xor %2,%1,%0\"; - return \"xor %1,%2,%0\"; -}") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d") - (xor:SI (match_operand:SI 1 "arith_operand" "dI") - (match_operand:SI 2 "power2_operand" "n")))] - "" - "* -{ - operands[2] = GEN_INT (bitpos (INTVAL (operands[2]))); - return \"notbit %2,%1,%0\"; -}") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d") - (not:SI (xor:SI (match_operand:SI 1 "register_operand" "%d") - (match_operand:SI 2 "register_operand" "d"))))] - "" - "* -{ - if (i960_bypass (insn, operands[1], operands[2], 0)) - return \"xnor %2,%1,%0\"; - return \"xnor %2,%1,%0\"; -}") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d") - (ior:SI (ashift:SI (const_int 1) - (match_operand:SI 1 "register_operand" "d")) - (match_operand:SI 2 "arith_operand" "dI")))] - "" - "setbit %1,%2,%0") - -;; (not (ashift 1 reg)) canonicalizes to (rotate -2 reg) -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d") - (and:SI (rotate:SI (const_int -2) - (match_operand:SI 1 "register_operand" "d")) - (match_operand:SI 2 "register_operand" "d")))] - "" - "clrbit %1,%2,%0") - -;; The above pattern canonicalizes to this when both the input and output -;; are the same pseudo-register. -(define_insn "" - [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+d") - (const_int 1) - (match_operand:SI 1 "register_operand" "d")) - (const_int 0))] - "" - "clrbit %1,%0,%0") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d") - (xor:SI (ashift:SI (const_int 1) - (match_operand:SI 1 "register_operand" "d")) - (match_operand:SI 2 "arith_operand" "dI")))] - "" - "notbit %1,%2,%0") - -(define_insn "negsi2" - [(set (match_operand:SI 0 "register_operand" "=d") - (neg:SI (match_operand:SI 1 "arith_operand" "dI")))] - "" - "subo %1,0,%0" - [(set_attr "length" "1")]) - -(define_insn "one_cmplsi2" - [(set (match_operand:SI 0 "register_operand" "=d") - (not:SI (match_operand:SI 1 "arith_operand" "dI")))] - "" - "not %1,%0" - [(set_attr "length" "1")]) - -;; Floating point arithmetic instructions. - -(define_insn "adddf3" - [(set (match_operand:DF 0 "register_operand" "=d*f") - (plus:DF (match_operand:DF 1 "fp_arith_operand" "%rGH") - (match_operand:DF 2 "fp_arith_operand" "rGH")))] - "TARGET_NUMERICS" - "addrl %1,%2,%0" - [(set_attr "type" "fpadd")]) - -(define_insn "addsf3" - [(set (match_operand:SF 0 "register_operand" "=d*f") - (plus:SF (match_operand:SF 1 "fp_arith_operand" "%rGH") - (match_operand:SF 2 "fp_arith_operand" "rGH")))] - "TARGET_NUMERICS" - "addr %1,%2,%0" - [(set_attr "type" "fpadd")]) - - -(define_insn "subdf3" - [(set (match_operand:DF 0 "register_operand" "=d*f") - (minus:DF (match_operand:DF 1 "fp_arith_operand" "rGH") - (match_operand:DF 2 "fp_arith_operand" "rGH")))] - "TARGET_NUMERICS" - "subrl %2,%1,%0" - [(set_attr "type" "fpadd")]) - -(define_insn "subsf3" - [(set (match_operand:SF 0 "register_operand" "=d*f") - (minus:SF (match_operand:SF 1 "fp_arith_operand" "rGH") - (match_operand:SF 2 "fp_arith_operand" "rGH")))] - "TARGET_NUMERICS" - "subr %2,%1,%0" - [(set_attr "type" "fpadd")]) - - -(define_insn "muldf3" - [(set (match_operand:DF 0 "register_operand" "=d*f") - (mult:DF (match_operand:DF 1 "fp_arith_operand" "%rGH") - (match_operand:DF 2 "fp_arith_operand" "rGH")))] - "TARGET_NUMERICS" - "mulrl %1,%2,%0" - [(set_attr "type" "fpmul")]) - -(define_insn "mulsf3" - [(set (match_operand:SF 0 "register_operand" "=d*f") - (mult:SF (match_operand:SF 1 "fp_arith_operand" "%rGH") - (match_operand:SF 2 "fp_arith_operand" "rGH")))] - "TARGET_NUMERICS" - "mulr %1,%2,%0" - [(set_attr "type" "fpmul")]) - - -(define_insn "divdf3" - [(set (match_operand:DF 0 "register_operand" "=d*f") - (div:DF (match_operand:DF 1 "fp_arith_operand" "rGH") - (match_operand:DF 2 "fp_arith_operand" "rGH")))] - "TARGET_NUMERICS" - "divrl %2,%1,%0" - [(set_attr "type" "fpdiv")]) - -(define_insn "divsf3" - [(set (match_operand:SF 0 "register_operand" "=d*f") - (div:SF (match_operand:SF 1 "fp_arith_operand" "rGH") - (match_operand:SF 2 "fp_arith_operand" "rGH")))] - "TARGET_NUMERICS" - "divr %2,%1,%0" - [(set_attr "type" "fpdiv")]) - -(define_insn "negdf2" - [(set (match_operand:DF 0 "register_operand" "=d,d*f") - (neg:DF (match_operand:DF 1 "register_operand" "d,r")))] - "" - "* -{ - if (which_alternative == 0) - { - if (REGNO (operands[0]) == REGNO (operands[1])) - return \"notbit 31,%D1,%D0\"; - return \"mov %1,%0\;notbit 31,%D1,%D0\"; - } - return \"subrl %1,0f0.0,%0\"; -}" - [(set_attr "type" "fpadd")]) - -(define_insn "negsf2" - [(set (match_operand:SF 0 "register_operand" "=d,d*f") - (neg:SF (match_operand:SF 1 "register_operand" "d,r")))] - "" - "@ - notbit 31,%1,%0 - subr %1,0f0.0,%0" - [(set_attr "type" "fpadd")]) - -;;; The abs patterns also work even if the target machine doesn't have -;;; floating point, because in that case dstreg and srcreg will always be -;;; less than 32. - -(define_insn "absdf2" - [(set (match_operand:DF 0 "register_operand" "=d*f") - (abs:DF (match_operand:DF 1 "register_operand" "df")))] - "" - "* -{ - int dstreg = REGNO (operands[0]); - int srcreg = REGNO (operands[1]); - - if (dstreg < 32) - { - if (srcreg < 32) - { - if (dstreg != srcreg) - output_asm_insn (\"mov %1,%0\", operands); - return \"clrbit 31,%D1,%D0\"; - } - /* Src is an fp reg. */ - return \"movrl %1,%0\;clrbit 31,%D1,%D0\"; - } - if (srcreg >= 32) - return \"cpysre %1,0f0.0,%0\"; - return \"movrl %1,%0\;cpysre %0,0f0.0,%0\"; -}" - [(set_attr "type" "multi")]) - -(define_insn "abssf2" - [(set (match_operand:SF 0 "register_operand" "=d*f") - (abs:SF (match_operand:SF 1 "register_operand" "df")))] - "" - "* -{ - int dstreg = REGNO (operands[0]); - int srcreg = REGNO (operands[1]); - - if (dstreg < 32 && srcreg < 32) - return \"clrbit 31,%1,%0\"; - - if (dstreg >= 32 && srcreg >= 32) - return \"cpysre %1,0f0.0,%0\"; - - if (dstreg < 32) - return \"movr %1,%0\;clrbit 31,%0,%0\"; - - return \"movr %1,%0\;cpysre %0,0f0.0,%0\"; -}" - [(set_attr "type" "multi")]) - -;; Tetra (16 byte) float support. - -(define_expand "cmptf" - [(set (reg:CC 36) - (compare:CC (match_operand:TF 0 "register_operand" "") - (match_operand:TF 1 "nonmemory_operand" "")))] - "TARGET_NUMERICS" - " -{ - i960_compare_op0 = operands[0]; - i960_compare_op1 = operands[1]; - DONE; -}") - -(define_insn "" - [(set (reg:CC 36) - (compare:CC (match_operand:TF 0 "register_operand" "f") - (match_operand:TF 1 "nonmemory_operand" "fGH")))] - "TARGET_NUMERICS" - "cmpr %0,%1" - [(set_attr "type" "fpcc")]) - -(define_expand "movtf" - [(set (match_operand:TF 0 "general_operand" "") - (match_operand:TF 1 "fpmove_src_operand" ""))] - "" - " -{ - if (emit_move_sequence (operands, TFmode)) - DONE; -}") - -(define_insn "" - [(set (match_operand:TF 0 "general_operand" "=r,f,d,d,m") - (match_operand:TF 1 "fpmove_src_operand" "r,GH,F,m,d"))] - "register_operand (operands[0], TFmode) - || register_operand (operands[1], TFmode)" - "* -{ - switch (which_alternative) - { - case 0: - if (FP_REG_P (operands[0]) || FP_REG_P (operands[1])) - return \"movre %1,%0\"; - else - return \"movq %1,%0\"; - case 1: - return \"movre %1,%0\"; - case 2: - return i960_output_ldconst (operands[0], operands[1]); - case 3: - return \"ldt %1,%0\"; - case 4: - return \"stt %1,%0\"; - default: - abort(); - } -}" - [(set_attr "type" "move,move,load,fpload,fpstore")]) - -(define_insn "extendsftf2" - [(set (match_operand:TF 0 "register_operand" "=f,d") - (float_extend:TF - (match_operand:SF 1 "register_operand" "d,f")))] - "TARGET_NUMERICS" - "@ - movr %1,%0 - movre %1,%0" - [(set_attr "type" "fpmove")]) - -(define_insn "extenddftf2" - [(set (match_operand:TF 0 "register_operand" "=f,d") - (float_extend:TF - (match_operand:DF 1 "register_operand" "d,f")))] - "TARGET_NUMERICS" - "@ - movrl %1,%0 - movre %1,%0" - [(set_attr "type" "fpmove")]) - -(define_insn "trunctfdf2" - [(set (match_operand:DF 0 "register_operand" "=d") - (float_truncate:DF - (match_operand:TF 1 "register_operand" "f")))] - "TARGET_NUMERICS" - "movrl %1,%0" - [(set_attr "type" "fpmove")]) - -(define_insn "trunctfsf2" - [(set (match_operand:SF 0 "register_operand" "=d") - (float_truncate:SF - (match_operand:TF 1 "register_operand" "f")))] - "TARGET_NUMERICS" - "movr %1,%0" - [(set_attr "type" "fpmove")]) - -(define_insn "floatsitf2" - [(set (match_operand:TF 0 "register_operand" "=f") - (float:TF (match_operand:SI 1 "register_operand" "d")))] - "TARGET_NUMERICS" - "cvtir %1,%0" - [(set_attr "type" "fpcvt")]) - -(define_insn "fix_trunctfsi2" - [(set (match_operand:SI 0 "register_operand" "=d") - (fix:SI (fix:TF (match_operand:TF 1 "register_operand" "f"))))] - "TARGET_NUMERICS" - "cvtzri %1,%0" - [(set_attr "type" "fpcvt")]) - -(define_insn "fixuns_trunctfsi2" - [(set (match_operand:SI 0 "register_operand" "=d") - (unsigned_fix:SI (fix:TF (match_operand:TF 1 "register_operand" "f"))))] - "TARGET_NUMERICS" - "cvtzri %1,%0" - [(set_attr "type" "fpcvt")]) - -(define_insn "addtf3" - [(set (match_operand:TF 0 "register_operand" "=f") - (plus:TF (match_operand:TF 1 "nonmemory_operand" "%fGH") - (match_operand:TF 2 "nonmemory_operand" "fGH")))] - "TARGET_NUMERICS" - "addr %1,%2,%0" - [(set_attr "type" "fpadd")]) - -(define_insn "subtf3" - [(set (match_operand:TF 0 "register_operand" "=f") - (minus:TF (match_operand:TF 1 "nonmemory_operand" "fGH") - (match_operand:TF 2 "nonmemory_operand" "fGH")))] - "TARGET_NUMERICS" - "subr %2,%1,%0" - [(set_attr "type" "fpadd")]) - -(define_insn "multf3" - [(set (match_operand:TF 0 "register_operand" "=f") - (mult:TF (match_operand:TF 1 "nonmemory_operand" "%fGH") - (match_operand:TF 2 "nonmemory_operand" "fGH")))] - "TARGET_NUMERICS" - "mulr %1,%2,%0" - [(set_attr "type" "fpmul")]) - -(define_insn "divtf3" - [(set (match_operand:TF 0 "register_operand" "=f") - (div:TF (match_operand:TF 1 "nonmemory_operand" "fGH") - (match_operand:TF 2 "nonmemory_operand" "fGH")))] - "TARGET_NUMERICS" - "divr %2,%1,%0" - [(set_attr "type" "fpdiv")]) - -(define_insn "negtf2" - [(set (match_operand:TF 0 "register_operand" "=f") - (neg:TF (match_operand:TF 1 "register_operand" "f")))] - "TARGET_NUMERICS" - "subr %1,0f0.0,%0" - [(set_attr "type" "fpadd")]) - -(define_insn "abstf2" - [(set (match_operand:TF 0 "register_operand" "=f") - (abs:TF (match_operand:TF 1 "register_operand" "f")))] - "(TARGET_NUMERICS)" - "cpysre %1,0f0.0,%0" - [(set_attr "type" "fpmove")]) - -;; Arithmetic shift instructions. - -;; The shli instruction generates an overflow fault if the sign changes. -;; In the case of overflow, it does not give the natural result, it instead -;; gives the last shift value before the overflow. We can not use this -;; instruction because gcc thinks that arithmetic left shift and logical -;; left shift are identical, and sometimes canonicalizes the logical left -;; shift to an arithmetic left shift. Therefore we must always use the -;; logical left shift instruction. - -(define_insn "ashlsi3" - [(set (match_operand:SI 0 "register_operand" "=d") - (ashift:SI (match_operand:SI 1 "arith_operand" "dI") - (match_operand:SI 2 "arith_operand" "dI")))] - "" - "shlo %2,%1,%0" - [(set_attr "type" "alu2")]) - -(define_insn "ashrsi3" - [(set (match_operand:SI 0 "register_operand" "=d") - (ashiftrt:SI (match_operand:SI 1 "arith_operand" "dI") - (match_operand:SI 2 "arith_operand" "dI")))] - "" - "shri %2,%1,%0" - [(set_attr "type" "alu2")]) - -(define_insn "lshrsi3" - [(set (match_operand:SI 0 "register_operand" "=d") - (lshiftrt:SI (match_operand:SI 1 "arith_operand" "dI") - (match_operand:SI 2 "arith_operand" "dI")))] - "" - "shro %2,%1,%0" - [(set_attr "type" "alu2")]) - -;; Unconditional and other jump instructions. - -(define_insn "jump" - [(set (pc) - (label_ref (match_operand 0 "" "")))] - "" - "b %l0" - [(set_attr "type" "branch")]) - -(define_insn "indirect_jump" - [(set (pc) (match_operand:SI 0 "address_operand" "p"))] - "" - "bx %a0" - [(set_attr "type" "branch")]) - -(define_insn "tablejump" - [(set (pc) (match_operand:SI 0 "register_operand" "d")) - (use (label_ref (match_operand 1 "" "")))] - "" - "* -{ - if (flag_pic) - return \"bx %l1(%0)\"; - else - return \"bx (%0)\"; -}" - [(set_attr "type" "branch")]) - -;;- jump to subroutine - -(define_expand "call" - [(call (match_operand:SI 0 "memory_operand" "m") - (match_operand:SI 1 "immediate_operand" "i"))] - "" - " -{ - emit_call_insn (gen_call_internal (operands[0], operands[1], - virtual_outgoing_args_rtx)); - DONE; -}") - -;; We need a call saved register allocated for the match_scratch, so we use -;; 'l' because all local registers are call saved. - -;; ??? I would prefer to use a match_scratch here, but match_scratch allocated -;; registers can't be used for spills. In a function with lots of calls, -;; local-alloc may allocate all local registers to a match_scratch, leaving -;; no local registers available for spills. - -(define_insn "call_internal" - [(call (match_operand:SI 0 "memory_operand" "m") - (match_operand:SI 1 "immediate_operand" "i")) - (use (match_operand:SI 2 "address_operand" "p")) - (clobber (reg:SI 19))] - "" - "* return i960_output_call_insn (operands[0], operands[1], operands[2], - insn);" - [(set_attr "type" "call")]) - -(define_expand "call_value" - [(set (match_operand 0 "register_operand" "=d") - (call (match_operand:SI 1 "memory_operand" "m") - (match_operand:SI 2 "immediate_operand" "i")))] - "" - " -{ - emit_call_insn (gen_call_value_internal (operands[0], operands[1], - operands[2], - virtual_outgoing_args_rtx)); - DONE; -}") - -;; We need a call saved register allocated for the match_scratch, so we use -;; 'l' because all local registers are call saved. - -(define_insn "call_value_internal" - [(set (match_operand 0 "register_operand" "=d") - (call (match_operand:SI 1 "memory_operand" "m") - (match_operand:SI 2 "immediate_operand" "i"))) - (use (match_operand:SI 3 "address_operand" "p")) - (clobber (reg:SI 19))] - "" - "* return i960_output_call_insn (operands[1], operands[2], operands[3], - insn);" - [(set_attr "type" "call")]) - -(define_insn "return" - [(return)] - "" - "* return i960_output_ret_insn (insn);" - [(set_attr "type" "branch")]) - -;; A return instruction. Used only by nonlocal_goto to change the -;; stack pointer, frame pointer, previous frame pointer and the return -;; instruction pointer. -(define_insn "ret" - [(set (pc) (unspec_volatile [(reg:SI 16)] 3))] - "" - "ret" - [(set_attr "type" "branch") - (set_attr "length" "1")]) - -(define_expand "nonlocal_goto" - [(match_operand:SI 0 "" "") - (match_operand:SI 1 "general_operand" "") - (match_operand:SI 2 "general_operand" "") - (match_operand:SI 3 "general_operand" "")] - "" - " -{ - rtx chain = operands[0]; - rtx handler = operands[1]; - rtx stack = operands[2]; - - /* We must restore the stack pointer, frame pointer, previous frame - pointer and the return instruction pointer. Since the ret - instruction does all this for us with one instruction, we arrange - everything so that ret will do everything we need done. */ - - /* First, we must flush the register windows, so that we can modify - the saved local registers on the stack directly and because we - are going to change the previous frame pointer. */ - - emit_insn (gen_flush_register_windows ()); - - /* Load the static chain value for the containing fn into fp. This is needed - because STACK refers to fp. */ - emit_move_insn (hard_frame_pointer_rtx, chain); - - /* Now move the adjusted value into the pfp register for the following return - instruction. */ - emit_move_insn (gen_rtx (REG, SImode, 16), - plus_constant (hard_frame_pointer_rtx, -64)); - - /* Next, we put the address that we want to transfer to, into the - saved $rip value in the frame. Once we ret below, that value - will be loaded into the pc (IP). */ - - emit_move_insn (gen_rtx (MEM, SImode, - plus_constant (hard_frame_pointer_rtx, -56)), - handler); - - /* Next, we put stack into the saved $sp value in the frame. */ - emit_move_insn (gen_rtx (MEM, SImode, - plus_constant (hard_frame_pointer_rtx, -60)), - stack); - - /* And finally, we can now just ret to get all the values saved - above into all the right registers, and also, all the local - register that were in use in the function, are restored from - their saved values (from the call instruction) on the stack - because we are very careful to ret from the exact save area in - use during the original call. */ - - emit_jump_insn (gen_ret ()); - emit_barrier (); - DONE; -}") - -;; Special insn to flush register windows. -(define_insn "flush_register_windows" - [(unspec_volatile [(const_int 0)] 1)] - "" - "flushreg" - [(set_attr "type" "misc") - (set_attr "length" "1")]) - -(define_insn "nop" - [(const_int 0)] - "" - "") - -;; Various peephole optimizations for multiple-word moves, loads, and stores. -;; Multiple register moves. - -;; Matched 5/28/91 -(define_peephole - [(set (match_operand:SI 0 "register_operand" "=r") - (match_operand:SI 1 "register_operand" "r")) - (set (match_operand:SI 2 "register_operand" "=r") - (match_operand:SI 3 "register_operand" "r")) - (set (match_operand:SI 4 "register_operand" "=r") - (match_operand:SI 5 "register_operand" "r")) - (set (match_operand:SI 6 "register_operand" "=r") - (match_operand:SI 7 "register_operand" "r"))] - "((REGNO (operands[0]) & 3) == 0) - && ((REGNO (operands[1]) & 3) == 0) - && (REGNO (operands[0]) + 1 == REGNO (operands[2])) - && (REGNO (operands[1]) + 1 == REGNO (operands[3])) - && (REGNO (operands[0]) + 2 == REGNO (operands[4])) - && (REGNO (operands[1]) + 2 == REGNO (operands[5])) - && (REGNO (operands[0]) + 3 == REGNO (operands[6])) - && (REGNO (operands[1]) + 3 == REGNO (operands[7]))" - "movq %1,%0") - -;; Matched 4/17/92 -(define_peephole - [(set (match_operand:DI 0 "register_operand" "=r") - (match_operand:DI 1 "register_operand" "r")) - (set (match_operand:DI 2 "register_operand" "=r") - (match_operand:DI 3 "register_operand" "r"))] - "((REGNO (operands[0]) & 3) == 0) - && ((REGNO (operands[1]) & 3) == 0) - && (REGNO (operands[0]) + 2 == REGNO (operands[2])) - && (REGNO (operands[1]) + 2 == REGNO (operands[3]))" - "movq %1,%0") - -;; Matched 4/17/92 -(define_peephole - [(set (match_operand:DI 0 "register_operand" "=r") - (match_operand:DI 1 "register_operand" "r")) - (set (match_operand:SI 2 "register_operand" "=r") - (match_operand:SI 3 "register_operand" "r")) - (set (match_operand:SI 4 "register_operand" "=r") - (match_operand:SI 5 "register_operand" "r"))] - "((REGNO (operands[0]) & 3) == 0) - && ((REGNO (operands[1]) & 3) == 0) - && (REGNO (operands[0]) + 2 == REGNO (operands[2])) - && (REGNO (operands[1]) + 2 == REGNO (operands[3])) - && (REGNO (operands[0]) + 3 == REGNO (operands[4])) - && (REGNO (operands[1]) + 3 == REGNO (operands[5]))" - "movq %1,%0") - -;; Matched 4/17/92 -(define_peephole - [(set (match_operand:SI 0 "register_operand" "=r") - (match_operand:SI 1 "register_operand" "r")) - (set (match_operand:SI 2 "register_operand" "=r") - (match_operand:SI 3 "register_operand" "r")) - (set (match_operand:DI 4 "register_operand" "=r") - (match_operand:DI 5 "register_operand" "r"))] - "((REGNO (operands[0]) & 3) == 0) - && ((REGNO (operands[1]) & 3) == 0) - && (REGNO (operands[0]) + 1 == REGNO (operands[2])) - && (REGNO (operands[1]) + 1 == REGNO (operands[3])) - && (REGNO (operands[0]) + 2 == REGNO (operands[4])) - && (REGNO (operands[1]) + 2 == REGNO (operands[5]))" - "movq %1,%0") - -;; Matched 4/17/92 -(define_peephole - [(set (match_operand:DI 0 "register_operand" "=r") - (match_operand:DI 1 "register_operand" "r")) - (set (match_operand:SI 2 "register_operand" "=r") - (match_operand:SI 3 "register_operand" "r"))] - "((REGNO (operands[0]) & 3) == 0) - && ((REGNO (operands[1]) & 3) == 0) - && (REGNO (operands[0]) + 2 == REGNO (operands[2])) - && (REGNO (operands[1]) + 2 == REGNO (operands[3]))" - "movt %1,%0") - -;; Matched 5/28/91 -(define_peephole - [(set (match_operand:SI 0 "register_operand" "=r") - (match_operand:SI 1 "register_operand" "r")) - (set (match_operand:SI 2 "register_operand" "=r") - (match_operand:SI 3 "register_operand" "r")) - (set (match_operand:SI 4 "register_operand" "=r") - (match_operand:SI 5 "register_operand" "r"))] - "((REGNO (operands[0]) & 3) == 0) - && ((REGNO (operands[1]) & 3) == 0) - && (REGNO (operands[0]) + 1 == REGNO (operands[2])) - && (REGNO (operands[1]) + 1 == REGNO (operands[3])) - && (REGNO (operands[0]) + 2 == REGNO (operands[4])) - && (REGNO (operands[1]) + 2 == REGNO (operands[5]))" - "movt %1,%0") - -;; Matched 5/28/91 -(define_peephole - [(set (match_operand:SI 0 "register_operand" "=r") - (match_operand:SI 1 "register_operand" "r")) - (set (match_operand:SI 2 "register_operand" "=r") - (match_operand:SI 3 "register_operand" "r"))] - "((REGNO (operands[0]) & 1) == 0) - && ((REGNO (operands[1]) & 1) == 0) - && (REGNO (operands[0]) + 1 == REGNO (operands[2])) - && (REGNO (operands[1]) + 1 == REGNO (operands[3]))" - "movl %1,%0") - -; Multiple register loads. - -;; Matched 6/15/91 -(define_peephole - [(set (match_operand:SI 0 "register_operand" "=r") - (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "immediate_operand" "n")))) - (set (match_operand:SI 3 "register_operand" "=r") - (mem:SI (plus:SI (match_dup 1) - (match_operand:SI 4 "immediate_operand" "n")))) - (set (match_operand:SI 5 "register_operand" "=r") - (mem:SI (plus:SI (match_dup 1) - (match_operand:SI 6 "immediate_operand" "n")))) - (set (match_operand:SI 7 "register_operand" "=r") - (mem:SI (plus:SI (match_dup 1) - (match_operand:SI 8 "immediate_operand" "n"))))] - "(i960_si_ti (operands[1], operands[2]) && ((REGNO (operands[0]) & 3) == 0) - && (REGNO (operands[1]) != REGNO (operands[0])) - && (REGNO (operands[0]) + 1 == REGNO (operands[3])) - && (REGNO (operands[1]) != REGNO (operands[3])) - && (REGNO (operands[0]) + 2 == REGNO (operands[5])) - && (REGNO (operands[1]) != REGNO (operands[5])) - && (REGNO (operands[0]) + 3 == REGNO (operands[7])) - && (INTVAL (operands[2]) + 4 == INTVAL (operands[4])) - && (INTVAL (operands[2]) + 8 == INTVAL (operands[6])) - && (INTVAL (operands[2]) + 12 == INTVAL (operands[8])))" - "ldq %2(%1),%0") - -;; Matched 5/28/91 -(define_peephole - [(set (match_operand:DF 0 "register_operand" "=d") - (mem:DF (plus:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "immediate_operand" "n")))) - (set (match_operand:DF 3 "register_operand" "=d") - (mem:DF (plus:SI (match_dup 1) - (match_operand:SI 4 "immediate_operand" "n"))))] - "(i960_si_ti (operands[1], operands[2]) && ((REGNO (operands[0]) & 3) == 0) - && (REGNO (operands[1]) != REGNO (operands[0])) - && (REGNO (operands[0]) + 2 == REGNO (operands[3])) - && (REGNO (operands[1]) != REGNO (operands[3])) - && (INTVAL (operands[2]) + 8 == INTVAL (operands[4])))" - "ldq %2(%1),%0") - -;; Matched 1/24/92 -(define_peephole - [(set (match_operand:DI 0 "register_operand" "=d") - (mem:DI (plus:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "immediate_operand" "n")))) - (set (match_operand:DI 3 "register_operand" "=d") - (mem:DI (plus:SI (match_dup 1) - (match_operand:SI 4 "immediate_operand" "n"))))] - "(i960_si_ti (operands[1], operands[2]) && ((REGNO (operands[0]) & 3) == 0) - && (REGNO (operands[1]) != REGNO (operands[0])) - && (REGNO (operands[0]) + 2 == REGNO (operands[3])) - && (REGNO (operands[1]) != REGNO (operands[3])) - && (INTVAL (operands[2]) + 8 == INTVAL (operands[4])))" - "ldq %2(%1),%0") - -;; Matched 4/17/92 -(define_peephole - [(set (match_operand:SI 0 "register_operand" "=d") - (mem:SI (match_operand:SI 1 "register_operand" "d"))) - (set (match_operand:SI 2 "register_operand" "=d") - (mem:SI (plus:SI (match_dup 1) - (match_operand:SI 3 "immediate_operand" "n")))) - (set (match_operand:SI 4 "register_operand" "=d") - (mem:SI (plus:SI (match_dup 1) - (match_operand:SI 5 "immediate_operand" "n")))) - (set (match_operand:SI 6 "register_operand" "=d") - (mem:SI (plus:SI (match_dup 1) - (match_operand:SI 7 "immediate_operand" "n"))))] - "(i960_si_ti (operands[1], 0) && ((REGNO (operands[0]) & 3) == 0) - && (REGNO (operands[1]) != REGNO (operands[0])) - && (REGNO (operands[0]) + 1 == REGNO (operands[2])) - && (REGNO (operands[1]) != REGNO (operands[2])) - && (REGNO (operands[0]) + 2 == REGNO (operands[4])) - && (REGNO (operands[1]) != REGNO (operands[4])) - && (REGNO (operands[0]) + 3 == REGNO (operands[6])) - && (INTVAL (operands[3]) == 4) - && (INTVAL (operands[5]) == 8) - && (INTVAL (operands[7]) == 12))" - "ldq (%1),%0") - -;; Matched 5/28/91 -(define_peephole - [(set (match_operand:SI 0 "register_operand" "=d") - (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "immediate_operand" "n")))) - (set (match_operand:SI 3 "register_operand" "=d") - (mem:SI (plus:SI (match_dup 1) - (match_operand:SI 4 "immediate_operand" "n")))) - (set (match_operand:SI 5 "register_operand" "=d") - (mem:SI (plus:SI (match_dup 1) - (match_operand:SI 6 "immediate_operand" "n"))))] - "(i960_si_ti (operands[1], operands[2]) && ((REGNO (operands[0]) & 3) == 0) - && (REGNO (operands[1]) != REGNO (operands[0])) - && (REGNO (operands[0]) + 1 == REGNO (operands[3])) - && (REGNO (operands[1]) != REGNO (operands[3])) - && (REGNO (operands[0]) + 2 == REGNO (operands[5])) - && (INTVAL (operands[2]) + 4 == INTVAL (operands[4])) - && (INTVAL (operands[2]) + 8 == INTVAL (operands[6])))" - "ldt %2(%1),%0") - -;; Matched 6/15/91 -(define_peephole - [(set (match_operand:SI 0 "register_operand" "=d") - (mem:SI (match_operand:SI 1 "register_operand" "d"))) - (set (match_operand:SI 2 "register_operand" "=d") - (mem:SI (plus:SI (match_dup 1) - (match_operand:SI 3 "immediate_operand" "n")))) - (set (match_operand:SI 4 "register_operand" "=d") - (mem:SI (plus:SI (match_dup 1) - (match_operand:SI 5 "immediate_operand" "n"))))] - "(i960_si_ti (operands[1], 0) && ((REGNO (operands[0]) & 3) == 0) - && (REGNO (operands[1]) != REGNO (operands[0])) - && (REGNO (operands[0]) + 1 == REGNO (operands[2])) - && (REGNO (operands[1]) != REGNO (operands[2])) - && (REGNO (operands[0]) + 2 == REGNO (operands[4])) - && (INTVAL (operands[3]) == 4) - && (INTVAL (operands[5]) == 8))" - "ldt (%1),%0") - -;; Matched 5/28/91 -(define_peephole - [(set (match_operand:SI 0 "register_operand" "=d") - (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "immediate_operand" "n")))) - (set (match_operand:SI 3 "register_operand" "=d") - (mem:SI (plus:SI (match_dup 1) - (match_operand:SI 4 "immediate_operand" "n"))))] - "(i960_si_di (operands[1], operands[2]) && ((REGNO (operands[0]) & 1) == 0) - && (REGNO (operands[1]) != REGNO (operands[0])) - && (REGNO (operands[0]) + 1 == REGNO (operands[3])) - && (INTVAL (operands[2]) + 4 == INTVAL (operands[4])))" - "ldl %2(%1),%0") - -;; Matched 5/28/91 -(define_peephole - [(set (match_operand:SI 0 "register_operand" "=d") - (mem:SI (match_operand:SI 1 "register_operand" "d"))) - (set (match_operand:SI 2 "register_operand" "=d") - (mem:SI (plus:SI (match_dup 1) - (match_operand:SI 3 "immediate_operand" "n"))))] - "(i960_si_di (operands[1], 0) && ((REGNO (operands[0]) & 1) == 0) - && (REGNO (operands[1]) != REGNO (operands[0])) - && (REGNO (operands[0]) + 1 == REGNO (operands[2])) - && (INTVAL (operands[3]) == 4))" - "ldl (%1),%0") - -; Multiple register stores. - -;; Matched 5/28/91 -(define_peephole - [(set (mem:SI (plus:SI (match_operand:SI 0 "register_operand" "d") - (match_operand:SI 1 "immediate_operand" "n"))) - (match_operand:SI 2 "register_operand" "d")) - (set (mem:SI (plus:SI (match_dup 0) - (match_operand:SI 3 "immediate_operand" "n"))) - (match_operand:SI 4 "register_operand" "d")) - (set (mem:SI (plus:SI (match_dup 0) - (match_operand:SI 5 "immediate_operand" "n"))) - (match_operand:SI 6 "register_operand" "d")) - (set (mem:SI (plus:SI (match_dup 0) - (match_operand:SI 7 "immediate_operand" "n"))) - (match_operand:SI 8 "register_operand" "d"))] - "(i960_si_ti (operands[0], operands[1]) && ((REGNO (operands[2]) & 3) == 0) - && (REGNO (operands[2]) + 1 == REGNO (operands[4])) - && (REGNO (operands[2]) + 2 == REGNO (operands[6])) - && (REGNO (operands[2]) + 3 == REGNO (operands[8])) - && (INTVAL (operands[1]) + 4 == INTVAL (operands[3])) - && (INTVAL (operands[1]) + 8 == INTVAL (operands[5])) - && (INTVAL (operands[1]) + 12 == INTVAL (operands[7])))" - "stq %2,%1(%0)") - -;; Matched 6/16/91 -(define_peephole - [(set (mem:DF (plus:SI (match_operand:SI 0 "register_operand" "d") - (match_operand:SI 1 "immediate_operand" "n"))) - (match_operand:DF 2 "register_operand" "d")) - (set (mem:DF (plus:SI (match_dup 0) - (match_operand:SI 3 "immediate_operand" "n"))) - (match_operand:DF 4 "register_operand" "d"))] - "(i960_si_ti (operands[0], operands[1]) && ((REGNO (operands[2]) & 3) == 0) - && (REGNO (operands[2]) + 2 == REGNO (operands[4])) - && (INTVAL (operands[1]) + 8 == INTVAL (operands[3])))" - "stq %2,%1(%0)") - -;; Matched 4/17/92 -(define_peephole - [(set (mem:DI (plus:SI (match_operand:SI 0 "register_operand" "d") - (match_operand:SI 1 "immediate_operand" "n"))) - (match_operand:DI 2 "register_operand" "d")) - (set (mem:DI (plus:SI (match_dup 0) - (match_operand:SI 3 "immediate_operand" "n"))) - (match_operand:DI 4 "register_operand" "d"))] - "(i960_si_ti (operands[0], operands[1]) && ((REGNO (operands[2]) & 3) == 0) - && (REGNO (operands[2]) + 2 == REGNO (operands[4])) - && (INTVAL (operands[1]) + 8 == INTVAL (operands[3])))" - "stq %2,%1(%0)") - -;; Matched 1/23/92 -(define_peephole - [(set (mem:SI (match_operand:SI 0 "register_operand" "d")) - (match_operand:SI 1 "register_operand" "d")) - (set (mem:SI (plus:SI (match_dup 0) - (match_operand:SI 2 "immediate_operand" "n"))) - (match_operand:SI 3 "register_operand" "d")) - (set (mem:SI (plus:SI (match_dup 0) - (match_operand:SI 4 "immediate_operand" "n"))) - (match_operand:SI 5 "register_operand" "d")) - (set (mem:SI (plus:SI (match_dup 0) - (match_operand:SI 6 "immediate_operand" "n"))) - (match_operand:SI 7 "register_operand" "d"))] - "(i960_si_ti (operands[0], 0) && ((REGNO (operands[1]) & 3) == 0) - && (REGNO (operands[1]) + 1 == REGNO (operands[3])) - && (REGNO (operands[1]) + 2 == REGNO (operands[5])) - && (REGNO (operands[1]) + 3 == REGNO (operands[7])) - && (INTVAL (operands[2]) == 4) - && (INTVAL (operands[4]) == 8) - && (INTVAL (operands[6]) == 12))" - "stq %1,(%0)") - -;; Matched 5/29/91 -(define_peephole - [(set (mem:SI (plus:SI (match_operand:SI 0 "register_operand" "d") - (match_operand:SI 1 "immediate_operand" "n"))) - (match_operand:SI 2 "register_operand" "d")) - (set (mem:SI (plus:SI (match_dup 0) - (match_operand:SI 3 "immediate_operand" "n"))) - (match_operand:SI 4 "register_operand" "d")) - (set (mem:SI (plus:SI (match_dup 0) - (match_operand:SI 5 "immediate_operand" "n"))) - (match_operand:SI 6 "register_operand" "d"))] - "(i960_si_ti (operands[0], operands[1]) && ((REGNO (operands[2]) & 3) == 0) - && (REGNO (operands[2]) + 1 == REGNO (operands[4])) - && (REGNO (operands[2]) + 2 == REGNO (operands[6])) - && (INTVAL (operands[1]) + 4 == INTVAL (operands[3])) - && (INTVAL (operands[1]) + 8 == INTVAL (operands[5])))" - "stt %2,%1(%0)") - -;; Matched 5/29/91 -(define_peephole - [(set (mem:SI (match_operand:SI 0 "register_operand" "d")) - (match_operand:SI 1 "register_operand" "d")) - (set (mem:SI (plus:SI (match_dup 0) - (match_operand:SI 2 "immediate_operand" "n"))) - (match_operand:SI 3 "register_operand" "d")) - (set (mem:SI (plus:SI (match_dup 0) - (match_operand:SI 4 "immediate_operand" "n"))) - (match_operand:SI 5 "register_operand" "d"))] - "(i960_si_ti (operands[0], 0) && ((REGNO (operands[1]) & 3) == 0) - && (REGNO (operands[1]) + 1 == REGNO (operands[3])) - && (REGNO (operands[1]) + 2 == REGNO (operands[5])) - && (INTVAL (operands[2]) == 4) - && (INTVAL (operands[4]) == 8))" - "stt %1,(%0)") - -;; Matched 5/28/91 -(define_peephole - [(set (mem:SI (plus:SI (match_operand:SI 0 "register_operand" "d") - (match_operand:SI 1 "immediate_operand" "n"))) - (match_operand:SI 2 "register_operand" "d")) - (set (mem:SI (plus:SI (match_dup 0) - (match_operand:SI 3 "immediate_operand" "n"))) - (match_operand:SI 4 "register_operand" "d"))] - "(i960_si_di (operands[0], operands[1]) && ((REGNO (operands[2]) & 1) == 0) - && (REGNO (operands[2]) + 1 == REGNO (operands[4])) - && (INTVAL (operands[1]) + 4 == INTVAL (operands[3])))" - "stl %2,%1(%0)") - -;; Matched 5/28/91 -(define_peephole - [(set (mem:SI (match_operand:SI 0 "register_operand" "d")) - (match_operand:SI 1 "register_operand" "d")) - (set (mem:SI (plus:SI (match_dup 0) - (match_operand:SI 2 "immediate_operand" "n"))) - (match_operand:SI 3 "register_operand" "d"))] - "(i960_si_di (operands[0], 0) && ((REGNO (operands[1]) & 1) == 0) - && (REGNO (operands[1]) + 1 == REGNO (operands[3])) - && (INTVAL (operands[2]) == 4))" - "stl %1,(%0)") diff --git a/gcc/config/i960/rtems.h b/gcc/config/i960/rtems.h deleted file mode 100644 index 092b7920abf..00000000000 --- a/gcc/config/i960/rtems.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Definitions for rtems targeting an Intel i960. - Copyright (C) 1996, 1997, 2000, 2002 Free Software Foundation, Inc. - Contributed by Joel Sherrill (joel@OARcorp.com). - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GCC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/* Target OS builtins. */ -#define TARGET_OS_CPP_BUILTINS() \ - do \ - { \ - builtin_define ("__rtems__"); \ - builtin_assert ("system=rtems"); \ - } \ - while (0) diff --git a/gcc/config/i960/t-960bare b/gcc/config/i960/t-960bare deleted file mode 100644 index 9cbaa9f9065..00000000000 --- a/gcc/config/i960/t-960bare +++ /dev/null @@ -1,30 +0,0 @@ -LIB2FUNCS_EXTRA = xp-bit.c - -# We want fine grained libraries, so use the new code to build the -# floating point emulation libraries. -FPBIT = fp-bit.c -DPBIT = dp-bit.c - -dp-bit.c: $(srcdir)/config/fp-bit.c - echo '#define FLOAT_BIT_ORDER_MISMATCH' > dp-bit.c - cat $(srcdir)/config/fp-bit.c >> dp-bit.c - -fp-bit.c: $(srcdir)/config/fp-bit.c - echo '#define FLOAT' > fp-bit.c - echo '#define FLOAT_BIT_ORDER_MISMATCH' >> fp-bit.c - cat $(srcdir)/config/fp-bit.c >> fp-bit.c - -xp-bit.c: $(srcdir)/config/fp-bit.c - echo '#define EXTENDED_FLOAT_STUBS' > xp-bit.c - cat $(srcdir)/config/fp-bit.c >> xp-bit.c - -i960-c.o: $(srcdir)/config/i960/i960-c.c $(CONFIG_H) $(SYSTEM_H) \ - coretypes.h $(TM_H) $(CPPLIB_H) $(TREE_H) c-pragma.h toplev.h $(GGC_H) $(TM_P_H) - $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/i960/i960-c.c - -MULTILIB_OPTIONS=mnumerics/msoft-float mlong-double-64 -MULTILIB_DIRNAMES=float soft-float ld64 -MULTILIB_MATCHES=mnumerics=msb mnumerics=msc mnumerics=mkb mnumerics=mkc mnumerics=mmc mnumerics=mcb mnumerics=mcc mnumerics=mjf msoft-float=msa msoft-float=mka msoft-float=mca msoft-float=mcf - -LIBGCC = stmp-multilib -INSTALL_LIBGCC = install-multilib diff --git a/gcc/config/linux-aout.h b/gcc/config/linux-aout.h deleted file mode 100644 index 5701fd94ded..00000000000 --- a/gcc/config/linux-aout.h +++ /dev/null @@ -1,37 +0,0 @@ -/* Definitions for Linux-based GNU systems with a.out binaries. - Copyright (C) 1995, 1997, 1999, 2000 Free Software Foundation, Inc. - Contributed by H.J. Lu (hjl@nynexst.com) - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GCC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/* Don't assume anything about the header files. */ -#define NO_IMPLICIT_EXTERN_C - -#undef STARTFILE_SPEC -#define STARTFILE_SPEC "%{pg:gcrt0.o%s} %{!pg:%{p:gcrt0.o%s} %{!p:crt0.o%s}} %{static:-static}" - -#undef ASM_APP_ON -#define ASM_APP_ON "#APP\n" - -#undef ASM_APP_OFF -#define ASM_APP_OFF "#NO_APP\n" - -#define SET_ASM_OP "\t.set\t" - -/* We need that too. */ -#define HANDLE_SYSV_PRAGMA 1 diff --git a/gcc/config/m68k/hp310.h b/gcc/config/m68k/hp310.h deleted file mode 100644 index 1abbeaeddc9..00000000000 --- a/gcc/config/m68k/hp310.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Definitions of target machine for GNU compiler. HP-UX 68010 version. */ - -/* Don't try using XFmode. */ -#undef LONG_DOUBLE_TYPE_SIZE -#define LONG_DOUBLE_TYPE_SIZE 64 - -#undef CPP_SPEC -#undef ASM_SPEC - -/* HP does not support a 68020 without a 68881 or a 68010 with a 68881. - However, -m68020 does not imply -m68881. You must specify both - if you want both. */ - -#ifdef HPUX_ASM - -#define CPP_SPEC "-D__HPUX_ASM__ %{m68881: -D__HAVE_68881__}\ -%{m68020: -Dmc68020}%{mc68020: -Dmc68020} -D_INCLUDE__STDC__" - -#define ASM_SPEC "%{!m68020:%{!mc68020:+X}}" - -#else /* not HPUX_ASM */ - -#define CPP_SPEC "%{m68881: -D__HAVE_68881__}\ -%{m68020: -Dmc68020}%{mc68020: -Dmc68020} -D_INCLUDE__STDC__" - -#define ASM_SPEC \ - "%{m68000:-mc68000}%{mc68000:-mc68000}%{!mc68000:%{!m68000:-mc68020}}" - -#endif /* not HPUX_ASM */ diff --git a/gcc/config/m68k/hp320.h b/gcc/config/m68k/hp320.h deleted file mode 100644 index 69bb726934d..00000000000 --- a/gcc/config/m68k/hp320.h +++ /dev/null @@ -1,530 +0,0 @@ -/* Definitions of target machine for GNU compiler. HP-UX 68000/68020 version. - Copyright (C) 1987, 1988, 1993, 1994, 1995, 1996, 1997, 1999, 2000, 2002, 2003 - Free Software Foundation, Inc. - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GCC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/* gcc.c should find libgcc.a itself rather than expecting linker to. */ -#define LINK_LIBGCC_SPECIAL -/* The arguments of -L must be a separate argv element. */ -#define SPACE_AFTER_L_OPTION -/* HP/UX doesn't have libg.a. */ -#define LIB_SPEC "%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}" - -/* Be compatible with system stddef.h. */ -#define SIZE_TYPE "unsigned int" - -#undef INT_OP_GROUP -#define INT_OP_GROUP INT_OP_NO_DOT - -/* See m68k.h. 7 means 68020 with 68881. */ - -#ifndef TARGET_DEFAULT -#define TARGET_DEFAULT (MASK_BITFIELD|MASK_68881|MASK_68020) -#endif - -/* Define __HAVE_68881__ in preprocessor, unless -msoft-float is specified. - This will control the use of inline 68881 insns in certain macros. */ - -#ifdef HPUX_ASM - -#define ASM_SPEC "%{m68000:+X}%{mc68000:+X}" - -#define NO_DOT_IN_LABEL - -#if TARGET_DEFAULT & MASK_68881 /* -m68881 is the default */ - -/* These definitions differ from those used for GAS by defining __HPUX_ASM__. - This is needed because some programs, particularly GDB, need to - know which assembler is being used so that the correct `asm' - instructions can be used. */ - -#define CPP_SPEC \ -"%{!msoft-float:-D__HAVE_68881__ }\ -%{!ansi:%{!mc68000:%{!m68000:-Dmc68020}} -D_HPUX_SOURCE} -D__HPUX_ASM__" - -#else /* default is -msoft-float */ - -#define CPP_SPEC \ -"%{m68881:-D__HAVE_68881__ }\ -%{!ansi:%{!mc68000:%{!m68000:-Dmc68020}} -D_HPUX_SOURCE} -D__HPUX_ASM__" - -#endif /* default is -msoft-float */ - -#else /* not HPUX_ASM */ - -#if TARGET_DEFAULT & MASK_68881 /* -m68881 is the default */ - -#define CPP_SPEC \ -"%{!msoft-float:-D__HAVE_68881__ }\ -%{!ansi:%{!mc68000:%{!m68000:-Dmc68020}} -D_HPUX_SOURCE}" - -#else /* default is -msoft-float */ - -#define CPP_SPEC \ -"%{m68881:-D__HAVE_68881__ }\ -%{!ansi:%{!mc68000:%{!m68000:-Dmc68020}} -D_HPUX_SOURCE}" - -#endif /* default is -msoft-float */ - -/* -m68000 requires special flags to the assembler. */ -#define ASM_SPEC \ - "%{m68000:-mc68000}%{mc68000:-mc68000}%{!mc68000:%{!m68000:-mc68020}}" - -/* Tell GCC to put a space after -L when generating such options. */ -#define SPACE_AFTER_L_OPTION - -#endif /* Not HPUX_ASM */ - -/* Translate -static for HPUX linker. */ -#define LINK_SPEC "%{static:-a archive}" - - -/* Target OS builtins. These are the ones defined by HPUX cc. */ -#define TARGET_OS_CPP_BUILTINS() \ - do \ - { \ - builtin_define_std ("hp9000s200"); \ - builtin_define_std ("hp9000s300"); \ - builtin_define_std ("hpux"); \ - builtin_define_std ("unix"); \ - builtin_define_std ("PWB"); \ - builtin_define ("__motorola__"); \ - builtin_assert ("system=unix"); \ - builtin_assert ("system=hpux"); \ - } \ - while (0) - -/* Every structure or union's size must be a multiple of 2 bytes. */ - -#define STRUCTURE_SIZE_BOUNDARY 16 - -/* hpux doesn't use static area for struct returns. */ -#undef PCC_STATIC_STRUCT_RETURN - -/* Generate calls to memcpy, memcmp and memset. */ -#define TARGET_MEM_FUNCTIONS - -#if 0 /* No longer correct in HPUX version 6.5. */ -/* Function calls don't save any fp registers on hpux. */ -#undef CALL_USED_REGISTERS -#define CALL_USED_REGISTERS \ - {1, 1, 0, 0, 0, 0, 0, 0, \ - 1, 1, 0, 0, 0, 0, 0, 1, \ - 1, 1, 1, 1, 1, 1, 1, 1} -#endif /* 0 */ - -#ifdef HPUX_ASM - -/* Override parts of m68k.h to fit the HPUX assembler. */ - -#undef TARGET_VERSION -#undef REGISTER_NAMES -#undef ASM_OUTPUT_REG_PUSH -#undef ASM_OUTPUT_REG_POP -#undef ASM_APP_ON -#undef ASM_APP_OFF -#undef TEXT_SECTION_ASM_OP -#undef DATA_SECTION_ASM_OP -#undef READONLY_DATA_SECTION_ASM_OP -#undef ASM_OUTPUT_ADDR_VEC_ELT -#undef ASM_OUTPUT_ADDR_DIFF_ELT -#undef ASM_OUTPUT_ALIGN -#undef ASM_OUTPUT_SKIP -#undef ASM_OUTPUT_COMMON -#undef ASM_OUTPUT_LOCAL -#undef FUNCTION_PROFILER -#undef GLOBAL_ASM_OP -#undef IMMEDIATE_PREFIX -#undef REGISTER_PREFIX - -#define TARGET_VERSION fprintf (stderr, " (68k, SGS/hpux syntax)"); - -#define REGISTER_NAMES \ -{"%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7", \ - "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%fp", "%sp", \ - "%fp0", "%fp1", "%fp2", "%fp3", "%fp4", "%fp5", "%fp6", "%fp7", "argptr"} - -#define IMMEDIATE_PREFIX "&" -#define REGISTER_PREFIX "%" - -#define FUNCTION_PROFILER(FILE, LABEL_NO) \ - fprintf (FILE, "\tmov.l &LP%d,%%a0\n\tjsr mcount\n", (LABEL_NO)); - -/* This is how to output an insn to push a register on the stack. - It need not be very fast code. */ - -#define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \ - fprintf (FILE, "\tmov.l %s,-(%%sp)\n", reg_names[REGNO]) - -/* This is how to output an insn to pop a register from the stack. - It need not be very fast code. */ - -#define ASM_OUTPUT_REG_POP(FILE,REGNO) \ - fprintf (FILE, "\tmov.l (%%sp)+,%s\n", reg_names[REGNO]) - -/* For HPUX versions before 6.5, define this macro as empty. */ -#define TARGET_ASM_FILE_START m68k_hp320_file_start - -#define ASM_APP_ON "" - -#define ASM_APP_OFF "" - -#ifdef AS_BUG_TRAILING_LABEL -#define TEXT_SECTION_ASM_OP "\tlalign\t1\ntext" -#define DATA_SECTION_ASM_OP "\tlalign\t1\ndata" -#else -#define TEXT_SECTION_ASM_OP "text" -#define DATA_SECTION_ASM_OP "data" -#endif -#define ASCII_DATA_ASM_OP "\tbyte\t" - -/* This is the command to make the user-level label named NAME - defined for reference from other files. */ - -#define GLOBAL_ASM_OP "\tglobal\t" - -/* This says how to output an assembler line - to define a global common symbol. */ - -#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \ -( fputs ("\tcomm ", (FILE)), \ - assemble_name ((FILE), (NAME)), \ - fprintf ((FILE), ",%u\n", (int)(ROUNDED))) - -/* This says how to output an assembler line - to define a local common symbol. */ - -#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \ -( fputs ("\tlcomm ", (FILE)), \ - assemble_name ((FILE), (NAME)), \ - fprintf ((FILE), ",%u,2\n", (int)(ROUNDED))) - -#define ASM_PN_FORMAT "%s___%lu" - -#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ - fprintf (FILE, "\tlong L%d\n", VALUE) - -#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ - fprintf (FILE, "\tshort L%d-L%d\n", VALUE, REL) - -#define ASM_OUTPUT_ALIGN(FILE,LOG) \ -do { \ - if ((LOG) == 1) \ - fprintf (FILE, "\tlalign 2\n"); \ - else if ((LOG) != 0) \ - abort (); \ -} while (0) - -#define ASM_OUTPUT_SKIP(FILE,SIZE) \ - fprintf (FILE, "\tspace %u\n", (int)(SIZE)) - -#define ASM_OUTPUT_SOURCE_FILENAME(FILE, FILENAME) -#define ASM_OUTPUT_SOURCE_LINE(FILE, LINENO, COUNTER) - -/* Output a float value (represented as a C double) as an immediate operand. - This macro is a 68k-specific macro. */ - -#undef ASM_OUTPUT_FLOAT_OPERAND -#ifdef AS_BUG_FLOATING_CONSTANT -#define ASM_OUTPUT_FLOAT_OPERAND(CODE,FILE,VALUE) \ - do { long l; \ - REAL_VALUE_TO_TARGET_SINGLE (VALUE, l); \ - fprintf ((FILE), "&0x%lx", l); \ - } while (0) -#else -#define ASM_OUTPUT_FLOAT_OPERAND(CODE,FILE,VALUE) \ - do { \ - if (CODE == 'f') \ - { \ - char dstr[30]; \ - real_to_decimal (dstr, &(VALUE), sizeof (dstr), 9, 0); \ - fprintf ((FILE), "&0f%s", dstr); \ - } \ - else \ - { \ - long l; \ - REAL_VALUE_TO_TARGET_SINGLE (VALUE, l); \ - fprintf ((FILE), "&0x%lx", l); \ - } \ - } while (0) -#endif /* AS_BUG_FLOATING_CONSTANT */ - -/* Output a double value (represented as a C double) as an immediate operand. - This macro is a 68k-specific macro. */ -#undef ASM_OUTPUT_DOUBLE_OPERAND -#define ASM_OUTPUT_DOUBLE_OPERAND(FILE,VALUE) \ - do { char dstr[30]; \ - real_to_decimal (dstr, &(VALUE), sizeof (dstr), 0, 1); \ - fprintf (FILE, "&0f%s", dstr); \ - } while (0) - -/* Note, long double immediate operands are not actually - generated by m68k.md. */ -#undef ASM_OUTPUT_LONG_DOUBLE_OPERAND -#define ASM_OUTPUT_LONG_DOUBLE_OPERAND(FILE,VALUE) \ - do { char dstr[30]; \ - real_to_decimal (dstr, &(VALUE), sizeof (dstr), 0, 1); \ - fprintf (FILE, "&0f%s", dstr); \ - } while (0) - -#if 0 -#undef PRINT_OPERAND -#define PRINT_OPERAND(FILE, X, CODE) \ -{ if (CODE == '.') fprintf (FILE, "."); \ - else if (CODE == '#') fprintf (FILE, "&"); \ - else if (CODE == '-') fprintf (FILE, "-(%%sp)"); \ - else if (CODE == '+') fprintf (FILE, "(%%sp)+"); \ - else if (CODE == '@') fprintf (FILE, "(%%sp)"); \ - else if (CODE == '!') fprintf (FILE, "%%fpcr"); \ - else if (CODE == '$') { if (TARGET_68040_ONLY) fprintf (FILE, "s"); } \ - else if (CODE == '&') { if (TARGET_68040_ONLY) fprintf (FILE, "d"); } \ - else if (CODE == '/') \ - fprintf (FILE, "%%"); \ - else if (GET_CODE (X) == REG) \ - fprintf (FILE, "%s", reg_names[REGNO (X)]); \ - else if (GET_CODE (X) == MEM) \ - output_address (XEXP (X, 0)); \ - else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == SFmode) \ - { REAL_VALUE_TYPE r; long l; \ - REAL_VALUE_FROM_CONST_DOUBLE (r, X); \ - PRINT_OPERAND_FLOAT (CODE, FILE, r, l); } \ - else if (GET_CODE (X) == CONST_DOUBLE \ - && (GET_MODE (X) == DFmode || GET_MODE (X) == XFmode)) \ - { char dstr[30]; \ - real_to_decimal (dstr, CONST_DOUBLE_REAL_VALUE (X), \ - sizeof (dstr), 0, 1); \ - fprintf (FILE, "&0f%s", dstr); } \ - else { putc ('&', FILE); output_addr_const (FILE, X); }} -#endif - -#undef PRINT_OPERAND_ADDRESS -#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \ -{ register rtx reg1, reg2, breg, ireg; \ - register rtx addr = ADDR; \ - rtx offset; \ - switch (GET_CODE (addr)) \ - { \ - case REG: \ - fprintf (FILE, "(%s)", reg_names[REGNO (addr)]); \ - break; \ - case PRE_DEC: \ - fprintf (FILE, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]); \ - break; \ - case POST_INC: \ - fprintf (FILE, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]); \ - break; \ - case PLUS: \ - reg1 = 0; reg2 = 0; \ - ireg = 0; breg = 0; \ - offset = 0; \ - if (CONSTANT_ADDRESS_P (XEXP (addr, 0))) \ - { \ - offset = XEXP (addr, 0); \ - addr = XEXP (addr, 1); \ - } \ - else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))) \ - { \ - offset = XEXP (addr, 1); \ - addr = XEXP (addr, 0); \ - } \ - if (GET_CODE (addr) != PLUS) ; \ - else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND) \ - { \ - reg1 = XEXP (addr, 0); \ - addr = XEXP (addr, 1); \ - } \ - else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND) \ - { \ - reg1 = XEXP (addr, 1); \ - addr = XEXP (addr, 0); \ - } \ - else if (GET_CODE (XEXP (addr, 0)) == MULT) \ - { \ - reg1 = XEXP (addr, 0); \ - addr = XEXP (addr, 1); \ - } \ - else if (GET_CODE (XEXP (addr, 1)) == MULT) \ - { \ - reg1 = XEXP (addr, 1); \ - addr = XEXP (addr, 0); \ - } \ - else if (GET_CODE (XEXP (addr, 0)) == REG) \ - { \ - reg1 = XEXP (addr, 0); \ - addr = XEXP (addr, 1); \ - } \ - else if (GET_CODE (XEXP (addr, 1)) == REG) \ - { \ - reg1 = XEXP (addr, 1); \ - addr = XEXP (addr, 0); \ - } \ - if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT \ - || GET_CODE (addr) == SIGN_EXTEND) \ - { if (reg1 == 0) reg1 = addr; else reg2 = addr; addr = 0; } \ -/* for OLD_INDEXING \ - else if (GET_CODE (addr) == PLUS) \ - { \ - if (GET_CODE (XEXP (addr, 0)) == REG) \ - { \ - reg2 = XEXP (addr, 0); \ - addr = XEXP (addr, 1); \ - } \ - else if (GET_CODE (XEXP (addr, 1)) == REG) \ - { \ - reg2 = XEXP (addr, 1); \ - addr = XEXP (addr, 0); \ - } \ - } \ - */ \ - if (offset != 0) { if (addr != 0) abort (); addr = offset; } \ - if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND \ - || GET_CODE (reg1) == MULT)) \ - || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2)))) \ - { breg = reg2; ireg = reg1; } \ - else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1))) \ - { breg = reg1; ireg = reg2; } \ - if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF) \ - { int scale = 1; \ - if (GET_CODE (ireg) == MULT) \ - { scale = INTVAL (XEXP (ireg, 1)); \ - ireg = XEXP (ireg, 0); } \ - if (GET_CODE (ireg) == SIGN_EXTEND) \ - fprintf (FILE, "L%d-LI%d(%%pc,%s.w", \ - CODE_LABEL_NUMBER (XEXP (addr, 0)), \ - CODE_LABEL_NUMBER (XEXP (addr, 0)), \ - reg_names[REGNO (XEXP (ireg, 0))]); \ - else \ - fprintf (FILE, "L%d-LI%d(%%pc,%s.l", \ - CODE_LABEL_NUMBER (XEXP (addr, 0)), \ - CODE_LABEL_NUMBER (XEXP (addr, 0)), \ - reg_names[REGNO (ireg)]); \ - if (scale != 1) fprintf (FILE, "*%d", scale); \ - putc (')', FILE); \ - break; } \ - if (ireg != 0 || breg != 0) \ - { int scale = 1; \ - if (breg == 0) \ - abort (); \ - if (addr != 0) \ - output_addr_const (FILE, addr); \ - fprintf (FILE, "(%s", reg_names[REGNO (breg)]); \ - if (ireg != 0) \ - putc (',', FILE); \ - if (ireg != 0 && GET_CODE (ireg) == MULT) \ - { scale = INTVAL (XEXP (ireg, 1)); \ - ireg = XEXP (ireg, 0); } \ - if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND) \ - fprintf (FILE, "%s.w", reg_names[REGNO (XEXP (ireg, 0))]); \ - else if (ireg != 0) \ - fprintf (FILE, "%s.l", reg_names[REGNO (ireg)]); \ - if (scale != 1) fprintf (FILE, "*%d", scale); \ - putc (')', FILE); \ - break; \ - } \ - else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF) \ - { fprintf (FILE, "L%d-LI%d(%%pc,%s.w)", \ - CODE_LABEL_NUMBER (XEXP (addr, 0)), \ - CODE_LABEL_NUMBER (XEXP (addr, 0)), \ - reg_names[REGNO (reg1)]); \ - break; } \ - default: \ - if (GET_CODE (addr) == CONST_INT \ - && INTVAL (addr) < 0x8000 \ - && INTVAL (addr) >= -0x8000) \ - fprintf (FILE, "%d.w", (int) INTVAL (addr)); \ - else \ - output_addr_const (FILE, addr); \ - }} - -#define ASM_OUTPUT_ASCII(f, p, SIZE) \ -do { size_t i, limit = (SIZE); \ - int inside; \ - inside = FALSE; \ - for (i = 0; i < limit; i++) { \ - if (i % 8 == 0) { \ - if (i != 0) { \ - if (inside) \ - putc('"', (f)); \ - putc('\n', (f)); \ - inside = FALSE; \ - } \ - fprintf((f), "%s", ASCII_DATA_ASM_OP); \ - } \ - if ((p)[i] < 32 || (p)[i] == '\\' || (p)[i] == '"' || (p)[i] == 127) { \ - if (inside) { \ - putc('"', (f)); \ - inside = FALSE; \ - } \ - if (i % 8 != 0) \ - putc(',', (f)); \ - fprintf((f), "%d", (p)[i]); \ - } else { \ - if (!inside) { \ - if (i % 8 != 0) \ - putc(',', (f)); \ - putc('"', (f)); \ - inside = TRUE; \ - } \ - putc((p)[i], (f)); \ - } \ - } \ - if (inside) \ - putc('"', (f)); \ - putc('\n', (f)); \ -} while (0) - -/* Translate Motorola opcodes such as `jbeq' - into SGS opcodes such as `beq.w'. - Delete the `e' in `move...' and `fmove'. - Change `ftst' to `ftest'. */ - -#define ASM_OUTPUT_OPCODE(FILE, PTR) \ -{ if ((PTR)[0] == 'j' && (PTR)[1] == 'b') \ - { ++(PTR); \ - while (*(PTR) != ' ') \ - { putc (*(PTR), (FILE)); ++(PTR); } \ - fprintf ((FILE), ".w"); } \ - else if ((PTR)[0] == 'f') \ - { \ - if (!strncmp ((PTR), "fmove", 5)) \ - { fprintf ((FILE), "fmov"); (PTR) += 5; } \ - else if (!strncmp ((PTR), "ftst", 4)) \ - { fprintf ((FILE), "ftest"); (PTR) += 4; } \ - } \ - else if ((PTR)[0] == 'm' && (PTR)[1] == 'o' \ - && (PTR)[2] == 'v' && (PTR)[3] == 'e') \ - { fprintf ((FILE), "mov"); (PTR) += 4; } \ -} - -#else /* not HPUX_ASM */ - -#undef FUNCTION_PROFILER - -/* HP-UX needs the call to mcount before the link instruction. - Copy the return address onto the stack before the call to fake it out. */ -#define FUNCTION_PROFILER(FILE, LABEL_NO) \ - fprintf (FILE, \ - "\tmovel a6@(4),sp@-\n\tmovl #LP%d,a0\n\tjsr mcount\n\taddqw #4,sp\n", \ - (LABEL_NO)); - -#endif /* not HPUX_ASM */ - -/* hpux8 and later have C++ compatible include files, so do not - pretend they are `extern "C"'. */ -#define NO_IMPLICIT_EXTERN_C diff --git a/gcc/config/m68k/hp320base.h b/gcc/config/m68k/hp320base.h deleted file mode 100644 index b35c48be2a7..00000000000 --- a/gcc/config/m68k/hp320base.h +++ /dev/null @@ -1,40 +0,0 @@ -/* Configuration file for an HP 320. - Copyright (C) 2003 Free Software Foundation, Inc. - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GCC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/* Control assembler-syntax conditionals in m68k.md. */ - -#ifndef USE_GAS -#define MOTOROLA /* Use Motorola syntax rather than "MIT" */ -#define SGS /* Uses SGS assembler */ -#define SGS_CMP_ORDER /* Takes cmp operands in reverse order */ -#define HPUX_ASM - -#if !defined (CROSS_COMPILE) && !defined (NO_BUGS) -/* The assembler on HP 9k3xx machines running HPUX 8.0 doesn't translate - floating point constants behind some operands. The workaround is to - use hex constants. Reported by Thomas Nau (nau@medizin.uni-ulm.de). */ -#define AS_BUG_FLOATING_CONSTANT -/* The assembler on HP 9k3xx machines running HPUX 8.0 doesn't accept - labels followed by a text, data, or other section directive. Reported - by Thomas Nau (nau@medizin.uni-ulm.de). */ -#define AS_BUG_TRAILING_LABEL -#endif - -#endif /* not USE_GAS */ diff --git a/gcc/config/m68k/m68kv4.h b/gcc/config/m68k/m68kv4.h deleted file mode 100644 index f7886b50bcc..00000000000 --- a/gcc/config/m68k/m68kv4.h +++ /dev/null @@ -1,298 +0,0 @@ -/* Target definitions for GNU compiler for mc680x0 running System V.4 - Copyright (C) 1991, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2003, 2004 - Free Software Foundation, Inc. - Contributed by Ron Guilmette (rfg@monkeys.com) and - Fred Fish (fnf@cygnus.com). - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GCC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/* Target OS builtins. */ -#define TARGET_OS_CPP_BUILTINS() \ - do \ - { \ - builtin_define_std ("unix"); \ - builtin_define_std ("m68k"); \ - builtin_define ("__svr4__"); \ - builtin_define ("__motorola__"); \ - builtin_assert ("system=unix"); \ - builtin_assert ("system=svr4"); \ - } \ - while (0) - -#ifndef TARGET_DEFAULT -#define TARGET_DEFAULT (MASK_BITFIELD|MASK_68881|MASK_68020) -#endif - -/* Override the definition of NO_DOLLAR_IN_LABEL in svr4.h, for special - g++ assembler names. When this is defined, g++ uses embedded '.' - characters and some m68k assemblers have problems with this. The - chances are much greater that any particular assembler will permit - embedded '$' characters. */ - -#undef NO_DOLLAR_IN_LABEL - -/* Define PCC_STATIC_STRUCT_RETURN if the convention on the target machine - is to use the nonreentrant technique for returning structure and union - values, as commonly implemented by the AT&T Portable C Compiler (PCC). - When defined, the gcc option -fpcc-struct-return can be used to cause - this form to be generated. When undefined, the option does nothing. - For m68k SVR4, the convention is to use a reentrant technique compatible - with the gcc default, so override the definition of this macro in m68k.h */ - -#undef PCC_STATIC_STRUCT_RETURN - -/* Test to see if the target includes a 68881 by default, and use CPP_SPEC - to control whether or not __HAVE_68881__ is defined by default or not. - If a 68881 is the default, gcc will use inline 68881 instructions, by - predefining __HAVE_68881__, unless -msoft-float is specified. - If a 68881 is not the default, gcc will only define __HAVE_68881__ if - -m68881 is specified. */ - -#if TARGET_DEFAULT & MASK_68881 -#define CPP_SPEC "%{!msoft-float:-D__HAVE_68881__}" -#else -#define CPP_SPEC "%{m68881:-D__HAVE_68881__}" -#endif - -/* Output assembler code to FILE to increment profiler label # LABELNO - for profiling a function entry. We override the definition in m68k.h - and match the way the native m68k/SVR4 compiler does profiling, with the - address of the profile counter in a1, not a0, and using bsr rather - than jsr. */ - -#undef FUNCTION_PROFILER -#define FUNCTION_PROFILER(FILE, LABELNO) \ - asm_fprintf ((FILE), "\tlea.l\t(%LLP%d,%Rpc),%Ra1\n\tbsr\t_mcount\n", \ - (LABELNO)) - -/* Local common symbols are declared to the assembler with ".lcomm" rather - than ".bss", so override the definition in svr4.h */ -/* ??? svr4.h no longer defines this, and this is only used by m68k/amix.h. */ - -#undef BSS_ASM_OP -#define BSS_ASM_OP "\t.lcomm\t" - -/* Register in which address to store a structure value is passed to a - function. The default in m68k.h is a1. For m68k/SVR4 it is a0. */ - -#undef M68K_STRUCT_VALUE_REGNUM -#define M68K_STRUCT_VALUE_REGNUM 8 - -/* Register in which static-chain is passed to a function. The - default in m68k.h is a0, but that is already the struct value - regnum. Make it a1 instead. */ - -#undef STATIC_CHAIN_REGNUM -#define STATIC_CHAIN_REGNUM 9 - -#define ASM_COMMENT_START "#" - -/* Define how the m68k registers should be numbered for Dwarf output. - The numbering provided here should be compatible with the native - SVR4 SDB debugger in the m68k/SVR4 reference port, where d0-d7 - are 0-7, a0-a8 are 8-15, and fp0-fp7 are 16-23. */ - -#define DBX_REGISTER_NUMBER(REGNO) (REGNO) - -/* The ASM_OUTPUT_SKIP macro is first defined in m68k.h, using ".skip". - It is then overridden by m68k/sgs.h to use ".space", and again by svr4.h - to use ".zero". The m68k/SVR4 assembler uses ".space", so repeat the - definition from m68k/sgs.h here. Note that ASM_NO_SKIP_IN_TEXT is - defined in m68k/sgs.h, so we don't have to repeat it here. */ - -#undef ASM_OUTPUT_SKIP -#define ASM_OUTPUT_SKIP(FILE,SIZE) \ - fprintf (FILE, "%s%u\n", SPACE_ASM_OP, (int)(SIZE)) - -/* 1 if N is a possible register number for a function value. - For m68k/SVR4 allow d0, a0, or fp0 as return registers, for integral, - pointer, or floating types, respectively. Reject fp0 if not using a - 68881 coprocessor. */ - -#undef FUNCTION_VALUE_REGNO_P -#define FUNCTION_VALUE_REGNO_P(N) \ - ((N) == 0 || (N) == 8 || (TARGET_68881 && (N) == 16)) - -/* Define this to be true when FUNCTION_VALUE_REGNO_P is true for - more than one register. */ - -#undef NEEDS_UNTYPED_CALL -#define NEEDS_UNTYPED_CALL 1 - -/* Define how to generate (in the callee) the output value of a function - and how to find (in the caller) the value returned by a function. VALTYPE - is the data type of the value (as a tree). If the precise function being - called is known, FUNC is its FUNCTION_DECL; otherwise, FUNC is 0. - For m68k/SVR4 generate the result in d0, a0, or fp0 as appropriate. */ - -#undef FUNCTION_VALUE -#define FUNCTION_VALUE(VALTYPE, FUNC) \ - (TREE_CODE (VALTYPE) == REAL_TYPE && TARGET_68881 \ - ? gen_rtx_REG (TYPE_MODE (VALTYPE), 16) \ - : (POINTER_TYPE_P (VALTYPE) \ - ? gen_rtx_REG (TYPE_MODE (VALTYPE), 8) \ - : gen_rtx_REG (TYPE_MODE (VALTYPE), 0))) - -/* For compatibility with the large body of existing code which does not - always properly declare external functions returning pointer types, the - m68k/SVR4 convention is to copy the value returned for pointer functions - from a0 to d0 in the function epilogue, so that callers that have - neglected to properly declare the callee can still find the correct return - value. */ - -#define FUNCTION_EXTRA_EPILOGUE(FILE, SIZE) \ -do { \ - if (current_function_returns_pointer \ - && ! find_equiv_reg (0, get_last_insn (), 0, 0, 0, 8, Pmode)) \ - asm_fprintf (FILE, "\tmov.l %Ra0,%Rd0\n"); \ -} while (0); - -/* Define how to find the value returned by a library function assuming the - value has mode MODE. - For m68k/SVR4 look for integer values in d0, pointer values in d0 - (returned in both d0 and a0), and floating values in fp0. */ - -#undef LIBCALL_VALUE -#define LIBCALL_VALUE(MODE) \ - ((((MODE) == SFmode || (MODE) == DFmode || (MODE) == XFmode) \ - && TARGET_68881) \ - ? gen_rtx_REG ((MODE), 16) \ - : gen_rtx_REG ((MODE), 0)) - -/* Boundary (in *bits*) on which stack pointer should be aligned. - The m68k/SVR4 convention is to keep the stack pointer longword aligned. */ - -#undef STACK_BOUNDARY -#define STACK_BOUNDARY 32 - -/* Alignment of field after `int : 0' in a structure. - For m68k/SVR4, this is the next longword boundary. */ - -#undef EMPTY_FIELD_BOUNDARY -#define EMPTY_FIELD_BOUNDARY 32 - -/* No data type wants to be aligned rounder than this. - For m68k/SVR4, some types (doubles for example) are aligned on 8 byte - boundaries */ - -#undef BIGGEST_ALIGNMENT -#define BIGGEST_ALIGNMENT 64 - -/* SVR4 m68k assembler is bitching on the `comm i,1,1' which asks for - 1 byte alignment. Don't generate alignment for COMMON seems to be - safer until we the assembler is fixed. */ -#undef ASM_OUTPUT_ALIGNED_COMMON -/* Same problem with this one. */ -#undef ASM_OUTPUT_ALIGNED_LOCAL - -/* The `string' directive on m68k svr4 does not handle string with - escape char (ie., `\') right. Use normal way to output ASCII bytes - seems to be safer. */ -#undef ASM_OUTPUT_ASCII -#define ASM_OUTPUT_ASCII(FILE,PTR,LEN) \ -do { \ - register size_t sp = 0, limit = (LEN); \ - fputs (integer_asm_op (1, TRUE), (FILE)); \ - do { \ - int ch = (PTR)[sp]; \ - if (ch > ' ' && ! (ch & 0x80) && ch != '\\') \ - { \ - fprintf ((FILE), "'%c", ch); \ - } \ - else \ - { \ - fprintf ((FILE), "0x%x", ch); \ - } \ - if (++sp < limit) \ - { \ - if ((sp % 10) == 0) \ - { \ - fprintf ((FILE), "\n%s", integer_asm_op (1, TRUE)); \ - } \ - else \ - { \ - putc (',', (FILE)); \ - } \ - } \ - } while (sp < limit); \ - putc ('\n', (FILE)); \ -} while (0) - -/* SVR4 m68k assembler is bitching on the syntax `2.b'. - So use the "LLDnnn-LLnnn" format. Define LLDnnn after the table. */ - -#undef ASM_OUTPUT_CASE_END -#define ASM_OUTPUT_CASE_END(FILE,NUM,TABLE) \ -do { \ - if (switch_table_difference_label_flag) \ - asm_fprintf ((FILE), "%s%LLD%d,%LL%d\n", SET_ASM_OP, (NUM), (NUM)); \ - switch_table_difference_label_flag = 0; \ -} while (0) - -extern int switch_table_difference_label_flag; - -#undef ASM_OUTPUT_COMMON -#undef ASM_OUTPUT_LOCAL -#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \ -( fputs (".comm ", (FILE)), \ - assemble_name ((FILE), (NAME)), \ - fprintf ((FILE), ",%u\n", (int)(SIZE))) - -#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \ -( fputs (".lcomm ", (FILE)), \ - assemble_name ((FILE), (NAME)), \ - fprintf ((FILE), ",%u\n", (int)(SIZE))) - -/* Override the definition in svr4.h. In m68k svr4, using swbeg is the - standard way to do switch table. */ -#undef ASM_OUTPUT_BEFORE_CASE_LABEL -#define ASM_OUTPUT_BEFORE_CASE_LABEL(FILE,PREFIX,NUM,TABLE) \ - fprintf ((FILE), "%s&%d\n", SWBEG_ASM_OP, XVECLEN (PATTERN (TABLE), 1)); - -/* Output assembler code for a block containing the constant parts - of a trampoline, leaving space for the variable parts. */ - -/* On m68k svr4, the trampoline is different from the generic version - in that we use a1 as the static call chain. */ - -#undef TRAMPOLINE_TEMPLATE -#define TRAMPOLINE_TEMPLATE(FILE) \ -{ \ - assemble_aligned_integer (2, GEN_INT (0x227a)); \ - assemble_aligned_integer (2, GEN_INT (8)); \ - assemble_aligned_integer (2, GEN_INT (0x2f3a)); \ - assemble_aligned_integer (2, GEN_INT (8)); \ - assemble_aligned_integer (2, GEN_INT (0x4e75)); \ - assemble_aligned_integer (4, const0_rtx); \ - assemble_aligned_integer (4, const0_rtx); \ -} - -/* Redefine since we are using a different trampoline */ -#undef TRAMPOLINE_SIZE -#define TRAMPOLINE_SIZE 18 - -/* Emit RTL insns to initialize the variable parts of a trampoline. - FNADDR is an RTX for the address of the function's pure code. - CXT is an RTX for the static chain value for the function. */ - -#undef INITIALIZE_TRAMPOLINE -#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \ -{ \ - emit_move_insn (gen_rtx_MEM (SImode, plus_constant (TRAMP, 10)), CXT); \ - emit_move_insn (gen_rtx_MEM (SImode, plus_constant (TRAMP, 14)), FNADDR); \ -} diff --git a/gcc/config/m68k/netbsd.h b/gcc/config/m68k/netbsd.h deleted file mode 100644 index 2b4fd855a9f..00000000000 --- a/gcc/config/m68k/netbsd.h +++ /dev/null @@ -1,62 +0,0 @@ -#define TARGET_OS_CPP_BUILTINS() \ - do \ - { \ - NETBSD_OS_CPP_BUILTINS_AOUT(); \ - builtin_define_std ("unix"); \ - builtin_define_std ("m68k"); \ - builtin_define_std ("mc68000"); \ - builtin_define_std ("mc68020"); \ - } \ - while (0) - -#define TARGET_DEFAULT (MASK_BITFIELD|MASK_68881|MASK_68020) - -#define EXTRA_SPECS \ - { "netbsd_cpp_spec", NETBSD_CPP_SPEC }, - -/* Define __HAVE_68881__ in preprocessor, unless -msoft-float is specified. - This will control the use of inline 68881 insns in certain macros. */ - -#undef CPP_SPEC -#define CPP_SPEC \ - "%{!msoft-float:-D__HAVE_68881__ -D__HAVE_FPU__} %(netbsd_cpp_spec)" - -#undef ASM_SPEC -#define ASM_SPEC "%{m68030} %{m68040} %{m68060} %{fpic|fpie:-k} %{fPIC|fPIE:-k -K}" - -#define AS_NEEDS_DASH_FOR_PIPED_INPUT - - -/* Make gcc agree with */ - -#undef SIZE_TYPE -#define SIZE_TYPE "unsigned int" - -#undef PTRDIFF_TYPE -#define PTRDIFF_TYPE "int" - -/* Every structure or union's size must be a multiple of 2 bytes. */ - -#define STRUCTURE_SIZE_BOUNDARY 16 - -/* This is BSD, so it wants DBX format. */ - -#define DBX_DEBUGGING_INFO 1 - -/* Do not break .stabs pseudos into continuations. */ - -#define DBX_CONTIN_LENGTH 0 - -/* This is the char to use for continuation (in case we need to turn - continuation back on). */ - -#define DBX_CONTIN_CHAR '?' - -/* Don't default to pcc-struct-return, because gcc is the only compiler, and - we want to retain compatibility with older gcc versions. */ -#define DEFAULT_PCC_STRUCT_RETURN 0 - -/* Until they use ELF or something that handles dwarf2 unwinds - and initialization stuff better. */ -#define DWARF2_UNWIND_INFO 0 - diff --git a/gcc/config/m68k/sgs.h b/gcc/config/m68k/sgs.h deleted file mode 100644 index e1967df8990..00000000000 --- a/gcc/config/m68k/sgs.h +++ /dev/null @@ -1,367 +0,0 @@ -/* Definitions of target machine for GNU compiler for m68k targets using - assemblers derived from AT&T "SGS" releases. - Copyright (C) 1991, 1993, 1996, 2000, 2003 Free Software Foundation, Inc. - Written by Fred Fish (fnf@cygnus.com) - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GCC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -#undef INT_OP_GROUP -#define INT_OP_GROUP INT_OP_STANDARD - -/* SGS specific assembler pseudo ops. */ - -#define SPACE_ASM_OP "\t.space " -#define ALIGN_ASM_OP "\t.align " -#undef GLOBAL_ASM_OP -#define GLOBAL_ASM_OP "\t.global " -#define SWBEG_ASM_OP "\t.swbeg " -#define SET_ASM_OP "\t.set " - -#define ASM_PN_FORMAT "%s_%lu" /* Format for private names */ - -/* Here are four prefixes that are used by asm_fprintf to - facilitate customization for alternate assembler syntaxes. - Machines with no likelihood of an alternate syntax need not - define these and need not use asm_fprintf. */ - -/* The prefix for register names. Note that REGISTER_NAMES - is supposed to include this prefix. Also note that this is NOT an - fprintf format string, it is a literal string */ - -#undef REGISTER_PREFIX -#define REGISTER_PREFIX "%" - -/* The prefix for local (compiler generated) labels. - These labels will not appear in the symbol table. */ - -#undef LOCAL_LABEL_PREFIX -#define LOCAL_LABEL_PREFIX "." - -/* The prefix to add to user-visible assembler symbols. */ - -#undef USER_LABEL_PREFIX -#define USER_LABEL_PREFIX "" - -/* The prefix for immediate operands. */ - -#undef IMMEDIATE_PREFIX -#define IMMEDIATE_PREFIX "&" - -/* How to refer to registers in assembler output. - This sequence is indexed by compiler's hard-register-number. - Motorola format uses different register names than defined in m68k.h. - We also take this chance to convert 'a6' to 'fp' */ - -#undef REGISTER_NAMES - -#define REGISTER_NAMES \ -{"%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7", \ - "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%fp", "%sp", \ - "%fp0", "%fp1", "%fp2", "%fp3", "%fp4", "%fp5", "%fp6", "%fp7", "argptr" } - -/* This is how to output an assembler line that says to advance the - location counter to a multiple of 2**LOG bytes. */ - -#undef ASM_OUTPUT_ALIGN -#define ASM_OUTPUT_ALIGN(FILE,LOG) \ -do { \ - if ((LOG) > 0) \ - fprintf ((FILE), "%s%u\n", ALIGN_ASM_OP, 1 << (LOG)); \ - else if ((LOG) > 31) \ - abort (); \ -} while (0) - -/* The routine used to output null terminated string literals. We cannot - use the ".string" pseudo op, because it silently truncates strings to - 1023 bytes. There is no "partial string op" which works like ".string" - but doesn't append a null byte, so we can't chop the input string up - into small pieces and use that. Our only remaining alternative is to - output the string one byte at a time. */ - -#define ASM_OUTPUT_ASCII(FILE,PTR,LEN) \ -do { \ - register size_t sp = 0, limit = (LEN); \ - fputs (integer_asm_op (1, TRUE), (FILE)); \ - do { \ - int ch = (PTR)[sp]; \ - if (ch > ' ' && ! (ch & 0x80) && ch != '\\') \ - { \ - fprintf ((FILE), "'%c", ch); \ - } \ - else \ - { \ - fprintf ((FILE), "0x%x", ch); \ - } \ - if (++sp < limit) \ - { \ - if ((sp % 10) == 0) \ - { \ - fprintf ((FILE), "\n%s", integer_asm_op (1, TRUE)); \ - } \ - else \ - { \ - putc (',', (FILE)); \ - } \ - } \ - } while (sp < limit); \ - putc ('\n', (FILE)); \ -} while (0) - - -/* SGS based assemblers don't understand #NO_APP and #APP, so just don't - bother emitting them. */ - -#undef ASM_APP_ON -#define ASM_APP_ON "" - -#undef ASM_APP_OFF -#define ASM_APP_OFF "" - -/* When using SGS derived assemblers, change the "MIT" or "MOTOROLA" - to "SGS/AT&T" */ - -#undef TARGET_VERSION -#define TARGET_VERSION fprintf (stderr, " (68k, SGS/AT&T syntax)"); - -/* Use proper assembler syntax for these macros. */ -#undef ASM_OUTPUT_REG_PUSH -#define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \ - asm_fprintf (FILE, "\t%Omove.l %s,-(%Rsp)\n", reg_names[REGNO]) - -#undef ASM_OUTPUT_REG_POP -#define ASM_OUTPUT_REG_POP(FILE,REGNO) \ - asm_fprintf (FILE, "\t%Omove.l (%Rsp)+,%s\n", reg_names[REGNO]) - -#undef ASM_OUTPUT_FLOAT_OPERAND -#define ASM_OUTPUT_FLOAT_OPERAND(CODE,FILE,VALUE) \ - do { long l; \ - REAL_VALUE_TO_TARGET_SINGLE (VALUE, l); \ - asm_fprintf ((FILE), "%I0x%lx", l); \ - } while (0) - -#undef ASM_OUTPUT_DOUBLE_OPERAND -#define ASM_OUTPUT_DOUBLE_OPERAND(FILE,VALUE) \ - do { long l[2]; \ - REAL_VALUE_TO_TARGET_DOUBLE (VALUE, l); \ - asm_fprintf ((FILE), "%I0x%lx%08lx", l[0], l[1]);\ - } while (0) - -/* How to output a block of SIZE zero bytes. Note that the `space' pseudo, - when used in the text segment, causes SGS assemblers to output nop insns - rather than 0s, so we set ASM_NO_SKIP_IN_TEXT to prevent this. */ - -#define ASM_NO_SKIP_IN_TEXT 1 - -#undef ASM_OUTPUT_SKIP -#define ASM_OUTPUT_SKIP(FILE,SIZE) \ - fprintf (FILE, "%s%u\n", SPACE_ASM_OP, (int)(SIZE)) - -/* Translate Motorola opcodes such as `jbeq' into SGS opcodes such - as `beq.w'. - Delete the `e' in `move...' and `fmove'. - Change `ftst' to `ftest'. - Change `fbne' to `fbneq' - Change `fsne' to `fsneq' - Change `divsl' to `tdivs' (32/32 -> 32r:32q) - Change `divul' to `tdivu' (32/32 -> 32r:32q) - Optionally change swap to swap.w. - */ - -#ifdef SGS_SWAP_W -#define ASM_OUTPUT_OPCODE(FILE, PTR) \ -{ \ - extern int flag_pic; \ - if (!strncmp ((PTR), "jbsr", 4)) \ - { if (flag_pic) \ - fprintf ((FILE), "bsr"); \ - else \ - fprintf ((FILE), "jsr"); \ - (PTR) += 4; } \ - else if ((PTR)[0] == 'j' && (PTR)[1] == 'b') \ - { ++(PTR); \ - while (*(PTR) != ' ') \ - { putc (*(PTR), (FILE)); ++(PTR); } \ - fprintf ((FILE), ".w"); } \ - else if ((PTR)[0] == 's') \ - { \ - if (!strncmp ((PTR), "swap", 4)) \ - { fprintf ((FILE), "swap.w"); (PTR) += 4; } \ - } \ -/* FMOVE ==> FMOV, (and F%& F%$ translations) */ \ - else if ((PTR)[0] == 'f') \ - { \ - if (!strncmp ((PTR), "fmove", 5)) \ - { fprintf ((FILE), "fmov"); (PTR) += 5; } \ - else if (!strncmp ((PTR), "ftst", 4)) \ - { fprintf ((FILE), "ftest"); (PTR) += 4; } \ - else if (!strncmp ((PTR), "fbne", 4)) \ - { fprintf ((FILE), "fbneq"); (PTR) += 4; } \ - else if (!strncmp ((PTR), "fsne", 4)) \ - { fprintf ((FILE), "fsneq"); (PTR) += 4; } \ - else if (!strncmp ((PTR), "f%$move", 7)) \ - { (PTR) += 7; \ - if (TARGET_68040_ONLY) \ - fprintf ((FILE), "fsmov"); \ - else fprintf ((FILE), "fmov"); } \ - else if (!strncmp ((PTR), "f%&move", 7)) \ - { (PTR) += 7; \ - if (TARGET_68040_ONLY) \ - fprintf ((FILE), "fdmov"); \ - else fprintf ((FILE), "fmov"); } \ - } \ -/* MOVE, MOVEA, MOVEQ, MOVEC ==> MOV */ \ - else if ((PTR)[0] == 'm' && (PTR)[1] == 'o' \ - && (PTR)[2] == 'v' && (PTR)[3] == 'e') \ - { fprintf ((FILE), "mov"); (PTR) += 4; \ - if ((PTR)[0] == 'q' || (PTR)[0] == 'a' \ - || (PTR)[0] == 'c') (PTR)++; } \ -/* SUB, SUBQ, SUBA, SUBI ==> SUB */ \ - else if ((PTR)[0] == 's' && (PTR)[1] == 'u' \ - && (PTR)[2] == 'b') \ - { fprintf ((FILE), "sub"); (PTR) += 3; \ - if ((PTR)[0] == 'q' || (PTR)[0] == 'i' \ - || (PTR)[0] == 'a') (PTR)++; } \ -/* CMP, CMPA, CMPI, CMPM ==> CMP */ \ - else if ((PTR)[0] == 'c' && (PTR)[1] == 'm' \ - && (PTR)[2] == 'p') \ - { fprintf ((FILE), "cmp"); (PTR) += 3; \ - if ((PTR)[0] == 'a' || (PTR)[0] == 'i' \ - || (PTR)[0] == 'm') (PTR)++; } \ -/* DIVSL ==> TDIVS */ \ - else if ((PTR)[0] == 'd' && (PTR)[1] == 'i' \ - && (PTR)[2] == 'v' && (PTR)[3] == 's' \ - && (PTR)[4] == 'l') \ - { fprintf ((FILE), "tdivs"); (PTR) += 5; } \ -/* DIVUL ==> TDIVU */ \ - else if ((PTR)[0] == 'd' && (PTR)[1] == 'i' \ - && (PTR)[2] == 'v' && (PTR)[3] == 'u' \ - && (PTR)[4] == 'l') \ - { fprintf ((FILE), "tdivu"); (PTR) += 5; } \ -} - -#else /* not SGS_SWAP_W */ - -#define ASM_OUTPUT_OPCODE(FILE, PTR) \ -{ \ - extern int flag_pic; \ - if (!strncmp ((PTR), "jbsr", 4)) \ - { if (flag_pic) \ - fprintf ((FILE), "bsr"); \ - else \ - fprintf ((FILE), "jsr"); \ - (PTR) += 4; } \ - else if ((PTR)[0] == 'j' && (PTR)[1] == 'b') \ - { ++(PTR); \ - while (*(PTR) != ' ') \ - { putc (*(PTR), (FILE)); ++(PTR); } \ - fprintf ((FILE), ".w"); } \ -/* FMOVE ==> FMOV, (and F%& F%$ translations) */ \ - else if ((PTR)[0] == 'f') \ - { \ - if (!strncmp ((PTR), "fmove", 5)) \ - { fprintf ((FILE), "fmov"); (PTR) += 5; } \ - else if (!strncmp ((PTR), "ftst", 4)) \ - { fprintf ((FILE), "ftest"); (PTR) += 4; } \ - else if (!strncmp ((PTR), "fbne", 4)) \ - { fprintf ((FILE), "fbneq"); (PTR) += 4; } \ - else if (!strncmp ((PTR), "fsne", 4)) \ - { fprintf ((FILE), "fsneq"); (PTR) += 4; } \ - else if (!strncmp ((PTR), "f%$move", 7)) \ - { (PTR) += 7; \ - if (TARGET_68040_ONLY) \ - fprintf ((FILE), "fsmov"); \ - else fprintf ((FILE), "fmov"); } \ - else if (!strncmp ((PTR), "f%&move", 7)) \ - { (PTR) += 7; \ - if (TARGET_68040_ONLY) \ - fprintf ((FILE), "fdmov"); \ - else fprintf ((FILE), "fmov"); } \ - } \ -/* MOVE, MOVEA, MOVEQ, MOVEC ==> MOV */ \ - else if ((PTR)[0] == 'm' && (PTR)[1] == 'o' \ - && (PTR)[2] == 'v' && (PTR)[3] == 'e') \ - { fprintf ((FILE), "mov"); (PTR) += 4; \ - if ((PTR)[0] == 'q' || (PTR)[0] == 'a' \ - || (PTR)[0] == 'c') (PTR)++; } \ -/* SUB, SUBQ, SUBA, SUBI ==> SUB */ \ - else if ((PTR)[0] == 's' && (PTR)[1] == 'u' \ - && (PTR)[2] == 'b') \ - { fprintf ((FILE), "sub"); (PTR) += 3; \ - if ((PTR)[0] == 'q' || (PTR)[0] == 'i' \ - || (PTR)[0] == 'a') (PTR)++; } \ -/* CMP, CMPA, CMPI, CMPM ==> CMP */ \ - else if ((PTR)[0] == 'c' && (PTR)[1] == 'm' \ - && (PTR)[2] == 'p') \ - { fprintf ((FILE), "cmp"); (PTR) += 3; \ - if ((PTR)[0] == 'a' || (PTR)[0] == 'i' \ - || (PTR)[0] == 'm') (PTR)++; } \ -/* DIVSL ==> TDIVS */ \ - else if ((PTR)[0] == 'd' && (PTR)[1] == 'i' \ - && (PTR)[2] == 'v' && (PTR)[3] == 's' \ - && (PTR)[4] == 'l') \ - { fprintf ((FILE), "tdivs"); (PTR) += 5; } \ -/* DIVUL ==> TDIVU */ \ - else if ((PTR)[0] == 'd' && (PTR)[1] == 'i' \ - && (PTR)[2] == 'v' && (PTR)[3] == 'u' \ - && (PTR)[4] == 'l') \ - { fprintf ((FILE), "tdivu"); (PTR) += 5; } \ -} - -#endif /* not SGS_SWAP_W */ - -/* This macro outputs the label at the start of a switch table. The - ".swbeg " is an assembler directive that causes the switch table - size to be inserted into the object code so that disassemblers, for - example, can identify that it is the start of a switch table. */ - -#define ASM_OUTPUT_BEFORE_CASE_LABEL(FILE,PREFIX,NUM,TABLE) \ - fprintf ((FILE), "%s&%d\n", SWBEG_ASM_OP, XVECLEN (PATTERN (TABLE), 1)); - -#define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,TABLE) \ - do { \ - ASM_OUTPUT_BEFORE_CASE_LABEL((FILE),(PREFIX),(NUM),(TABLE)); \ - (*targetm.asm_out.internal_label)((FILE),(PREFIX),(NUM)); \ - } while (0) - -/* At end of a switch table, define LDnnn iff the symbol LInnn was defined. - Some SGS assemblers have a bug such that "Lnnn-LInnn-2.b(pc,d0.l*2)" - fails to assemble. Luckily "LDnnn(pc,d0.l*2)" produces the results - we want. This difference can be accommodated by making the assembler - define such "LDnnn" to be either "Lnnn-LInnn-2.b", "Lnnn", or any other - string, as necessary. This is accomplished via the ASM_OUTPUT_CASE_END - macro. */ - -#undef ASM_OUTPUT_CASE_END -#define ASM_OUTPUT_CASE_END(FILE,NUM,TABLE) \ -{ if (switch_table_difference_label_flag) \ - asm_fprintf (FILE, "%s%LLD%d,%LL%d-%LLI%d-2.b\n",\ - SET_ASM_OP, (NUM), (NUM), (NUM)); \ - switch_table_difference_label_flag = 0; } - -extern int switch_table_difference_label_flag; - -/* This is how to output an element of a case-vector that is relative. */ - -#undef ASM_OUTPUT_ADDR_DIFF_ELT -#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ - asm_fprintf (FILE, "%s%LL%d-%LL%d\n", integer_asm_op (2, TRUE), VALUE, REL) - -/* Currently, JUMP_TABLES_IN_TEXT_SECTION must be defined in order to - keep switch tables in the text section. */ - -#define JUMP_TABLES_IN_TEXT_SECTION 1 diff --git a/gcc/config/m68k/t-hp320 b/gcc/config/m68k/t-hp320 deleted file mode 100644 index d3bbb66f229..00000000000 --- a/gcc/config/m68k/t-hp320 +++ /dev/null @@ -1,2 +0,0 @@ -# So putenv and other functions get seen by fixproto. -FIXPROTO_DEFINES = -D_HPUX_SOURCE diff --git a/gcc/config/netware.h b/gcc/config/netware.h deleted file mode 100644 index 241e92dcf7c..00000000000 --- a/gcc/config/netware.h +++ /dev/null @@ -1,68 +0,0 @@ -/* netware.h -- operating system specific defines to be used when - targeting GCC for some generic NetWare 4 system. - Copyright (C) 1993, 1994, 2000, 2001, 2002 Free Software Foundation, Inc. - - Written by David V. Henkel-Wallace (gumby@cygnus.com) - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GCC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/* We don't actually need any of these; the MD_ vars are ignored - anyway for cross-compilers, and the other specs won't get picked up - 'coz the user is supposed to do ld -r (hmm, perhaps that should be - the default). In any case, setting them thus will catch some - common user errors. */ - -#undef MD_EXEC_PREFIX -#undef MD_STARTFILE_PREFIX - -#undef LIB_SPEC -#define LIB_SPEC "" - -/* Kinda useless, but what the hell */ -#undef LINK_SPEC -#define LINK_SPEC "%{h*} %{V} %{v:%{!V:-V}} \ - %{b} %{Wl,*:%*} \ - %{Qy:} %{!Qn:-Qy}" - -#undef STARTFILE_SPEC -#define STARTFILE_SPEC "" - -#undef ENDFILE_SPEC -#define ENDFILE_SPEC "" - -#undef RELATIVE_PREFIX_NOT_LINKDIR -#undef LIBGCC_SPEC - -/* set debugging info */ -#define DBX_DEBUGGING_INFO 1 -#undef SDB_DEBUGGING_INFO -#undef XCOFF_DEBUGGING_INFO -#undef PREFERRED_DEBUGGING_TYPE -#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG - -/* Support const sections and the ctors and dtors sections for g++. */ - -#undef HAS_INIT_SECTION -#undef INIT_SECTION_ASM_OP - -#undef READONLY_DATA_SECTION_ASM_OP -#define READONLY_DATA_SECTION_ASM_OP ".section\t.rodata" -#undef CTORS_SECTION_ASM_OP -#define CTORS_SECTION_ASM_OP ".section\t.ctors,\"x\"" -#undef DTORS_SECTION_ASM_OP -#define DTORS_SECTION_ASM_OP ".section\t.dtors,\"x\"" diff --git a/gcc/config/t-linux-gnulibc1 b/gcc/config/t-linux-gnulibc1 deleted file mode 100644 index 52effd5ca2f..00000000000 --- a/gcc/config/t-linux-gnulibc1 +++ /dev/null @@ -1,7 +0,0 @@ -# We are building for the Linux C library 5. -T_CFLAGS = -DUSE_GNULIBC_1 - -# Use unwind-dw2-fde -LIB2ADDEH = $(srcdir)/unwind-dw2.c $(srcdir)/unwind-dw2-fde.c \ - $(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c -LIB2ADDEHDEP = unwind.inc unwind-dw2-fde.h diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 9f0f6b91d4c..7c6b4fa8e27 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -7198,8 +7198,6 @@ declarations. @c Describe c4x pragmas here. @c Describe h8300 pragmas here. -@c Describe i370 pragmas here. -@c Describe i960 pragmas here. @c Describe sh pragmas here. @c Describe v850 pragmas here. diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi index 8379fe773bb..31f51040f59 100644 --- a/gcc/doc/install.texi +++ b/gcc/doc/install.texi @@ -530,7 +530,7 @@ provide a configure target when configuring a native compiler. @item @var{target} must be specified as @option{--target=@var{target}} when configuring a cross compiler; examples of valid targets would be -i960-rtems, m68k-coff, sh-elf, etc. +m68k-coff, sh-elf, etc. @item Specifying just @var{target} instead of @option{--target=@var{target}} @@ -2010,8 +2010,6 @@ GNU Compiler Collection on your machine. @item @uref{#dos,,DOS} @item -@uref{#dsp16xx,,dsp16xx} -@item @uref{#*-*-freebsd*,,*-*-freebsd*} @item @uref{#h8300-hms,,h8300-hms} @@ -2022,8 +2020,6 @@ GNU Compiler Collection on your machine. @item @uref{#hppa*-hp-hpux11,,hppa*-hp-hpux11} @item -@uref{#i370-*-*,,i370-*-*} -@item @uref{#*-*-linux-gnu,,*-*-linux-gnu} @item @uref{#ix86-*-linux*aout,,i?86-*-linux*aout} @@ -2401,12 +2397,6 @@ any MSDOS compiler except itself. You need to get the complete compilation package DJGPP, which includes binaries as well as sources, and includes all the necessary compilation tools and libraries. -@html -
-@end html -@heading @anchor{dsp16xx}dsp16xx -A port to the AT&T DSP1610 family of processors. - @html
@end html @@ -2622,13 +2612,6 @@ either HP's unbundled compiler, or a binary distribution of GCC@. This port still is undergoing significant development. -@html -
-@end html -@heading @anchor{i370-*-*}i370-*-* -This port is very preliminary and has many known bugs. We hope to -have a higher-quality port for this machine soon. - @html
@end html diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 54239048997..adf156f89e3 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -510,16 +510,6 @@ in the following sections. -mschedule=@var{cpu-type} -mspace-regs -msio -mwsio @gol -nolibdld -static -threads} -@emph{Intel 960 Options} -@gccoptlist{-m@var{cpu-type} -masm-compat -mclean-linkage @gol --mcode-align -mcomplex-addr -mleaf-procedures @gol --mic-compat -mic2.0-compat -mic3.0-compat @gol --mintel-asm -mno-clean-linkage -mno-code-align @gol --mno-complex-addr -mno-leaf-procedures @gol --mno-old-align -mno-strict-align -mno-tail-call @gol --mnumerics -mold-align -msoft-float -mstrict-align @gol --mtail-call} - @emph{DEC Alpha Options} @gccoptlist{-mno-fp-regs -msoft-float -malpha-as -mgas @gol -mieee -mieee-with-inexact -mieee-conformant @gol @@ -605,10 +595,6 @@ in the following sections. -minline-int-divide-max-throughput -mno-dwarf2-asm @gol -mfixed-range=@var{register-range}} -@emph{D30V Options} -@gccoptlist{-mextmem -mextmemory -monchip -mno-asm-optimize @gol --masm-optimize -mbranch-cost=@var{n} -mcond-exec=@var{n}} - @emph{S/390 and zSeries Options} @gccoptlist{-mtune=@var{cpu-type} -march=@var{cpu-type} @gol -mhard-float -msoft-float -mbackchain -mno-backchain @gol @@ -5847,7 +5833,6 @@ that macro, which enables you to change the defaults. * MIPS Options:: * i386 and x86-64 Options:: * HPPA Options:: -* Intel 960 Options:: * DEC Alpha Options:: * DEC Alpha/VMS Options:: * H8/300 Options:: @@ -5860,7 +5845,6 @@ that macro, which enables you to change the defaults. * AVR Options:: * MCore Options:: * IA-64 Options:: -* D30V Options:: * S/390 and zSeries Options:: * CRIS Options:: * MMIX Options:: @@ -8717,118 +8701,6 @@ under HP-UX. This option sets flags for both the preprocessor and linker. @end table -@node Intel 960 Options -@subsection Intel 960 Options - -These @samp{-m} options are defined for the Intel 960 implementations: - -@table @gcctabopt -@item -m@var{cpu-type} -@opindex mka -@opindex mkb -@opindex mmc -@opindex mca -@opindex mcf -@opindex msa -@opindex msb -Assume the defaults for the machine type @var{cpu-type} for some of -the other options, including instruction scheduling, floating point -support, and addressing modes. The choices for @var{cpu-type} are -@samp{ka}, @samp{kb}, @samp{mc}, @samp{ca}, @samp{cf}, -@samp{sa}, and @samp{sb}. -The default is -@samp{kb}. - -@item -mnumerics -@itemx -msoft-float -@opindex mnumerics -@opindex msoft-float -The @option{-mnumerics} option indicates that the processor does support -floating-point instructions. The @option{-msoft-float} option indicates -that floating-point support should not be assumed. - -@item -mleaf-procedures -@itemx -mno-leaf-procedures -@opindex mleaf-procedures -@opindex mno-leaf-procedures -Do (or do not) attempt to alter leaf procedures to be callable with the -@code{bal} instruction as well as @code{call}. This will result in more -efficient code for explicit calls when the @code{bal} instruction can be -substituted by the assembler or linker, but less efficient code in other -cases, such as calls via function pointers, or using a linker that doesn't -support this optimization. - -@item -mtail-call -@itemx -mno-tail-call -@opindex mtail-call -@opindex mno-tail-call -Do (or do not) make additional attempts (beyond those of the -machine-independent portions of the compiler) to optimize tail-recursive -calls into branches. You may not want to do this because the detection of -cases where this is not valid is not totally complete. The default is -@option{-mno-tail-call}. - -@item -mcomplex-addr -@itemx -mno-complex-addr -@opindex mcomplex-addr -@opindex mno-complex-addr -Assume (or do not assume) that the use of a complex addressing mode is a -win on this implementation of the i960. Complex addressing modes may not -be worthwhile on the K-series, but they definitely are on the C-series. -The default is currently @option{-mcomplex-addr} for all processors except -the CB and CC@. - -@item -mcode-align -@itemx -mno-code-align -@opindex mcode-align -@opindex mno-code-align -Align code to 8-byte boundaries for faster fetching (or don't bother). -Currently turned on by default for C-series implementations only. - -@ignore -@item -mclean-linkage -@itemx -mno-clean-linkage -@opindex mclean-linkage -@opindex mno-clean-linkage -These options are not fully implemented. -@end ignore - -@item -mic-compat -@itemx -mic2.0-compat -@itemx -mic3.0-compat -@opindex mic-compat -@opindex mic2.0-compat -@opindex mic3.0-compat -Enable compatibility with iC960 v2.0 or v3.0. - -@item -masm-compat -@itemx -mintel-asm -@opindex masm-compat -@opindex mintel-asm -Enable compatibility with the iC960 assembler. - -@item -mstrict-align -@itemx -mno-strict-align -@opindex mstrict-align -@opindex mno-strict-align -Do not permit (do permit) unaligned accesses. - -@item -mold-align -@opindex mold-align -Enable structure-alignment compatibility with Intel's gcc release version -1.3 (based on gcc 1.37). This option implies @option{-mstrict-align}. - -@item -mlong-double-64 -@opindex mlong-double-64 -Implement type @samp{long double} as 64-bit floating point numbers. -Without the option @samp{long double} is implemented by 80-bit -floating point numbers. The only reason we have it because there is -no 128-bit @samp{long double} support in @samp{fp-bit.c} yet. So it -is only useful for people using soft-float targets. Otherwise, we -should recommend against use of it. - -@end table - @node DEC Alpha Options @subsection DEC Alpha Options @@ -10020,50 +9892,6 @@ instruction that triggered the stop bit. This can improve instruction scheduling, but does not always do so. @end table -@node D30V Options -@subsection D30V Options -@cindex D30V Options - -These @samp{-m} options are defined for D30V implementations: - -@table @gcctabopt -@item -mextmem -@opindex mextmem -Link the @samp{.text}, @samp{.data}, @samp{.bss}, @samp{.strings}, -@samp{.rodata}, @samp{.rodata1}, @samp{.data1} sections into external -memory, which starts at location @code{0x80000000}. - -@item -mextmemory -@opindex mextmemory -Same as the @option{-mextmem} switch. - -@item -monchip -@opindex monchip -Link the @samp{.text} section into onchip text memory, which starts at -location @code{0x0}. Also link @samp{.data}, @samp{.bss}, -@samp{.strings}, @samp{.rodata}, @samp{.rodata1}, @samp{.data1} sections -into onchip data memory, which starts at location @code{0x20000000}. - -@item -mno-asm-optimize -@itemx -masm-optimize -@opindex mno-asm-optimize -@opindex masm-optimize -Disable (enable) passing @option{-O} to the assembler when optimizing. -The assembler uses the @option{-O} option to automatically parallelize -adjacent short instructions where possible. - -@item -mbranch-cost=@var{n} -@opindex mbranch-cost -Increase the internal costs of branches to @var{n}. Higher costs means -that the compiler will issue more instructions to avoid doing a branch. -The default is 2. - -@item -mcond-exec=@var{n} -@opindex mcond-exec -Specify the maximum number of conditionally executed instructions that -replace a branch. The default is 4. -@end table - @node S/390 and zSeries Options @subsection S/390 and zSeries Options @cindex S/390 and zSeries Options diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index 131280cae19..e81e350578b 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -1612,36 +1612,6 @@ Constant in range @minus{}2147483648 to 2147483647 or symbolic reference known t Standard 80387 floating point constant @end table -@item Intel 960---@file{i960.h} -@table @code -@item f -Floating point register (@code{fp0} to @code{fp3}) - -@item l -Local register (@code{r0} to @code{r15}) - -@item b -Global register (@code{g0} to @code{g15}) - -@item d -Any local or global register - -@item I -Integers from 0 to 31 - -@item J -0 - -@item K -Integers from @minus{}31 to 0 - -@item G -Floating point 0 - -@item H -Floating point 1 -@end table - @item Intel IA-64---@file{ia64.h} @table @code @item a diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 0e6147374d1..62ae2ac8dff 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2004-02-04 Kazu Hirata + + * gcc.dg/20020312-2.c, gcc.dg/builtin-inf-1.c, + gcc.dg/sibcall-3.c, gcc.dg/sibcall-4.c, gcc.dg/cpp/assert4.c: + Remove mentions of obsolete ports. + 2004-02-04 Paolo Bonzini * gcc.dg/noncompile/20001228-1.c: Fix for new diff --git a/gcc/testsuite/gcc.dg/20020312-2.c b/gcc/testsuite/gcc.dg/20020312-2.c index c6b9d8e26fa..6e59cd6cf6f 100644 --- a/gcc/testsuite/gcc.dg/20020312-2.c +++ b/gcc/testsuite/gcc.dg/20020312-2.c @@ -18,22 +18,14 @@ /* No pic register. */ #elif defined(__cris__) # define PIC_REG "0" -#elif defined(__D30V__) -/* No pic register. */ -#elif defined(__dsp1600__) -/* No pic register. */ #elif defined(__fr30__) /* No pic register. */ #elif defined(__H8300__) || defined(__H8300H__) || defined(__H8300S__) /* No pic register. */ #elif defined(_IBMR2) /* No pic register. */ -#elif #cpu(i370) -/* No pic register. */ #elif defined(__i386__) # define PIC_REG "ebx" -#elif defined(__i960__) -/* No pic register. */ #elif defined(__ia64__) /* PIC register is r1, but is used even without -fpic. */ #elif defined(__M32R__) diff --git a/gcc/testsuite/gcc.dg/builtin-inf-1.c b/gcc/testsuite/gcc.dg/builtin-inf-1.c index ca235adeec0..d2d28415899 100644 --- a/gcc/testsuite/gcc.dg/builtin-inf-1.c +++ b/gcc/testsuite/gcc.dg/builtin-inf-1.c @@ -8,6 +8,6 @@ float fh = __builtin_huge_valf(); double dh = __builtin_huge_val(); long double lh = __builtin_huge_vall(); -/* { dg-warning "does not support infinity" "INF unsupported" { target vax-*-* i370-*-* c4x-*-* } 3 } */ -/* { dg-warning "does not support infinity" "INF unsupported" { target vax-*-* i370-*-* c4x-*-* } 4 } */ -/* { dg-warning "does not support infinity" "INF unsupported" { target vax-*-* i370-*-* c4x-*-* } 5 } */ +/* { dg-warning "does not support infinity" "INF unsupported" { target vax-*-* c4x-*-* } 3 } */ +/* { dg-warning "does not support infinity" "INF unsupported" { target vax-*-* c4x-*-* } 4 } */ +/* { dg-warning "does not support infinity" "INF unsupported" { target vax-*-* c4x-*-* } 5 } */ diff --git a/gcc/testsuite/gcc.dg/cpp/assert4.c b/gcc/testsuite/gcc.dg/cpp/assert4.c index e71baf2bb35..82ae7aa6efb 100644 --- a/gcc/testsuite/gcc.dg/cpp/assert4.c +++ b/gcc/testsuite/gcc.dg/cpp/assert4.c @@ -192,14 +192,6 @@ # error #endif -#if defined __d30v__ -# if !#cpu(d30v) || !#machine(d30v) -# error -# endif -#elif #cpu(d30v) || #machine(d30v) -# error -#endif - #if defined __fr30__ # if !#cpu(fr30) || !#machine(fr30) # error @@ -270,14 +262,6 @@ # error #endif -#if defined __i960__ -# if !#cpu(i960) || !#machine(i960) -# error -# endif -#elif #cpu(i960) || #machine(i960) -# error -#endif - #if defined __ia64__ # if !#cpu(ia64) || !#machine(ia64) # error diff --git a/gcc/testsuite/gcc.dg/sibcall-3.c b/gcc/testsuite/gcc.dg/sibcall-3.c index aafda2be41f..f1e9fa1ca7f 100644 --- a/gcc/testsuite/gcc.dg/sibcall-3.c +++ b/gcc/testsuite/gcc.dg/sibcall-3.c @@ -5,7 +5,7 @@ Copyright (C) 2002 Free Software Foundation Inc. Contributed by Hans-Peter Nilsson */ -/* { dg-do run { xfail arc-*-* avr-*-* c4x-*-* cris-*-* h8300-*-* i370-*-* i960-*-* ip2k-*-* m32r-*-* m68hc1?-*-* m681?-*-* m680*-*-* m68k-*-* mcore-*-* mips*-*-* mn10300-*-* ns32k-*-* s390*-*-* xstormy16-*-* v850*-*-* vax-*-* xtensa-*-* } } */ +/* { dg-do run { xfail arc-*-* avr-*-* c4x-*-* cris-*-* h8300-*-* ip2k-*-* m32r-*-* m68hc1?-*-* m681?-*-* m680*-*-* m68k-*-* mcore-*-* mips*-*-* mn10300-*-* ns32k-*-* s390*-*-* xstormy16-*-* v850*-*-* vax-*-* xtensa-*-* } } */ /* { dg-options "-O2 -foptimize-sibling-calls" } */ /* The option -foptimize-sibling-calls is the default, but serves as diff --git a/gcc/testsuite/gcc.dg/sibcall-4.c b/gcc/testsuite/gcc.dg/sibcall-4.c index 73a5744c174..1624b897874 100644 --- a/gcc/testsuite/gcc.dg/sibcall-4.c +++ b/gcc/testsuite/gcc.dg/sibcall-4.c @@ -5,7 +5,7 @@ Copyright (C) 2002 Free Software Foundation Inc. Contributed by Hans-Peter Nilsson */ -/* { dg-do run { xfail arc-*-* avr-*-* c4x-*-* cris-*-* h8300-*-* i370-*-* i960-*-* ip2k-*-* m32r-*-* m68hc1?-*-* m681?-*-* m680*-*-* m68k-*-* mcore-*-* mips*-*-* mn10300-*-* ns32k-*-* s390*-*-* xstormy16-*-* v850*-*-* vax-*-* xtensa-*-* } } */ +/* { dg-do run { xfail arc-*-* avr-*-* c4x-*-* cris-*-* h8300-*-* ip2k-*-* m32r-*-* m68hc1?-*-* m681?-*-* m680*-*-* m68k-*-* mcore-*-* mips*-*-* mn10300-*-* ns32k-*-* s390*-*-* xstormy16-*-* v850*-*-* vax-*-* xtensa-*-* } } */ /* { dg-options "-O2 -foptimize-sibling-calls" } */ /* The option -foptimize-sibling-calls is the default, but serves as