+2004-02-04 Kazu Hirata <kazu@cs.umass.edu>
+
+ * 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 <jh@suse.cz>
* alias.c (find_base_term, get_addr): Do not dereference NULL
# 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}.
# 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
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
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
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"
;;
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
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
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
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"
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"
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"
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"
;;
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"
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
+++ /dev/null
--*- 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
+++ /dev/null
-/* 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 *);
-\f
-
-/* 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
+++ /dev/null
-/* 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];
-\f
-/* 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;
-\f
-/* 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;
-}
-
-\f
-/* 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;
-}
-
-\f
-/* 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;
-}
-
-\f
-/* 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))
- : "<unknown>"));
-
- 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);
-}
-
-\f
-/* 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;
-}
-
-\f
-/* 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);
- }
-}
-
-\f
-/* 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;
-}
-
-\f
-/* 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;
-}
-
-\f
-/* 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;
-}
-
-\f
-/* 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;
-}
-
-\f
-/* 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);
-}
-
-\f
-/* 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));
-}
-
-\f
-/* 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);
-}
-
-\f
-/* 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));
-}
-
-\f
-/* 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);
-}
-
-\f
-/* 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;
-}
-\f
-/* 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. */
-}
-
-\f
-/* 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 ());
-}
-
-\f
-/* 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 */
-}
-
-\f
-
-/* 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));
-}
-
-\f
-/* 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");
-}
-
-\f
-/* 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 ();
- }
-}
-
-\f
-/* 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);
-}
-
-\f
-/* 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);
-}
-
-\f
-/* 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);
- }
- }
-}
-
-\f
-/* A C expression for the size in bytes of the trampoline, as an integer. */
-
-int
-d30v_trampoline_size ()
-{
- return 16;
-}
-
-\f
-/* 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));
-}
-
-\f
-/* 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,<static-chain>
- jmp <fnaddr> */
- 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)));
-}
-
-\f
-/* 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;
-}
-
-\f
-/* 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;
-}
-
-\f
-/* 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;
-}
-
-\f
-/* 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);
-}
-
-\f
-/* 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);
-}
-
-\f
-/* 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;
-}
-
-\f
-/* 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;
-}
-
-\f
-/* 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);
-}
-\f
-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;
- }
-}
+++ /dev/null
-/* 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))
-
-\f
-/* 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 "" */
-
-\f
-/* 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
-
-\f
-/* 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
-\f
-/* 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 */
-
-\f
-/* 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)
-
-\f
-/* 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 */ \
-}
-
-\f
-/* 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, \
-}
-
-\f
-/* 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
-
-\f
-/* 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)
-
-\f
-/* 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 ()
-
-\f
-/* 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)
-
-\f
-/* 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 (); \
-}
-
-\f
-/* 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
-
-\f
-/* 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)
-
-\f
-/* 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)
-
-\f
-/* 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
-
-\f
-/* 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;
-
-\f
-/* 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)
-
-\f
-/* 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))
-\f
-/* 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)
-
-\f
-/* 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
-
-\f
-/* 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
-
-\f
-/* 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"
-
-\f
-/* 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"
-
-\f
-/* Output and Generation of Labels. */
-
-/* Globalizing directive for a label. */
-#define GLOBAL_ASM_OP "\t.globl "
-
-\f
-/* 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
-
-\f
-/* 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 ""
-
-\f
-/* 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)
-
-\f
-/* 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))
-
-\f
-/* 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
-
-\f
-/* 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 */
+++ /dev/null
-;; 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.
-
-\f
-;; ::::::::::::::::::::
-;; ::
-;; :: 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.
-
-\f
-;; ::::::::::::::::::::
-;; ::
-;; :: 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"))
-\f
-;; ::::::::::::::::::::
-;; ::
-;; :: 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")])
-
-\f
-;; ::::::::::::::::::::
-;; ::
-;; :: 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)])
-
-\f
-;; ::::::::::::::::::::
-;; ::
-;; :: 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]);
-}")
-
-\f
-;; ::::::::::::::::::::
-;; ::
-;; :: 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]);
-}")
-
-\f
-;; ::::::::::::::::::::
-;; ::
-;; :: 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")])
-
-\f
-;; ::::::::::::::::::::
-;; ::
-;; :: 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]);
-}")
-
-\f
-;; ::::::::::::::::::::
-;; ::
-;; :: 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")])
-
-\f
-;; ::::::::::::::::::::
-;; ::
-;; :: 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")])
-
-\f
-;; ::::::::::::::::::::
-;; ::
-;; :: 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")])
-
-\f
-;; ::::::::::::::::::::
-;; ::
-;; :: 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]);
-}")
-
-\f
-;; ::::::::::::::::::::
-;; ::
-;; :: 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")])
-
-\f
-;; ::::::::::::::::::::
-;; ::
-;; :: 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])));
-}")
-
-\f
-;; ::::::::::::::::::::
-;; ::
-;; :: 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")])
-\f
-;; ::::::::::::::::::::
-;; ::
-;; :: 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)))]
- "")
-
-\f
-;; ::::::::::::::::::::
-;; ::
-;; :: 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")])
-\f
-;; ::::::::::::::::::::
-;; ::
-;; :: 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")])
-
-\f
-
-;; ::::::::::::::::::::
-;; ::
-;; :: 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;
- }
-}")
-
-\f
-;; ::::::::::::::::::::
-;; ::
-;; :: 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);
-}")
-
-\f
-;; ::::::::::::::::::::
-;; ::
-;; :: 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")])
-\f
-;; ::::::::::::::::::::
-;; ::
-;; :: Conditional execution
-;; ::
-;; ::::::::::::::::::::
-
-(define_cond_exec
- [(match_operator:CC 0 "condexec_test_operator"
- [(match_operand:CC 1 "br_flag_operand" "b")
- (const_int 0)])]
- ""
- "")
+++ /dev/null
-/* 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.
- *
- */
-
-\f
-#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 */
-
-\f
-#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 */
+++ /dev/null
-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
+++ /dev/null
-/* 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);
+++ /dev/null
-/* 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);
+++ /dev/null
-/* 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);
-\f
-/* 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;
-}
-
-\f
-/* 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;
-}
-\f
-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;
-}
+++ /dev/null
-/* 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; \
- } \
-}
-\f
-/* 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
-\f
-/* 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"
-
-\f
-/* 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
-\f
-/* 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)
-\f
-/* 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)
-\f
-
-/* 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(); \
-}
-\f
-/* 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
-
-\f
-/* 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
-\f
-/* 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; \
-}
-
-\f
-/* 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)
-
-\f
-/* 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) )
-\f
-/* 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
-\f
-
-/* 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) */
-
-\f
-/* 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"
-\f
-/* 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 ""
-\f
-/* 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"
-\f
-/* 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);
-\f
-/* 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))
-
-\f
-/* 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");
-\f
-/* 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)
-
-\f
-/* 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
-
+++ /dev/null
-;;- 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.
-\f
-;; 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)
-
-\f
-;; ....................
-;;
-;; 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")])
-
-\f
-;;
-;; ....................
-;;
-;; 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")])
-\f
-;;
-;;
-;; 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;
-}")
-
-\f
-;; ....................
-;;
-;; 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;
-}")
-
-\f
-;;
-;; ....................
-;;
-;; 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;
-}")
-
-\f
-
-;;
-;; *******************
-;;
-;; 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;
-}")
-\f
-;;
-;; ....................
-;;
-;; 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;
-}")
-
-\f
-
-;;
-;; ********************
-;;
-;; 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")])
-
-\f
-;;
-;; 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); }")
-
-\f
-;; 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;
-}")
-
-\f
-;;
-;; 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")])
-\f
-;;
-;; 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 \"}\";
- }
-}")
-
-
-\f
-;;
-;; 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\";
- }
-}")
-
-\f
-;;
-;; 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")])
-
-
-\f
-;; 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 \"}\";
- }
-}")
-
-\f
-
-
-(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")])
-\f
-;;
-;; 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")])
-\f
-;;
-;; 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")])
-\f
-;;
-;; 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")
+++ /dev/null
-
-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
-
-
-
-
-
-
+++ /dev/null
-/* 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
+++ /dev/null
-/* 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 */
+++ /dev/null
-/* 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 */
-/* ===================================================== */
-
-\f
-/* 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;
-\f
-/* 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;
- }
-}
+++ /dev/null
-/* 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<<LOG.
-
- However, GAS now has .p2align and .balign pseudo-ops so to remove any
- doubt or guess work, and since this file is used for both a.out and other
- file formats, we use one of them. */
-
-#define ASM_OUTPUT_ALIGN(FILE,LOG) \
- if ((LOG)!=0) fprintf ((FILE), "\t.balign %d\n", 1<<(LOG))
-
-/* Globalizing directive for a label. */
-#define GLOBAL_ASM_OP ".globl "
-
-/* This says how to output an assembler line
- to define a global common symbol. */
-
-#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
-( fputs (".comm ", (FILE)), \
- assemble_name ((FILE), (NAME)), \
- fprintf ((FILE), ","HOST_WIDE_INT_PRINT_UNSIGNED"\n", (ROUNDED)))
-
-/* This says how to output an assembler line
- to define a local common symbol. */
-
-#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
-( fputs (".lcomm ", (FILE)), \
- assemble_name ((FILE), (NAME)), \
- fprintf ((FILE), ","HOST_WIDE_INT_PRINT_UNSIGNED"\n", (ROUNDED)))
-
-#endif /* TARGET_ELF_ABI */
-#endif /* ! GCC_I370_H */
+++ /dev/null
-;;- Machine description for GNU compiler -- System/370 version.
-;; Copyright (C) 1989, 1993, 1994, 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)
-;; Lots of Bug Fixes & Enhancements 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.
-
-;; =======================================================================
-;; Condition codes for some of the instructions (in particular, for
-;; add, sub, shift, abs, etc. are handled with the cpp macro NOTICE_UPDATE_CC
-;;
-;; Special constraints for 370 machine description:
-;;
-;; a -- Any address register from 1 to 15.
-;; d -- Any register from 0 to 15.
-;; I -- An 8-bit constant (0..255).
-;; J -- A 12-bit constant (0..4095).
-;; K -- A 16-bit constant (-32768..32767).
-;; R -- a valid S operand in an RS, SI or SS instruction, or register
-;; S -- a valid S operand in an RS, SI or SS instruction
-;;
-;; Note this well:
-;; When defining an instruction, e.g. the movsi pattern:
-;;
-;; (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"))]
-;;
-;; The "r_or_s_operand" predicate is used to recognize the instruction;
-;; however, it is not further used to enforce a constraint at later stages.
-;; Thus, for example, although "r_or_s_operand" bars operands of the form
-;; base+index+displacement, such operands can none-the-less show up during
-;; post-instruction-recog processing: thus, for example, garbage like
-;; MVC 152(4,r13),0(r5,r13) might be generated if both op0 and op1 are
-;; mem operands. To avoid this, use the S constraint.
-;;
-;;
-;; Special formats used for outputting 370 instructions.
-;;
-;; %B -- Print a constant byte integer.
-;; %H -- Print a signed 16-bit constant.
-;; %K -- Print a signed 16-bit constant signed-extended to 32-bits.
-;; %L -- Print least significant word of a CONST_DOUBLE.
-;; %M -- Print most significant word of a CONST_DOUBLE.
-;; %N -- Print next register (second word of a DImode reg).
-;; %O -- Print the offset of a memory reference (PLUS (REG) (CONST_INT)).
-;; %R -- Print the register of a memory reference (PLUS (REG) (CONST_INT)).
-;; %X -- Print a constant byte integer in hex.
-;; %W -- Print a signed 32-bit int sign-extended to 64-bits.
-;;
-;; We have a special constraint for pattern matching.
-;;
-;; s_operand -- Matches a valid S operand in a RS, SI or SS type instruction.
-;;
-;; r_or_s_operand -- Matches a register or a valid S operand in a RS, SI
-;; or SS type instruction or a register
-;;
-;; For MVS C/370 we use the following stack locations for:
-;;
-;; 136 - internal function result buffer
-;; 140 - numeric conversion buffer
-;; 144 - pointer to internal function result buffer
-;; 148 - start of automatic variables and function arguments
-;;
-;; To support programs larger than a page, 4096 bytes, PAGE_REGISTER points
-;; to a page origin table, all internal labels are generated to reload the
-;; BASE_REGISTER knowing what page it is on and all branch instructions go
-;; directly to the target if it is known that the target is on the current
-;; page (essentially backward references). All forward references and off
-;; page references are handled by loading the address of target into a
-;; register and branching indirectly.
-;;
-;; Some *di patterns have been commented out per advice from RMS, as gcc
-;; will generate the right things to do.
-;;
-;; See the note in i370.h about register 14, clobbering it, and optimization.
-;; Basically, using clobber in egcs-1.1.1 will ruin ability to optimize around
-;; branches, so don't do it.
-;;
-;; We use the "length" attirbute to store the max possible code size of an
-;; insn. We use this length to estimate the length of forward branches, to
-;; determine if they're on page or off.
-
-(define_attr "length" "" (const_int 0))
-
-;;
-;;- Test instructions.
-;;
-
-;
-; tstdi instruction pattern(s).
-;
-
-(define_insn "tstdi"
- [(set (cc0)
- (match_operand:DI 0 "register_operand" "d"))]
- ""
- "*
-{
- check_label_emit ();
- mvs_check_page (0, 4, 0);
- return \"SRDA %0,0\";
-}"
- [(set_attr "length" "4")]
-)
-
-;
-; tstsi instruction pattern(s).
-;
-
-(define_insn "tstsi"
- [(set (cc0)
- (match_operand:SI 0 "register_operand" "d"))]
- ""
- "*
-{
- check_label_emit ();
- mvs_check_page (0, 2, 0);
- return \"LTR %0,%0\";
-}"
- [(set_attr "length" "2")]
-)
-
-;
-; tsthi instruction pattern(s).
-;
-
-(define_insn "tsthi"
- [(set (cc0)
- (match_operand:HI 0 "register_operand" "d"))]
- ""
- "*
-{
- check_label_emit ();
- mvs_check_page (0, 4, 2);
- return \"CH %0,=H'0'\";
-}"
- [(set_attr "length" "4")]
-)
-
-;
-; tstqi instruction pattern(s).
-;
-
-(define_insn ""
- [(set (cc0)
- (match_operand:QI 0 "r_or_s_operand" "dm"))]
- "unsigned_jump_follows_p (insn)"
- "*
-{
- check_label_emit ();
- if (REG_P (operands[0]))
- {
- /* an unsigned compare to zero is always zero/not-zero... */
- mvs_check_page (0, 4, 4);
- return \"N %0,=XL4'000000FF'\";
- }
- mvs_check_page (0, 4, 0);
- return \"CLI %0,0\";
-}"
- [(set_attr "length" "4")]
-)
-
-(define_insn "tstqi"
- [(set (cc0)
- (match_operand:QI 0 "register_operand" "d"))]
- ""
- "*
-{
- check_label_emit ();
- if (unsigned_jump_follows_p (insn))
- {
- /* an unsigned compare to zero is always zero/not-zero... */
- mvs_check_page (0, 4, 4);
- return \"N %0,=XL4'000000FF'\";
- }
- mvs_check_page (0, 8, 0);
- return \"SLL %0,24\;SRA %0,24\";
-}"
- [(set_attr "length" "8")]
-)
-
-;
-; tstdf instruction pattern(s).
-;
-
-(define_insn "tstdf"
- [(set (cc0)
- (match_operand:DF 0 "general_operand" "f"))]
- ""
- "*
-{
- check_label_emit ();
- mvs_check_page (0, 2, 0);
- return \"LTDR %0,%0\";
-}"
- [(set_attr "length" "2")]
-)
-
-;
-; tstsf instruction pattern(s).
-;
-
-(define_insn "tstsf"
- [(set (cc0)
- (match_operand:SF 0 "general_operand" "f"))]
- ""
- "*
-{
- check_label_emit ();
- mvs_check_page (0, 2, 0);
- return \"LTER %0,%0\";
-}"
- [(set_attr "length" "2")]
-)
-
-;;
-;;- Compare instructions.
-;;
-
-;
-; cmpdi instruction pattern(s).
-;
-
-;(define_insn "cmpdi"
-; [(set (cc0)
-; (compare (match_operand:DI 0 "register_operand" "d")
-; (match_operand:DI 1 "general_operand" "")))]
-; ""
-; "*
-;{
-; check_label_emit ();
-; if (REG_P (operands[1]))
-; {
-; mvs_check_page (0, 8, 0);
-; if (unsigned_jump_follows_p (insn))
-; return \"CLR %0,%1\;BNE *+6\;CLR %N0,%N1\";
-; return \"CR %0,%1\;BNE *+6\;CLR %N0,%N1\";
-; }
-; mvs_check_page (0, 12, 0);
-; if (unsigned_jump_follows_p (insn))
-; return \"CL %0,%M1\;BNE *+8\;CL %N0,%L1\";
-; return \"C %0,%M1\;BNE *+8\;CL %N0,%L1\";
-;}")
-
-;
-; cmpsi instruction pattern(s).
-;
-
-(define_insn "cmpsi"
- [(set (cc0)
- (compare (match_operand:SI 0 "register_operand" "d")
- (match_operand:SI 1 "general_operand" "md")))]
- ""
- "*
-{
- check_label_emit ();
- if (REG_P (operands[1]))
- {
- mvs_check_page (0, 2, 0);
- if (unsigned_jump_follows_p (insn))
- return \"CLR %0,%1\";
- return \"CR %0,%1\";
- }
- if (GET_CODE (operands[1]) == CONST_INT)
- {
- mvs_check_page (0, 4, 4);
- if (unsigned_jump_follows_p (insn))
- return \"CL %0,=F'%c1'\";
- return \"C %0,=F'%c1'\";
- }
- mvs_check_page (0, 4, 0);
- if (unsigned_jump_follows_p (insn))
- return \"CL %0,%1\";
- return \"C %0,%1\";
-}"
- [(set_attr "length" "4")]
-)
-
-;
-; cmphi instruction pattern(s).
-;
-
-; deprecate constraint d because it takes multiple instructions
-; and a memeory access ...
-(define_insn "cmphi"
- [(set (cc0)
- (compare (match_operand:HI 0 "register_operand" "d")
- (match_operand:HI 1 "general_operand" "???dim")))]
- ""
- "*
-{
- check_label_emit ();
- if (REG_P (operands[1]))
- {
- mvs_check_page (0, 8, 0);
- if (unsigned_jump_follows_p (insn))
- return \"STH %1,140(,13)\;CLM %0,3,140(13)\";
- return \"STH %1,140(,13)\;CH %0,140(,13)\";
- }
- if (GET_CODE (operands[1]) == CONST_INT)
- {
- mvs_check_page (0, 4, 0);
- return \"CH %0,%H1\";
- }
- mvs_check_page (0, 4, 0);
- return \"CH %0,%1\";
-}"
- [(set_attr "length" "8")]
-)
-
-;
-; cmpqi instruction pattern(s).
-;
-
-(define_insn ""
- [(set (cc0)
- (compare (match_operand:QI 0 "r_or_s_operand" "dS")
- (match_operand:QI 1 "r_or_s_operand" "diS")))]
- "unsigned_jump_follows_p (insn)"
- "*
-{
- check_label_emit ();
- if (REG_P (operands[0]))
- {
- if (REG_P (operands[1]))
- {
- mvs_check_page (0, 8, 0);
- return \"STC %1,140(,13)\;CLM %0,1,140(13)\";
- }
- if (GET_CODE (operands[1]) == CONST_INT)
- {
- mvs_check_page (0, 4, 1);
- return \"CLM %0,1,=XL1'%X1'\";
- }
- mvs_check_page (0, 4, 0);
- return \"CLM %0,1,%1\";
- }
- else if (GET_CODE (operands[0]) == CONST_INT)
- {
- cc_status.flags |= CC_REVERSED;
- if (REG_P (operands[1]))
- {
- mvs_check_page (0, 4, 1);
- return \"CLM %1,1,=XL1'%X0'\";
- }
- mvs_check_page (0, 4, 0);
- return \"CLI %1,%B0\";
- }
- if (GET_CODE (operands[1]) == CONST_INT)
- {
- mvs_check_page (0, 4, 0);
- return \"CLI %0,%B1\";
- }
- if (GET_CODE (operands[1]) == MEM)
- {
- mvs_check_page (0, 6, 0);
- return \"CLC %O0(1,%R0),%1\";
- }
- cc_status.flags |= CC_REVERSED;
- mvs_check_page (0, 4, 0);
- return \"CLM %1,1,%0\";
-}"
- [(set_attr "length" "8")]
-)
-
-(define_insn "cmpqi"
- [(set (cc0)
- (compare (match_operand:QI 0 "register_operand" "d")
- (match_operand:QI 1 "general_operand" "di")))]
- ""
- "*
-{
- check_label_emit ();
- if (unsigned_jump_follows_p (insn))
- {
- if (GET_CODE (operands[1]) == CONST_INT)
- {
- mvs_check_page (0, 4, 1);
- return \"CLM %0,1,=XL1'%X1'\";
- }
- if (!(REG_P (operands[1])))
- {
- mvs_check_page (0, 4, 0);
- return \"CLM %0,1,%1\";
- }
- mvs_check_page (0, 8, 0);
- return \"STC %1,140(,13)\;CLM %0,1,140(13)\";
- }
- if (REG_P (operands[1]))
- {
- mvs_check_page (0, 18, 0);
- return \"SLL %0,24\;SRA %0,24\;SLL %1,24\;SRA %1,24\;CR %0,%1\";
- }
- mvs_check_page (0, 12, 0);
- return \"SLL %0,24\;SRA %0,24\;C %0,%1\";
-}"
- [(set_attr "length" "18")]
-)
-
-;
-; cmpdf instruction pattern(s).
-;
-
-(define_insn "cmpdf"
- [(set (cc0)
- (compare (match_operand:DF 0 "general_operand" "f,mF")
- (match_operand:DF 1 "general_operand" "fmF,f")))]
- ""
- "*
-{
- check_label_emit ();
- if (FP_REG_P (operands[0]))
- {
- if (FP_REG_P (operands[1]))
- {
- mvs_check_page (0, 2, 0);
- return \"CDR %0,%1\";
- }
- mvs_check_page (0, 4, 0);
- return \"CD %0,%1\";
- }
- cc_status.flags |= CC_REVERSED;
- mvs_check_page (0, 4, 0);
- return \"CD %1,%0\";
-}"
- [(set_attr "length" "4")]
-)
-
-;
-; cmpsf instruction pattern(s).
-;
-
-(define_insn "cmpsf"
- [(set (cc0)
- (compare (match_operand:SF 0 "general_operand" "f,mF")
- (match_operand:SF 1 "general_operand" "fmF,f")))]
- ""
- "*
-{
-check_label_emit ();
- if (FP_REG_P (operands[0]))
- {
- if (FP_REG_P (operands[1]))
- {
- mvs_check_page (0, 2, 0);
- return \"CER %0,%1\";
- }
- mvs_check_page (0, 4, 0);
- return \"CE %0,%1\";
- }
- cc_status.flags |= CC_REVERSED;
- mvs_check_page (0, 4, 0);
- return \"CE %1,%0\";
-}"
- [(set_attr "length" "4")]
-)
-
-;
-; cmpmemsi instruction pattern(s).
-;
-
-(define_expand "cmpmemsi"
- [(set (match_operand:SI 0 "general_operand" "")
- (compare (match_operand:BLK 1 "general_operand" "")
- (match_operand:BLK 2 "general_operand" "")))
- (use (match_operand:SI 3 "general_operand" ""))
- (use (match_operand:SI 4 "" ""))]
- ""
- "
-{
- rtx op1, op2;
-
- 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 = gen_rtx_MEM (BLKmode, copy_to_mode_reg (SImode, op1));
- }
-
- op2 = XEXP (operands[2], 0);
- if (GET_CODE (op2) == REG
- || (GET_CODE (op2) == PLUS && GET_CODE (XEXP (op2, 0)) == REG
- && GET_CODE (XEXP (op2, 1)) == CONST_INT
- && (unsigned) INTVAL (XEXP (op2, 1)) < 4096))
- {
- op2 = operands[2];
- }
- else
- {
- op2 = gen_rtx_MEM (BLKmode, copy_to_mode_reg (SImode, op2));
- }
-
- if (GET_CODE (operands[3]) == CONST_INT && INTVAL (operands[3]) < 256)
- {
- emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2,
- gen_rtx_SET (VOIDmode, operands[0],
- gen_rtx_COMPARE (VOIDmode, op1, op2)),
- gen_rtx_USE (VOIDmode, operands[3]))));
- }
- else
- {
- /* implementation suggested by Richard Henderson <rth@cygnus.com> */
- 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 <rth@cygnus.com> */
- 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 <rth@cygnus.com> */
- 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")]
-)
+++ /dev/null
-/* 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 */
+++ /dev/null
-/* 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
+++ /dev/null
-/* 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)
-
+++ /dev/null
-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
+++ /dev/null
-/* 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 <phk@login.dkuug.dk>
- Continued development by David O'Brien <obrien@NUXI.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. */
-
-/* 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
-\f
-/* 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
-\f
-/* 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))
-\f
-/* 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
+++ /dev/null
-/* 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
-
-\f
-#undef LINK_SPEC
-#define LINK_SPEC "-m i386linux"
+++ /dev/null
-/* Definitions for Intel 386 running MOSS
- Copyright (C) 1996, 2001 Free Software Foundation, Inc.
- Contributed by Bryan Ford <baford@cs.utah.edu>
-
-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
-
+++ /dev/null
-/* 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
+++ /dev/null
-/*
- * 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 : { }
- }
-}
+++ /dev/null
-/* 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"
+++ /dev/null
-/* 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
-\f
-/* ??? 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
+++ /dev/null
-/*
- * 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 : { }
- }
-}
+++ /dev/null
-# Tell fixincludes to work on this set of headers
-SYSTEM_HEADER_DIR = /udk/usr/include
+++ /dev/null
-/* 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}"
-
+++ /dev/null
-/* 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)
+++ /dev/null
-/* 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;
-}
+++ /dev/null
-/* 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 */
+++ /dev/null
-/* 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);
+++ /dev/null
-/* 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 */
+++ /dev/null
-/* 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 <math.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 "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)
-\f
-/* 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;
-\f
-/* 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;
- }
-}
-\f
-/* 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);
-}
-\f
-/* 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;
-}
-\f
-/* 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 "";
-}
-
-\f
-/* 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;
-}
-\f
-/* 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;
- }
-}
-\f
-/* 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";
-}
-\f
-/* 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;
-}
-\f
-/* 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));
-}
-\f
-/* 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;
-}
-\f
-#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
-\f
-
-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 ();
-}
-
-\f
-/* 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);
-}
-\f
-/* 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;
-}
-\f
-/* 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;
-}
-\f
-/* 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;
-}
-\f
-/* 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;
-}
-\f
-/* 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;
- }
-}
+++ /dev/null
-/* 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
-\f
-/* 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)
-\f
-/* 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 */
-\f
-/* 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)))
-\f
-/* 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)
-\f
-/* 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
-\f
-/* 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
-\f
-/* 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
-\f
-/* 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
-\f
-/* 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)
-\f
-/* 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)
-\f
-/* 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
-\f
-/* 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)
-
-\f
-/* 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) == '+')
-\f
-/* 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;
+++ /dev/null
-;;- 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.
-\f
-;; 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.
-\f
-;; 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)
-\f
-;; 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")])
-\f
-;; 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")])
-\f
-;; 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); }")
-\f
-;; 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")])
-\f
-;; 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")
-\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;
-}")
-\f
-;; 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")])
-\f
-;; 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")])
-\f
-;; 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;
-}")
-\f
-;; 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")])
-\f
-;; 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")])
-\f
-;; 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")])
-\f
-;; 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")])
-\f
-;; 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)]
- ""
- "")
-\f
-;; 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")
-\f
-; 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")
-\f
-; 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)")
+++ /dev/null
-/* 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)
+++ /dev/null
-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
+++ /dev/null
-/* 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
+++ /dev/null
-/* 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 */
+++ /dev/null
-/* 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
+++ /dev/null
-/* 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 */
+++ /dev/null
-/* 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); \
-}
+++ /dev/null
-#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
-
-\f
-/* Make gcc agree with <machine/ansi.h> */
-
-#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
-
+++ /dev/null
-/* 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))
-\f
-/* 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 */
-\f
-/* This macro outputs the label at the start of a switch table. The
- ".swbeg <N>" 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
+++ /dev/null
-# So putenv and other functions get seen by fixproto.
-FIXPROTO_DEFINES = -D_HPUX_SOURCE
+++ /dev/null
-/* 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\""
+++ /dev/null
-# 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
@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.
@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}}
@item
@uref{#dos,,DOS}
@item
-@uref{#dsp16xx,,dsp16xx}
-@item
@uref{#*-*-freebsd*,,*-*-freebsd*}
@item
@uref{#h8300-hms,,h8300-hms}
@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}
compilation package DJGPP, which includes binaries as well as sources,
and includes all the necessary compilation tools and libraries.
-@html
-<hr />
-@end html
-@heading @anchor{dsp16xx}dsp16xx
-A port to the AT&T DSP1610 family of processors.
-
@html
<hr />
@end html
This port still is undergoing significant development.
-@html
-<hr />
-@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
<hr />
@end html
-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
-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
* MIPS Options::
* i386 and x86-64 Options::
* HPPA Options::
-* Intel 960 Options::
* DEC Alpha Options::
* DEC Alpha/VMS Options::
* H8/300 Options::
* AVR Options::
* MCore Options::
* IA-64 Options::
-* D30V Options::
* S/390 and zSeries Options::
* CRIS Options::
* MMIX Options::
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
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
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
+2004-02-04 Kazu Hirata <kazu@cs.umass.edu>
+
+ * 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 <bonzini@gnu.org>
* gcc.dg/noncompile/20001228-1.c: Fix for new
/* 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__)
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 } */
# 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
# 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
Copyright (C) 2002 Free Software Foundation Inc.
Contributed by Hans-Peter Nilsson <hp@bitrange.com> */
-/* { 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
Copyright (C) 2002 Free Software Foundation Inc.
Contributed by Hans-Peter Nilsson <hp@bitrange.com> */
-/* { 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