+2011-03-22 Joseph Myers <joseph@codesourcery.com>
+
+ * MAINTAINERS (crx port, m68hc11 port): Remove. Move maintainers
+ to Write After Approval.
+ * config-ml.in: Don't handle arc-*-elf*.
+ * configure.ac (arc-*-*, crx-*-*, i[[3456789]]86-*-pe,
+ m68hc11-*-*|m6811-*-*|m68hc12-*-*|m6812-*-*, mcore-*-pe*): Don't
+ handle GCC libraries.
+ * configure: Regenerate.
+
2011-03-21 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
PR bootstrap/48120:
bfin port Bernd Schmidt bernds@codesourcery.com
bfin port Jie Zhang jie@codesourcery.com
cris port Hans-Peter Nilsson hp@axis.com
-crx port Pompapathi V Gadad Pompapathi.V.Gadad@nsc.com
fr30 port Nick Clifton nickc@redhat.com
frv port Nick Clifton nickc@redhat.com
frv port Alexandre Oliva aoliva@redhat.com
lm32 port Sebastien Bourdeauducq sebastien@milkymist.org
m32c port DJ Delorie dj@redhat.com
m32r port Nick Clifton nickc@redhat.com
-m68hc11 port Stephane Carrez stcarrez@nerim.fr
m68k port (?) Jeff Law law@redhat.com
m68k port Andreas Schwab schwab@linux-m68k.org
m68k-motorola-sysv port Philippe De Muyter phdm@macqel.be
Christian Bruel christian.bruel@st.com
Kevin Buettner kevinb@redhat.com
Andrew Cagney cagney@redhat.com
+Stephane Carrez stcarrez@nerim.fr
Chandra Chavva cchavva@redhat.com
Fabien Chêne fabien@gcc.gnu.org
William Cohen wcohen@redhat.com
Nathan Froyd froydnj@codesourcery.com
Chao-ying Fu fu@mips.com
Gary Funck gary@intrepid.com
+Pompapathi V Gadad Pompapathi.V.Gadad@nsc.com
Kaveh Ghazi ghazi@gcc.gnu.org
Matthew Gingell gingell@gnat.com
Tristan Gingold gingold@adacore.com
# wanting multilib support.
#
# Copyright (C) 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-# 2005, 2006, 2007, 2008, 2010 Free Software Foundation, Inc.
+# 2005, 2006, 2007, 2008, 2010, 2011 Free Software Foundation, Inc.
#
# 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
# $host here, not $target.
case "${host}" in
-arc-*-elf*)
- if [ x$enable_biendian != xyes ]
- then
- old_multidirs=${multidirs}
- multidirs=""
- for x in ${old_multidirs}; do
- case "${x}" in
- *be*) : ;;
- *) multidirs="${multidirs} ${x}" ;;
- esac
- done
- fi
- ;;
arm-*-*)
if [ x"$enable_fpu" = xno ]
then
libgloss_dir=wince
;;
arc-*-*)
- noconfigdirs="$noconfigdirs target-libgloss ${libgcj}"
+ noconfigdirs="$noconfigdirs target-libgloss"
;;
arm-semi-aof )
;;
libgloss_dir=cris
;;
crx-*-*)
- noconfigdirs="$noconfigdirs target-libstdc++-v3 target-mudflap ${libgcj}"
;;
d10v-*-*)
noconfigdirs="$noconfigdirs target-libstdc++-v3 target-libgloss ${libgcj}"
i[3456789]86-*-uwin* | i[3456789]86-*-interix* )
;;
i[3456789]86-*-pe)
- noconfigdirs="$noconfigdirs target-libstdc++-v3 target-libgloss ${libgcj}"
+ noconfigdirs="$noconfigdirs target-libgloss"
;;
i[3456789]86-*-sco3.2v5*)
# The linker does not yet know about weak symbols in COFF,
noconfigdirs="$noconfigdirs ${libgcj}"
;;
m68hc11-*-*|m6811-*-*|m68hc12-*-*|m6812-*-*)
- noconfigdirs="$noconfigdirs target-libiberty target-libstdc++-v3 ${libgcj}"
+ noconfigdirs="$noconfigdirs target-libiberty"
libgloss_dir=m68hc11
;;
m68k-*-elf*)
libgloss_dir=m68k
;;
mcore-*-pe*)
- # The EPOC C++ environment does not support exceptions or rtti,
- # and so building libstdc++-v3 tends not to always work.
- noconfigdirs="$noconfigdirs target-libstdc++-v3"
;;
mmix-*-*)
noconfigdirs="$noconfigdirs target-libffi target-boehm-gc gdb libgloss"
libgloss_dir=wince
;;
arc-*-*)
- noconfigdirs="$noconfigdirs target-libgloss ${libgcj}"
+ noconfigdirs="$noconfigdirs target-libgloss"
;;
arm-semi-aof )
;;
libgloss_dir=cris
;;
crx-*-*)
- noconfigdirs="$noconfigdirs target-libstdc++-v3 target-mudflap ${libgcj}"
;;
d10v-*-*)
noconfigdirs="$noconfigdirs target-libstdc++-v3 target-libgloss ${libgcj}"
i[[3456789]]86-*-uwin* | i[[3456789]]86-*-interix* )
;;
i[[3456789]]86-*-pe)
- noconfigdirs="$noconfigdirs target-libstdc++-v3 target-libgloss ${libgcj}"
+ noconfigdirs="$noconfigdirs target-libgloss"
;;
i[[3456789]]86-*-sco3.2v5*)
# The linker does not yet know about weak symbols in COFF,
noconfigdirs="$noconfigdirs ${libgcj}"
;;
m68hc11-*-*|m6811-*-*|m68hc12-*-*|m6812-*-*)
- noconfigdirs="$noconfigdirs target-libiberty target-libstdc++-v3 ${libgcj}"
+ noconfigdirs="$noconfigdirs target-libiberty"
libgloss_dir=m68hc11
;;
m68k-*-elf*)
libgloss_dir=m68k
;;
mcore-*-pe*)
- # The EPOC C++ environment does not support exceptions or rtti,
- # and so building libstdc++-v3 tends not to always work.
- noconfigdirs="$noconfigdirs target-libstdc++-v3"
;;
mmix-*-*)
noconfigdirs="$noconfigdirs target-libffi target-boehm-gc gdb libgloss"
+2011-03-22 Joseph Myers <joseph@codesourcery.com>
+
+ * compare-all-tests (all_targets): Remove crx and m68hc11.
+
2011-03-21 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
PR bootstrap/48135
#! /bin/bash
# Compare the assembly language output for all the gcc tests.
-# Copyright (C) 2009 Free Software Foundation, Inc.
+# Copyright (C) 2009, 2011 Free Software Foundation, Inc.
# Contributed by Paolo Bonzini.
#
# Invoke it as "bash compare-all-tests target1 target2 ... targetN".
sh_opts='-m3 -m3e -m4 -m4a -m4al -m4/-mieee -m1 -m1/-mno-cbranchdi -m2a -m2a/-mieee -m2e -m2e/-mieee'
sparc_opts='-mcpu=v8/-m32 -mcpu=v9/-m32 -m64'
-all_targets='alpha arm avr bfin cris crx fr30 frv h8300 ia64 iq2000 m32c m32r m68hc11 m68k mcore mips mmix mn10300 pa pdp11 picochip ppc score sh sh64 sparc spu v850 vax xstormy16 xtensa' # e500
+all_targets='alpha arm avr bfin cris fr30 frv h8300 ia64 iq2000 m32c m32r m68k mcore mips mmix mn10300 pa pdp11 picochip ppc score sh sh64 sparc spu v850 vax xstormy16 xtensa' # e500
test_one_file ()
{
+2011-03-22 Joseph Myers <joseph@codesourcery.com>
+
+ * mkfixinc.sh: Don't handle i?86-moss-msdos* or i?86-*-pe.
+
2010-11-20 Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
PR other/46202
# Check for special fix rules for particular targets
case $machine in
alpha*-dec-*vms* | \
- i?86-moss-msdos* | \
- i?86-*-pe | \
i?86-*-cygwin* | \
i?86-*-mingw32* | \
x86_64-*-mingw32* | \
+2011-03-22 Joseph Myers <joseph@codesourcery.com>
+
+ * config/alpha/gnu.h: Remove.
+ * config/arc: Remove directory.
+ * config/arm/netbsd.h: Remove.
+ * config/arm/t-pe: Remove.
+ * config/crx: Remove directory.
+ * config/i386/netbsd.h: Remove.
+ * config/m68hc11: Remove directory.
+ * config/m68k/uclinux-oldabi.h: Remove.
+ * config/mcore/mcore-pe.h: Remove.
+ * config/mcore/t-mcore-pe: Remove.
+ * config/netbsd-aout.h: Remove.
+ * config/rs6000/gnu.h: Remove.
+ * config/sh/sh-symbian.h: Remove.
+ * config/sh/symbian-base.c: Remove.
+ * config/sh/symbian-c.c: Remove.
+ * config/sh/symbian-cxx.c: Remove.
+ * config/sh/symbian-post.h: Remove.
+ * config/sh/symbian-pre.h: Remove.
+ * config/sh/t-symbian: Remove.
+ * config/svr3.h: Remove.
+ * config/vax/netbsd.h: Remove.
+ * config.build: Don't handle i[34567]86-*-pe.
+ * config.gcc: Remove handling of deprecations for most deprecated
+ targets.
+ (m68k-*-uclinuxoldabi*): Add to second deprecated list.
+ (alpha*-*-gnu*, arc-*-elf*, arm*-*-netbsd*, arm-*-pe*, crx-*-elf,
+ i[34567]86-*-netbsd*, i[34567]86-*-pe, m68hc11-*-*|m6811-*-*,
+ m68hc12-*-*|m6812-*-*, m68k-*-uclinuxoldabi*, mcore-*-pe*,
+ powerpc64-*-gnu*, powerpc-*-gnu-gnualtivec*, powerpc-*-gnu*,
+ sh-*-symbianelf* | sh[12346l]*-*-symbianelf*, vax-*-netbsd*):
+ Remove cases.
+ * config.host: Don't handle i[34567]86-*-pe.
+ * config/rs6000/linux64.h (LINK_OS_GNU_SPEC): Remove.
+ (ASM_SPEC32): Don't handle -mcall-gnu.
+ * config/rs6000/sysv4.h (SUBTARGET_OVERRIDE_OPTIONS): Don't handle
+ -mcall-gnu.
+ (ASM_SPEC, CC1_SPEC, LINK_START_SPEC, LINK_OS_SPEC, CPP_SPEC,
+ STARTFILE_SPEC, LIB_SPEC, ENDFILE_SPEC): Don't handle -mcall-gnu.
+ (LIB_GNU_SPEC, STARTFILE_GNU_SPEC, ENDFILE_GNU_SPEC,
+ LINK_START_GNU_SPEC, LINK_OS_GNU_SPEC, CPP_OS_GNU_SPEC): Remove.
+ (SUBTARGET_EXTRA_SPECS): Remove *_gnu specs.
+ * config/sh/sh-protos.h, config/sh/sh.c: Remove all code
+ conditional on SYMBIAN.
+ * configure.ac: Don't handle powerpc*-*-gnu*.
+ * configure: Regenerate.
+ * doc/extend.texi (interrupt attribute): Don't mention CRX.
+ * doc/install-old.texi (m6811, m6812): Don't mention.
+ * doc/install.texi (arc-*-elf*): Don't document multilib option.
+ (arc-*-elf, CRX, m6811-elf, m6812-elf): Remove.
+ (m68k-uclinuxoldabi): Don't mention.
+ * doc/invoke.texi (ARC Options, CRX Options, M68hc1x Options):
+ Remove.
+ (-mcall-gnu): Remove.
+ * doc/md.texi (CRX Architecture, Motorola 68HC11 & 68HC12
+ families): Remove constraint documentation.
+
2011-03-22 Marius Strobl <marius@FreeBSD.org>
* config/sparc/freebsd.h (CPP_CPU64_DEFAULT_SPEC): Replace with...
# GCC build-specific configuration file.
-# Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2007, 2008, 2009, 2010
+# Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2007, 2008, 2009, 2010,
+# 2011
# Free Software Foundation, Inc.
#This file is part of GCC.
# IBM 360/370/390 Architecture
build_xm_defines='FATAL_EXIT_CODE=12'
;;
- i[34567]86-*-cygwin* | i[34567]86-*-pe )
+ i[34567]86-*-cygwin* )
build_xm_file=i386/xm-cygwin.h
build_exeext=.exe
;;
# Obsolete configurations.
case ${target} in
-# Avoid cases below matching.
- alpha*-*-linux* \
- | arm*-wince-pe* \
- | arm*-*-netbsdelf* \
- | i[34567]86-*-netbsdelf* \
- | powerpc*-*-linux* \
- | vax-*-netbsdelf*) ;;
- arc-* \
- | alpha*-*-gnu* \
- | arm*-*-netbsd* \
- | arm-*-pe* \
- | crx-* \
- | i[34567]86-*-interix3* \
- | i[34567]86-*-netbsd* \
- | i[34567]86-*-pe \
- | m68hc11-*-* \
- | m6811-*-* \
- | m68hc12-*-* \
- | m6812-*-* \
- | m68k-*-uclinuxoldabi* \
- | mcore-*-pe* \
- | powerpc*-*-gnu* \
+ i[34567]86-*-interix3* \
| score-* \
- | sh*-*-symbianelf* \
| *-*-solaris2.8* \
- | vax-*-netbsd* \
)
if test "x$enable_obsolete" != xyes; then
echo "*** Configuration ${target} is obsolete." >&2
case ${target} in
i[34567]86-go32-* \
| i[34567]86-*-go32* \
+ | m68k-*-uclinuxoldabi* \
| mips64orion*-*-rtems* \
| pdp11-*-bsd \
| sparc-hal-solaris2* \
target_cpu_default="MASK_GAS"
tmake_file="${tmake_file} alpha/t-crtfm alpha/t-alpha alpha/t-ieee alpha/t-linux"
;;
-alpha*-*-gnu*)
- tm_file="$tm_file alpha/elf.h alpha/linux.h alpha/linux-elf.h gnu.h glibc-stdint.h alpha/gnu.h"
- extra_options="${extra_options} alpha/elf.opt"
- target_cpu_default="MASK_GAS"
- tmake_file="${tmake_file} alpha/t-crtfm alpha/t-alpha alpha/t-ieee"
- ;;
alpha*-*-freebsd*)
tm_file="${tm_file} ${fbsd_tm_file} alpha/elf.h alpha/freebsd.h"
extra_options="${extra_options} alpha/elf.opt"
install_headers_dir=install-headers-cp
extra_options="${extra_options} vms/vms.opt"
;;
-arc-*-elf*)
- tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file}"
- extra_parts="crtinit.o crtfini.o"
- ;;
arm-wrs-vxworks)
tm_file="elfos.h arm/elf.h arm/aout.h ${tm_file} vx-common.h vxworks.h arm/vxworks.h"
extra_options="${extra_options} arm/vxworks.opt"
extra_options="${extra_options} netbsd.opt netbsd-elf.opt"
tmake_file="${tmake_file} arm/t-arm arm/t-netbsd"
;;
-arm*-*-netbsd*)
- tm_file="arm/aout.h arm/arm.h netbsd.h netbsd-aout.h arm/netbsd.h"
- extra_options="${extra_options} netbsd.opt"
- tmake_file="t-netbsd arm/t-arm arm/t-netbsd"
- extra_parts=""
- use_collect2=yes
- ;;
arm*-*-linux*) # ARM GNU/Linux with ELF
tm_file="dbxelf.h elfos.h gnu-user.h linux.h linux-android.h glibc-stdint.h arm/elf.h arm/linux-gas.h arm/linux-elf.h"
case $target in
extra_options="${extra_options} arm/pe.opt"
extra_objs="pe.o"
;;
-arm-*-pe*)
- tm_file="arm/semi.h arm/aout.h arm/arm.h arm/coff.h dbxcoff.h arm/pe.h newlib-stdint.h"
- tmake_file="arm/t-arm arm/t-pe"
- use_gcc_stdint=wrap
- extra_options="${extra_options} arm/pe.opt"
- extra_objs="pe.o"
- ;;
avr-*-rtems*)
tm_file="avr/avr.h dbxelf.h avr/rtems.h rtems.h newlib-stdint.h"
tmake_file="avr/t-avr t-rtems avr/t-rtems"
;;
esac
;;
-crx-*-elf)
- tm_file="elfos.h newlib-stdint.h ${tm_file}"
- extra_parts="crtbegin.o crtend.o"
- use_collect2=no
- ;;
fr30-*-elf)
tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file}"
tmake_file=fr30/t-fr30
tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h netbsd.h netbsd-elf.h i386/netbsd-elf.h"
extra_options="${extra_options} netbsd.opt netbsd-elf.opt"
;;
-i[34567]86-*-netbsd*)
- tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h i386/gstabs.h netbsd.h netbsd-aout.h i386/netbsd.h"
- extra_options="${extra_options} netbsd.opt"
- tmake_file="${tmake_file} t-netbsd"
- extra_parts=""
- use_collect2=yes
- ;;
x86_64-*-netbsd*)
tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h netbsd.h netbsd-elf.h i386/x86-64.h i386/netbsd64.h"
extra_options="${extra_options} netbsd.opt netbsd-elf.opt"
;;
esac
;;
-i[34567]86-*-pe | i[34567]86-*-cygwin*)
+i[34567]86-*-cygwin*)
tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h dbxcoff.h i386/cygming.h i386/cygwin.h i386/cygwin-stdint.h"
xm_file=i386/xm-cygwin.h
# This has to match the logic for DWARF2_UNWIND_INFO in gcc/config/i386/cygming.h
thread_file='posix'
fi
;;
-# m68hc11 and m68hc12 share the same machine description.
-m68hc11-*-*|m6811-*-*)
- tm_file="dbxelf.h elfos.h usegas.h newlib-stdint.h m68hc11/m68hc11.h"
- tm_p_file="m68hc11/m68hc11-protos.h"
- md_file="m68hc11/m68hc11.md"
- out_file="m68hc11/m68hc11.c"
- tmake_file="m68hc11/t-m68hc11"
- use_gcc_stdint=wrap
- ;;
-m68hc12-*-*|m6812-*-*)
- tm_file="m68hc11/m68hc12.h dbxelf.h elfos.h usegas.h newlib-stdint.h m68hc11/m68hc11.h"
- tm_p_file="m68hc11/m68hc11-protos.h"
- md_file="m68hc11/m68hc11.md"
- out_file="m68hc11/m68hc11.c"
- tmake_file="m68hc11/t-m68hc11"
- extra_options="${extra_options} m68hc11/m68hc11.opt"
- use_gcc_stdint=wrap
- ;;
m68k-*-elf* | fido-*-elf*)
case ${target} in
fido-*-elf*)
# we need collect2 until our bug is fixed...
use_collect2=yes
;;
-m68k-*-uclinuxoldabi*) # Motorola m68k/ColdFire running uClinux
- # with uClibc, using the original
- # m68k-elf-based ABI
- default_m68k_cpu=68020
- default_cf_cpu=5206
- tm_file="${tm_file} m68k/m68k-none.h m68k/m68kelf.h dbxelf.h elfos.h m68k/uclinux-oldabi.h glibc-stdint.h"
- tm_defines="${tm_defines} MOTOROLA=1"
- tmake_file="m68k/t-floatlib m68k/t-uclinux"
- ;;
m68k-*-uclinux*) # Motorola m68k/ColdFire running uClinux
# with uClibc, using the new GNU/Linux-style
# ABI.
tmake_file=mcore/t-mcore
inhibit_libc=true
;;
-mcore-*-pe*)
- tm_file="svr3.h dbxcoff.h newlib-stdint.h ${tm_file} mcore/mcore-pe.h"
- tmake_file=mcore/t-mcore-pe
- inhibit_libc=true
- use_gcc_stdint=wrap
- ;;
mep-*-*)
tm_file="dbxelf.h elfos.h ${tm_file}"
tmake_file=mep/t-mep
tm_file="rs6000/secureplt.h ${tm_file}"
fi
;;
-powerpc64-*-gnu*)
- tm_file="${tm_file} elfos.h freebsd-spec.h gnu.h rs6000/sysv4.h rs6000/default64.h rs6000/linux64.h rs6000/gnu.h glibc-stdint.h"
- extra_options="${extra_options} rs6000/sysv4.opt rs6000/linux64.opt"
- tmake_file="t-slibgcc-elf-ver t-slibgcc-libgcc t-gnu"
- ;;
-powerpc-*-gnu-gnualtivec*)
- tm_file="${cpu_type}/${cpu_type}.h elfos.h freebsd-spec.h gnu.h rs6000/sysv4.h rs6000/linux.h rs6000/linuxaltivec.h rs6000/gnu.h glibc-stdint.h"
- extra_options="${extra_options} rs6000/sysv4.opt"
- tmake_file="rs6000/t-fprules rs6000/t-fprules-fpbit rs6000/t-ppcos t-slibgcc-elf-ver t-slibgcc-libgcc t-gnu rs6000/t-ppccomm"
- if test x$enable_threads = xyes; then
- thread_file='posix'
- fi
- ;;
-powerpc-*-gnu*)
- tm_file="${cpu_type}/${cpu_type}.h elfos.h freebsd-spec.h gnu.h rs6000/sysv4.h rs6000/linux.h rs6000/gnu.h glibc-stdint.h"
- tmake_file="rs6000/t-fprules rs6000/t-fprules-fpbit rs6000/t-ppcos t-slibgcc-elf-ver t-slibgcc-libgcc t-gnu rs6000/t-ppccomm"
- extra_options="${extra_options} rs6000/sysv4.opt"
- if test x$enable_threads = xyes; then
- thread_file='posix'
- fi
- ;;
powerpc-wrs-vxworks|powerpc-wrs-vxworksae)
tm_file="${tm_file} elfos.h freebsd-spec.h rs6000/sysv4.h"
tmake_file="${tmake_file} rs6000/t-fprules rs6000/t-fprules-fpbit rs6000/t-ppccomm rs6000/t-vxworks"
extra_objs="score7.o"
;;
sh-*-elf* | sh[12346l]*-*-elf* | \
-sh-*-symbianelf* | sh[12346l]*-*-symbianelf* | \
sh-*-linux* | sh[2346lbe]*-*-linux* | \
sh-*-netbsdelf* | shl*-*-netbsdelf* | sh5-*-netbsd* | sh5l*-*-netbsd* | \
sh64-*-netbsd* | sh64l*-*-netbsd*)
fi
extra_headers="shmedia.h ushmedia.h sshmedia.h"
;;
- *-*-symbianelf*)
- tmake_file="sh/t-symbian"
- tm_file="sh/symbian-pre.h sh/little.h ${tm_file} sh/symbian-post.h"
- c_target_objs="symbian-base.o symbian-c.o"
- cxx_target_objs="symbian-base.o symbian-cxx.o"
- extra_parts="crt1.o crti.o crtn.o crtbegin.o crtend.o crtbeginS.o crtendS.o"
- ;;
*-*-elf*)
tm_file="${tm_file} newlib-stdint.h"
;;
tm_file="${tm_file} elfos.h netbsd.h netbsd-elf.h vax/elf.h vax/netbsd-elf.h"
extra_options="${extra_options} netbsd.opt netbsd-elf.opt vax/elf.opt"
;;
-vax-*-netbsd*)
- tm_file="${tm_file} netbsd.h netbsd-aout.h vax/netbsd.h"
- extra_options="${extra_options} netbsd.opt"
- tmake_file=t-netbsd
- extra_parts=""
- use_collect2=yes
- ;;
vax-*-openbsd*)
tm_file="vax/vax.h vax/openbsd1.h openbsd.h openbsd-stdint.h openbsd-pthread.h vax/openbsd.h"
extra_options="${extra_options} openbsd.opt"
;;
esac
;;
- i[34567]86-*-pe | i[34567]86-*-cygwin*)
+ i[34567]86-*-cygwin*)
host_xm_file=i386/xm-cygwin.h
out_host_hook_obj=host-cygwin.o
host_xmake_file="${host_xmake_file} i386/x-cygwin"
+++ /dev/null
-/* Configuration for an Alpha running GNU with ELF as the target machine.
-
-Copyright (C) 2002, 2003, 2004, 2010 Free Software Foundation, Inc.
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 3, or (at your option) any later
-version.
-
-GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-for more details.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-#undef TARGET_VERSION
-#define TARGET_VERSION fprintf (stderr, " (Alpha GNU)");
-
-#undef TARGET_OS_CPP_BUILTINS /* config.gcc includes alpha/linux.h. */
-#define TARGET_OS_CPP_BUILTINS() \
- do { \
- LINUX_TARGET_OS_CPP_BUILTINS(); \
- builtin_define ("_LONGLONG"); \
- } while (0)
-
-#undef ELF_DYNAMIC_LINKER
-#define ELF_DYNAMIC_LINKER "/lib/ld.so"
-
-#undef STARTFILE_SPEC
-#define STARTFILE_SPEC \
- "%{!shared: \
- %{!static: \
- %{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} %{!p:crt1.o%s}}} \
- %{static:crt0.o%s}} \
- crti.o%s \
- %{!static:%{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}}"
-
-/* FIXME: Is a Hurd-specific fallback mechanism necessary? */
-#undef MD_UNWIND_SUPPORT
+++ /dev/null
-/* Definitions of target machine for GNU compiler, Argonaut ARC cpu.
- Copyright (C) 2002, 2007 Free Software Foundation, Inc.
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-/* Some insns set all condition code flags, some only set the ZNC flags, and
- some only set the ZN flags. */
-
-CC_MODE (CCZNC);
-CC_MODE (CCZN);
+++ /dev/null
-/* Definitions of target machine for GNU compiler, Argonaut ARC cpu.
- Copyright (C) 2000, 2004, 2007, 2010 Free Software Foundation, Inc.
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-#ifdef RTX_CODE
-extern enum machine_mode arc_select_cc_mode (enum rtx_code, rtx, rtx);
-
-/* Define the function that build the compare insn for scc and bcc. */
-extern struct rtx_def *gen_compare_reg (enum rtx_code, rtx, rtx);
-#endif
-
-/* Declarations for various fns used in the .md file. */
-extern const char *output_shift (rtx *);
-
-extern int symbolic_operand (rtx, enum machine_mode);
-extern int arc_double_limm_p (rtx);
-extern int arc_eligible_for_epilogue_delay (rtx, int);
-extern void arc_initialize_trampoline (rtx, rtx, rtx);
-extern void arc_print_operand (FILE *, rtx, int);
-extern void arc_print_operand_address (FILE *, rtx);
-extern void arc_final_prescan_insn (rtx, rtx *, int);
-extern int call_address_operand (rtx, enum machine_mode);
-extern int call_operand (rtx, enum machine_mode);
-extern int symbolic_memory_operand (rtx, enum machine_mode);
-extern int short_immediate_operand (rtx, enum machine_mode);
-extern int long_immediate_operand (rtx, enum machine_mode);
-extern int long_immediate_loadstore_operand (rtx, enum machine_mode);
-extern int move_src_operand (rtx, enum machine_mode);
-extern int move_double_src_operand (rtx, enum machine_mode);
-extern int move_dest_operand (rtx, enum machine_mode);
-extern int load_update_operand (rtx, enum machine_mode);
-extern int store_update_operand (rtx, enum machine_mode);
-extern int nonvol_nonimm_operand (rtx, enum machine_mode);
-extern int const_sint32_operand (rtx, enum machine_mode);
-extern int const_uint32_operand (rtx, enum machine_mode);
-extern int proper_comparison_operator (rtx, enum machine_mode);
-extern int shift_operator (rtx, enum machine_mode);
-
-extern enum arc_function_type arc_compute_function_type (tree);
-
-
-extern unsigned int arc_compute_frame_size (int);
-extern void arc_save_restore (FILE *, const char *, unsigned int,
- unsigned int, const char *);
-extern int arc_delay_slots_for_epilogue (void);
-extern void arc_ccfsm_at_label (const char *, int);
-extern int arc_ccfsm_branch_deleted_p (void);
-extern void arc_ccfsm_record_branch_deleted (void);
+++ /dev/null
-/* Subroutines used for code generation on the Argonaut ARC cpu.
- Copyright (C) 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
- 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-/* ??? This is an old port, and is undoubtedly suffering from bit rot. */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "tm.h"
-#include "tree.h"
-#include "rtl.h"
-#include "regs.h"
-#include "hard-reg-set.h"
-#include "insn-config.h"
-#include "conditions.h"
-#include "output.h"
-#include "insn-attr.h"
-#include "flags.h"
-#include "function.h"
-#include "expr.h"
-#include "recog.h"
-#include "diagnostic-core.h"
-#include "df.h"
-#include "tm_p.h"
-#include "target.h"
-#include "target-def.h"
-
-/* Which cpu we're compiling for. */
-int arc_cpu_type;
-
-/* Name of mangle string to add to symbols to separate code compiled for each
- cpu (or NULL). */
-const char *arc_mangle_cpu;
-
-/* Name of text, data, and rodata sections used in varasm.c. */
-const char *arc_text_section;
-const char *arc_data_section;
-const char *arc_rodata_section;
-
-/* Array of valid operand punctuation characters. */
-char arc_punct_chars[256];
-
-/* Variables used by arc_final_prescan_insn to implement conditional
- execution. */
-static int arc_ccfsm_state;
-static int arc_ccfsm_current_cc;
-static rtx arc_ccfsm_target_insn;
-static int arc_ccfsm_target_label;
-
-/* The maximum number of insns skipped which will be conditionalised if
- possible. */
-#define MAX_INSNS_SKIPPED 3
-
-/* A nop is needed between a 4 byte insn that sets the condition codes and
- a branch that uses them (the same isn't true for an 8 byte insn that sets
- the condition codes). Set by arc_final_prescan_insn. Used by
- arc_print_operand. */
-static int last_insn_set_cc_p;
-static int current_insn_set_cc_p;
-static bool arc_handle_option (size_t, const char *, int);
-static void record_cc_ref (rtx);
-static void arc_init_reg_tables (void);
-static int get_arc_condition_code (rtx);
-static tree arc_handle_interrupt_attribute (tree *, tree, tree, int, bool *);
-static bool arc_assemble_integer (rtx, unsigned int, int);
-static void arc_output_function_prologue (FILE *, HOST_WIDE_INT);
-static void arc_output_function_epilogue (FILE *, HOST_WIDE_INT);
-static void arc_file_start (void);
-static void arc_internal_label (FILE *, const char *, unsigned long);
-static void arc_va_start (tree, rtx);
-static void arc_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode,
- tree, int *, int);
-static bool arc_rtx_costs (rtx, int, int, int *, bool);
-static int arc_address_cost (rtx, bool);
-static void arc_external_libcall (rtx);
-static bool arc_return_in_memory (const_tree, const_tree);
-static bool arc_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode,
- const_tree, bool);
-static rtx arc_function_arg (CUMULATIVE_ARGS *, enum machine_mode,
- const_tree, bool);
-static void arc_function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode,
- const_tree, bool);
-static unsigned int arc_function_arg_boundary (enum machine_mode, const_tree);
-static void arc_trampoline_init (rtx, tree, rtx);
-static void arc_option_override (void);
-static void arc_conditional_register_usage (void);
-
-\f
-/* ARC specific attributs. */
-
-static const struct attribute_spec arc_attribute_table[] =
-{
- /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
- affects_type_identity } */
- { "interrupt", 1, 1, true, false, false, arc_handle_interrupt_attribute,
- false },
- { NULL, 0, 0, false, false, false, NULL, false }
-};
-\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_INTEGER
-#define TARGET_ASM_INTEGER arc_assemble_integer
-
-#undef TARGET_ASM_FUNCTION_PROLOGUE
-#define TARGET_ASM_FUNCTION_PROLOGUE arc_output_function_prologue
-#undef TARGET_ASM_FUNCTION_EPILOGUE
-#define TARGET_ASM_FUNCTION_EPILOGUE arc_output_function_epilogue
-#undef TARGET_ASM_FILE_START
-#define TARGET_ASM_FILE_START arc_file_start
-#undef TARGET_ATTRIBUTE_TABLE
-#define TARGET_ATTRIBUTE_TABLE arc_attribute_table
-#undef TARGET_ASM_INTERNAL_LABEL
-#define TARGET_ASM_INTERNAL_LABEL arc_internal_label
-#undef TARGET_ASM_EXTERNAL_LIBCALL
-#define TARGET_ASM_EXTERNAL_LIBCALL arc_external_libcall
-
-#undef TARGET_HANDLE_OPTION
-#define TARGET_HANDLE_OPTION arc_handle_option
-
-#undef TARGET_OPTION_OVERRIDE
-#define TARGET_OPTION_OVERRIDE arc_option_override
-
-#undef TARGET_RTX_COSTS
-#define TARGET_RTX_COSTS arc_rtx_costs
-#undef TARGET_ADDRESS_COST
-#define TARGET_ADDRESS_COST arc_address_cost
-
-#undef TARGET_PROMOTE_FUNCTION_MODE
-#define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote
-#undef TARGET_PROMOTE_PROTOTYPES
-#define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
-
-#undef TARGET_RETURN_IN_MEMORY
-#define TARGET_RETURN_IN_MEMORY arc_return_in_memory
-#undef TARGET_PASS_BY_REFERENCE
-#define TARGET_PASS_BY_REFERENCE arc_pass_by_reference
-#undef TARGET_FUNCTION_ARG
-#define TARGET_FUNCTION_ARG arc_function_arg
-#undef TARGET_FUNCTION_ARG_ADVANCE
-#define TARGET_FUNCTION_ARG_ADVANCE arc_function_arg_advance
-#undef TARGET_FUNCTION_ARG_BOUNDARY
-#define TARGET_FUNCTION_ARG_BOUNDARY arc_function_arg_boundary
-#undef TARGET_CALLEE_COPIES
-#define TARGET_CALLEE_COPIES hook_bool_CUMULATIVE_ARGS_mode_tree_bool_true
-
-#undef TARGET_SETUP_INCOMING_VARARGS
-#define TARGET_SETUP_INCOMING_VARARGS arc_setup_incoming_varargs
-
-#undef TARGET_EXPAND_BUILTIN_VA_START
-#define TARGET_EXPAND_BUILTIN_VA_START arc_va_start
-
-#undef TARGET_TRAMPOLINE_INIT
-#define TARGET_TRAMPOLINE_INIT arc_trampoline_init
-
-#undef TARGET_CONDITIONAL_REGISTER_USAGE
-#define TARGET_CONDITIONAL_REGISTER_USAGE arc_conditional_register_usage
-
-struct gcc_target targetm = TARGET_INITIALIZER;
-\f
-/* Implement TARGET_HANDLE_OPTION. */
-
-static bool
-arc_handle_option (size_t code, const char *arg, int value ATTRIBUTE_UNUSED)
-{
- switch (code)
- {
- case OPT_mcpu_:
- return strcmp (arg, "base") == 0 || ARC_EXTENSION_CPU (arg);
-
- default:
- return true;
- }
-}
-
-/* Implement TARGET_OPTION_OVERRIDE.
- These need to be done at start up. It's convenient to do them here. */
-
-static void
-arc_option_override (void)
-{
- char *tmp;
-
- /* Set the pseudo-ops for the various standard sections. */
- arc_text_section = tmp = XNEWVEC (char, strlen (arc_text_string) + sizeof (ARC_SECTION_FORMAT) + 1);
- sprintf (tmp, ARC_SECTION_FORMAT, arc_text_string);
- arc_data_section = tmp = XNEWVEC (char, strlen (arc_data_string) + sizeof (ARC_SECTION_FORMAT) + 1);
- sprintf (tmp, ARC_SECTION_FORMAT, arc_data_string);
- arc_rodata_section = tmp = XNEWVEC (char, strlen (arc_rodata_string) + sizeof (ARC_SECTION_FORMAT) + 1);
- sprintf (tmp, ARC_SECTION_FORMAT, arc_rodata_string);
-
- arc_init_reg_tables ();
-
- /* Initialize array for PRINT_OPERAND_PUNCT_VALID_P. */
- memset (arc_punct_chars, 0, sizeof (arc_punct_chars));
- arc_punct_chars['#'] = 1;
- arc_punct_chars['*'] = 1;
- arc_punct_chars['?'] = 1;
- arc_punct_chars['!'] = 1;
- arc_punct_chars['~'] = 1;
-}
-\f
-/* The condition codes of the ARC, and the inverse function. */
-static const char *const arc_condition_codes[] =
-{
- "al", 0, "eq", "ne", "p", "n", "c", "nc", "v", "nv",
- "gt", "le", "ge", "lt", "hi", "ls", "pnz", 0
-};
-
-#define ARC_INVERSE_CONDITION_CODE(X) ((X) ^ 1)
-
-/* Returns the index of the ARC condition code string in
- `arc_condition_codes'. COMPARISON should be an rtx like
- `(eq (...) (...))'. */
-
-static int
-get_arc_condition_code (rtx comparison)
-{
- switch (GET_CODE (comparison))
- {
- case EQ : return 2;
- case NE : return 3;
- case GT : return 10;
- case LE : return 11;
- case GE : return 12;
- case LT : return 13;
- case GTU : return 14;
- case LEU : return 15;
- case LTU : return 6;
- case GEU : return 7;
- default : gcc_unreachable ();
- }
- /*NOTREACHED*/
- return (42);
-}
-
-/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
- return the mode to be used for the comparison. */
-
-enum machine_mode
-arc_select_cc_mode (enum rtx_code op,
- rtx x ATTRIBUTE_UNUSED,
- rtx y ATTRIBUTE_UNUSED)
-{
- switch (op)
- {
- case EQ :
- case NE :
- return CCZNmode;
- default :
- switch (GET_CODE (x))
- {
- case AND :
- case IOR :
- case XOR :
- case SIGN_EXTEND :
- case ZERO_EXTEND :
- return CCZNmode;
- case ASHIFT :
- case ASHIFTRT :
- case LSHIFTRT :
- return CCZNCmode;
- default:
- break;
- }
- }
- return CCmode;
-}
-\f
-/* Vectors to keep interesting information about registers where it can easily
- be got. We use to use the actual mode value as the bit number, but there
- is (or may be) more than 32 modes now. Instead we use two tables: one
- indexed by hard register number, and one indexed by mode. */
-
-/* The purpose of arc_mode_class is to shrink the range of modes so that
- they all fit (as bit numbers) in a 32-bit word (again). Each real mode is
- mapped into one arc_mode_class mode. */
-
-enum arc_mode_class {
- C_MODE,
- S_MODE, D_MODE, T_MODE, O_MODE,
- SF_MODE, DF_MODE, TF_MODE, OF_MODE
-};
-
-/* Modes for condition codes. */
-#define C_MODES (1 << (int) C_MODE)
-
-/* Modes for single-word and smaller quantities. */
-#define S_MODES ((1 << (int) S_MODE) | (1 << (int) SF_MODE))
-
-/* Modes for double-word and smaller quantities. */
-#define D_MODES (S_MODES | (1 << (int) D_MODE) | (1 << DF_MODE))
-
-/* Modes for quad-word and smaller quantities. */
-#define T_MODES (D_MODES | (1 << (int) T_MODE) | (1 << (int) TF_MODE))
-
-/* Value is 1 if register/mode pair is acceptable on arc. */
-
-const unsigned int arc_hard_regno_mode_ok[] = {
- T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES,
- T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES,
- T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, D_MODES,
- D_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES,
-
- /* ??? Leave these as S_MODES for now. */
- S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES,
- S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES,
- S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES,
- S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, C_MODES
-};
-
-unsigned int arc_mode_class [NUM_MACHINE_MODES];
-
-enum reg_class arc_regno_reg_class[FIRST_PSEUDO_REGISTER];
-
-static void
-arc_init_reg_tables (void)
-{
- int i;
-
- for (i = 0; i < NUM_MACHINE_MODES; i++)
- {
- switch (GET_MODE_CLASS (i))
- {
- case MODE_INT:
- case MODE_PARTIAL_INT:
- case MODE_COMPLEX_INT:
- if (GET_MODE_SIZE (i) <= 4)
- arc_mode_class[i] = 1 << (int) S_MODE;
- else if (GET_MODE_SIZE (i) == 8)
- arc_mode_class[i] = 1 << (int) D_MODE;
- else if (GET_MODE_SIZE (i) == 16)
- arc_mode_class[i] = 1 << (int) T_MODE;
- else if (GET_MODE_SIZE (i) == 32)
- arc_mode_class[i] = 1 << (int) O_MODE;
- else
- arc_mode_class[i] = 0;
- break;
- case MODE_FLOAT:
- case MODE_COMPLEX_FLOAT:
- if (GET_MODE_SIZE (i) <= 4)
- arc_mode_class[i] = 1 << (int) SF_MODE;
- else if (GET_MODE_SIZE (i) == 8)
- arc_mode_class[i] = 1 << (int) DF_MODE;
- else if (GET_MODE_SIZE (i) == 16)
- arc_mode_class[i] = 1 << (int) TF_MODE;
- else if (GET_MODE_SIZE (i) == 32)
- arc_mode_class[i] = 1 << (int) OF_MODE;
- else
- arc_mode_class[i] = 0;
- break;
- case MODE_CC:
- arc_mode_class[i] = 1 << (int) C_MODE;
- break;
- default:
- arc_mode_class[i] = 0;
- break;
- }
- }
-
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- {
- if (i < 60)
- arc_regno_reg_class[i] = GENERAL_REGS;
- else if (i == 60)
- arc_regno_reg_class[i] = LPCOUNT_REG;
- else if (i == 61)
- arc_regno_reg_class[i] = NO_REGS /* CC_REG: must be NO_REGS */;
- else
- arc_regno_reg_class[i] = NO_REGS;
- }
-}
-\f
-/* ARC specific attribute support.
-
- The ARC has these attributes:
- interrupt - for interrupt functions
-*/
-
-/* Handle an "interrupt" attribute; arguments as in
- struct attribute_spec.handler. */
-static tree
-arc_handle_interrupt_attribute (tree *node ATTRIBUTE_UNUSED,
- tree name,
- tree args,
- int flags ATTRIBUTE_UNUSED,
- bool *no_add_attrs)
-{
- tree value = TREE_VALUE (args);
-
- if (TREE_CODE (value) != STRING_CST)
- {
- warning (OPT_Wattributes,
- "argument of %qE attribute is not a string constant",
- name);
- *no_add_attrs = true;
- }
- else if (strcmp (TREE_STRING_POINTER (value), "ilink1")
- && strcmp (TREE_STRING_POINTER (value), "ilink2"))
- {
- warning (OPT_Wattributes,
- "argument of %qE attribute is not \"ilink1\" or \"ilink2\"",
- name);
- *no_add_attrs = true;
- }
-
- return NULL_TREE;
-}
-
-\f
-/* Acceptable arguments to the call insn. */
-
-int
-call_address_operand (rtx op, enum machine_mode mode)
-{
- return (symbolic_operand (op, mode)
- || (GET_CODE (op) == CONST_INT && LEGITIMATE_CONSTANT_P (op))
- || (GET_CODE (op) == REG));
-}
-
-int
-call_operand (rtx op, enum machine_mode mode)
-{
- if (GET_CODE (op) != MEM)
- return 0;
- op = XEXP (op, 0);
- return call_address_operand (op, mode);
-}
-
-/* Returns 1 if OP is a symbol reference. */
-
-int
-symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- switch (GET_CODE (op))
- {
- case SYMBOL_REF:
- case LABEL_REF:
- case CONST :
- return 1;
- default:
- return 0;
- }
-}
-
-/* Return truth value of statement that OP is a symbolic memory
- operand of mode MODE. */
-
-int
-symbolic_memory_operand (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) == LABEL_REF);
-}
-
-/* Return true if OP is a short immediate (shimm) value. */
-
-int
-short_immediate_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- if (GET_CODE (op) != CONST_INT)
- return 0;
- return SMALL_INT (INTVAL (op));
-}
-
-/* Return true if OP will require a long immediate (limm) value.
- This is currently only used when calculating length attributes. */
-
-int
-long_immediate_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- switch (GET_CODE (op))
- {
- case SYMBOL_REF :
- case LABEL_REF :
- case CONST :
- return 1;
- case CONST_INT :
- return !SMALL_INT (INTVAL (op));
- case CONST_DOUBLE :
- /* These can happen because large unsigned 32-bit constants are
- represented this way (the multiplication patterns can cause these
- to be generated). They also occur for SFmode values. */
- return 1;
- default:
- break;
- }
- return 0;
-}
-
-/* Return true if OP is a MEM that when used as a load or store address will
- require an 8 byte insn.
- Load and store instructions don't allow the same possibilities but they're
- similar enough that this one function will do.
- This is currently only used when calculating length attributes. */
-
-int
-long_immediate_loadstore_operand (rtx op,
- enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- if (GET_CODE (op) != MEM)
- return 0;
-
- op = XEXP (op, 0);
- switch (GET_CODE (op))
- {
- case SYMBOL_REF :
- case LABEL_REF :
- case CONST :
- return 1;
- case CONST_INT :
- /* This must be handled as "st c,[limm]". Ditto for load.
- Technically, the assembler could translate some possibilities to
- "st c,[limm/2 + limm/2]" if limm/2 will fit in a shimm, but we don't
- assume that it does. */
- return 1;
- case CONST_DOUBLE :
- /* These can happen because large unsigned 32-bit constants are
- represented this way (the multiplication patterns can cause these
- to be generated). They also occur for SFmode values. */
- return 1;
- case REG :
- return 0;
- case PLUS :
- if (GET_CODE (XEXP (op, 1)) == CONST_INT
- && !SMALL_INT (INTVAL (XEXP (op, 1))))
- return 1;
- return 0;
- default:
- break;
- }
- return 0;
-}
-
-/* Return true if OP is an acceptable argument for a single word
- move source. */
-
-int
-move_src_operand (rtx op, enum machine_mode mode)
-{
- switch (GET_CODE (op))
- {
- case SYMBOL_REF :
- case LABEL_REF :
- case CONST :
- return 1;
- case CONST_INT :
- return (LARGE_INT (INTVAL (op)));
- case CONST_DOUBLE :
- /* We can handle DImode integer constants in SImode if the value
- (signed or unsigned) will fit in 32 bits. This is needed because
- large unsigned 32-bit constants are represented as CONST_DOUBLEs. */
- if (mode == SImode)
- return arc_double_limm_p (op);
- /* We can handle 32-bit floating point constants. */
- if (mode == SFmode)
- return GET_MODE (op) == SFmode;
- return 0;
- case REG :
- return register_operand (op, mode);
- case SUBREG :
- /* (subreg (mem ...) ...) can occur here if the inner part was once a
- pseudo-reg and is now a stack slot. */
- if (GET_CODE (SUBREG_REG (op)) == MEM)
- return address_operand (XEXP (SUBREG_REG (op), 0), mode);
- else
- return register_operand (op, mode);
- case MEM :
- return address_operand (XEXP (op, 0), mode);
- default :
- return 0;
- }
-}
-
-/* Return true if OP is an acceptable argument for a double word
- move source. */
-
-int
-move_double_src_operand (rtx op, enum machine_mode mode)
-{
- switch (GET_CODE (op))
- {
- case REG :
- return register_operand (op, mode);
- case SUBREG :
- /* (subreg (mem ...) ...) can occur here if the inner part was once a
- pseudo-reg and is now a stack slot. */
- if (GET_CODE (SUBREG_REG (op)) == MEM)
- return move_double_src_operand (SUBREG_REG (op), mode);
- else
- return register_operand (op, mode);
- case MEM :
- /* Disallow auto inc/dec for now. */
- if (GET_CODE (XEXP (op, 0)) == PRE_DEC
- || GET_CODE (XEXP (op, 0)) == PRE_INC)
- return 0;
- return address_operand (XEXP (op, 0), mode);
- case CONST_INT :
- case CONST_DOUBLE :
- return 1;
- default :
- return 0;
- }
-}
-
-/* Return true if OP is an acceptable argument for a move destination. */
-
-int
-move_dest_operand (rtx op, enum machine_mode mode)
-{
- switch (GET_CODE (op))
- {
- case REG :
- return register_operand (op, mode);
- case SUBREG :
- /* (subreg (mem ...) ...) can occur here if the inner part was once a
- pseudo-reg and is now a stack slot. */
- if (GET_CODE (SUBREG_REG (op)) == MEM)
- return address_operand (XEXP (SUBREG_REG (op), 0), mode);
- else
- return register_operand (op, mode);
- case MEM :
- return address_operand (XEXP (op, 0), mode);
- default :
- return 0;
- }
-}
-
-/* Return true if OP is valid load with update operand. */
-
-int
-load_update_operand (rtx op, enum machine_mode mode)
-{
- if (GET_CODE (op) != MEM
- || GET_MODE (op) != mode)
- return 0;
- op = XEXP (op, 0);
- if (GET_CODE (op) != PLUS
- || GET_MODE (op) != Pmode
- || !register_operand (XEXP (op, 0), Pmode)
- || !nonmemory_operand (XEXP (op, 1), Pmode))
- return 0;
- return 1;
-}
-
-/* Return true if OP is valid store with update operand. */
-
-int
-store_update_operand (rtx op, enum machine_mode mode)
-{
- if (GET_CODE (op) != MEM
- || GET_MODE (op) != mode)
- return 0;
- op = XEXP (op, 0);
- if (GET_CODE (op) != PLUS
- || GET_MODE (op) != Pmode
- || !register_operand (XEXP (op, 0), Pmode)
- || !(GET_CODE (XEXP (op, 1)) == CONST_INT
- && SMALL_INT (INTVAL (XEXP (op, 1)))))
- return 0;
- return 1;
-}
-
-/* Return true if OP is a non-volatile non-immediate operand.
- Volatile memory refs require a special "cache-bypass" instruction
- and only the standard movXX patterns are set up to handle them. */
-
-int
-nonvol_nonimm_operand (rtx op, enum machine_mode mode)
-{
- if (GET_CODE (op) == MEM && MEM_VOLATILE_P (op))
- return 0;
- return nonimmediate_operand (op, mode);
-}
-
-/* Accept integer operands in the range -0x80000000..0x7fffffff. We have
- to check the range carefully since this predicate is used in DImode
- contexts. */
-
-int
-const_sint32_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- /* All allowed constants will fit a CONST_INT. */
- return (GET_CODE (op) == CONST_INT
- && (INTVAL (op) >= (-0x7fffffff - 1) && INTVAL (op) <= 0x7fffffff));
-}
-
-/* Accept integer operands in the range 0..0xffffffff. We have to check the
- range carefully since this predicate is used in DImode contexts. Also, we
- need some extra crud to make it work when hosted on 64-bit machines. */
-
-int
-const_uint32_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
-#if HOST_BITS_PER_WIDE_INT > 32
- /* All allowed constants will fit a CONST_INT. */
- return (GET_CODE (op) == CONST_INT
- && (INTVAL (op) >= 0 && INTVAL (op) <= 0xffffffffL));
-#else
- return ((GET_CODE (op) == CONST_INT && INTVAL (op) >= 0)
- || (GET_CODE (op) == CONST_DOUBLE && CONST_DOUBLE_HIGH (op) == 0));
-#endif
-}
-
-/* Return 1 if OP is a comparison operator valid for the mode of CC.
- This allows the use of MATCH_OPERATOR to recognize all the branch insns.
-
- Some insns only set a few bits in the condition code. So only allow those
- comparisons that use the bits that are valid. */
-
-int
-proper_comparison_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- enum rtx_code code;
- if (!COMPARISON_P (op))
- return 0;
-
- code = GET_CODE (op);
- if (GET_MODE (XEXP (op, 0)) == CCZNmode)
- return (code == EQ || code == NE);
- if (GET_MODE (XEXP (op, 0)) == CCZNCmode)
- return (code == EQ || code == NE
- || code == LTU || code == GEU || code == GTU || code == LEU);
- return 1;
-}
-\f
-/* Misc. utilities. */
-
-/* X and Y are two things to compare using CODE. Return the rtx
- for the cc reg in the proper mode. */
-
-rtx
-gen_compare_reg (enum rtx_code code, rtx x, rtx y)
-{
- enum machine_mode mode = SELECT_CC_MODE (code, x, y);
- return gen_rtx_REG (mode, 61);
-}
-
-/* Return 1 if VALUE, a const_double, will fit in a limm (4 byte number).
- We assume the value can be either signed or unsigned. */
-
-int
-arc_double_limm_p (rtx value)
-{
- HOST_WIDE_INT low, high;
-
- gcc_assert (GET_CODE (value) == CONST_DOUBLE);
-
- low = CONST_DOUBLE_LOW (value);
- high = CONST_DOUBLE_HIGH (value);
-
- if (low & 0x80000000)
- {
- return (((unsigned HOST_WIDE_INT) low <= 0xffffffff && high == 0)
- || (((low & - (unsigned HOST_WIDE_INT) 0x80000000)
- == - (unsigned HOST_WIDE_INT) 0x80000000)
- && high == -1));
- }
- else
- {
- return (unsigned HOST_WIDE_INT) low <= 0x7fffffff && high == 0;
- }
-}
-\f
-/* Do any needed setup for a variadic function. For the ARC, we must
- create a register parameter block, and then copy any anonymous arguments
- in registers to memory.
-
- CUM has not been updated for the last named argument which has type TYPE
- and mode MODE, and we rely on this fact.
-
- We do things a little weird here. We're supposed to only allocate space
- for the anonymous arguments. However we need to keep the stack eight byte
- aligned. So we round the space up if necessary, and leave it to va_start
- to compensate. */
-
-static void
-arc_setup_incoming_varargs (CUMULATIVE_ARGS *cum,
- enum machine_mode mode,
- tree type ATTRIBUTE_UNUSED,
- int *pretend_size,
- int no_rtl)
-{
- int first_anon_arg;
-
- /* All BLKmode values are passed by reference. */
- gcc_assert (mode != BLKmode);
-
- first_anon_arg = *cum + ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1)
- / UNITS_PER_WORD);
-
- if (first_anon_arg < MAX_ARC_PARM_REGS && !no_rtl)
- {
- /* Note that first_reg_offset < MAX_ARC_PARM_REGS. */
- int first_reg_offset = first_anon_arg;
- /* Size in words to "pretend" allocate. */
- int size = MAX_ARC_PARM_REGS - first_reg_offset;
- /* Extra slop to keep stack eight byte aligned. */
- int align_slop = size & 1;
- rtx regblock;
-
- regblock = gen_rtx_MEM (BLKmode,
- plus_constant (arg_pointer_rtx,
- FIRST_PARM_OFFSET (0)
- + align_slop * UNITS_PER_WORD));
- set_mem_alias_set (regblock, get_varargs_alias_set ());
- set_mem_align (regblock, BITS_PER_WORD);
- move_block_from_reg (first_reg_offset, regblock,
- MAX_ARC_PARM_REGS - first_reg_offset);
-
- *pretend_size = ((MAX_ARC_PARM_REGS - first_reg_offset + align_slop)
- * UNITS_PER_WORD);
- }
-}
-\f
-/* Cost functions. */
-
-/* Compute a (partial) cost for rtx X. Return true if the complete
- cost has been computed, and false if subexpressions should be
- scanned. In either case, *TOTAL contains the cost result. */
-
-static bool
-arc_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int *total,
- bool speed ATTRIBUTE_UNUSED)
-{
- switch (code)
- {
- /* Small integers are as cheap as registers. 4 byte values can
- be fetched as immediate constants - let's give that the cost
- of an extra insn. */
- case CONST_INT:
- if (SMALL_INT (INTVAL (x)))
- {
- *total = 0;
- return true;
- }
- /* FALLTHRU */
-
- case CONST:
- case LABEL_REF:
- case SYMBOL_REF:
- *total = COSTS_N_INSNS (1);
- return true;
-
- case CONST_DOUBLE:
- {
- rtx high, low;
- split_double (x, &high, &low);
- *total = COSTS_N_INSNS (!SMALL_INT (INTVAL (high))
- + !SMALL_INT (INTVAL (low)));
- return true;
- }
-
- /* Encourage synth_mult to find a synthetic multiply when reasonable.
- If we need more than 12 insns to do a multiply, then go out-of-line,
- since the call overhead will be < 10% of the cost of the multiply. */
- case ASHIFT:
- case ASHIFTRT:
- case LSHIFTRT:
- if (TARGET_SHIFTER)
- *total = COSTS_N_INSNS (1);
- else if (GET_CODE (XEXP (x, 1)) != CONST_INT)
- *total = COSTS_N_INSNS (16);
- else
- *total = COSTS_N_INSNS (INTVAL (XEXP ((x), 1)));
- return false;
-
- default:
- return false;
- }
-}
-
-
-/* Provide the costs of an addressing mode that contains ADDR.
- If ADDR is not a valid address, its cost is irrelevant. */
-
-static int
-arc_address_cost (rtx addr, bool speed ATTRIBUTE_UNUSED)
-{
- switch (GET_CODE (addr))
- {
- case REG :
- return 1;
-
- case LABEL_REF :
- case SYMBOL_REF :
- case CONST :
- return 2;
-
- case PLUS :
- {
- register rtx plus0 = XEXP (addr, 0);
- register rtx plus1 = XEXP (addr, 1);
-
- if (GET_CODE (plus0) != REG)
- break;
-
- switch (GET_CODE (plus1))
- {
- case CONST_INT :
- return SMALL_INT (INTVAL (plus1)) ? 1 : 2;
- case CONST :
- case SYMBOL_REF :
- case LABEL_REF :
- return 2;
- default:
- break;
- }
- break;
- }
- default:
- break;
- }
-
- return 4;
-}
-\f
-/* Function prologue/epilogue handlers. */
-
-/* ARC stack frames look like:
-
- Before call After call
- +-----------------------+ +-----------------------+
- | | | |
- high | local variables, | | local variables, |
- mem | reg save area, etc. | | reg save area, etc. |
- | | | |
- +-----------------------+ +-----------------------+
- | | | |
- | arguments on stack. | | arguments on stack. |
- | | | |
- SP+16->+-----------------------+FP+48->+-----------------------+
- | 4 word save area for | | reg parm save area, |
- | return addr, prev %fp | | only created for |
- SP+0->+-----------------------+ | variable argument |
- | functions |
- FP+16->+-----------------------+
- | 4 word save area for |
- | return addr, prev %fp |
- FP+0->+-----------------------+
- | |
- | local variables |
- | |
- +-----------------------+
- | |
- | register save area |
- | |
- +-----------------------+
- | |
- | alloca allocations |
- | |
- +-----------------------+
- | |
- | arguments on stack |
- | |
- SP+16->+-----------------------+
- low | 4 word save area for |
- memory | return addr, prev %fp |
- SP+0->+-----------------------+
-
-Notes:
-1) The "reg parm save area" does not exist for non variable argument fns.
- The "reg parm save area" can be eliminated completely if we created our
- own va-arc.h, but that has tradeoffs as well (so it's not done). */
-
-/* Structure to be filled in by arc_compute_frame_size with register
- save masks, and offsets for the current function. */
-struct arc_frame_info
-{
- unsigned int total_size; /* # bytes that the entire frame takes up. */
- unsigned int extra_size; /* # bytes of extra stuff. */
- unsigned int pretend_size; /* # bytes we push and pretend caller did. */
- unsigned int args_size; /* # bytes that outgoing arguments take up. */
- unsigned int reg_size; /* # bytes needed to store regs. */
- unsigned int var_size; /* # bytes that variables take up. */
- unsigned int reg_offset; /* Offset from new sp to store regs. */
- unsigned int gmask; /* Mask of saved gp registers. */
- int initialized; /* Nonzero if frame size already calculated. */
-};
-
-/* Current frame information calculated by arc_compute_frame_size. */
-static struct arc_frame_info current_frame_info;
-
-/* Zero structure to initialize current_frame_info. */
-static struct arc_frame_info zero_frame_info;
-
-/* Type of function DECL.
-
- The result is cached. To reset the cache at the end of a function,
- call with DECL = NULL_TREE. */
-
-enum arc_function_type
-arc_compute_function_type (tree decl)
-{
- tree a;
- /* Cached value. */
- static enum arc_function_type fn_type = ARC_FUNCTION_UNKNOWN;
- /* Last function we were called for. */
- static tree last_fn = NULL_TREE;
-
- /* Resetting the cached value? */
- if (decl == NULL_TREE)
- {
- fn_type = ARC_FUNCTION_UNKNOWN;
- last_fn = NULL_TREE;
- return fn_type;
- }
-
- if (decl == last_fn && fn_type != ARC_FUNCTION_UNKNOWN)
- return fn_type;
-
- /* Assume we have a normal function (not an interrupt handler). */
- fn_type = ARC_FUNCTION_NORMAL;
-
- /* Now see if this is an interrupt handler. */
- for (a = DECL_ATTRIBUTES (current_function_decl);
- a;
- a = TREE_CHAIN (a))
- {
- tree name = TREE_PURPOSE (a), args = TREE_VALUE (a);
-
- if (name == get_identifier ("__interrupt__")
- && list_length (args) == 1
- && TREE_CODE (TREE_VALUE (args)) == STRING_CST)
- {
- tree value = TREE_VALUE (args);
-
- if (!strcmp (TREE_STRING_POINTER (value), "ilink1"))
- fn_type = ARC_FUNCTION_ILINK1;
- else if (!strcmp (TREE_STRING_POINTER (value), "ilink2"))
- fn_type = ARC_FUNCTION_ILINK2;
- else
- gcc_unreachable ();
- break;
- }
- }
-
- last_fn = decl;
- return fn_type;
-}
-
-#define ILINK1_REGNUM 29
-#define ILINK2_REGNUM 30
-#define RETURN_ADDR_REGNUM 31
-#define FRAME_POINTER_MASK (1 << (FRAME_POINTER_REGNUM))
-#define RETURN_ADDR_MASK (1 << (RETURN_ADDR_REGNUM))
-
-/* Tell prologue and epilogue if register REGNO should be saved / restored.
- The return address and frame pointer are treated separately.
- Don't consider them here. */
-#define MUST_SAVE_REGISTER(regno, interrupt_p) \
-((regno) != RETURN_ADDR_REGNUM && (regno) != FRAME_POINTER_REGNUM \
- && (df_regs_ever_live_p (regno) && (!call_used_regs[regno] || interrupt_p)))
-
-#define MUST_SAVE_RETURN_ADDR (df_regs_ever_live_p (RETURN_ADDR_REGNUM))
-
-/* Return the bytes needed to compute the frame pointer from the current
- stack pointer.
-
- SIZE is the size needed for local variables. */
-
-unsigned int
-arc_compute_frame_size (int size /* # of var. bytes allocated. */)
-{
- int regno;
- unsigned int total_size, var_size, args_size, pretend_size, extra_size;
- unsigned int reg_size, reg_offset;
- unsigned int gmask;
- enum arc_function_type fn_type;
- int interrupt_p;
-
- var_size = size;
- args_size = crtl->outgoing_args_size;
- pretend_size = crtl->args.pretend_args_size;
- extra_size = FIRST_PARM_OFFSET (0);
- total_size = extra_size + pretend_size + args_size + var_size;
- reg_offset = FIRST_PARM_OFFSET(0) + crtl->outgoing_args_size;
- reg_size = 0;
- gmask = 0;
-
- /* See if this is an interrupt handler. Call used registers must be saved
- for them too. */
- fn_type = arc_compute_function_type (current_function_decl);
- interrupt_p = ARC_INTERRUPT_P (fn_type);
-
- /* Calculate space needed for registers.
- ??? We ignore the extension registers for now. */
-
- for (regno = 0; regno <= 31; regno++)
- {
- if (MUST_SAVE_REGISTER (regno, interrupt_p))
- {
- reg_size += UNITS_PER_WORD;
- gmask |= 1 << regno;
- }
- }
-
- total_size += reg_size;
-
- /* If the only space to allocate is the fp/blink save area this is an
- empty frame. However, if we'll be making a function call we need to
- allocate a stack frame for our callee's fp/blink save area. */
- if (total_size == extra_size
- && !MUST_SAVE_RETURN_ADDR)
- total_size = extra_size = 0;
-
- total_size = ARC_STACK_ALIGN (total_size);
-
- /* Save computed information. */
- current_frame_info.total_size = total_size;
- current_frame_info.extra_size = extra_size;
- current_frame_info.pretend_size = pretend_size;
- current_frame_info.var_size = var_size;
- current_frame_info.args_size = args_size;
- current_frame_info.reg_size = reg_size;
- current_frame_info.reg_offset = reg_offset;
- current_frame_info.gmask = gmask;
- current_frame_info.initialized = reload_completed;
-
- /* Ok, we're done. */
- return total_size;
-}
-\f
-/* Common code to save/restore registers. */
-
-void
-arc_save_restore (FILE *file,
- const char *base_reg,
- unsigned int offset,
- unsigned int gmask,
- const char *op)
-{
- int regno;
-
- if (gmask == 0)
- return;
-
- for (regno = 0; regno <= 31; regno++)
- {
- if ((gmask & (1L << regno)) != 0)
- {
- fprintf (file, "\t%s %s,[%s,%d]\n",
- op, reg_names[regno], base_reg, offset);
- offset += UNITS_PER_WORD;
- }
- }
-}
-\f
-/* Target hook to assemble an integer object. The ARC version needs to
- emit a special directive for references to labels and function
- symbols. */
-
-static bool
-arc_assemble_integer (rtx x, unsigned int size, int aligned_p)
-{
- if (size == UNITS_PER_WORD && aligned_p
- && ((GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (x))
- || GET_CODE (x) == LABEL_REF))
- {
- fputs ("\t.word\t%st(", asm_out_file);
- output_addr_const (asm_out_file, x);
- fputs (")\n", asm_out_file);
- return true;
- }
- return default_assemble_integer (x, size, aligned_p);
-}
-\f
-/* Set up the stack and frame pointer (if desired) for the function. */
-
-static void
-arc_output_function_prologue (FILE *file, HOST_WIDE_INT size)
-{
- const char *sp_str = reg_names[STACK_POINTER_REGNUM];
- const char *fp_str = reg_names[FRAME_POINTER_REGNUM];
- unsigned int gmask = current_frame_info.gmask;
- enum arc_function_type fn_type = arc_compute_function_type (current_function_decl);
-
- /* If this is an interrupt handler, set up our stack frame.
- ??? Optimize later. */
- if (ARC_INTERRUPT_P (fn_type))
- {
- fprintf (file, "\t%s interrupt handler\n",
- ASM_COMMENT_START);
- fprintf (file, "\tsub %s,%s,16\n", sp_str, sp_str);
- }
-
- /* This is only for the human reader. */
- fprintf (file, "\t%s BEGIN PROLOGUE %s vars= %d, regs= %d, args= %d, extra= %d\n",
- ASM_COMMENT_START, ASM_COMMENT_START,
- current_frame_info.var_size,
- current_frame_info.reg_size / 4,
- current_frame_info.args_size,
- current_frame_info.extra_size);
-
- size = ARC_STACK_ALIGN (size);
- size = (! current_frame_info.initialized
- ? arc_compute_frame_size (size)
- : current_frame_info.total_size);
-
- /* These cases shouldn't happen. Catch them now. */
- gcc_assert (size || !gmask);
-
- /* Allocate space for register arguments if this is a variadic function. */
- if (current_frame_info.pretend_size != 0)
- fprintf (file, "\tsub %s,%s,%d\n",
- sp_str, sp_str, current_frame_info.pretend_size);
-
- /* The home-grown ABI says link register is saved first. */
- if (MUST_SAVE_RETURN_ADDR)
- fprintf (file, "\tst %s,[%s,%d]\n",
- reg_names[RETURN_ADDR_REGNUM], sp_str, UNITS_PER_WORD);
-
- /* Set up the previous frame pointer next (if we need to). */
- if (frame_pointer_needed)
- {
- fprintf (file, "\tst %s,[%s]\n", fp_str, sp_str);
- fprintf (file, "\tmov %s,%s\n", fp_str, sp_str);
- }
-
- /* ??? We don't handle the case where the saved regs are more than 252
- bytes away from sp. This can be handled by decrementing sp once, saving
- the regs, and then decrementing it again. The epilogue doesn't have this
- problem as the `ld' insn takes reg+limm values (though it would be more
- efficient to avoid reg+limm). */
-
- /* Allocate the stack frame. */
- if (size - current_frame_info.pretend_size > 0)
- fprintf (file, "\tsub %s,%s," HOST_WIDE_INT_PRINT_DEC "\n",
- sp_str, sp_str, size - current_frame_info.pretend_size);
-
- /* Save any needed call-saved regs (and call-used if this is an
- interrupt handler). */
- arc_save_restore (file, sp_str, current_frame_info.reg_offset,
- /* The zeroing of these two bits is unnecessary,
- but leave this in for clarity. */
- gmask & ~(FRAME_POINTER_MASK | RETURN_ADDR_MASK),
- "st");
-
- fprintf (file, "\t%s END PROLOGUE\n", ASM_COMMENT_START);
-}
-\f
-/* Do any necessary cleanup after a function to restore stack, frame,
- and regs. */
-
-static void
-arc_output_function_epilogue (FILE *file, HOST_WIDE_INT size)
-{
- rtx epilogue_delay = crtl->epilogue_delay_list;
- int noepilogue = FALSE;
- enum arc_function_type fn_type = arc_compute_function_type (current_function_decl);
-
- /* This is only for the human reader. */
- fprintf (file, "\t%s EPILOGUE\n", ASM_COMMENT_START);
-
- size = ARC_STACK_ALIGN (size);
- size = (!current_frame_info.initialized
- ? arc_compute_frame_size (size)
- : current_frame_info.total_size);
-
- if (size == 0 && epilogue_delay == 0)
- {
- rtx insn = get_last_insn ();
-
- /* If the last insn was a BARRIER, we don't have to write any code
- because a jump (aka return) was put there. */
- if (GET_CODE (insn) == NOTE)
- insn = prev_nonnote_insn (insn);
- if (insn && GET_CODE (insn) == BARRIER)
- noepilogue = TRUE;
- }
-
- if (!noepilogue)
- {
- unsigned int pretend_size = current_frame_info.pretend_size;
- unsigned int frame_size = size - pretend_size;
- int restored, fp_restored_p;
- int can_trust_sp_p = !cfun->calls_alloca;
- const char *sp_str = reg_names[STACK_POINTER_REGNUM];
- const char *fp_str = reg_names[FRAME_POINTER_REGNUM];
-
- /* ??? There are lots of optimizations that can be done here.
- EG: Use fp to restore regs if it's closer.
- Maybe in time we'll do them all. For now, always restore regs from
- sp, but don't restore sp if we don't have to. */
-
- if (!can_trust_sp_p)
- {
- gcc_assert (frame_pointer_needed);
- fprintf (file,"\tsub %s,%s,%d\t\t%s sp not trusted here\n",
- sp_str, fp_str, frame_size, ASM_COMMENT_START);
- }
-
- /* Restore any saved registers. */
- arc_save_restore (file, sp_str, current_frame_info.reg_offset,
- /* The zeroing of these two bits is unnecessary,
- but leave this in for clarity. */
- current_frame_info.gmask & ~(FRAME_POINTER_MASK | RETURN_ADDR_MASK),
- "ld");
-
- if (MUST_SAVE_RETURN_ADDR)
- fprintf (file, "\tld %s,[%s,%d]\n",
- reg_names[RETURN_ADDR_REGNUM],
- frame_pointer_needed ? fp_str : sp_str,
- UNITS_PER_WORD + (frame_pointer_needed ? 0 : frame_size));
-
- /* Keep track of how much of the stack pointer we've restored.
- It makes the following a lot more readable. */
- restored = 0;
- fp_restored_p = 0;
-
- /* We try to emit the epilogue delay slot insn right after the load
- of the return address register so that it can execute with the
- stack intact. Secondly, loads are delayed. */
- /* ??? If stack intactness is important, always emit now. */
- if (MUST_SAVE_RETURN_ADDR && epilogue_delay != NULL_RTX)
- {
- final_scan_insn (XEXP (epilogue_delay, 0), file, 1, 1, NULL);
- epilogue_delay = NULL_RTX;
- }
-
- if (frame_pointer_needed)
- {
- /* Try to restore the frame pointer in the delay slot. We can't,
- however, if any of these is true. */
- if (epilogue_delay != NULL_RTX
- || !SMALL_INT (frame_size)
- || pretend_size
- || ARC_INTERRUPT_P (fn_type))
- {
- /* Note that we restore fp and sp here! */
- fprintf (file, "\tld.a %s,[%s,%d]\n", fp_str, sp_str, frame_size);
- restored += frame_size;
- fp_restored_p = 1;
- }
- }
- else if (!SMALL_INT (size /* frame_size + pretend_size */)
- || ARC_INTERRUPT_P (fn_type))
- {
- fprintf (file, "\tadd %s,%s,%d\n", sp_str, sp_str, frame_size);
- restored += frame_size;
- }
-
- /* These must be done before the return insn because the delay slot
- does the final stack restore. */
- if (ARC_INTERRUPT_P (fn_type))
- {
- if (epilogue_delay)
- {
- final_scan_insn (XEXP (epilogue_delay, 0), file, 1, 1, NULL);
- }
- }
-
- /* Emit the return instruction. */
- {
- static const int regs[4] = {
- 0, RETURN_ADDR_REGNUM, ILINK1_REGNUM, ILINK2_REGNUM
- };
-
- /* Update the flags, if returning from an interrupt handler. */
- if (ARC_INTERRUPT_P (fn_type))
- fprintf (file, "\tj.d.f %s\n", reg_names[regs[fn_type]]);
- else
- fprintf (file, "\tj.d %s\n", reg_names[regs[fn_type]]);
- }
-
- /* If the only register saved is the return address, we need a
- nop, unless we have an instruction to put into it. Otherwise
- we don't since reloading multiple registers doesn't reference
- the register being loaded. */
-
- if (ARC_INTERRUPT_P (fn_type))
- fprintf (file, "\tadd %s,%s,16\n", sp_str, sp_str);
- else if (epilogue_delay != NULL_RTX)
- {
- gcc_assert (!frame_pointer_needed || fp_restored_p);
- gcc_assert (restored >= size);
- final_scan_insn (XEXP (epilogue_delay, 0), file, 1, 1, NULL);
- }
- else if (frame_pointer_needed && !fp_restored_p)
- {
- gcc_assert (SMALL_INT (frame_size));
- /* Note that we restore fp and sp here! */
- fprintf (file, "\tld.a %s,[%s,%d]\n", fp_str, sp_str, frame_size);
- }
- else if (restored < size)
- {
- gcc_assert (SMALL_INT (size - restored));
- fprintf (file, "\tadd %s,%s," HOST_WIDE_INT_PRINT_DEC "\n",
- sp_str, sp_str, size - restored);
- }
- else
- fprintf (file, "\tnop\n");
- }
-
- /* Reset state info for each function. */
- current_frame_info = zero_frame_info;
- arc_compute_function_type (NULL_TREE);
-}
-\f
-/* Define the number of delay slots needed for the function epilogue.
-
- Interrupt handlers can't have any epilogue delay slots (it's always needed
- for something else, I think). For normal functions, we have to worry about
- using call-saved regs as they'll be restored before the delay slot insn.
- Functions with non-empty frames already have enough choices for the epilogue
- delay slot so for now we only consider functions with empty frames. */
-
-int
-arc_delay_slots_for_epilogue (void)
-{
- if (arc_compute_function_type (current_function_decl) != ARC_FUNCTION_NORMAL)
- return 0;
- if (!current_frame_info.initialized)
- (void) arc_compute_frame_size (get_frame_size ());
- if (current_frame_info.total_size == 0)
- return 1;
- return 0;
-}
-
-/* Return true if TRIAL is a valid insn for the epilogue delay slot.
- Any single length instruction which doesn't reference the stack or frame
- pointer or any call-saved register is OK. SLOT will always be 0. */
-
-int
-arc_eligible_for_epilogue_delay (rtx trial, int slot)
-{
- gcc_assert (!slot);
-
- if (get_attr_length (trial) == 1
- /* If registers where saved, presumably there's more than enough
- possibilities for the delay slot. The alternative is something
- more complicated (of course, if we expanded the epilogue as rtl
- this problem would go away). */
- /* ??? Note that this will always be true since only functions with
- empty frames have epilogue delay slots. See
- arc_delay_slots_for_epilogue. */
- && current_frame_info.gmask == 0
- && ! reg_mentioned_p (stack_pointer_rtx, PATTERN (trial))
- && ! reg_mentioned_p (frame_pointer_rtx, PATTERN (trial)))
- return 1;
- return 0;
-}
-\f
-/* Return true if OP is a shift operator. */
-
-int
-shift_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- switch (GET_CODE (op))
- {
- case ASHIFTRT:
- case LSHIFTRT:
- case ASHIFT:
- return 1;
- default:
- return 0;
- }
-}
-
-/* Output the assembler code for doing a shift.
- We go to a bit of trouble to generate efficient code as the ARC only has
- single bit shifts. This is taken from the h8300 port. We only have one
- mode of shifting and can't access individual bytes like the h8300 can, so
- this is greatly simplified (at the expense of not generating hyper-
- efficient code).
-
- This function is not used if the variable shift insns are present. */
-
-/* ??? We assume the output operand is the same as operand 1.
- This can be optimized (deleted) in the case of 1 bit shifts. */
-/* ??? We use the loop register here. We don't use it elsewhere (yet) and
- using it here will give us a chance to play with it. */
-
-const char *
-output_shift (rtx *operands)
-{
- rtx shift = operands[3];
- enum machine_mode mode = GET_MODE (shift);
- enum rtx_code code = GET_CODE (shift);
- const char *shift_one;
-
- gcc_assert (mode == SImode);
-
- switch (code)
- {
- case ASHIFT: shift_one = "asl %0,%0"; break;
- case ASHIFTRT: shift_one = "asr %0,%0"; break;
- case LSHIFTRT: shift_one = "lsr %0,%0"; break;
- default: gcc_unreachable ();
- }
-
- if (GET_CODE (operands[2]) != CONST_INT)
- {
- if (optimize)
- {
- output_asm_insn ("sub.f 0,%2,0", operands);
- output_asm_insn ("mov lp_count,%2", operands);
- output_asm_insn ("bz 2f", operands);
- }
- else
- output_asm_insn ("mov %4,%2", operands);
- goto shiftloop;
- }
- else
- {
- int n;
-
- /* If the count is negative, make it 0. */
- n = INTVAL (operands[2]);
- if (n < 0)
- n = 0;
- /* If the count is too big, truncate it.
- ANSI says shifts of GET_MODE_BITSIZE are undefined - we choose to
- do the intuitive thing. */
- else if (n > GET_MODE_BITSIZE (mode))
- n = GET_MODE_BITSIZE (mode);
-
- /* First see if we can do them inline. */
- if (n <= 8)
- {
- while (--n >= 0)
- output_asm_insn (shift_one, operands);
- }
- /* See if we can use a rotate/and. */
- else if (n == BITS_PER_WORD - 1)
- {
- switch (code)
- {
- case ASHIFT :
- output_asm_insn ("and %0,%0,1\n\tror %0,%0", operands);
- break;
- case ASHIFTRT :
- /* The ARC doesn't have a rol insn. Use something else. */
- output_asm_insn ("asl.f 0,%0\n\tsbc %0,0,0", operands);
- break;
- case LSHIFTRT :
- /* The ARC doesn't have a rol insn. Use something else. */
- output_asm_insn ("asl.f 0,%0\n\tadc %0,0,0", operands);
- break;
- default:
- break;
- }
- }
- /* Must loop. */
- else
- {
- char buf[100];
-
- if (optimize)
- output_asm_insn ("mov lp_count,%c2", operands);
- else
- output_asm_insn ("mov %4,%c2", operands);
- shiftloop:
- if (optimize)
- {
- if (flag_pic)
- sprintf (buf, "lr %%4,[status]\n\tadd %%4,%%4,6\t%s single insn loop start",
- ASM_COMMENT_START);
- else
- sprintf (buf, "mov %%4,%%%%st(1f)\t%s (single insn loop start) >> 2",
- ASM_COMMENT_START);
- output_asm_insn (buf, operands);
- output_asm_insn ("sr %4,[lp_start]", operands);
- output_asm_insn ("add %4,%4,1", operands);
- output_asm_insn ("sr %4,[lp_end]", operands);
- output_asm_insn ("nop\n\tnop", operands);
- if (flag_pic)
- fprintf (asm_out_file, "\t%s single insn loop\n",
- ASM_COMMENT_START);
- else
- fprintf (asm_out_file, "1:\t%s single insn loop\n",
- ASM_COMMENT_START);
- output_asm_insn (shift_one, operands);
- fprintf (asm_out_file, "2:\t%s end single insn loop\n",
- ASM_COMMENT_START);
- }
- else
- {
- fprintf (asm_out_file, "1:\t%s begin shift loop\n",
- ASM_COMMENT_START);
- output_asm_insn ("sub.f %4,%4,1", operands);
- output_asm_insn ("nop", operands);
- output_asm_insn ("bn.nd 2f", operands);
- output_asm_insn (shift_one, operands);
- output_asm_insn ("b.nd 1b", operands);
- fprintf (asm_out_file, "2:\t%s end shift loop\n",
- ASM_COMMENT_START);
- }
- }
- }
-
- return "";
-}
-\f
-/* Nested function support. */
-
-/* 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. */
-
-void
-arc_initialize_trampoline (rtx tramp ATTRIBUTE_UNUSED,
- rtx fnaddr ATTRIBUTE_UNUSED,
- rtx cxt ATTRIBUTE_UNUSED)
-{
-}
-\f
-/* Set the cpu type and print out other fancy things,
- at the top of the file. */
-
-static void
-arc_file_start (void)
-{
- default_file_start ();
- fprintf (asm_out_file, "\t.cpu %s\n", arc_cpu_string);
-}
-\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. */
-
-void
-arc_print_operand (FILE *file, rtx x, int code)
-{
- switch (code)
- {
- case '#' :
- /* Conditional branches. For now these are equivalent. */
- case '*' :
- /* Unconditional branches. Output the appropriate delay slot suffix. */
- if (!final_sequence || XVECLEN (final_sequence, 0) == 1)
- {
- /* There's nothing in the delay slot. */
- fputs (".nd", file);
- }
- else
- {
- rtx jump = XVECEXP (final_sequence, 0, 0);
- rtx delay = XVECEXP (final_sequence, 0, 1);
- if (INSN_ANNULLED_BRANCH_P (jump))
- fputs (INSN_FROM_TARGET_P (delay) ? ".jd" : ".nd", file);
- else
- fputs (".d", file);
- }
- return;
- case '?' : /* with leading "." */
- case '!' : /* without leading "." */
- /* This insn can be conditionally executed. See if the ccfsm machinery
- says it should be conditionalized. */
- if (arc_ccfsm_state == 3 || arc_ccfsm_state == 4)
- {
- /* Is this insn in a delay slot? */
- if (final_sequence && XVECLEN (final_sequence, 0) == 2)
- {
- rtx insn = XVECEXP (final_sequence, 0, 1);
-
- /* If the insn is annulled and is from the target path, we need
- to inverse the condition test. */
- if (INSN_ANNULLED_BRANCH_P (insn))
- {
- if (INSN_FROM_TARGET_P (insn))
- fprintf (file, "%s%s",
- code == '?' ? "." : "",
- arc_condition_codes[ARC_INVERSE_CONDITION_CODE (arc_ccfsm_current_cc)]);
- else
- fprintf (file, "%s%s",
- code == '?' ? "." : "",
- arc_condition_codes[arc_ccfsm_current_cc]);
- }
- else
- {
- /* This insn is executed for either path, so don't
- conditionalize it at all. */
- ; /* nothing to do */
- }
- }
- else
- {
- /* This insn isn't in a delay slot. */
- fprintf (file, "%s%s",
- code == '?' ? "." : "",
- arc_condition_codes[arc_ccfsm_current_cc]);
- }
- }
- return;
- case '~' :
- /* Output a nop if we're between a set of the condition codes,
- and a conditional branch. */
- if (last_insn_set_cc_p)
- fputs ("nop\n\t", file);
- return;
- case 'd' :
- fputs (arc_condition_codes[get_arc_condition_code (x)], file);
- return;
- case 'D' :
- fputs (arc_condition_codes[ARC_INVERSE_CONDITION_CODE
- (get_arc_condition_code (x))],
- file);
- return;
- case 'R' :
- /* Write second word of DImode or DFmode reference,
- register or memory. */
- if (GET_CODE (x) == REG)
- fputs (reg_names[REGNO (x)+1], file);
- else if (GET_CODE (x) == MEM)
- {
- fputc ('[', file);
- /* Handle possible auto-increment. Since it is pre-increment and
- we have already done it, we can just use an offset of four. */
- /* ??? This is taken from rs6000.c I think. I don't think it is
- currently necessary, but keep it around. */
- if (GET_CODE (XEXP (x, 0)) == PRE_INC
- || GET_CODE (XEXP (x, 0)) == PRE_DEC)
- output_address (plus_constant (XEXP (XEXP (x, 0), 0), 4));
- else
- output_address (plus_constant (XEXP (x, 0), 4));
- fputc (']', file);
- }
- else
- output_operand_lossage ("invalid operand to %%R code");
- return;
- case 'S' :
- if ((GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (x))
- || GET_CODE (x) == LABEL_REF)
- {
- fprintf (file, "%%st(");
- output_addr_const (file, x);
- fprintf (file, ")");
- return;
- }
- break;
- case 'H' :
- case 'L' :
- if (GET_CODE (x) == REG)
- {
- /* L = least significant word, H = most significant word */
- if ((TARGET_BIG_ENDIAN != 0) ^ (code == 'L'))
- fputs (reg_names[REGNO (x)], file);
- else
- fputs (reg_names[REGNO (x)+1], file);
- }
- else if (GET_CODE (x) == CONST_INT
- || GET_CODE (x) == CONST_DOUBLE)
- {
- rtx first, second;
-
- split_double (x, &first, &second);
- fprintf (file, "0x%08lx",
- (long)(code == 'L' ? INTVAL (first) : INTVAL (second)));
- }
- else
- output_operand_lossage ("invalid operand to %%H/%%L code");
- return;
- case 'A' :
- {
- char str[30];
-
- gcc_assert (GET_CODE (x) == CONST_DOUBLE
- && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT);
-
- real_to_decimal (str, CONST_DOUBLE_REAL_VALUE (x), sizeof (str), 0, 1);
- fprintf (file, "%s", str);
- return;
- }
- case 'U' :
- /* Output a load/store with update indicator if appropriate. */
- if (GET_CODE (x) == MEM)
- {
- if (GET_CODE (XEXP (x, 0)) == PRE_INC
- || GET_CODE (XEXP (x, 0)) == PRE_DEC)
- fputs (".a", file);
- }
- else
- output_operand_lossage ("invalid operand to %%U code");
- return;
- case 'V' :
- /* Output cache bypass indicator for a load/store insn. Volatile memory
- refs are defined to use the cache bypass mechanism. */
- if (GET_CODE (x) == MEM)
- {
- if (MEM_VOLATILE_P (x))
- fputs (".di", file);
- }
- else
- output_operand_lossage ("invalid operand to %%V code");
- return;
- case 0 :
- /* Do nothing special. */
- break;
- default :
- /* Unknown flag. */
- output_operand_lossage ("invalid operand output code");
- }
-
- switch (GET_CODE (x))
- {
- case REG :
- fputs (reg_names[REGNO (x)], file);
- break;
- case MEM :
- fputc ('[', file);
- if (GET_CODE (XEXP (x, 0)) == PRE_INC)
- output_address (plus_constant (XEXP (XEXP (x, 0), 0),
- GET_MODE_SIZE (GET_MODE (x))));
- else if (GET_CODE (XEXP (x, 0)) == PRE_DEC)
- output_address (plus_constant (XEXP (XEXP (x, 0), 0),
- - GET_MODE_SIZE (GET_MODE (x))));
- else
- output_address (XEXP (x, 0));
- fputc (']', file);
- break;
- case CONST_DOUBLE :
- /* We handle SFmode constants here as output_addr_const doesn't. */
- if (GET_MODE (x) == SFmode)
- {
- REAL_VALUE_TYPE d;
- long l;
-
- REAL_VALUE_FROM_CONST_DOUBLE (d, x);
- REAL_VALUE_TO_TARGET_SINGLE (d, l);
- fprintf (file, "0x%08lx", l);
- break;
- }
- /* Fall through. Let output_addr_const deal with it. */
- default :
- output_addr_const (file, x);
- break;
- }
-}
-
-/* Print a memory address as an operand to reference that memory location. */
-
-void
-arc_print_operand_address (FILE *file, rtx addr)
-{
- register rtx base, index = 0;
- int offset = 0;
-
- switch (GET_CODE (addr))
- {
- case REG :
- fputs (reg_names[REGNO (addr)], file);
- break;
- case SYMBOL_REF :
- if (/*???*/ 0 && SYMBOL_REF_FUNCTION_P (addr))
- {
- fprintf (file, "%%st(");
- output_addr_const (file, addr);
- fprintf (file, ")");
- }
- else
- output_addr_const (file, addr);
- 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
- base = XEXP (addr, 0), index = XEXP (addr, 1);
- gcc_assert (GET_CODE (base) == REG);
- fputs (reg_names[REGNO (base)], file);
- if (index == 0)
- {
- if (offset != 0)
- fprintf (file, ",%d", offset);
- }
- else
- {
- switch (GET_CODE (index))
- {
- case REG:
- fprintf (file, ",%s", reg_names[REGNO (index)]);
- break;
- case SYMBOL_REF:
- fputc (',', file), output_addr_const (file, index);
- break;
- default:
- gcc_unreachable ();
- }
- }
- break;
- case PRE_INC :
- case PRE_DEC :
- /* We shouldn't get here as we've lost the mode of the memory object
- (which says how much to inc/dec by. */
- gcc_unreachable ();
- break;
- default :
- output_addr_const (file, addr);
- break;
- }
-}
-
-/* Update compare/branch separation marker. */
-
-static void
-record_cc_ref (rtx insn)
-{
- last_insn_set_cc_p = current_insn_set_cc_p;
-
- switch (get_attr_cond (insn))
- {
- case COND_SET :
- case COND_SET_ZN :
- case COND_SET_ZNC :
- if (get_attr_length (insn) == 1)
- current_insn_set_cc_p = 1;
- else
- current_insn_set_cc_p = 0;
- break;
- default :
- current_insn_set_cc_p = 0;
- break;
- }
-}
-\f
-/* Conditional execution support.
-
- This is based on the ARM port but for now is much simpler.
-
- A finite state machine takes care of noticing whether or not instructions
- can be conditionally executed, and thus decrease execution time and code
- size by deleting branch instructions. The fsm is controlled by
- final_prescan_insn, and controls the actions of PRINT_OPERAND. The patterns
- in the .md file for the branch insns also have a hand in this. */
-
-/* The state of the fsm controlling condition codes are:
- 0: normal, do nothing special
- 1: don't output this insn
- 2: don't output this insn
- 3: make insns conditional
- 4: make insns conditional
-
- State transitions (state->state by whom, under what condition):
- 0 -> 1 final_prescan_insn, if insn is conditional branch
- 0 -> 2 final_prescan_insn, if the `target' is an unconditional branch
- 1 -> 3 branch patterns, after having not output the conditional branch
- 2 -> 4 branch patterns, after having not output the conditional branch
- 3 -> 0 (*targetm.asm_out.internal_label), if the `target' label is reached
- (the target label has CODE_LABEL_NUMBER equal to
- arc_ccfsm_target_label).
- 4 -> 0 final_prescan_insn, if `target' unconditional branch is reached
-
- If the jump clobbers the conditions then we use states 2 and 4.
-
- A similar thing can be done with conditional return insns.
-
- We also handle separating branches from sets of the condition code.
- This is done here because knowledge of the ccfsm state is required,
- we may not be outputting the branch. */
-
-void
-arc_final_prescan_insn (rtx insn,
- rtx *opvec ATTRIBUTE_UNUSED,
- int noperands ATTRIBUTE_UNUSED)
-{
- /* BODY will hold the body of INSN. */
- register rtx body = PATTERN (insn);
-
- /* This will be 1 if trying to repeat the trick (i.e.: do the `else' part of
- an if/then/else), and things need to be reversed. */
- int reverse = 0;
-
- /* If we start with a return insn, we only succeed if we find another one. */
- int seeking_return = 0;
-
- /* START_INSN will hold the insn from where we start looking. This is the
- first insn after the following code_label if REVERSE is true. */
- rtx start_insn = insn;
-
- /* Update compare/branch separation marker. */
- record_cc_ref (insn);
-
- /* Allow -mdebug-ccfsm to turn this off so we can see how well it does.
- We can't do this in macro FINAL_PRESCAN_INSN because its called from
- final_scan_insn which has `optimize' as a local. */
- if (optimize < 2 || TARGET_NO_COND_EXEC)
- return;
-
- /* If in state 4, check if the target branch is reached, in order to
- change back to state 0. */
- if (arc_ccfsm_state == 4)
- {
- if (insn == arc_ccfsm_target_insn)
- {
- arc_ccfsm_target_insn = NULL;
- arc_ccfsm_state = 0;
- }
- return;
- }
-
- /* If in state 3, it is possible to repeat the trick, if this insn is an
- unconditional branch to a label, and immediately following this branch
- is the previous target label which is only used once, and the label this
- branch jumps to is not too far off. Or in other words "we've done the
- `then' part, see if we can do the `else' part." */
- if (arc_ccfsm_state == 3)
- {
- if (simplejump_p (insn))
- {
- start_insn = next_nonnote_insn (start_insn);
- if (GET_CODE (start_insn) == BARRIER)
- {
- /* ??? Isn't this always a barrier? */
- start_insn = next_nonnote_insn (start_insn);
- }
- if (GET_CODE (start_insn) == CODE_LABEL
- && CODE_LABEL_NUMBER (start_insn) == arc_ccfsm_target_label
- && LABEL_NUSES (start_insn) == 1)
- reverse = TRUE;
- else
- return;
- }
- else if (GET_CODE (body) == RETURN)
- {
- start_insn = next_nonnote_insn (start_insn);
- if (GET_CODE (start_insn) == BARRIER)
- start_insn = next_nonnote_insn (start_insn);
- if (GET_CODE (start_insn) == CODE_LABEL
- && CODE_LABEL_NUMBER (start_insn) == arc_ccfsm_target_label
- && LABEL_NUSES (start_insn) == 1)
- {
- reverse = TRUE;
- seeking_return = 1;
- }
- else
- return;
- }
- else
- return;
- }
-
- if (GET_CODE (insn) != JUMP_INSN)
- return;
-
- /* This jump might be paralleled with a clobber of the condition codes,
- the jump should always come first. */
- if (GET_CODE (body) == PARALLEL && XVECLEN (body, 0) > 0)
- body = XVECEXP (body, 0, 0);
-
- if (reverse
- || (GET_CODE (body) == SET && GET_CODE (SET_DEST (body)) == PC
- && GET_CODE (SET_SRC (body)) == IF_THEN_ELSE))
- {
- int insns_skipped = 0, fail = FALSE, succeed = FALSE;
- /* Flag which part of the IF_THEN_ELSE is the LABEL_REF. */
- int then_not_else = TRUE;
- /* Nonzero if next insn must be the target label. */
- int next_must_be_target_label_p;
- rtx this_insn = start_insn, label = 0;
-
- /* Register the insn jumped to. */
- if (reverse)
- {
- if (!seeking_return)
- label = XEXP (SET_SRC (body), 0);
- }
- else if (GET_CODE (XEXP (SET_SRC (body), 1)) == LABEL_REF)
- label = XEXP (XEXP (SET_SRC (body), 1), 0);
- else if (GET_CODE (XEXP (SET_SRC (body), 2)) == LABEL_REF)
- {
- label = XEXP (XEXP (SET_SRC (body), 2), 0);
- then_not_else = FALSE;
- }
- else if (GET_CODE (XEXP (SET_SRC (body), 1)) == RETURN)
- seeking_return = 1;
- else if (GET_CODE (XEXP (SET_SRC (body), 2)) == RETURN)
- {
- seeking_return = 1;
- then_not_else = FALSE;
- }
- else
- gcc_unreachable ();
-
- /* See how many insns this branch skips, and what kind of insns. If all
- insns are okay, and the label or unconditional branch to the same
- label is not too far away, succeed. */
- for (insns_skipped = 0, next_must_be_target_label_p = FALSE;
- !fail && !succeed && insns_skipped < MAX_INSNS_SKIPPED;
- insns_skipped++)
- {
- rtx scanbody;
-
- this_insn = next_nonnote_insn (this_insn);
- if (!this_insn)
- break;
-
- if (next_must_be_target_label_p)
- {
- if (GET_CODE (this_insn) == BARRIER)
- continue;
- if (GET_CODE (this_insn) == CODE_LABEL
- && this_insn == label)
- {
- arc_ccfsm_state = 1;
- succeed = TRUE;
- }
- else
- fail = TRUE;
- break;
- }
-
- scanbody = PATTERN (this_insn);
-
- switch (GET_CODE (this_insn))
- {
- case CODE_LABEL:
- /* Succeed if it is the target label, otherwise fail since
- control falls in from somewhere else. */
- if (this_insn == label)
- {
- arc_ccfsm_state = 1;
- succeed = TRUE;
- }
- else
- fail = TRUE;
- break;
-
- case BARRIER:
- /* Succeed if the following insn is the target label.
- Otherwise fail.
- If return insns are used then the last insn in a function
- will be a barrier. */
- next_must_be_target_label_p = TRUE;
- break;
-
- case CALL_INSN:
- /* Can handle a call insn if there are no insns after it.
- IE: The next "insn" is the target label. We don't have to
- worry about delay slots as such insns are SEQUENCE's inside
- INSN's. ??? It is possible to handle such insns though. */
- if (get_attr_cond (this_insn) == COND_CANUSE)
- next_must_be_target_label_p = TRUE;
- else
- fail = TRUE;
- break;
-
- case JUMP_INSN:
- /* If this is an unconditional branch to the same label, succeed.
- If it is to another label, do nothing. If it is conditional,
- fail. */
- /* ??? Probably, the test for the SET and the PC are unnecessary. */
-
- if (GET_CODE (scanbody) == SET
- && GET_CODE (SET_DEST (scanbody)) == PC)
- {
- if (GET_CODE (SET_SRC (scanbody)) == LABEL_REF
- && XEXP (SET_SRC (scanbody), 0) == label && !reverse)
- {
- arc_ccfsm_state = 2;
- succeed = TRUE;
- }
- else if (GET_CODE (SET_SRC (scanbody)) == IF_THEN_ELSE)
- fail = TRUE;
- }
- else if (GET_CODE (scanbody) == RETURN
- && seeking_return)
- {
- arc_ccfsm_state = 2;
- succeed = TRUE;
- }
- else if (GET_CODE (scanbody) == PARALLEL)
- {
- if (get_attr_cond (this_insn) != COND_CANUSE)
- fail = TRUE;
- }
- break;
-
- case INSN:
- /* We can only do this with insns that can use the condition
- codes (and don't set them). */
- if (GET_CODE (scanbody) == SET
- || GET_CODE (scanbody) == PARALLEL)
- {
- if (get_attr_cond (this_insn) != COND_CANUSE)
- fail = TRUE;
- }
- /* We can't handle other insns like sequences. */
- else
- fail = TRUE;
- break;
-
- default:
- break;
- }
- }
-
- if (succeed)
- {
- if ((!seeking_return) && (arc_ccfsm_state == 1 || reverse))
- arc_ccfsm_target_label = CODE_LABEL_NUMBER (label);
- else
- {
- gcc_assert (seeking_return || arc_ccfsm_state == 2);
- while (this_insn && GET_CODE (PATTERN (this_insn)) == USE)
- {
- this_insn = next_nonnote_insn (this_insn);
- gcc_assert (!this_insn
- || (GET_CODE (this_insn) != BARRIER
- && GET_CODE (this_insn) != CODE_LABEL));
- }
- if (!this_insn)
- {
- /* Oh dear! we ran off the end, give up. */
- extract_insn_cached (insn);
- arc_ccfsm_state = 0;
- arc_ccfsm_target_insn = NULL;
- return;
- }
- arc_ccfsm_target_insn = this_insn;
- }
-
- /* If REVERSE is true, ARM_CURRENT_CC needs to be inverted from
- what it was. */
- if (!reverse)
- arc_ccfsm_current_cc = get_arc_condition_code (XEXP (SET_SRC (body),
- 0));
-
- if (reverse || then_not_else)
- arc_ccfsm_current_cc = ARC_INVERSE_CONDITION_CODE (arc_ccfsm_current_cc);
- }
-
- /* Restore recog_data. Getting the attributes of other insns can
- destroy this array, but final.c assumes that it remains intact
- across this call. */
- extract_insn_cached (insn);
- }
-}
-
-/* Record that we are currently outputting label NUM with prefix PREFIX.
- It it's the label we're looking for, reset the ccfsm machinery.
-
- Called from (*targetm.asm_out.internal_label). */
-
-void
-arc_ccfsm_at_label (const char *prefix, int num)
-{
- if (arc_ccfsm_state == 3 && arc_ccfsm_target_label == num
- && !strcmp (prefix, "L"))
- {
- arc_ccfsm_state = 0;
- arc_ccfsm_target_insn = NULL_RTX;
- }
-}
-
-/* See if the current insn, which is a conditional branch, is to be
- deleted. */
-
-int
-arc_ccfsm_branch_deleted_p (void)
-{
- if (arc_ccfsm_state == 1 || arc_ccfsm_state == 2)
- return 1;
- return 0;
-}
-
-/* Record a branch isn't output because subsequent insns can be
- conditionalized. */
-
-void
-arc_ccfsm_record_branch_deleted (void)
-{
- /* Indicate we're conditionalizing insns now. */
- arc_ccfsm_state += 2;
-
- /* If the next insn is a subroutine call, we still need a nop between the
- cc setter and user. We need to undo the effect of calling record_cc_ref
- for the just deleted branch. */
- current_insn_set_cc_p = last_insn_set_cc_p;
-}
-\f
-static void
-arc_va_start (tree valist, rtx nextarg)
-{
- /* See arc_setup_incoming_varargs for reasons for this oddity. */
- if (crtl->args.info < 8
- && (crtl->args.info & 1))
- nextarg = plus_constant (nextarg, UNITS_PER_WORD);
-
- std_expand_builtin_va_start (valist, nextarg);
-}
-
-/* This is how to output a definition of an internal numbered label where
- PREFIX is the class of label and NUM is the number within the class. */
-
-static void
-arc_internal_label (FILE *stream, const char *prefix, unsigned long labelno)
-{
- arc_ccfsm_at_label (prefix, labelno);
- default_internal_label (stream, prefix, labelno);
-}
-
-/* Worker function for TARGET_ASM_EXTERNAL_LIBCALL. */
-
-static void
-arc_external_libcall (rtx fun ATTRIBUTE_UNUSED)
-{
-#if 0
-/* On the ARC we want to have libgcc's for multiple cpus in one binary.
- We can't use `assemble_name' here as that will call ASM_OUTPUT_LABELREF
- and we'll get another suffix added on if -mmangle-cpu. */
- if (TARGET_MANGLE_CPU_LIBGCC)
- {
- fprintf (FILE, "\t.rename\t_%s, _%s%s\n",
- XSTR (SYMREF, 0), XSTR (SYMREF, 0),
- arc_mangle_suffix);
- }
-#endif
-}
-
-/* Worker function for TARGET_RETURN_IN_MEMORY. */
-
-static bool
-arc_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
-{
- if (AGGREGATE_TYPE_P (type))
- return true;
- else
- {
- HOST_WIDE_INT size = int_size_in_bytes (type);
- return (size == -1 || size > 8);
- }
-}
-
-/* For ARC, All aggregates and arguments greater than 8 bytes are
- passed by reference. */
-
-static bool
-arc_pass_by_reference (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
- enum machine_mode mode, const_tree type,
- bool named ATTRIBUTE_UNUSED)
-{
- unsigned HOST_WIDE_INT size;
-
- if (type)
- {
- if (AGGREGATE_TYPE_P (type))
- return true;
- size = int_size_in_bytes (type);
- }
- else
- size = GET_MODE_SIZE (mode);
-
- return size > 8;
-}
-
-/* Round SIZE up to a word boundary. */
-#define ROUND_ADVANCE(SIZE) \
-(((SIZE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
-
-/* Round arg MODE/TYPE up to the next word boundary. */
-#define ROUND_ADVANCE_ARG(MODE, TYPE) \
-((MODE) == BLKmode \
- ? ROUND_ADVANCE (int_size_in_bytes (TYPE)) \
- : ROUND_ADVANCE (GET_MODE_SIZE (MODE)))
-
-/* Round CUM up to the necessary point for argument MODE/TYPE. */
-#define ROUND_ADVANCE_CUM(CUM, MODE, TYPE) \
-((((MODE) == BLKmode ? TYPE_ALIGN (TYPE) : GET_MODE_BITSIZE (MODE)) \
- > BITS_PER_WORD) \
- ? (((CUM) + 1) & ~1) \
- : (CUM))
-
-/* Return boolean indicating arg of type TYPE and mode MODE will be passed in
- a reg. This includes arguments that have to be passed by reference as the
- pointer to them is passed in a reg if one is available (and that is what
- we're given). */
-#define PASS_IN_REG_P(CUM, MODE, TYPE) \
-((CUM) < MAX_ARC_PARM_REGS \
- && ((ROUND_ADVANCE_CUM ((CUM), (MODE), (TYPE)) \
- + ROUND_ADVANCE_ARG ((MODE), (TYPE)) \
- <= MAX_ARC_PARM_REGS)))
-
-/* Determine where to put an argument to a function.
- Value is zero to push the argument on the stack,
- or a hard register in which to store the argument.
-
- MODE is the argument's machine mode.
- TYPE is the data type of the argument (as a tree).
- This is null for libcalls where that information may
- not be available.
- CUM is a variable of type CUMULATIVE_ARGS which gives info about
- the preceding args and about the function being called.
- NAMED is nonzero if this argument is a named parameter
- (otherwise it is an extra parameter matching an ellipsis). */
-/* On the ARC the first MAX_ARC_PARM_REGS args are normally in registers
- and the rest are pushed. */
-
-static rtx
-arc_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
- const_tree type, bool named ATTRIBUTE_UNUSED)
-{
- return (PASS_IN_REG_P (*cum, mode, type)
- ? gen_rtx_REG (mode, ROUND_ADVANCE_CUM (*cum, mode, type))
- : NULL_RTX);
-}
-
-/* Worker function for TARGET_FUNCTION_ARG_ADVANCE. */
-
-static void
-arc_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
- const_tree type, bool named ATTRIBUTE_UNUSED)
-{
- *cum = (ROUND_ADVANCE_CUM (*cum, mode, type)
- + ROUND_ADVANCE_ARG (mode, type));
-}
-
-/* Worker function for TARGET_FUNCTION_ARG_BOUNDARY. */
-
-static unsigned int
-arc_function_arg_boundary (enum machine_mode mode, const_tree type)
-{
- return (type != NULL_TREE
- ? TYPE_ALIGN (type)
- : (GET_MODE_BITSIZE (mode) <= PARM_BOUNDARY
- ? PARM_BOUNDARY
- : 2 * PARM_BOUNDARY));
-}
-
-/* Trampolines. */
-/* ??? This doesn't work yet because GCC will use as the address of a nested
- function the address of the trampoline. We need to use that address
- right shifted by 2. It looks like we'll need PSImode after all. :-(
-
- ??? The above comment sounds like it's doable via
- TARGET_TRAMPOLINE_ADJUST_ADDRESS; no PSImode needed.
-
- On the ARC, the trampoline is quite simple as we have 32-bit immediate
- constants.
-
- mov r24,STATIC
- j.nd FUNCTION
-*/
-
-static void
-arc_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
-{
- rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
- rtx mem;
-
- mem = adjust_address (m_tramp, SImode, 0);
- emit_move_insn (mem, GEN_INT (0x631f7c00));
-
- mem = adjust_address (m_tramp, SImode, 4);
- emit_move_insn (mem, chain_value);
-
- mem = adjust_address (m_tramp, SImode, 8);
- emit_move_insn (mem, GEN_INT (0x381f0000));
-
- mem = adjust_address (m_tramp, SImode, 12);
- emit_move_insn (mem, fnaddr);
-
- emit_insn (gen_flush_icache (m_tramp));
-}
-
-/* Worker function for TARGET_CONDITIONAL_REGISTER_USAGE. */
-
-static void
-arc_conditional_register_usage (void)
-{
- if (PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM)
- {
- fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
- call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
- }
-}
-
+++ /dev/null
-/* Definitions of target machine for GNU compiler, Argonaut ARC cpu.
- Copyright (C) 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2004, 2005,
- 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-/* ??? This is an old port, and is undoubtedly suffering from bit rot. */
-
-/* Things to do:
-
- - incscc, decscc?
- - print active compiler options in assembler output
-*/
-
-
-#undef ASM_SPEC
-#undef LINK_SPEC
-#undef LIB_SPEC
-#undef STARTFILE_SPEC
-#undef ENDFILE_SPEC
-#undef SIZE_TYPE
-#undef PTRDIFF_TYPE
-#undef WCHAR_TYPE
-#undef WCHAR_TYPE_SIZE
-#undef ASM_OUTPUT_LABELREF
-\f
-/* Print subsidiary information on the compiler version in use. */
-#define TARGET_VERSION fprintf (stderr, " (arc)")
-
-/* Names to predefine in the preprocessor for this target machine. */
-#define TARGET_CPU_CPP_BUILTINS() \
- do \
- { \
- builtin_define ("__arc__"); \
- if (TARGET_BIG_ENDIAN) \
- builtin_define ("__big_endian__"); \
- if (arc_cpu_type == 0) \
- builtin_define ("__base__"); \
- builtin_assert ("cpu=arc"); \
- builtin_assert ("machine=arc"); \
- } while (0)
-
-/* Pass -mmangle-cpu if we get -mcpu=*.
- Doing it this way lets one have it on as default with -mcpu=*,
- but also lets one turn it off with -mno-mangle-cpu. */
-#define CC1_SPEC "\
-%{mcpu=*:-mmangle-cpu} \
-%{EB:%{EL:%emay not use both -EB and -EL}} \
-%{EB:-mbig-endian} %{EL:-mlittle-endian} \
-"
-
-#define ASM_SPEC "%{EB} %{EL}"
-
-#define LINK_SPEC "%{v} %{EB} %{EL}"
-
-#define LIB_SPEC "-lc"
-
-#define STARTFILE_SPEC "%{!shared:crt0.o%s} crtinit.o%s"
-
-#define ENDFILE_SPEC "crtfini.o%s"
-\f
-/* Instruction set characteristics.
- These are internal macros, set by the appropriate -mcpu= option. */
-
-/* Nonzero means the cpu has a barrel shifter. */
-#define TARGET_SHIFTER 0
-
-/* Which cpu we're compiling for. */
-extern int arc_cpu_type;
-
-/* Check if CPU is an extension and set `arc_cpu_type' and `arc_mangle_cpu'
- appropriately. The result should be nonzero if the cpu is recognized,
- otherwise zero. This is intended to be redefined in a cover file.
- This is used by arc_handle_option. */
-#define ARC_EXTENSION_CPU(cpu) 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 1
-
-/* Define this if most significant byte of a word is the lowest numbered. */
-#define BYTES_BIG_ENDIAN (TARGET_BIG_ENDIAN)
-
-/* Define this if most significant word of a multiword number is the lowest
- numbered. */
-#define WORDS_BIG_ENDIAN (TARGET_BIG_ENDIAN)
-
-/* Width of a word, in units (bytes). */
-#define UNITS_PER_WORD 4
-
-/* Define this macro if it is advisable to hold scalars in registers
- in a wider mode than that declared by the program. In such cases,
- the value is constrained to be within the bounds of the declared
- type, but kept valid in the wider mode. The signedness of the
- extension may differ from that of the type. */
-#define PROMOTE_MODE(MODE,UNSIGNEDP,TYPE) \
-if (GET_MODE_CLASS (MODE) == MODE_INT \
- && GET_MODE_SIZE (MODE) < UNITS_PER_WORD) \
-{ \
- (MODE) = SImode; \
-}
-
-/* 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 64
-
-/* ALIGN FRAMES on word boundaries */
-#define ARC_STACK_ALIGN(LOC) (((LOC)+7) & ~7)
-
-/* Allocation boundary (in *bits*) for the code of a function. */
-#define FUNCTION_BOUNDARY 32
-
-/* Alignment of field after `int : 0' in a structure. */
-#define EMPTY_FIELD_BOUNDARY 32
-
-/* Every structure's size must be a multiple of this. */
-#define STRUCTURE_SIZE_BOUNDARY 8
-
-/* A bit-field declared as `int' forces `int' alignment for the struct. */
-#define PCC_BITFIELD_TYPE_MATTERS 1
-
-/* No data type wants to be aligned rounder than this. */
-/* This is bigger than currently necessary for the ARC. If 8 byte floats are
- ever added it's not clear whether they'll need such alignment or not. For
- now we assume they will. We can always relax it if necessary but the
- reverse isn't true. */
-#define BIGGEST_ALIGNMENT 64
-
-/* The best alignment to use in cases where we have a choice. */
-#define FASTEST_ALIGNMENT 32
-
-/* Make strings word-aligned so strcpy from constants will be faster. */
-#define CONSTANT_ALIGNMENT(EXP, ALIGN) \
- ((TREE_CODE (EXP) == STRING_CST \
- && (ALIGN) < FASTEST_ALIGNMENT) \
- ? FASTEST_ALIGNMENT : (ALIGN))
-
-/* Make arrays of chars word-aligned for the same reasons. */
-#define DATA_ALIGNMENT(TYPE, ALIGN) \
- (TREE_CODE (TYPE) == ARRAY_TYPE \
- && TYPE_MODE (TREE_TYPE (TYPE)) == QImode \
- && (ALIGN) < FASTEST_ALIGNMENT ? FASTEST_ALIGNMENT : (ALIGN))
-
-/* Set this nonzero if move instructions will actually fail to work
- when given unaligned data. */
-/* On the ARC the lower address bits are masked to 0 as necessary. The chip
- won't croak when given an unaligned address, but the insn will still fail
- to produce the correct result. */
-#define STRICT_ALIGNMENT 1
-\f
-/* Layout of source language data types. */
-
-#define SHORT_TYPE_SIZE 16
-#define INT_TYPE_SIZE 32
-#define LONG_TYPE_SIZE 32
-#define LONG_LONG_TYPE_SIZE 64
-#define FLOAT_TYPE_SIZE 32
-#define DOUBLE_TYPE_SIZE 64
-#define LONG_DOUBLE_TYPE_SIZE 64
-
-/* Define this as 1 if `char' should by default be signed; else as 0. */
-#define DEFAULT_SIGNED_CHAR 1
-
-#define SIZE_TYPE "long unsigned int"
-#define PTRDIFF_TYPE "long int"
-#define WCHAR_TYPE "short unsigned int"
-#define WCHAR_TYPE_SIZE 16
-\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 61, 62, and 63 are not really registers and we needn't treat
- them as such. We still need a register for the condition code. */
-#define FIRST_PSEUDO_REGISTER 62
-
-/* 1 for registers that have pervasive standard uses
- and are not available for the register allocator.
-
- 0-28 - general purpose registers
- 29 - ilink1 (interrupt link register)
- 30 - ilink2 (interrupt link register)
- 31 - blink (branch link register)
- 32-59 - reserved for extensions
- 60 - LP_COUNT
- 61 - condition code
-
- For doc purposes:
- 61 - short immediate data indicator (setting flags)
- 62 - long immediate data indicator
- 63 - short immediate data indicator (not setting flags).
-
- The general purpose registers are further broken down into:
- 0-7 - arguments/results
- 8-15 - call used
- 16-23 - call saved
- 24 - call used, static chain pointer
- 25 - call used, gptmp
- 26 - global pointer
- 27 - frame pointer
- 28 - stack pointer
-
- By default, the extension registers are not available. */
-
-#define FIXED_REGISTERS \
-{ 0, 0, 0, 0, 0, 0, 0, 0, \
- 0, 0, 0, 0, 0, 0, 0, 0, \
- 0, 0, 0, 0, 0, 0, 0, 0, \
- 0, 0, 0, 1, 1, 1, 1, 0, \
- \
- 1, 1, 1, 1, 1, 1, 1, 1, \
- 1, 1, 1, 1, 1, 1, 1, 1, \
- 1, 1, 1, 1, 1, 1, 1, 1, \
- 1, 1, 1, 1, 1, 1 }
-
-/* 1 for registers not available across function calls.
- These must include the FIXED_REGISTERS and also any
- registers that can be used without being saved.
- The latter must include the registers where values are returned
- and the register where structure-value addresses are passed.
- Aside from that, you can include as many other registers as you like. */
-
-#define CALL_USED_REGISTERS \
-{ 1, 1, 1, 1, 1, 1, 1, 1, \
- 1, 1, 1, 1, 1, 1, 1, 1, \
- 0, 0, 0, 0, 0, 0, 0, 0, \
- 1, 1, 1, 1, 1, 1, 1, 1, \
- \
- 1, 1, 1, 1, 1, 1, 1, 1, \
- 1, 1, 1, 1, 1, 1, 1, 1, \
- 1, 1, 1, 1, 1, 1, 1, 1, \
- 1, 1, 1, 1, 1, 1 }
-
-/* 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). */
-#define REG_ALLOC_ORDER \
-{ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, \
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 31, \
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, \
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, \
- 27, 28, 29, 30 }
-
-/* 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) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
-
-/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. */
-extern const unsigned int arc_hard_regno_mode_ok[];
-extern unsigned int arc_mode_class[];
-#define HARD_REGNO_MODE_OK(REGNO, MODE) \
-((arc_hard_regno_mode_ok[REGNO] & arc_mode_class[MODE]) != 0)
-
-/* 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. */
-
-/* Tie QI/HI/SI modes together. */
-#define MODES_TIEABLE_P(MODE1, MODE2) \
-(GET_MODE_CLASS (MODE1) == MODE_INT \
- && GET_MODE_CLASS (MODE2) == MODE_INT \
- && GET_MODE_SIZE (MODE1) <= UNITS_PER_WORD \
- && GET_MODE_SIZE (MODE2) <= UNITS_PER_WORD)
-\f
-/* Register classes and constants. */
-
-/* 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.
-
- It is important that any condition codes have class NO_REGS.
- See `register_operand'. */
-
-enum reg_class {
- NO_REGS, LPCOUNT_REG, GENERAL_REGS, ALL_REGS, LIM_REG_CLASSES
-};
-
-#define N_REG_CLASSES (int) LIM_REG_CLASSES
-
-/* Give names of register classes as strings for dump file. */
-#define REG_CLASS_NAMES \
-{ "NO_REGS", "LPCOUNT_REG", "GENERAL_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}, {0, 0x10000000}, {0xffffffff, 0xfffffff}, \
- {0xffffffff, 0x1fffffff} }
-
-/* 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. */
-extern enum reg_class arc_regno_reg_class[FIRST_PSEUDO_REGISTER];
-#define REGNO_REG_CLASS(REGNO) \
-(arc_regno_reg_class[REGNO])
-
-/* The class value for index registers, and the one for base regs. */
-#define INDEX_REG_CLASS GENERAL_REGS
-#define BASE_REG_CLASS GENERAL_REGS
-
-/* Get reg_class from a letter such as appears in the machine description. */
-#define REG_CLASS_FROM_LETTER(C) \
-((C) == 'l' ? LPCOUNT_REG /* ??? needed? */ \
- : NO_REGS)
-
-/* 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_BASE_P(REGNO) \
-((REGNO) < 32 || (unsigned) reg_renumber[REGNO] < 32)
-#define REGNO_OK_FOR_INDEX_P(REGNO) \
-((REGNO) < 32 || (unsigned) reg_renumber[REGNO] < 32)
-
-/* Return the maximum number of consecutive registers
- needed to represent mode MODE in a register of class CLASS. */
-#define CLASS_MAX_NREGS(CLASS, MODE) \
-((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
-
-/* The letters I, J, K, L, M, N, O, 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. */
-/* 'I' is used for short immediates (always signed).
- 'J' is used for long immediates.
- 'K' is used for any constant up to 64 bits (for 64x32 situations?). */
-
-/* local to this file */
-#define SMALL_INT(X) ((unsigned) ((X) + 0x100) < 0x200)
-/* local to this file */
-#define LARGE_INT(X) \
-((X) >= (-(HOST_WIDE_INT) 0x7fffffff - 1) \
- && (unsigned HOST_WIDE_INT)(X) <= (unsigned HOST_WIDE_INT) 0xffffffff)
-
-#define CONST_OK_FOR_LETTER_P(VALUE, C) \
-((C) == 'I' ? SMALL_INT (VALUE) \
- : (C) == 'J' ? LARGE_INT (VALUE) \
- : (C) == 'K' ? 1 \
- : 0)
-
-/* Similar, but for floating constants, and defining letters G and H.
- Here VALUE is the CONST_DOUBLE rtx itself. */
-/* 'G' is used for integer values for the multiplication insns where the
- operands are extended from 4 bytes to 8 bytes.
- 'H' is used when any 64-bit constant is allowed. */
-#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \
-((C) == 'G' ? arc_double_limm_p (VALUE) \
- : (C) == 'H' ? 1 \
- : 0)
-
-/* A C expression that defines the optional machine-dependent constraint
- letters that can be used to segregate specific types of operands,
- usually memory references, for the 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. */
-/* ??? This currently isn't used. Waiting for PIC. */
-#if 0
-#define EXTRA_CONSTRAINT(VALUE, C) \
-((C) == 'R' ? (SYMBOL_REF_FUNCTION_P (VALUE) || GET_CODE (VALUE) == LABEL_REF) \
- : 0)
-#endif
-\f
-/* Stack layout and stack pointer usage. */
-
-/* Define this macro if pushing a word onto the stack moves the stack
- pointer to a smaller address. */
-#define STACK_GROWS_DOWNWARD
-
-/* Define this to nonzero if the nominal address of the stack frame
- is at the high-address end of the local variables;
- that is, each additional local variable allocated
- goes at a more negative offset in the frame. */
-#define FRAME_GROWS_DOWNWARD 1
-
-/* Offset within stack frame to start allocating local variables at.
- If FRAME_GROWS_DOWNWARD, this is the offset to the END of the
- first local allocated. Otherwise, it is the offset to the BEGINNING
- of the first local allocated. */
-#define STARTING_FRAME_OFFSET 0
-
-/* Offset from the stack pointer register to the first location at which
- outgoing arguments are placed. */
-#define STACK_POINTER_OFFSET FIRST_PARM_OFFSET (0)
-
-/* Offset of first parameter from the argument pointer register value. */
-/* 4 bytes for each of previous fp, return address, and previous gp.
- 4 byte reserved area for future considerations. */
-#define FIRST_PARM_OFFSET(FNDECL) 16
-
-/* A C expression whose value is RTL representing the address in a
- stack frame where the pointer to the caller's frame is stored.
- Assume that FRAMEADDR is an RTL expression for the address of the
- stack frame itself.
-
- If you don't define this macro, the default is to return the value
- of FRAMEADDR--that is, the stack frame address is also the address
- of the stack word that points to the previous frame. */
-/* ??? unfinished */
-/*define DYNAMIC_CHAIN_ADDRESS (FRAMEADDR)*/
-
-/* A C expression whose value is RTL representing the value of the
- return address for the frame COUNT steps up from the current frame.
- FRAMEADDR is 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 current return address is in r31. The return address of anything
- farther back is at [%fp,4]. */
-#if 0 /* The default value should work. */
-#define RETURN_ADDR_RTX(COUNT, FRAME) \
-(((COUNT) == -1) \
- ? gen_rtx_REG (Pmode, 31) \
- : copy_to_reg (gen_rtx_MEM (Pmode, \
- memory_address (Pmode, \
- plus_constant ((FRAME), \
- UNITS_PER_WORD)))))
-#endif
-
-/* Register to use for pushing function arguments. */
-#define STACK_POINTER_REGNUM 28
-
-/* Base register for access to local variables of the function. */
-#define FRAME_POINTER_REGNUM 27
-
-/* 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. This must
- not be a register used by the prologue. */
-#define STATIC_CHAIN_REGNUM 24
-
-/* C statement to store the difference between the frame pointer
- and the stack pointer values immediately after the function prologue. */
-#define INITIAL_FRAME_POINTER_OFFSET(VAR) \
-((VAR) = arc_compute_frame_size (get_frame_size ()))
-\f
-/* Function argument passing. */
-
-/* If defined, the maximum amount of space required for outgoing
- arguments will be computed and placed into the variable
- `crtl->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. */
-#define ACCUMULATE_OUTGOING_ARGS 1
-
-/* 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, N_NAMED_ARGS) \
-((CUM) = 0)
-
-/* The number of registers used for parameter passing. Local to this file. */
-#define MAX_ARC_PARM_REGS 8
-
-/* 1 if N is a possible register number for function argument passing. */
-#define FUNCTION_ARG_REGNO_P(N) \
-((unsigned) (N) < MAX_ARC_PARM_REGS)
-
-\f
-/* Function results. */
-
-/* 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(VALTYPE, FUNC) gen_rtx_REG (TYPE_MODE (VALTYPE), 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. */
-/* ??? What about r1 in DI/DF values. */
-#define FUNCTION_VALUE_REGNO_P(N) ((N) == 0)
-
-/* Tell GCC to use TARGET_RETURN_IN_MEMORY. */
-#define DEFAULT_PCC_STRUCT_RETURN 0
-\f
-/* 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
-
-/* Epilogue delay slots. */
-#define DELAY_SLOTS_FOR_EPILOGUE arc_delay_slots_for_epilogue ()
-
-#define ELIGIBLE_FOR_EPILOGUE_DELAY(TRIAL, SLOTS_FILLED) \
-arc_eligible_for_epilogue_delay (TRIAL, SLOTS_FILLED)
-
-/* Output assembler code to FILE to increment profiler label # LABELNO
- for profiling a function entry. */
-#define FUNCTION_PROFILER(FILE, LABELNO)
-\f
-#define TRAMPOLINE_ALIGNMENT 32
-#define TRAMPOLINE_SIZE 16
-\f
-/* Addressing modes, and classification of registers for them. */
-
-/* Maximum number of registers that can appear in a valid memory address. */
-/* The `ld' insn allows 2, but the `st' insn only allows 1. */
-#define MAX_REGS_PER_ADDRESS 1
-
-/* We have pre inc/dec (load/store with update). */
-#define HAVE_PRE_INCREMENT 1
-#define HAVE_PRE_DECREMENT 1
-
-/* 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)
-
-/* Nonzero if the constant value X is a legitimate general operand.
- We can handle any 32- or 64-bit constant. */
-/* "1" should work since the largest constant should be a 64 bit critter. */
-/* ??? Not sure what to do for 64x32 compiler. */
-#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 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) \
-((unsigned) REGNO (X) - 32 >= FIRST_PSEUDO_REGISTER - 32)
-/* 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) \
-((unsigned) REGNO (X) - 32 >= FIRST_PSEUDO_REGISTER - 32)
-
-#else
-
-/* Nonzero if X is a hard reg that can be used as an index. */
-#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X))
-/* Nonzero if X is a hard reg that can be used as a base reg. */
-#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
-
-#endif
-
-/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
- that is a valid memory address for an instruction.
- The MODE argument is the machine mode for the MEM expression
- that wants to use this address. */
-/* The `ld' insn allows [reg],[reg+shimm],[reg+limm],[reg+reg],[limm]
- but the `st' insn only allows [reg],[reg+shimm],[limm].
- The only thing we can do is only allow the most strict case `st' and hope
- other parts optimize out the restrictions for `ld'. */
-
-/* local to this file */
-#define RTX_OK_FOR_BASE_P(X) \
-(REG_P (X) && REG_OK_FOR_BASE_P (X))
-
-/* local to this file */
-#define RTX_OK_FOR_INDEX_P(X) \
-(0 && /*???*/ REG_P (X) && REG_OK_FOR_INDEX_P (X))
-
-/* local to this file */
-/* ??? Loads can handle any constant, stores can only handle small ones. */
-#define RTX_OK_FOR_OFFSET_P(X) \
-(GET_CODE (X) == CONST_INT && SMALL_INT (INTVAL (X)))
-
-#define LEGITIMATE_OFFSET_ADDRESS_P(MODE, X) \
-(GET_CODE (X) == PLUS \
- && RTX_OK_FOR_BASE_P (XEXP (X, 0)) \
- && (RTX_OK_FOR_INDEX_P (XEXP (X, 1)) \
- || RTX_OK_FOR_OFFSET_P (XEXP (X, 1))))
-
-#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
-{ if (RTX_OK_FOR_BASE_P (X)) \
- goto ADDR; \
- if (LEGITIMATE_OFFSET_ADDRESS_P ((MODE), (X))) \
- goto ADDR; \
- if (GET_CODE (X) == CONST_INT && LARGE_INT (INTVAL (X))) \
- goto ADDR; \
- if (GET_CODE (X) == SYMBOL_REF \
- || GET_CODE (X) == LABEL_REF \
- || GET_CODE (X) == CONST) \
- goto ADDR; \
- if ((GET_CODE (X) == PRE_DEC || GET_CODE (X) == PRE_INC) \
- /* We're restricted here by the `st' insn. */ \
- && RTX_OK_FOR_BASE_P (XEXP ((X), 0))) \
- goto ADDR; \
-}
-\f
-/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
- return the mode to be used for the comparison. */
-#define SELECT_CC_MODE(OP, X, Y) \
-arc_select_cc_mode (OP, X, Y)
-
-/* Return nonzero if SELECT_CC_MODE will never return MODE for a
- floating point inequality comparison. */
-#define REVERSIBLE_CC_MODE(MODE) 1 /*???*/
-\f
-/* Costs. */
-
-/* Compute extra cost of moving data between one register class
- and another. */
-#define REGISTER_MOVE_COST(MODE, CLASS1, CLASS2) 2
-
-/* Compute the cost of moving data between registers and memory. */
-/* Memory is 3 times as expensive as registers.
- ??? Is that the right way to look at it? */
-#define MEMORY_MOVE_COST(MODE,CLASS,IN) \
-(GET_MODE_SIZE (MODE) <= UNITS_PER_WORD ? 6 : 12)
-
-/* The cost of a branch insn. */
-/* ??? What's the right value here? Branches are certainly more
- expensive than reg->reg moves. */
-#define BRANCH_COST(speed_p, predictable_p) 2
-
-/* Nonzero if access to memory by bytes is slow and undesirable.
- For RISC chips, it means that access to memory by bytes is no
- better than access by words when possible, so grab a whole word
- and maybe make use of that. */
-#define SLOW_BYTE_ACCESS 1
-
-/* Define this macro if it is as good or better to call a constant
- function address than to call an address kept in a register. */
-/* On the ARC, calling through registers is slow. */
-#define NO_FUNCTION_CSE
-\f
-/* Section selection. */
-/* WARNING: These section names also appear in dwarfout.c. */
-
-/* The names of the text, data, and readonly-data sections are runtime
- selectable. */
-
-#define ARC_SECTION_FORMAT "\t.section %s"
-#define ARC_DEFAULT_TEXT_SECTION ".text"
-#define ARC_DEFAULT_DATA_SECTION ".data"
-#define ARC_DEFAULT_RODATA_SECTION ".rodata"
-
-extern const char *arc_text_section, *arc_data_section, *arc_rodata_section;
-
-/* initfini.c uses this in an asm. */
-#if defined (CRT_INIT) || defined (CRT_FINI)
-#define TEXT_SECTION_ASM_OP "\t.section .text"
-#else
-#define TEXT_SECTION_ASM_OP arc_text_section
-#endif
-#define DATA_SECTION_ASM_OP arc_data_section
-
-#undef READONLY_DATA_SECTION_ASM_OP
-#define READONLY_DATA_SECTION_ASM_OP arc_rodata_section
-
-#define BSS_SECTION_ASM_OP "\t.section .bss"
-
-/* Define this macro if jump tables (for tablejump insns) should be
- output in the text section, along with the assembler instructions.
- Otherwise, the readonly data section is used.
- This macro is irrelevant if there is no separate readonly data section. */
-/*#define JUMP_TABLES_IN_TEXT_SECTION*/
-
-/* For DWARF. Marginally different than default so output is "prettier"
- (and consistent with above). */
-#define PUSHSECTION_ASM_OP "\t.section "
-
-/* Tell crtstuff.c we're using ELF. */
-#define OBJECT_FORMAT_ELF
-\f
-/* PIC */
-
-/* The register number of the register used to address a table of static
- data addresses in memory. In some cases this register is defined by a
- processor's ``application binary interface'' (ABI). When this macro
- is defined, RTL is generated for this register once, as with the stack
- pointer and frame pointer registers. If this macro is not defined, it
- is up to the machine-dependent files to allocate such a register (if
- necessary). */
-#define PIC_OFFSET_TABLE_REGNUM (flag_pic ? 26 : INVALID_REGNUM)
-
-/* Define this macro if the register defined by PIC_OFFSET_TABLE_REGNUM is
- clobbered by calls. Do not define this macro if PIC_OFFSET_TABLE_REGNUM
- is not defined. */
-/* This register is call-saved on the ARC. */
-/*#define PIC_OFFSET_TABLE_REG_CALL_CLOBBERED*/
-
-/* A C expression that is nonzero if X is a legitimate immediate
- operand on the target machine when generating position independent code.
- You can assume that X satisfies CONSTANT_P, so you need not
- check this. You can also assume `flag_pic' is true, so you need not
- check it either. You need not define this macro if all constants
- (including SYMBOL_REF) can be immediate operands when generating
- position independent code. */
-/*#define LEGITIMATE_PIC_OPERAND_P(X)*/
-\f
-/* Control the assembler format that we output. */
-
-/* A C string constant describing how to begin a comment in the target
- assembler language. The compiler assumes that the comment will
- end at the end of the line. */
-#define ASM_COMMENT_START ";"
-
-/* Output to assembler file text saying following lines
- may contain character constants, extra white space, comments, etc. */
-#define ASM_APP_ON ""
-
-/* Output to assembler file text saying following lines
- no longer contain unusual constructs. */
-#define ASM_APP_OFF ""
-
-/* Globalizing directive for a label. */
-#define GLOBAL_ASM_OP "\t.global\t"
-
-/* This is how to output a reference to a user-level label named NAME.
- `assemble_name' uses this. */
-/* We mangle all user labels to provide protection from linking code
- compiled for different cpus. */
-/* We work around a dwarfout.c deficiency by watching for labels from it and
- not adding the '_' prefix nor the cpu suffix. There is a comment in
- dwarfout.c that says it should be using (*targetm.asm_out.internal_label). */
-extern const char *arc_mangle_cpu;
-#define ASM_OUTPUT_LABELREF(FILE, NAME) \
-do { \
- if ((NAME)[0] == '.' && (NAME)[1] == 'L') \
- fprintf (FILE, "%s", NAME); \
- else \
- { \
- fputc ('_', FILE); \
- if (TARGET_MANGLE_CPU && arc_mangle_cpu != NULL) \
- fprintf (FILE, "%s_", arc_mangle_cpu); \
- fprintf (FILE, "%s", NAME); \
- } \
-} while (0)
-
-/* Assembler pseudo-op to equate one value with another. */
-/* ??? This is needed because dwarfout.c provides a default definition too
- late for defaults.h (which contains the default definition of ASM_OUTPUT_DEF
- that we use). */
-#define SET_ASM_OP "\t.set\t"
-
-/* 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", \
- "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", \
- "r24", "r25", "r26", "fp", "sp", "ilink1", "ilink2", "blink", \
- "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", "lp_count", "cc"}
-
-/* Entry to the insn conditionalizer. */
-#define FINAL_PRESCAN_INSN(INSN, OPVEC, NOPERANDS) \
-arc_final_prescan_insn (INSN, OPVEC, NOPERANDS)
-
-/* A C expression which evaluates to true if CODE is a valid
- punctuation character for use in the `PRINT_OPERAND' macro. */
-extern char arc_punct_chars[256];
-#define PRINT_OPERAND_PUNCT_VALID_P(CHAR) \
-arc_punct_chars[(unsigned char) (CHAR)]
-
-/* 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) \
-arc_print_operand (FILE, X, 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 ADDR. ADDR is an RTL expression. */
-#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
-arc_print_operand_address (FILE, ADDR)
-
-/* This is how to output an element of a case-vector that is absolute. */
-#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
-do { \
- char label[30]; \
- ASM_GENERATE_INTERNAL_LABEL (label, "L", VALUE); \
- fprintf (FILE, "\t.word %%st("); \
- assemble_name (FILE, label); \
- fprintf (FILE, ")\n"); \
-} while (0)
-
-/* This is how to output an element of a case-vector that is relative. */
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
-do { \
- char label[30]; \
- ASM_GENERATE_INTERNAL_LABEL (label, "L", VALUE); \
- fprintf (FILE, "\t.word %%st("); \
- assemble_name (FILE, label); \
- fprintf (FILE, "-"); \
- ASM_GENERATE_INTERNAL_LABEL (label, "L", REL); \
- assemble_name (FILE, label); \
- fprintf (FILE, ")\n"); \
-} while (0)
-
-/* The desired alignment for the location counter at the beginning
- of a loop. */
-/* On the ARC, align loops to 32 byte boundaries (cache line size)
- if -malign-loops. */
-#define LOOP_ALIGN(LABEL) (TARGET_ALIGN_LOOPS ? 5 : 0)
-
-/* 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) \
-do { if ((LOG) != 0) fprintf (FILE, "\t.align %d\n", 1 << (LOG)); } while (0)
-\f
-/* Debugging information. */
-
-/* Generate DBX and DWARF debugging information. */
-#define DBX_DEBUGGING_INFO 1
-
-/* Prefer STABS (for now). */
-#undef PREFERRED_DEBUGGING_TYPE
-#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
-
-/* Turn off splitting of long stabs. */
-#define DBX_CONTIN_LENGTH 0
-\f
-/* Miscellaneous. */
-
-/* Specify the machine mode that this machine uses
- for the index in the tablejump instruction. */
-#define CASE_VECTOR_MODE Pmode
-
-/* 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, UNKNOWN if none. */
-#define LOAD_EXTEND_OP(MODE) ZERO_EXTEND
-
-/* Max number of bytes we can move from memory to memory
- in one reasonably fast instruction. */
-#define MOVE_MAX 4
-
-/* Define this to be nonzero if shift instructions ignore all but the low-order
- few bits. */
-#define SHIFT_COUNT_TRUNCATED 1
-
-/* 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. */
-/* ??? The arc doesn't have full 32-bit pointers, but making this PSImode has
- its own problems (you have to add extendpsisi2 and trucnsipsi2 but how does
- one do it without getting excess code?). Try to avoid it. */
-#define Pmode SImode
-
-/* A function address in a call instruction. */
-#define FUNCTION_MODE SImode
-
-/* alloca should avoid clobbering the old register save area. */
-/* ??? Not defined in tm.texi. */
-#define SETJMP_VIA_SAVE_AREA
-\f
-/* ARC function types. */
-enum arc_function_type {
- ARC_FUNCTION_UNKNOWN, ARC_FUNCTION_NORMAL,
- /* These are interrupt handlers. The name corresponds to the register
- name that contains the return address. */
- ARC_FUNCTION_ILINK1, ARC_FUNCTION_ILINK2
-};
-#define ARC_INTERRUPT_P(TYPE) \
-((TYPE) == ARC_FUNCTION_ILINK1 || (TYPE) == ARC_FUNCTION_ILINK2)
-/* Compute the type of a function from its DECL. */
+++ /dev/null
-;; Machine description of the Argonaut ARC cpu for GNU C compiler
-;; Copyright (C) 1994, 1997, 1998, 1999, 2000, 2004, 2005, 2007, 2008
-;; Free Software Foundation, Inc.
-
-;; This file is part of GCC.
-
-;; GCC is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 3, or (at your option)
-;; any later version.
-
-;; GCC is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GCC; see the file COPYING3. If not see
-;; <http://www.gnu.org/licenses/>.
-
-;; See file "rtl.def" for documentation on define_insn, match_*, et. al.
-
-;; ??? This is an old port, and is undoubtedly suffering from bit rot.
-\f
-;; Insn type. Used to default other attribute values.
-
-(define_attr "type"
- "move,load,store,cmove,unary,binary,compare,shift,mul,uncond_branch,branch,call,call_no_delay_slot,multi,misc"
- (const_string "binary"))
-
-;; Length (in # of insns, long immediate constants counted too).
-;; ??? There's a nasty interaction between the conditional execution fsm
-;; and insn lengths: insns with shimm values cannot be conditionally executed.
-(define_attr "length" ""
- (cond [(eq_attr "type" "load")
- (if_then_else (match_operand 1 "long_immediate_loadstore_operand" "")
- (const_int 2) (const_int 1))
-
- (eq_attr "type" "store")
- (if_then_else (match_operand 0 "long_immediate_loadstore_operand" "")
- (const_int 2) (const_int 1))
-
- (eq_attr "type" "move,unary,compare")
- (if_then_else (match_operand 1 "long_immediate_operand" "")
- (const_int 2) (const_int 1))
-
- (eq_attr "type" "binary,mul")
- (if_then_else (match_operand 2 "long_immediate_operand" "")
- (const_int 2) (const_int 1))
-
- (eq_attr "type" "cmove")
- (if_then_else (match_operand 2 "register_operand" "")
- (const_int 1) (const_int 2))
-
- (eq_attr "type" "multi") (const_int 2)
- ]
-
- (const_int 1)))
-
-;; The length here is the length of a single asm. Unfortunately it might be
-;; 1 or 2 so we must allow for 2. That's ok though. How often will users
-;; lament asm's not being put in delay slots?
-(define_asm_attributes
- [(set_attr "length" "2")
- (set_attr "type" "multi")])
-
-;; Condition codes: this one is used by final_prescan_insn to speed up
-;; conditionalizing instructions. It saves having to scan the rtl to see if
-;; it uses or alters the condition codes.
-
-;; USE: This insn uses the condition codes (e.g.: a conditional branch).
-;; CANUSE: This insn can use the condition codes (for conditional execution).
-;; SET: All condition codes are set by this insn.
-;; SET_ZN: the Z and N flags are set by this insn.
-;; SET_ZNC: the Z, N, and C flags are set by this insn.
-;; CLOB: The condition codes are set to unknown values by this insn.
-;; NOCOND: This insn can't use and doesn't affect the condition codes.
-
-(define_attr "cond" "use,canuse,set,set_zn,set_znc,clob,nocond"
- (cond [(and (eq_attr "type" "unary,binary,move")
- (eq_attr "length" "1"))
- (const_string "canuse")
-
- (eq_attr "type" "compare")
- (const_string "set")
-
- (eq_attr "type" "cmove,branch")
- (const_string "use")
-
- (eq_attr "type" "multi,misc")
- (const_string "clob")
- ]
-
- (const_string "nocond")))
-\f
-;; Delay slots.
-
-(define_attr "in_delay_slot" "false,true"
- (cond [(eq_attr "type" "uncond_branch,branch,call,call_no_delay_slot,multi")
- (const_string "false")
- ]
-
- (if_then_else (eq_attr "length" "1")
- (const_string "true")
- (const_string "false"))))
-
-(define_delay (eq_attr "type" "call")
- [(eq_attr "in_delay_slot" "true")
- (eq_attr "in_delay_slot" "true")
- (eq_attr "in_delay_slot" "true")])
-
-(define_delay (eq_attr "type" "branch,uncond_branch")
- [(eq_attr "in_delay_slot" "true")
- (eq_attr "in_delay_slot" "true")
- (eq_attr "in_delay_slot" "true")])
-\f
-;; Scheduling description for the ARC
-
-(define_cpu_unit "branch")
-
-(define_insn_reservation "any_insn" 1 (eq_attr "type" "!load,compare,branch")
- "nothing")
-
-;; 1) A conditional jump cannot immediately follow the insn setting the flags.
-;; This isn't a complete solution as it doesn't come with guarantees. That
-;; is done in the branch patterns and in arc_print_operand. This exists to
-;; avoid inserting a nop when we can.
-
-(define_insn_reservation "compare" 1 (eq_attr "type" "compare")
- "nothing,branch")
-
-(define_insn_reservation "branch" 1 (eq_attr "type" "branch")
- "branch")
-
-;; 2) References to loaded registers should wait a cycle.
-
-;; Memory with load-delay of 1 (i.e., 2 cycle load).
-
-(define_insn_reservation "memory" 2 (eq_attr "type" "load")
- "nothing")
-\f
-;; Move instructions.
-
-(define_expand "movqi"
- [(set (match_operand:QI 0 "general_operand" "")
- (match_operand:QI 1 "general_operand" ""))]
- ""
- "
-{
- /* Everything except mem = const or mem = mem can be done easily. */
-
- if (GET_CODE (operands[0]) == MEM)
- operands[1] = force_reg (QImode, operands[1]);
-}")
-
-(define_insn "*movqi_insn"
- [(set (match_operand:QI 0 "move_dest_operand" "=r,r,r,m")
- (match_operand:QI 1 "move_src_operand" "rI,Ji,m,r"))]
-;; ??? Needed?
- "register_operand (operands[0], QImode)
- || register_operand (operands[1], QImode)"
- "@
- mov%? %0,%1
- mov%? %0,%1
- ldb%U1%V1 %0,%1
- stb%U0%V0 %1,%0"
- [(set_attr "type" "move,move,load,store")])
-
-;; ??? This may never match since there's no cmpqi insn.
-
-(define_insn "*movqi_set_cc_insn"
- [(set (reg:CCZN 61) (compare:CCZN
- (sign_extend:SI (match_operand:QI 1 "move_src_operand" "rIJi"))
- (const_int 0)))
- (set (match_operand:QI 0 "move_dest_operand" "=r")
- (match_dup 1))]
- ""
- "mov%?.f %0,%1"
- [(set_attr "type" "move")
- (set_attr "cond" "set_zn")])
-
-(define_expand "movhi"
- [(set (match_operand:HI 0 "general_operand" "")
- (match_operand:HI 1 "general_operand" ""))]
- ""
- "
-{
- /* Everything except mem = const or mem = mem can be done easily. */
-
- if (GET_CODE (operands[0]) == MEM)
- operands[1] = force_reg (HImode, operands[1]);
-}")
-
-(define_insn "*movhi_insn"
- [(set (match_operand:HI 0 "move_dest_operand" "=r,r,r,m")
- (match_operand:HI 1 "move_src_operand" "rI,Ji,m,r"))]
- "register_operand (operands[0], HImode)
- || register_operand (operands[1], HImode)"
- "@
- mov%? %0,%1
- mov%? %0,%1
- ldw%U1%V1 %0,%1
- stw%U0%V0 %1,%0"
- [(set_attr "type" "move,move,load,store")])
-
-;; ??? Will this ever match?
-
-(define_insn "*movhi_set_cc_insn"
- [(set (reg:CCZN 61) (compare:CCZN
- (sign_extend:SI (match_operand:HI 1 "move_src_operand" "rIJi"))
- (const_int 0)))
- (set (match_operand:HI 0 "move_dest_operand" "=r")
- (match_dup 1))]
-;; ??? Needed?
- "register_operand (operands[0], HImode)
- || register_operand (operands[1], HImode)"
- "mov%?.f %0,%1"
- [(set_attr "type" "move")
- (set_attr "cond" "set_zn")])
-
-(define_expand "movsi"
- [(set (match_operand:SI 0 "general_operand" "")
- (match_operand:SI 1 "general_operand" ""))]
- ""
- "
-{
- /* Everything except mem = const or mem = mem can be done easily. */
-
- if (GET_CODE (operands[0]) == MEM)
- operands[1] = force_reg (SImode, operands[1]);
-}")
-
-(define_insn "*movsi_insn"
- [(set (match_operand:SI 0 "move_dest_operand" "=r,r,r,m")
- (match_operand:SI 1 "move_src_operand" "rI,GJi,m,r"))]
- "register_operand (operands[0], SImode)
- || register_operand (operands[1], SImode)"
- "@
- mov%? %0,%1
- mov%? %0,%S1
- ld%U1%V1 %0,%1
- st%U0%V0 %1,%0"
- [(set_attr "type" "move,move,load,store")])
-
-(define_insn "*movsi_set_cc_insn"
- [(set (reg:CCZN 61) (compare:CCZN
- (match_operand:SI 1 "move_src_operand" "rIJi")
- (const_int 0)))
- (set (match_operand:SI 0 "move_dest_operand" "=r")
- (match_dup 1))]
- "register_operand (operands[0], SImode)
- || register_operand (operands[1], SImode)"
- "mov%?.f %0,%S1"
- [(set_attr "type" "move")
- (set_attr "cond" "set_zn")])
-
-(define_expand "movdi"
- [(set (match_operand:DI 0 "general_operand" "")
- (match_operand:DI 1 "general_operand" ""))]
- ""
- "
-{
- /* Everything except mem = const or mem = mem can be done easily. */
-
- if (GET_CODE (operands[0]) == MEM)
- operands[1] = force_reg (DImode, operands[1]);
-}")
-
-(define_insn "*movdi_insn"
- [(set (match_operand:DI 0 "move_dest_operand" "=r,r,r,m")
- (match_operand:DI 1 "move_double_src_operand" "r,HK,m,r"))]
- "register_operand (operands[0], DImode)
- || register_operand (operands[1], DImode)"
- "*
-{
- switch (which_alternative)
- {
- case 0 :
- /* We normally copy the low-numbered register first. However, if
- the first register operand 0 is the same as the second register of
- operand 1, we must copy in the opposite order. */
- if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
- return \"mov %R0,%R1\;mov %0,%1\";
- else
- return \"mov %0,%1\;mov %R0,%R1\";
- case 1 :
- return \"mov %0,%L1\;mov %R0,%H1\";
- case 2 :
- /* If the low-address word is used in the address, we must load it
- last. Otherwise, load it first. Note that we cannot have
- auto-increment in that case since the address register is known to be
- dead. */
- if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
- operands [1], 0))
- return \"ld%V1 %R0,%R1\;ld%V1 %0,%1\";
- else
- return \"ld%V1 %0,%1\;ld%V1 %R0,%R1\";
- case 3 :
- return \"st%V0 %1,%0\;st%V0 %R1,%R0\";
- default:
- gcc_unreachable ();
- }
-}"
- [(set_attr "type" "move,move,load,store")
- ;; ??? The ld/st values could be 4 if it's [reg,bignum].
- (set_attr "length" "2,4,2,2")])
-
-;(define_expand "movdi"
-; [(set (match_operand:DI 0 "general_operand" "")
-; (match_operand:DI 1 "general_operand" ""))]
-; ""
-; "
-;{
-; /* Flow doesn't understand that this is effectively a DFmode move.
-; It doesn't know that all of `operands[0]' is set. */
-; emit_clobber (operands[0]);
-;
-; /* Emit insns that movsi_insn can handle. */
-; emit_insn (gen_movsi (operand_subword (operands[0], 0, 0, DImode),
-; operand_subword (operands[1], 0, 0, DImode)));
-; emit_insn (gen_movsi (operand_subword (operands[0], 1, 0, DImode),
-; operand_subword (operands[1], 1, 0, DImode)));
-; DONE;
-;}")
-\f
-;; Floating point move insns.
-
-(define_expand "movsf"
- [(set (match_operand:SF 0 "general_operand" "")
- (match_operand:SF 1 "general_operand" ""))]
- ""
- "
-{
- /* Everything except mem = const or mem = mem can be done easily. */
- if (GET_CODE (operands[0]) == MEM)
- operands[1] = force_reg (SFmode, operands[1]);
-}")
-
-(define_insn "*movsf_insn"
- [(set (match_operand:SF 0 "move_dest_operand" "=r,r,r,m")
- (match_operand:SF 1 "move_src_operand" "r,E,m,r"))]
- "register_operand (operands[0], SFmode)
- || register_operand (operands[1], SFmode)"
- "@
- mov%? %0,%1
- mov%? %0,%1 ; %A1
- ld%U1%V1 %0,%1
- st%U0%V0 %1,%0"
- [(set_attr "type" "move,move,load,store")])
-
-(define_expand "movdf"
- [(set (match_operand:DF 0 "general_operand" "")
- (match_operand:DF 1 "general_operand" ""))]
- ""
- "
-{
- /* Everything except mem = const or mem = mem can be done easily. */
- if (GET_CODE (operands[0]) == MEM)
- operands[1] = force_reg (DFmode, operands[1]);
-}")
-
-(define_insn "*movdf_insn"
- [(set (match_operand:DF 0 "move_dest_operand" "=r,r,r,m")
- (match_operand:DF 1 "move_double_src_operand" "r,E,m,r"))]
- "register_operand (operands[0], DFmode)
- || register_operand (operands[1], DFmode)"
- "*
-{
- switch (which_alternative)
- {
- case 0 :
- /* We normally copy the low-numbered register first. However, if
- the first register operand 0 is the same as the second register of
- operand 1, we must copy in the opposite order. */
- if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
- return \"mov %R0,%R1\;mov %0,%1\";
- else
- return \"mov %0,%1\;mov %R0,%R1\";
- case 1 :
- return \"mov %0,%L1\;mov %R0,%H1 ; %A1\";
- case 2 :
- /* If the low-address word is used in the address, we must load it
- last. Otherwise, load it first. Note that we cannot have
- auto-increment in that case since the address register is known to be
- dead. */
- if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
- operands [1], 0))
- return \"ld%V1 %R0,%R1\;ld%V1 %0,%1\";
- else
- return \"ld%V1 %0,%1\;ld%V1 %R0,%R1\";
- case 3 :
- return \"st%V0 %1,%0\;st%V0 %R1,%R0\";
- default:
- gcc_unreachable ();
- }
-}"
- [(set_attr "type" "move,move,load,store")
- ;; ??? The ld/st values could be 4 if it's [reg,bignum].
- (set_attr "length" "2,4,2,2")])
-
-;(define_expand "movdf"
-; [(set (match_operand:DF 0 "general_operand" "")
-; (match_operand:DF 1 "general_operand" ""))]
-; ""
-; "
-;{
-; /* Flow doesn't understand that this is effectively a DFmode move.
-; It doesn't know that all of `operands[0]' is set. */
-; emit_clobber (operands[0]);
-;
-; /* Emit insns that movsi_insn can handle. */
-; emit_insn (gen_movsi (operand_subword (operands[0], 0, 0, DFmode),
-; operand_subword (operands[1], 0, 0, DFmode)));
-; emit_insn (gen_movsi (operand_subword (operands[0], 1, 0, DFmode),
-; operand_subword (operands[1], 1, 0, DFmode)));
-; DONE;
-;}")
-\f
-;; Load/Store with update instructions.
-;;
-;; Some of these we can get by using pre-decrement or pre-increment, but the
-;; hardware can also do cases where the increment is not the size of the
-;; object.
-;;
-;; In all these cases, we use operands 0 and 1 for the register being
-;; incremented because those are the operands that local-alloc will
-;; tie and these are the pair most likely to be tieable (and the ones
-;; that will benefit the most).
-;;
-;; We use match_operator here because we need to know whether the memory
-;; object is volatile or not.
-
-(define_insn "*loadqi_update"
- [(set (match_operand:QI 3 "register_operand" "=r,r")
- (match_operator:QI 4 "load_update_operand"
- [(match_operand:SI 1 "register_operand" "0,0")
- (match_operand:SI 2 "nonmemory_operand" "rI,J")]))
- (set (match_operand:SI 0 "register_operand" "=r,r")
- (plus:SI (match_dup 1) (match_dup 2)))]
- ""
- "ldb.a%V4 %3,[%0,%2]"
- [(set_attr "type" "load,load")
- (set_attr "length" "1,2")])
-
-(define_insn "*load_zeroextendqisi_update"
- [(set (match_operand:SI 3 "register_operand" "=r,r")
- (zero_extend:SI (match_operator:QI 4 "load_update_operand"
- [(match_operand:SI 1 "register_operand" "0,0")
- (match_operand:SI 2 "nonmemory_operand" "rI,J")])))
- (set (match_operand:SI 0 "register_operand" "=r,r")
- (plus:SI (match_dup 1) (match_dup 2)))]
- ""
- "ldb.a%V4 %3,[%0,%2]"
- [(set_attr "type" "load,load")
- (set_attr "length" "1,2")])
-
-(define_insn "*load_signextendqisi_update"
- [(set (match_operand:SI 3 "register_operand" "=r,r")
- (sign_extend:SI (match_operator:QI 4 "load_update_operand"
- [(match_operand:SI 1 "register_operand" "0,0")
- (match_operand:SI 2 "nonmemory_operand" "rI,J")])))
- (set (match_operand:SI 0 "register_operand" "=r,r")
- (plus:SI (match_dup 1) (match_dup 2)))]
- ""
- "ldb.x.a%V4 %3,[%0,%2]"
- [(set_attr "type" "load,load")
- (set_attr "length" "1,2")])
-
-(define_insn "*storeqi_update"
- [(set (match_operator:QI 4 "store_update_operand"
- [(match_operand:SI 1 "register_operand" "0")
- (match_operand:SI 2 "short_immediate_operand" "I")])
- (match_operand:QI 3 "register_operand" "r"))
- (set (match_operand:SI 0 "register_operand" "=r")
- (plus:SI (match_dup 1) (match_dup 2)))]
- ""
- "stb.a%V4 %3,[%0,%2]"
- [(set_attr "type" "store")
- (set_attr "length" "1")])
-
-(define_insn "*loadhi_update"
- [(set (match_operand:HI 3 "register_operand" "=r,r")
- (match_operator:HI 4 "load_update_operand"
- [(match_operand:SI 1 "register_operand" "0,0")
- (match_operand:SI 2 "nonmemory_operand" "rI,J")]))
- (set (match_operand:SI 0 "register_operand" "=r,r")
- (plus:SI (match_dup 1) (match_dup 2)))]
- ""
- "ldw.a%V4 %3,[%0,%2]"
- [(set_attr "type" "load,load")
- (set_attr "length" "1,2")])
-
-(define_insn "*load_zeroextendhisi_update"
- [(set (match_operand:SI 3 "register_operand" "=r,r")
- (zero_extend:SI (match_operator:HI 4 "load_update_operand"
- [(match_operand:SI 1 "register_operand" "0,0")
- (match_operand:SI 2 "nonmemory_operand" "rI,J")])))
- (set (match_operand:SI 0 "register_operand" "=r,r")
- (plus:SI (match_dup 1) (match_dup 2)))]
- ""
- "ldw.a%V4 %3,[%0,%2]"
- [(set_attr "type" "load,load")
- (set_attr "length" "1,2")])
-
-(define_insn "*load_signextendhisi_update"
- [(set (match_operand:SI 3 "register_operand" "=r,r")
- (sign_extend:SI (match_operator:HI 4 "load_update_operand"
- [(match_operand:SI 1 "register_operand" "0,0")
- (match_operand:SI 2 "nonmemory_operand" "rI,J")])))
- (set (match_operand:SI 0 "register_operand" "=r,r")
- (plus:SI (match_dup 1) (match_dup 2)))]
- ""
- "ldw.x.a%V4 %3,[%0,%2]"
- [(set_attr "type" "load,load")
- (set_attr "length" "1,2")])
-
-(define_insn "*storehi_update"
- [(set (match_operator:HI 4 "store_update_operand"
- [(match_operand:SI 1 "register_operand" "0")
- (match_operand:SI 2 "short_immediate_operand" "I")])
- (match_operand:HI 3 "register_operand" "r"))
- (set (match_operand:SI 0 "register_operand" "=r")
- (plus:SI (match_dup 1) (match_dup 2)))]
- ""
- "stw.a%V4 %3,[%0,%2]"
- [(set_attr "type" "store")
- (set_attr "length" "1")])
-
-(define_insn "*loadsi_update"
- [(set (match_operand:SI 3 "register_operand" "=r,r")
- (match_operator:SI 4 "load_update_operand"
- [(match_operand:SI 1 "register_operand" "0,0")
- (match_operand:SI 2 "nonmemory_operand" "rI,J")]))
- (set (match_operand:SI 0 "register_operand" "=r,r")
- (plus:SI (match_dup 1) (match_dup 2)))]
- ""
- "ld.a%V4 %3,[%0,%2]"
- [(set_attr "type" "load,load")
- (set_attr "length" "1,2")])
-
-(define_insn "*storesi_update"
- [(set (match_operator:SI 4 "store_update_operand"
- [(match_operand:SI 1 "register_operand" "0")
- (match_operand:SI 2 "short_immediate_operand" "I")])
- (match_operand:SI 3 "register_operand" "r"))
- (set (match_operand:SI 0 "register_operand" "=r")
- (plus:SI (match_dup 1) (match_dup 2)))]
- ""
- "st.a%V4 %3,[%0,%2]"
- [(set_attr "type" "store")
- (set_attr "length" "1")])
-
-(define_insn "*loadsf_update"
- [(set (match_operand:SF 3 "register_operand" "=r,r")
- (match_operator:SF 4 "load_update_operand"
- [(match_operand:SI 1 "register_operand" "0,0")
- (match_operand:SI 2 "nonmemory_operand" "rI,J")]))
- (set (match_operand:SI 0 "register_operand" "=r,r")
- (plus:SI (match_dup 1) (match_dup 2)))]
- ""
- "ld.a%V4 %3,[%0,%2]"
- [(set_attr "type" "load,load")
- (set_attr "length" "1,2")])
-
-(define_insn "*storesf_update"
- [(set (match_operator:SF 4 "store_update_operand"
- [(match_operand:SI 1 "register_operand" "0")
- (match_operand:SI 2 "short_immediate_operand" "I")])
- (match_operand:SF 3 "register_operand" "r"))
- (set (match_operand:SI 0 "register_operand" "=r")
- (plus:SI (match_dup 1) (match_dup 2)))]
- ""
- "st.a%V4 %3,[%0,%2]"
- [(set_attr "type" "store")
- (set_attr "length" "1")])
-\f
-;; Conditional move instructions.
-
-(define_expand "movsicc"
- [(set (match_operand:SI 0 "register_operand" "")
- (if_then_else:SI (match_operand 1 "comparison_operator" "")
- (match_operand:SI 2 "nonmemory_operand" "")
- (match_operand:SI 3 "register_operand" "")))]
- ""
- "
-{
- enum rtx_code code = GET_CODE (operands[1]);
- rtx cc_reg = gen_compare_reg (code, XEXP (operands[1], 0),
- XEXP (operands[1], 1));
- operands[1] = gen_rtx_fmt_ee (code, VOIDmode, cc_reg, const0_rtx);
-}")
-
-(define_expand "movsfcc"
- [(set (match_operand:SF 0 "register_operand" "")
- (if_then_else:SF (match_operand 1 "comparison_operator" "")
- (match_operand:SF 2 "nonmemory_operand" "")
- (match_operand:SF 3 "register_operand" "")))]
- ""
- "
-{
- enum rtx_code code = GET_CODE (operands[1]);
- rtx cc_reg = gen_compare_reg (code, XEXP (operands[1], 0),
- XEXP (operands[1], 1));
- operands[1] = gen_rtx_fmt_ee (code, VOIDmode, cc_reg, const0_rtx);
-}")
-
-(define_insn "*movsicc_insn"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (if_then_else:SI (match_operand 1 "comparison_operator" "")
- (match_operand:SI 2 "nonmemory_operand" "rJi")
- (match_operand:SI 3 "register_operand" "0")))]
- ""
- "mov.%d1 %0,%S2"
- [(set_attr "type" "cmove")])
-
-(define_insn "*movsfcc_insn"
- [(set (match_operand:SF 0 "register_operand" "=r,r")
- (if_then_else:SF (match_operand 1 "comparison_operator" "")
- (match_operand:SF 2 "nonmemory_operand" "r,E")
- (match_operand:SF 3 "register_operand" "0,0")))]
- ""
- "@
- mov.%d1 %0,%2
- mov.%d1 %0,%2 ; %A2"
- [(set_attr "type" "cmove,cmove")])
-
-\f
-;; Zero extension instructions.
-;; ??? We don't support volatile memrefs here, but I'm not sure why.
-
-(define_insn "zero_extendqihi2"
- [(set (match_operand:HI 0 "register_operand" "=r,r")
- (zero_extend:HI (match_operand:QI 1 "nonvol_nonimm_operand" "r,m")))]
- ""
- "@
- extb%? %0,%1
- ldb%U1 %0,%1"
- [(set_attr "type" "unary,load")])
-
-(define_insn "*zero_extendqihi2_set_cc_insn"
- [(set (reg:CCZN 61) (compare:CCZN
- (zero_extend:SI (match_operand:QI 1 "register_operand" "r"))
- (const_int 0)))
- (set (match_operand:HI 0 "register_operand" "=r")
- (zero_extend:HI (match_dup 1)))]
- ""
- "extb%?.f %0,%1"
- [(set_attr "type" "unary")
- (set_attr "cond" "set_zn")])
-
-(define_insn "zero_extendqisi2"
- [(set (match_operand:SI 0 "register_operand" "=r,r")
- (zero_extend:SI (match_operand:QI 1 "nonvol_nonimm_operand" "r,m")))]
- ""
- "@
- extb%? %0,%1
- ldb%U1 %0,%1"
- [(set_attr "type" "unary,load")])
-
-(define_insn "*zero_extendqisi2_set_cc_insn"
- [(set (reg:CCZN 61) (compare:CCZN
- (zero_extend:SI (match_operand:QI 1 "register_operand" "r"))
- (const_int 0)))
- (set (match_operand:SI 0 "register_operand" "=r")
- (zero_extend:SI (match_dup 1)))]
- ""
- "extb%?.f %0,%1"
- [(set_attr "type" "unary")
- (set_attr "cond" "set_zn")])
-
-(define_insn "zero_extendhisi2"
- [(set (match_operand:SI 0 "register_operand" "=r,r")
- (zero_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "r,m")))]
- ""
- "@
- extw%? %0,%1
- ldw%U1 %0,%1"
- [(set_attr "type" "unary,load")])
-
-(define_insn "*zero_extendhisi2_set_cc_insn"
- [(set (reg:CCZN 61) (compare:CCZN
- (zero_extend:SI (match_operand:HI 1 "register_operand" "r"))
- (const_int 0)))
- (set (match_operand:SI 0 "register_operand" "=r")
- (zero_extend:SI (match_dup 1)))]
- ""
- "extw%?.f %0,%1"
- [(set_attr "type" "unary")
- (set_attr "cond" "set_zn")])
-\f
-;; Sign extension instructions.
-
-(define_insn "extendqihi2"
- [(set (match_operand:HI 0 "register_operand" "=r,r")
- (sign_extend:HI (match_operand:QI 1 "nonvol_nonimm_operand" "r,m")))]
- ""
- "@
- sexb%? %0,%1
- ldb.x%U1 %0,%1"
- [(set_attr "type" "unary,load")])
-
-(define_insn "*extendqihi2_set_cc_insn"
- [(set (reg:CCZN 61) (compare:CCZN
- (sign_extend:SI (match_operand:QI 1 "register_operand" "r"))
- (const_int 0)))
- (set (match_operand:HI 0 "register_operand" "=r")
- (sign_extend:HI (match_dup 1)))]
- ""
- "sexb%?.f %0,%1"
- [(set_attr "type" "unary")
- (set_attr "cond" "set_zn")])
-
-(define_insn "extendqisi2"
- [(set (match_operand:SI 0 "register_operand" "=r,r")
- (sign_extend:SI (match_operand:QI 1 "nonvol_nonimm_operand" "r,m")))]
- ""
- "@
- sexb%? %0,%1
- ldb.x%U1 %0,%1"
- [(set_attr "type" "unary,load")])
-
-(define_insn "*extendqisi2_set_cc_insn"
- [(set (reg:CCZN 61) (compare:CCZN
- (sign_extend:SI (match_operand:QI 1 "register_operand" "r"))
- (const_int 0)))
- (set (match_operand:SI 0 "register_operand" "=r")
- (sign_extend:SI (match_dup 1)))]
- ""
- "sexb%?.f %0,%1"
- [(set_attr "type" "unary")
- (set_attr "cond" "set_zn")])
-
-(define_insn "extendhisi2"
- [(set (match_operand:SI 0 "register_operand" "=r,r")
- (sign_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "r,m")))]
- ""
- "@
- sexw%? %0,%1
- ldw.x%U1 %0,%1"
- [(set_attr "type" "unary,load")])
-
-(define_insn "*extendhisi2_set_cc_insn"
- [(set (reg:CCZN 61) (compare:CCZN
- (sign_extend:SI (match_operand:HI 1 "register_operand" "r"))
- (const_int 0)))
- (set (match_operand:SI 0 "register_operand" "=r")
- (sign_extend:SI (match_dup 1)))]
- ""
- "sexw%?.f %0,%1"
- [(set_attr "type" "unary")
- (set_attr "cond" "set_zn")])
-\f
-;; Arithmetic instructions.
-
-(define_insn "addsi3"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (plus:SI (match_operand:SI 1 "register_operand" "%r")
- (match_operand:SI 2 "nonmemory_operand" "rIJ")))]
- ""
- "add%? %0,%1,%2")
-
-(define_insn "*addsi3_set_cc_insn"
- [(set (reg:CC 61) (compare:CC
- (plus:SI (match_operand:SI 1 "register_operand" "%r")
- (match_operand:SI 2 "nonmemory_operand" "rIJ"))
- (const_int 0)))
- (set (match_operand:SI 0 "register_operand" "=r")
- (plus:SI (match_dup 1)
- (match_dup 2)))]
- ""
- "add%?.f %0,%1,%2"
- [(set_attr "cond" "set")])
-
-(define_insn "adddi3"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (plus:DI (match_operand:DI 1 "nonmemory_operand" "%r")
- (match_operand:DI 2 "nonmemory_operand" "ri")))
- (clobber (reg:CC 61))]
- ""
- "*
-{
- rtx op2 = operands[2];
-
- if (GET_CODE (op2) == CONST_INT)
- {
- int sign = INTVAL (op2);
- if (sign < 0)
- return \"add.f %L0,%L1,%2\;adc %H0,%H1,-1\";
- else
- return \"add.f %L0,%L1,%2\;adc %H0,%H1,0\";
- }
- else
- return \"add.f %L0,%L1,%L2\;adc %H0,%H1,%H2\";
-}"
- [(set_attr "length" "2")])
-
-(define_insn "subsi3"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (minus:SI (match_operand:SI 1 "register_operand" "r")
- (match_operand:SI 2 "nonmemory_operand" "rIJ")))]
- ""
- "sub%? %0,%1,%2")
-
-(define_insn "*subsi3_set_cc_insn"
- [(set (reg:CC 61) (compare:CC
- (minus:SI (match_operand:SI 1 "register_operand" "%r")
- (match_operand:SI 2 "nonmemory_operand" "rIJ"))
- (const_int 0)))
- (set (match_operand:SI 0 "register_operand" "=r")
- (minus:SI (match_dup 1)
- (match_dup 2)))]
- ""
- "sub%?.f %0,%1,%2"
- [(set_attr "cond" "set")])
-
-(define_insn "subdi3"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (minus:DI (match_operand:DI 1 "nonmemory_operand" "r")
- (match_operand:DI 2 "nonmemory_operand" "ri")))
- (clobber (reg:CC 61))]
- ""
- "*
-{
- rtx op2 = operands[2];
-
- if (GET_CODE (op2) == CONST_INT)
- {
- int sign = INTVAL (op2);
- if (sign < 0)
- return \"sub.f %L0,%L1,%2\;sbc %H0,%H1,-1\";
- else
- return \"sub.f %L0,%L1,%2\;sbc %H0,%H1,0\";
- }
- else
- return \"sub.f %L0,%L1,%L2\;sbc %H0,%H1,%H2\";
-}"
- [(set_attr "length" "2")])
-\f
-;; Boolean instructions.
-;;
-;; We don't define the DImode versions as expand_binop does a good enough job.
-
-(define_insn "andsi3"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (and:SI (match_operand:SI 1 "register_operand" "%r")
- (match_operand:SI 2 "nonmemory_operand" "rIJ")))]
- ""
- "and%? %0,%1,%2")
-
-(define_insn "*andsi3_set_cc_insn"
- [(set (reg:CCZN 61) (compare:CCZN
- (and:SI (match_operand:SI 1 "register_operand" "%r")
- (match_operand:SI 2 "nonmemory_operand" "rIJ"))
- (const_int 0)))
- (set (match_operand:SI 0 "register_operand" "=r")
- (and:SI (match_dup 1)
- (match_dup 2)))]
- ""
- "and%?.f %0,%1,%2"
- [(set_attr "cond" "set_zn")])
-
-(define_insn "*bicsi3_insn"
- [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
- (and:SI (match_operand:SI 1 "nonmemory_operand" "r,r,I,J")
- (not:SI (match_operand:SI 2 "nonmemory_operand" "rI,J,r,r"))))]
- ""
- "bic%? %0,%1,%2"
- [(set_attr "length" "1,2,1,2")])
-
-(define_insn "*bicsi3_set_cc_insn"
- [(set (reg:CCZN 61) (compare:CCZN
- (and:SI (match_operand:SI 1 "register_operand" "%r")
- (not:SI (match_operand:SI 2 "nonmemory_operand" "rIJ")))
- (const_int 0)))
- (set (match_operand:SI 0 "register_operand" "=r")
- (and:SI (match_dup 1)
- (not:SI (match_dup 2))))]
- ""
- "bic%?.f %0,%1,%2"
- [(set_attr "cond" "set_zn")])
-
-(define_insn "iorsi3"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (ior:SI (match_operand:SI 1 "register_operand" "%r")
- (match_operand:SI 2 "nonmemory_operand" "rIJ")))]
- ""
- "or%? %0,%1,%2")
-
-(define_insn "*iorsi3_set_cc_insn"
- [(set (reg:CCZN 61) (compare:CCZN
- (ior:SI (match_operand:SI 1 "register_operand" "%r")
- (match_operand:SI 2 "nonmemory_operand" "rIJ"))
- (const_int 0)))
- (set (match_operand:SI 0 "register_operand" "=r")
- (ior:SI (match_dup 1)
- (match_dup 2)))]
- ""
- "or%?.f %0,%1,%2"
- [(set_attr "cond" "set_zn")])
-
-(define_insn "xorsi3"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (xor:SI (match_operand:SI 1 "register_operand" "%r")
- (match_operand:SI 2 "nonmemory_operand" "rIJ")))]
- ""
- "xor%? %0,%1,%2")
-
-(define_insn "*xorsi3_set_cc_insn"
- [(set (reg:CCZN 61) (compare:CCZN
- (xor:SI (match_operand:SI 1 "register_operand" "%r")
- (match_operand:SI 2 "nonmemory_operand" "rIJ"))
- (const_int 0)))
- (set (match_operand:SI 0 "register_operand" "=r")
- (xor:SI (match_dup 1)
- (match_dup 2)))]
- ""
- "xor%?.f %0,%1,%2"
- [(set_attr "cond" "set_zn")])
-
-(define_insn "negsi2"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (neg:SI (match_operand:SI 1 "register_operand" "r")))]
- ""
- "sub%? %0,0,%1"
- [(set_attr "type" "unary")])
-
-(define_insn "*negsi2_set_cc_insn"
- [(set (reg:CC 61) (compare:CC
- (neg:SI (match_operand:SI 1 "register_operand" "r"))
- (const_int 0)))
- (set (match_operand:SI 0 "register_operand" "=r")
- (neg:SI (match_dup 1)))]
- ""
- "sub%?.f %0,0,%1"
- [(set_attr "type" "unary")
- (set_attr "cond" "set")])
-
-(define_insn "negdi2"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (neg:DI (match_operand:DI 1 "register_operand" "r")))
- (clobber (reg:SI 61))]
- ""
- "sub.f %L0,0,%L1\;sbc %H0,0,%H1"
- [(set_attr "type" "unary")
- (set_attr "length" "2")])
-
-(define_insn "one_cmplsi2"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (not:SI (match_operand:SI 1 "register_operand" "r")))]
- ""
- "xor%? %0,%1,-1"
- [(set_attr "type" "unary")])
-
-(define_insn "*one_cmplsi2_set_cc_insn"
- [(set (reg:CCZN 61) (compare:CCZN
- (not:SI (match_operand:SI 1 "register_operand" "r"))
- (const_int 0)))
- (set (match_operand:SI 0 "register_operand" "=r")
- (not:SI (match_dup 1)))]
- ""
- "xor%?.f %0,%1,-1"
- [(set_attr "type" "unary")
- (set_attr "cond" "set_zn")])
-\f
-;; Shift instructions.
-
-(define_expand "ashlsi3"
- [(set (match_operand:SI 0 "register_operand" "")
- (ashift:SI (match_operand:SI 1 "register_operand" "")
- (match_operand:SI 2 "nonmemory_operand" "")))]
- ""
- "
-{
- if (! TARGET_SHIFTER)
- {
- emit_insn (gen_rtx_PARALLEL
- (VOIDmode,
- gen_rtvec (2,
- gen_rtx_SET (VOIDmode, operands[0],
- gen_rtx_ASHIFT (SImode, operands[1],
- operands[2])),
- gen_rtx_CLOBBER (VOIDmode,
- gen_rtx_SCRATCH (SImode)))));
- DONE;
- }
-}")
-
-(define_expand "ashrsi3"
- [(set (match_operand:SI 0 "register_operand" "")
- (ashiftrt:SI (match_operand:SI 1 "register_operand" "")
- (match_operand:SI 2 "nonmemory_operand" "")))]
- ""
- "
-{
- if (! TARGET_SHIFTER)
- {
- emit_insn (gen_rtx_PARALLEL
- (VOIDmode,
- gen_rtvec (2,
- gen_rtx_SET (VOIDmode, operands[0],
- gen_rtx_ASHIFTRT (SImode,
- operands[1],
- operands[2])),
- gen_rtx_CLOBBER (VOIDmode,
- gen_rtx_SCRATCH (SImode)))));
- DONE;
- }
-}")
-
-(define_expand "lshrsi3"
- [(set (match_operand:SI 0 "register_operand" "")
- (lshiftrt:SI (match_operand:SI 1 "register_operand" "")
- (match_operand:SI 2 "nonmemory_operand" "")))]
- ""
- "
-{
- if (! TARGET_SHIFTER)
- {
- emit_insn (gen_rtx_PARALLEL
- (VOIDmode,
- gen_rtvec (2,
- gen_rtx_SET (VOIDmode, operands[0],
- gen_rtx_LSHIFTRT (SImode,
- operands[1],
- operands[2])),
- gen_rtx_CLOBBER (VOIDmode,
- gen_rtx_SCRATCH (SImode)))));
- DONE;
- }
-}")
-
-(define_insn "*ashlsi3_insn"
- [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
- (ashift:SI (match_operand:SI 1 "nonmemory_operand" "r,r,I,J")
- (match_operand:SI 2 "nonmemory_operand" "rI,J,r,r")))]
- "TARGET_SHIFTER"
- "asl%? %0,%1,%2"
- [(set_attr "type" "shift")
- (set_attr "length" "1,2,1,2")])
-
-(define_insn "*ashrsi3_insn"
- [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
- (ashiftrt:SI (match_operand:SI 1 "nonmemory_operand" "r,r,I,J")
- (match_operand:SI 2 "nonmemory_operand" "rI,J,r,r")))]
- "TARGET_SHIFTER"
- "asr%? %0,%1,%2"
- [(set_attr "type" "shift")
- (set_attr "length" "1,2,1,2")])
-
-(define_insn "*lshrsi3_insn"
- [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
- (lshiftrt:SI (match_operand:SI 1 "nonmemory_operand" "r,r,I,J")
- (match_operand:SI 2 "nonmemory_operand" "rI,J,r,r")))]
- "TARGET_SHIFTER"
- "lsr%? %0,%1,%2"
- [(set_attr "type" "shift")
- (set_attr "length" "1,2,1,2")])
-
-(define_insn "*shift_si3"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (match_operator:SI 3 "shift_operator"
- [(match_operand:SI 1 "register_operand" "0")
- (match_operand:SI 2 "nonmemory_operand" "rIJ")]))
- (clobber (match_scratch:SI 4 "=&r"))]
- "! TARGET_SHIFTER"
- "* return output_shift (operands);"
- [(set_attr "type" "shift")
- (set_attr "length" "8")])
-\f
-;; Compare instructions.
-;; This controls RTL generation and register allocation.
-
-;; ??? We may be able to relax this a bit by adding a new constant 'K' for 0.
-;; This assumes sub.f 0,symbol,0 is a valid insn.
-;; Note that "sub.f 0,r0,1" is an 8 byte insn. To avoid unnecessarily
-;; creating 8 byte insns we duplicate %1 in the destination reg of the insn
-;; if it's a small constant.
-
-(define_insn "*cmpsi_cc_insn"
- [(set (reg:CC 61)
- (compare:CC (match_operand:SI 0 "register_operand" "r,r,r")
- (match_operand:SI 1 "nonmemory_operand" "r,I,J")))]
- ""
- "@
- sub.f 0,%0,%1
- sub.f %1,%0,%1
- sub.f 0,%0,%1"
- [(set_attr "type" "compare,compare,compare")])
-
-(define_insn "*cmpsi_cczn_insn"
- [(set (reg:CCZN 61)
- (compare:CCZN (match_operand:SI 0 "register_operand" "r,r,r")
- (match_operand:SI 1 "nonmemory_operand" "r,I,J")))]
- ""
- "@
- sub.f 0,%0,%1
- sub.f %1,%0,%1
- sub.f 0,%0,%1"
- [(set_attr "type" "compare,compare,compare")])
-
-(define_insn "*cmpsi_ccznc_insn"
- [(set (reg:CCZNC 61)
- (compare:CCZNC (match_operand:SI 0 "register_operand" "r,r,r")
- (match_operand:SI 1 "nonmemory_operand" "r,I,J")))]
- ""
- "@
- sub.f 0,%0,%1
- sub.f %1,%0,%1
- sub.f 0,%0,%1"
- [(set_attr "type" "compare,compare,compare")])
-
-;; Next come the scc insn and its expander.
-
-(define_expand "cstoresi4"
- [(set (match_dup 4)
- (match_op_dup 5
- [(match_operand:SI 2 "register_operand" "")
- (match_operand:SI 3 "nonmemory_operand" "")]))
- (set (match_operand:SI 0 "register_operand")
- (match_operator:SI 1 "ordered_comparison_operator"
- [(match_dup 4)
- (const_int 0)]))]
- ""
- "
-{
- operands[4] = gen_compare_reg (GET_CODE (operands[1]),
- operands[2], operands[3]);
- operands[5] = gen_rtx_fmt_ee (COMPARE,
- GET_MODE (operands[4]),
- operands[2], operands[3]);
-}")
-
-(define_insn "*scc_insn"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (match_operator:SI 1 "comparison_operator" [(reg 61) (const_int 0)]))]
- ""
- "mov %0,1\;sub.%D1 %0,%0,%0"
- [(set_attr "type" "unary")
- (set_attr "length" "2")])
-
-;; ??? Look up negscc insn. See pa.md for example.
-(define_insn "*neg_scc_insn"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (neg:SI (match_operator:SI 1 "comparison_operator"
- [(reg 61) (const_int 0)])))]
- ""
- "mov %0,-1\;sub.%D1 %0,%0,%0"
- [(set_attr "type" "unary")
- (set_attr "length" "2")])
-
-(define_insn "*not_scc_insn"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (not:SI (match_operator:SI 1 "comparison_operator"
- [(reg 61) (const_int 0)])))]
- ""
- "mov %0,1\;sub.%d1 %0,%0,%0"
- [(set_attr "type" "unary")
- (set_attr "length" "2")])
-\f
-;; These control RTL generation for conditional jump insns
-
-(define_expand "cbranchsi4"
- [(set (match_dup 4)
- (match_op_dup 5
- [(match_operand:SI 1 "register_operand" "")
- (match_operand:SI 2 "nonmemory_operand" "")]))
- (set (pc)
- (if_then_else
- (match_operator 0 "ordered_comparison_operator"
- [(match_dup 4)
- (const_int 0)])
- (label_ref (match_operand 3 "" ""))
- (pc)))]
- ""
- "
-{
- operands[4] = gen_compare_reg (GET_CODE (operands[0]),
- operands[1], operands[2]);
- operands[5] = gen_rtx_fmt_ee (COMPARE,
- GET_MODE (operands[4]),
- operands[1], operands[2]);
-}")
-
-;; Now match both normal and inverted jump.
-
-(define_insn "*branch_insn"
- [(set (pc)
- (if_then_else (match_operator 1 "proper_comparison_operator"
- [(reg 61) (const_int 0)])
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "*
-{
- if (arc_ccfsm_branch_deleted_p ())
- {
- arc_ccfsm_record_branch_deleted ();
- return \"; branch deleted, next insns conditionalized\";
- }
- else
- return \"%~b%d1%# %l0\";
-}"
- [(set_attr "type" "branch")])
-
-(define_insn "*rev_branch_insn"
- [(set (pc)
- (if_then_else (match_operator 1 "proper_comparison_operator"
- [(reg 61) (const_int 0)])
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- "REVERSIBLE_CC_MODE (GET_MODE (XEXP (operands[1], 0)))"
- "*
-{
- if (arc_ccfsm_branch_deleted_p ())
- {
- arc_ccfsm_record_branch_deleted ();
- return \"; branch deleted, next insns conditionalized\";
- }
- else
- return \"%~b%D1%# %l0\";
-}"
- [(set_attr "type" "branch")])
-\f
-;; Unconditional and other jump instructions.
-
-(define_insn "jump"
- [(set (pc) (label_ref (match_operand 0 "" "")))]
- ""
- "b%* %l0"
- [(set_attr "type" "uncond_branch")])
-
-(define_insn "indirect_jump"
- [(set (pc) (match_operand:SI 0 "address_operand" "p"))]
- ""
- "j%* %a0"
- [(set_attr "type" "uncond_branch")])
-
-;; Implement a switch statement.
-;; This wouldn't be necessary in the non-pic case if we could distinguish
-;; label refs of the jump table from other label refs. The problem is that
-;; label refs are output as "%st(.LL42)" but we don't want the %st - we want
-;; the real address since it's the address of the table.
-
-(define_expand "casesi"
- [(set (match_dup 5)
- (minus:SI (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "nonmemory_operand" "")))
- (set (reg:CC 61)
- (compare:CC (match_dup 5)
- (match_operand:SI 2 "nonmemory_operand" "")))
- (set (pc)
- (if_then_else (gtu (reg:CC 61)
- (const_int 0))
- (label_ref (match_operand 4 "" ""))
- (pc)))
- (parallel
- [(set (pc)
- (mem:SI (plus:SI (mult:SI (match_dup 5)
- (const_int 4))
- (label_ref (match_operand 3 "" "")))))
- (clobber (match_scratch:SI 6 ""))
- (clobber (match_scratch:SI 7 ""))])]
- ""
- "
-{
- operands[5] = gen_reg_rtx (SImode);
-}")
-
-(define_insn "*casesi_insn"
- [(set (pc)
- (mem:SI (plus:SI (mult:SI (match_operand:SI 0 "register_operand" "r")
- (const_int 4))
- (label_ref (match_operand 1 "" "")))))
- (clobber (match_scratch:SI 2 "=r"))
- (clobber (match_scratch:SI 3 "=r"))]
- ""
- "*
-{
- output_asm_insn (\"mov %2,%1\", operands);
- if (TARGET_SHIFTER)
- output_asm_insn (\"asl %3,%0,2\", operands);
- else
- output_asm_insn (\"asl %3,%0\;asl %3,%3\", operands);
- output_asm_insn (\"ld %2,[%2,%3]\", operands);
- output_asm_insn (\"j.nd %a2\", operands);
- return \"\";
-}"
- [(set_attr "type" "uncond_branch")
- (set_attr "length" "6")])
-
-(define_insn "tablejump"
- [(set (pc) (match_operand:SI 0 "address_operand" "p"))
- (use (label_ref (match_operand 1 "" "")))]
- "0 /* disabled -> using casesi now */"
- "j%* %a0"
- [(set_attr "type" "uncond_branch")])
-
-(define_expand "call"
- ;; operands[1] is stack_size_rtx
- ;; operands[2] is next_arg_register
- [(parallel [(call (match_operand:SI 0 "call_operand" "")
- (match_operand 1 "" ""))
- (clobber (reg:SI 31))])]
- ""
- "")
-
-(define_insn "*call_via_reg"
- [(call (mem:SI (match_operand:SI 0 "register_operand" "r"))
- (match_operand 1 "" ""))
- (clobber (reg:SI 31))]
- ""
- "lr blink,[status]\;j.d %0\;add blink,blink,2"
- [(set_attr "type" "call_no_delay_slot")
- (set_attr "length" "3")])
-
-(define_insn "*call_via_label"
- [(call (mem:SI (match_operand:SI 0 "call_address_operand" ""))
- (match_operand 1 "" ""))
- (clobber (reg:SI 31))]
- ""
- ; The %~ is necessary in case this insn gets conditionalized and the previous
- ; insn is the cc setter.
- "%~bl%!%* %0"
- [(set_attr "type" "call")
- (set_attr "cond" "canuse")])
-
-(define_expand "call_value"
- ;; operand 2 is stack_size_rtx
- ;; operand 3 is next_arg_register
- [(parallel [(set (match_operand 0 "register_operand" "=r")
- (call (match_operand:SI 1 "call_operand" "")
- (match_operand 2 "" "")))
- (clobber (reg:SI 31))])]
- ""
- "")
-
-(define_insn "*call_value_via_reg"
- [(set (match_operand 0 "register_operand" "=r")
- (call (mem:SI (match_operand:SI 1 "register_operand" "r"))
- (match_operand 2 "" "")))
- (clobber (reg:SI 31))]
- ""
- "lr blink,[status]\;j.d %1\;add blink,blink,2"
- [(set_attr "type" "call_no_delay_slot")
- (set_attr "length" "3")])
-
-(define_insn "*call_value_via_label"
- [(set (match_operand 0 "register_operand" "=r")
- (call (mem:SI (match_operand:SI 1 "call_address_operand" ""))
- (match_operand 2 "" "")))
- (clobber (reg:SI 31))]
- ""
- ; The %~ is necessary in case this insn gets conditionalized and the previous
- ; insn is the cc setter.
- "%~bl%!%* %1"
- [(set_attr "type" "call")
- (set_attr "cond" "canuse")])
-\f
-(define_insn "nop"
- [(const_int 0)]
- ""
- "nop"
- [(set_attr "type" "misc")])
-
-;; Special pattern to flush the icache.
-;; ??? Not sure what to do here. Some ARC's are known to support this.
-
-(define_insn "flush_icache"
- [(unspec_volatile [(match_operand 0 "memory_operand" "m")] 0)]
- ""
- "* return \"\";"
- [(set_attr "type" "misc")])
-\f
-;; Split up troublesome insns for better scheduling.
-\f
-;; Peepholes go at the end.
+++ /dev/null
-; Options for the Argonaut ARC port of the compiler
-;
-; Copyright (C) 2005, 2007, 2011 Free Software Foundation, Inc.
-;
-; This file is part of GCC.
-;
-; GCC is free software; you can redistribute it and/or modify it under
-; the terms of the GNU General Public License as published by the Free
-; Software Foundation; either version 3, or (at your option) any later
-; version.
-;
-; GCC is distributed in the hope that it will be useful, but WITHOUT
-; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
-; License for more details.
-;
-; You should have received a copy of the GNU General Public License
-; along with GCC; see the file COPYING3. If not see
-; <http://www.gnu.org/licenses/>.
-
-EB
-Driver
-
-EL
-Driver
-
-malign-loops
-Target Undocumented Report Mask(ALIGN_LOOPS)
-
-mbig-endian
-Target Undocumented Report RejectNegative Mask(BIG_ENDIAN)
-
-mlittle-endian
-Target Undocumented Report RejectNegative InverseMask(BIG_ENDIAN)
-
-mmangle-cpu
-Target Report Mask(MANGLE_CPU)
-Prepend the name of the cpu to all public symbol names
-
-; mmangle-cpu-libgcc
-; Target Undocumented Mask(MANGLE_CPU_LIBGC)
-
-mno-cond-exec
-Target Undocumented Report RejectNegative Mask(NO_COND_EXEC)
-
-mcpu=
-Target RejectNegative Joined Var(arc_cpu_string) Init("base")
--mcpu=CPU Compile code for ARC variant CPU
-
-mtext=
-Target RejectNegative Joined Var(arc_text_string) Init(ARC_DEFAULT_TEXT_SECTION)
--mtext=SECTION Put functions in SECTION
-
-mdata=
-Target RejectNegative Joined Var(arc_data_string) Init(ARC_DEFAULT_DATA_SECTION)
--mdata=SECTION Put data in SECTION
-
-mrodata=
-Target RejectNegative Joined Var(arc_rodata_string) Init(ARC_DEFAULT_RODATA_SECTION)
--mrodata=SECTION Put read-only data in SECTION
+++ /dev/null
-/* .init/.fini section handling + C++ global constructor/destructor handling.
- This file is based on crtstuff.c, sol2-crti.asm, sol2-crtn.asm.
-
-Copyright (C) 1995, 1997, 1998, 2009 Free Software Foundation, Inc.
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-/* Declare a pointer to void function type. */
-typedef void (*func_ptr) (void);
-
-#ifdef CRT_INIT
-
-/* NOTE: In order to be able to support SVR4 shared libraries, we arrange
- to have one set of symbols { __CTOR_LIST__, __DTOR_LIST__, __CTOR_END__,
- __DTOR_END__ } per root executable and also one set of these symbols
- per shared library. So in any given whole process image, we may have
- multiple definitions of each of these symbols. In order to prevent
- these definitions from conflicting with one another, and in order to
- ensure that the proper lists are used for the initialization/finalization
- of each individual shared library (respectively), we give these symbols
- only internal (i.e. `static') linkage, and we also make it a point to
- refer to only the __CTOR_END__ symbol in crtfini.o and the __DTOR_LIST__
- symbol in crtinit.o, where they are defined. */
-
-static func_ptr __CTOR_LIST__[1] __attribute__ ((section (".ctors")))
- = { (func_ptr) (-1) };
-
-static func_ptr __DTOR_LIST__[1] __attribute__ ((section (".dtors")))
- = { (func_ptr) (-1) };
-
-/* Run all the global destructors on exit from the program. */
-
-/* Some systems place the number of pointers in the first word of the
- table. On SVR4 however, that word is -1. In all cases, the table is
- null-terminated. On SVR4, we start from the beginning of the list and
- invoke each per-compilation-unit destructor routine in order
- until we find that null.
-
- Note that this function MUST be static. There will be one of these
- functions in each root executable and one in each shared library, but
- although they all have the same code, each one is unique in that it
- refers to one particular associated `__DTOR_LIST__' which belongs to the
- same particular root executable or shared library file. */
-
-static void __do_global_dtors (void)
-asm ("__do_global_dtors") __attribute__ ((section (".text")));
-
-static void
-__do_global_dtors (void)
-{
- func_ptr *p;
- for (p = __DTOR_LIST__ + 1; *p; p++)
- (*p) ();
-}
-
-/* .init section start.
- This must appear at the start of the .init section. */
-
-asm ("\n\
- .section .init\n\
- .global init\n\
- .word 0\n\
-init:\n\
- st blink,[sp,4]\n\
- st fp,[sp]\n\
- mov fp,sp\n\
- sub sp,sp,16\n\
-");
-
-/* .fini section start.
- This must appear at the start of the .init section. */
-
-asm ("\n\
- .section .fini\n\
- .global fini\n\
- .word 0\n\
-fini:\n\
- st blink,[sp,4]\n\
- st fp,[sp]\n\
- mov fp,sp\n\
- sub sp,sp,16\n\
- bl.nd __do_global_dtors\n\
-");
-
-#endif /* CRT_INIT */
-
-#ifdef CRT_FINI
-
-/* Put a word containing zero at the end of each of our two lists of function
- addresses. Note that the words defined here go into the .ctors and .dtors
- sections of the crtend.o file, and since that file is always linked in
- last, these words naturally end up at the very ends of the two lists
- contained in these two sections. */
-
-static func_ptr __CTOR_END__[1] __attribute__ ((section (".ctors")))
- = { (func_ptr) 0 };
-
-static func_ptr __DTOR_END__[1] __attribute__ ((section (".dtors")))
- = { (func_ptr) 0 };
-
-/* Run all global constructors for the program.
- Note that they are run in reverse order. */
-
-static void __do_global_ctors (void)
-asm ("__do_global_ctors") __attribute__ ((section (".text")));
-
-static void
-__do_global_ctors (void)
-{
- func_ptr *p;
- for (p = __CTOR_END__ - 1; *p != (func_ptr) -1; p--)
- (*p) ();
-}
-
-/* .init section end.
- This must live at the end of the .init section. */
-
-asm ("\n\
- .section .init\n\
- bl.nd __do_global_ctors\n\
- ld blink,[fp,4]\n\
- j.d blink\n\
- ld.a fp,[sp,16]\n\
-");
-
-/* .fini section end.
- This must live at the end of the .fini section. */
-
-asm ("\n\
- .section .fini\n\
- ld blink,[fp,4]\n\
- j.d blink\n\
- ld.a fp,[sp,16]\n\
-");
-
-#endif /* CRT_FINI */
+++ /dev/null
-; libgcc routines for ARC cpu.
-
-/* Copyright (C) 1995, 1997,2004, 2009 Free Software Foundation, Inc.
-
-This file is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3, or (at your option) any
-later version.
-
-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.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-#ifdef L_mulsi3
- .section .text
- .align 4
-
-#ifdef __base__
- .cpu base
- .global ___mulsi3
-___mulsi3:
-
-/* This the simple version.
-
- while (a)
- {
- if (a & 1)
- r += b;
- a >>= 1;
- b <<= 1;
- }
-*/
- mov r2,0 ; Accumulate result here.
-.Lloop:
- sub.f 0,r0,0 ; while (a)
- nop
- beq.nd .Ldone
- and.f 0,r0,1 ; if (a & 1)
- add.nz r2,r2,r1 ; r += b
- lsr r0,r0 ; a >>= 1
- b.d .Lloop
- lsl r1,r1 ; b <<= 1
-.Ldone:
- j.d blink
- mov r0,r2
-#endif
-
-#endif /* L_mulsi3 */
-
-#ifdef L_umulsidi3
- .section .text
- .align 4
-
-#ifdef __base__
- .cpu base
- .global ___umulsidi3
-___umulsidi3:
-
-/* This the simple version.
-
- while (a)
- {
- if (a & 1)
- r += b;
- a >>= 1;
- b <<= 1;
- }
-*/
- mov r2,0 ; Top part of b.
- mov r3,0 ; Accumulate result here.
- mov r4,0
-.Lloop:
- sub.f 0,r0,0 ; while (a)
- nop
- beq.nd .Ldone
- and.f 0,r0,1 ; if (a & 1)
- sub.f 0,r0,0
- nop
- beq .Ldontadd
- add.f r4,r4,r1 ; r += b
- adc r3,r3,r2
-.Ldontadd:
- lsr r0,r0 ; a >>= 1
- lsl.f r1,r1 ; b <<= 1
- b.d .Lloop
- rlc r2,r2
-.Ldone:
-#ifdef __big_endian__
- mov r1,r4
- j.d blink
- mov r0,r3
-#else
- mov r0,r4
- j.d blink
- mov r1,r3
-#endif
-#endif
-
-#endif /* L_umulsidi3 */
-
-#ifdef L_divmod_tools
-
-; Utilities used by all routines.
-
- .section .text
- .align 4
-
-; inputs: r0 = numerator, r1 = denominator
-; outputs: positive r0/r1,
-; r6.bit1 = sign of numerator, r6.bit0 = sign of result
-
- .global ___divnorm
-___divnorm:
- mov r6,0 ; keep sign in r6
- sub.f 0,r0,0 ; is numerator -ve?
- sub.lt r0,0,r0 ; negate numerator
- mov.lt r6,3 ; sign is -ve
- sub.f 0,r1,0 ; is denominator -ve?
- sub.lt r1,0,r1 ; negate denominator
- xor.lt r6,r6,1 ; toggle sign
- j.nd blink
-
-/*
-unsigned long
-udivmodsi4(int modwanted, unsigned long num, unsigned long den)
-{
- unsigned long bit = 1;
- unsigned long res = 0;
-
- while (den < num && bit && !(den & (1L<<31)))
- {
- den <<=1;
- bit <<=1;
- }
- while (bit)
- {
- if (num >= den)
- {
- num -= den;
- res |= bit;
- }
- bit >>=1;
- den >>=1;
- }
- if (modwanted) return num;
- return res;
-}
-*/
-
-; inputs: r0 = numerator, r1 = denominator
-; outputs: r0 = quotient, r1 = remainder, r2/r3 trashed
-
- .global ___udivmodsi4
-___udivmodsi4:
- mov r2,1 ; bit = 1
- mov r3,0 ; res = 0
-.Lloop1:
- sub.f 0,r1,r0 ; while (den < num
- nop
- bnc.nd .Lloop2
- sub.f 0,r2,0 ; && bit
- nop
- bz.nd .Lloop2
- lsl.f 0,r1 ; && !(den & (1<<31))
- nop
- bc.nd .Lloop2
- lsl r1,r1 ; den <<= 1
- b.d .Lloop1
- lsl r2,r2 ; bit <<= 1
-.Lloop2:
- sub.f 0,r2,0 ; while (bit)
- nop
- bz.nd .Ldivmodend
- sub.f 0,r0,r1 ; if (num >= den)
- nop
- bc.nd .Lshiftdown
- sub r0,r0,r1 ; num -= den
- or r3,r3,r2 ; res |= bit
-.Lshiftdown:
- lsr r2,r2 ; bit >>= 1
- b.d .Lloop2
- lsr r1,r1 ; den >>= 1
-.Ldivmodend:
- mov r1,r0 ; r1 = mod
- j.d blink
- mov r0,r3 ; r0 = res
-
-#endif
-
-#ifdef L_udivsi3
- .section .text
- .align 4
-
-#ifdef __base__
- .cpu base
- .global ___udivsi3
-___udivsi3:
- mov r7,blink
- bl.nd ___udivmodsi4
- j.nd r7
-#endif
-
-#endif /* L_udivsi3 */
-
-#ifdef L_divsi3
- .section .text
- .align 4
-
-#ifdef __base__
- .cpu base
- .global ___divsi3
-___divsi3:
- mov r7,blink
- bl.nd ___divnorm
- bl.nd ___udivmodsi4
- and.f 0,r6,1
- sub.nz r0,0,r0 ; cannot go in delay slot, has limm value
- j.nd r7
-#endif
-
-#endif /* L_divsi3 */
-
-#ifdef L_umodsi3
- .section .text
- .align 4
-
-#ifdef __base__
- .cpu base
- .global ___umodsi3
-___umodsi3:
- mov r7,blink
- bl.nd ___udivmodsi4
- j.d r7
- mov r0,r1
-#endif
-
-#endif /* L_umodsi3 */
-
-#ifdef L_modsi3
- .section .text
- .align 4
-
-#ifdef __base__
- .cpu base
- .global ___modsi3
-___modsi3:
- mov r7,blink
- bl.nd ___divnorm
- bl.nd ___udivmodsi4
- and.f 0,r6,2
- sub.nz r1,0,r1
- j.d r7
- mov r0,r1
-#endif
-
-#endif /* L_modsi3 */
+++ /dev/null
-# Copyright (C) 1997, 1998, 1999, 2001, 2002, 2003,
-# 2004 Free Software Foundation, Inc.
-#
-# This file is part of GCC.
-#
-# GCC is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3, or (at your option)
-# any later version.
-#
-# GCC is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with GCC; see the file COPYING3. If not see
-# <http://www.gnu.org/licenses/>.
-
-LIB1ASMSRC = arc/lib1funcs.asm
-LIB1ASMFUNCS = _mulsi3 _umulsidi3 _udivsi3 _divsi3 _umodsi3 _modsi3 _divmod_tools
-
-# We need libgcc routines to be mangled according to which cpu they
-# were compiled for.
-# ??? -mmangle-cpu passed by default for now.
-#LIBGCC2_CFLAGS = -g1 -O2 $(LIBGCC2_INCLUDES) $(GCC_CFLAGS) -mmangle-cpu
-
-# 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 '#ifndef __big_endian__' > dp-bit.c
- echo '#define FLOAT_BIT_ORDER_MISMATCH' >> dp-bit.c
- echo '#endif' >> 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 '#ifndef __big_endian__' >> fp-bit.c
- echo '#define FLOAT_BIT_ORDER_MISMATCH' >> fp-bit.c
- echo '#endif' >> fp-bit.c
- cat $(srcdir)/config/fp-bit.c >> fp-bit.c
-
-# .init/.fini section routines
-
-$(T)crtinit.o: $(srcdir)/config/arc/initfini.c $(GCC_PASSES) $(CONFIG_H)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(CRTSTUFF_T_CFLAGS) \
- $(MULTILIB_CFLAGS) -DCRT_INIT -finhibit-size-directive -fno-inline-functions \
- -g0 -c $(srcdir)/config/arc/initfini.c -o $(T)crtinit.o
-
-$(T)crtfini.o: $(srcdir)/config/arc/initfini.c $(GCC_PASSES) $(CONFIG_H)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(CRTSTUFF_T_CFLAGS) \
- -DCRT_FINI $(MULTILIB_CFLAGS) -finhibit-size-directive -fno-inline-functions \
- -g0 -c $(srcdir)/config/arc/initfini.c -o $(T)crtfini.o
-
-MULTILIB_OPTIONS = EB
-MULTILIB_DIRNAMES = be
-EXTRA_MULTILIB_PARTS = crtinit.o crtfini.o
+++ /dev/null
-/* NetBSD/arm a.out version.
- Copyright (C) 1993, 1994, 1997, 1998, 2003, 2004, 2005, 2007, 2008, 2010
- Free Software Foundation, Inc.
- Contributed by Mark Brinicombe (amb@physig.ph.kcl.ac.uk)
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
- <http://www.gnu.org/licenses/>. */
-
-/* Run-time Target Specification. */
-#undef TARGET_VERSION
-#define TARGET_VERSION fputs (" (ARM/NetBSD)", stderr);
-
-/* Unsigned chars produces much better code than signed. */
-#define DEFAULT_SIGNED_CHAR 0
-
-/* Since we always use GAS as our assembler we support stabs. */
-#define DBX_DEBUGGING_INFO 1
-
-/*#undef ASM_DECLARE_FUNCTION_NAME*/
-
-/* ARM6 family default cpu. */
-#define SUBTARGET_CPU_DEFAULT TARGET_CPU_arm6
-
-#undef TARGET_DEFAULT
-#define TARGET_DEFAULT (MASK_APCS_FRAME)
-
-/* Some defines for CPP.
- arm32 is the NetBSD port name, so we always define arm32 and __arm32__. */
-#define TARGET_OS_CPP_BUILTINS() \
- do { \
- NETBSD_OS_CPP_BUILTINS_AOUT(); \
- builtin_define_std ("arm32"); \
- builtin_define_std ("unix"); \
- builtin_define_std ("riscbsd"); \
- } while (0)
-
-#undef SUBTARGET_EXTRA_SPECS
-#define SUBTARGET_EXTRA_SPECS \
- { "netbsd_cpp_spec", NETBSD_CPP_SPEC }, \
- { "netbsd_link_spec", NETBSD_LINK_SPEC_AOUT },
-
-#undef CPP_SPEC
-#define CPP_SPEC "\
-%(cpp_cpu_arch) %(cpp_float) %(cpp_endian) %(netbsd_cpp_spec) \
-"
-
-/* Because TARGET_DEFAULT sets MASK_SOFT_FLOAT */
-#undef CPP_FLOAT_DEFAULT_SPEC
-#define CPP_FLOAT_DEFAULT_SPEC "-D__SOFTFP__"
-
-/* Pass -X to the linker so that it will strip symbols starting with 'L' */
-#undef LINK_SPEC
-#define LINK_SPEC "-X %(netbsd_link_spec)"
-
-#undef SIZE_TYPE
-#define SIZE_TYPE "unsigned int"
-
-#undef PTRDIFF_TYPE
-#define PTRDIFF_TYPE "int"
-
-/* We don't have any limit on the length as out debugger is GDB. */
-#undef DBX_CONTIN_LENGTH
-
-/* NetBSD does its profiling differently to the Acorn compiler. We
- don't need a word following the mcount call; and to skip it
- requires either an assembly stub or use of fomit-frame-pointer when
- compiling the profiling functions. Since we break Acorn CC
- compatibility below a little more won't hurt. */
-
-#undef ARM_FUNCTION_PROFILER
-#define ARM_FUNCTION_PROFILER(STREAM,LABELNO) \
-{ \
- fprintf(STREAM, "\tmov\t%sip, %slr\n", REGISTER_PREFIX, REGISTER_PREFIX); \
- fprintf(STREAM, "\tbl\tmcount\n"); \
-}
-
-/* On the ARM `@' introduces a comment, so we must use something else
- for .type directives. */
-#undef TYPE_OPERAND_FMT
-#define TYPE_OPERAND_FMT "%%%s"
-
-/* NetBSD uses the old PCC style aggregate returning conventions. */
-#undef DEFAULT_PCC_STRUCT_RETURN
-#define DEFAULT_PCC_STRUCT_RETURN 1
-
-/* Although not normally relevant (since by default, all aggregates
- are returned in memory) compiling some parts of libc requires
- non-APCS style struct returns. */
-#undef TARGET_RETURN_IN_MEMORY
-
-/* VERY BIG NOTE : Change of structure alignment for RiscBSD.
- There are consequences you should be aware of...
-
- Normally GCC/arm uses a structure alignment of 32 for compatibility
- with armcc. This means that structures are padded to a word
- boundary. However this causes problems with bugged NetBSD kernel
- code (possibly userland code as well - I have not checked every
- binary). The nature of this bugged code is to rely on sizeof()
- returning the correct size of various structures rounded to the
- nearest byte (SCSI and ether code are two examples, the vm system
- is another). This code breaks when the structure alignment is 32
- as sizeof() will report a word=rounded size. By changing the
- structure alignment to 8. GCC will conform to what is expected by
- NetBSD.
-
- This has several side effects that should be considered.
- 1. Structures will only be aligned to the size of the largest member.
- i.e. structures containing only bytes will be byte aligned.
- structures containing shorts will be half word aligned.
- structures containing ints will be word aligned.
-
- This means structures should be padded to a word boundary if
- alignment of 32 is required for byte structures etc.
-
- 2. A potential performance penalty may exist if strings are no longer
- word aligned. GCC will not be able to use word load/stores to copy
- short strings.
-
- This modification is not encouraged but with the present state of the
- NetBSD source tree it is currently the only solution that meets the
- requirements. */
-#undef DEFAULT_STRUCTURE_SIZE_BOUNDARY
-#define DEFAULT_STRUCTURE_SIZE_BOUNDARY 8
-
-/* Clear the instruction cache from `BEG' to `END'. This makes a
- call to the ARM32_SYNC_ICACHE architecture specific syscall. */
-#define CLEAR_INSN_CACHE(BEG, END) \
-{ \
- extern int sysarch(int number, void *args); \
- struct { \
- unsigned int addr; \
- int len; \
- } s; \
- s.addr = (unsigned int)(BEG); \
- s.len = (END) - (BEG); \
- (void)sysarch(0, &s); \
-}
+++ /dev/null
-# Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006, 2008, 2009,
-# 2010
-# Free Software Foundation, Inc.
-#
-# This file is part of GCC.
-#
-# GCC is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3, or (at your option)
-# any later version.
-#
-# GCC is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with GCC; see the file COPYING3. If not see
-# <http://www.gnu.org/licenses/>.
-
-LIB1ASMFUNCS += _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _call_via_rX _interwork_call_via_rX _clzsi2 _clzdi2
-
-# 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
-
-fp-bit.c: $(srcdir)/config/fp-bit.c
- echo '#define FLOAT' > fp-bit.c
- echo '#ifndef __ARMEB__' >> fp-bit.c
- echo '#define FLOAT_BIT_ORDER_MISMATCH' >> fp-bit.c
- echo '#endif' >> fp-bit.c
- cat $(srcdir)/config/fp-bit.c >> fp-bit.c
-
-dp-bit.c: $(srcdir)/config/fp-bit.c
- echo '#ifndef __ARMEB__' > dp-bit.c
- echo '#define FLOAT_BIT_ORDER_MISMATCH' >> dp-bit.c
- echo '#define FLOAT_WORD_ORDER_MISMATCH' >> dp-bit.c
- echo '#endif' >> dp-bit.c
- cat $(srcdir)/config/fp-bit.c >> dp-bit.c
-
-pe.o: $(srcdir)/config/arm/pe.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(RTL_H) output.h flags.h $(TREE_H) expr.h $(TM_P_H)
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
- $(srcdir)/config/arm/pe.c
-
-MULTILIB_OPTIONS = mhard-float mthumb
-MULTILIB_DIRNAMES = fpu thumb
-
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
-TARGET_LIBGCC2_CFLAGS =
+++ /dev/null
-/* Prototypes for exported functions defined in crx.c
- Copyright (C) 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
- 2002, 2003, 2004, 2007, 2010 Free Software Foundation, Inc.
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
- <http://www.gnu.org/licenses/>. */
-
-#ifndef GCC_CRX_PROTOS_H
-#define GCC_CRX_PROTOS_H
-
-
-/* Register usage. */
-extern enum reg_class crx_regno_reg_class (int);
-extern int crx_hard_regno_mode_ok (int regno, enum machine_mode);
-#ifdef RTX_CODE
-extern enum reg_class crx_secondary_reload_class (enum reg_class, enum machine_mode, rtx);
-#endif /* RTX_CODE */
-
-/* Passing function arguments. */
-extern int crx_function_arg_regno_p (int);
-#ifdef TREE_CODE
-#ifdef RTX_CODE
-extern void crx_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx);
-#endif /* RTX_CODE */
-#endif /* TREE_CODE */
-
-#ifdef RTX_CODE
-/* Addressing Modes. */
-struct crx_address
-{
- rtx base, index, disp, side_effect;
- int scale;
-};
-
-enum crx_addrtype
-{
- CRX_INVALID, CRX_REG_REL, CRX_POST_INC, CRX_SCALED_INDX, CRX_ABSOLUTE
-};
-
-extern enum crx_addrtype crx_decompose_address (rtx addr, struct crx_address *out);
-
-extern int crx_const_double_ok (rtx op);
-
-/* Instruction output. */
-extern void crx_print_operand (FILE *, rtx, int);
-extern void crx_print_operand_address (FILE *, rtx);
-
-/* Misc functions called from crx.md. */
-extern void crx_expand_movmem_single (rtx, rtx, rtx, rtx, rtx, unsigned HOST_WIDE_INT *);
-extern int crx_expand_movmem (rtx, rtx, rtx, rtx);
-#endif /* RTX_CODE */
-
-/* Routines to compute costs. */
-extern int crx_memory_move_cost (enum machine_mode, enum reg_class, int);
-
-/* Prologue/Epilogue functions. */
-extern int crx_initial_elimination_offset (int, int);
-extern char *crx_prepare_push_pop_string (int);
-extern void crx_expand_prologue (void);
-extern void crx_expand_epilogue (void);
-
-
-/* Handling the "interrupt" attribute */
-extern int crx_interrupt_function_p (void);
-
-#endif /* GCC_CRX_PROTOS_H */
+++ /dev/null
-/* Output routines for GCC for CRX.
- Copyright (C) 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
- 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
- Free Software Foundation, Inc.
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
- <http://www.gnu.org/licenses/>. */
-
-/*****************************************************************************/
-/* HEADER INCLUDES */
-/*****************************************************************************/
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "tm.h"
-#include "rtl.h"
-#include "tree.h"
-#include "tm_p.h"
-#include "regs.h"
-#include "hard-reg-set.h"
-#include "insn-config.h"
-#include "conditions.h"
-#include "output.h"
-#include "insn-codes.h"
-#include "insn-attr.h"
-#include "flags.h"
-#include "except.h"
-#include "function.h"
-#include "recog.h"
-#include "expr.h"
-#include "optabs.h"
-#include "diagnostic-core.h"
-#include "basic-block.h"
-#include "df.h"
-#include "target.h"
-#include "target-def.h"
-
-/*****************************************************************************/
-/* DEFINITIONS */
-/*****************************************************************************/
-
-/* Maximum number of register used for passing parameters. */
-#define MAX_REG_FOR_PASSING_ARGS 6
-
-/* Minimum number register used for passing parameters. */
-#define MIN_REG_FOR_PASSING_ARGS 2
-
-/* The maximum count of words supported in the assembly of the architecture in
- * a push/pop instruction. */
-#define MAX_COUNT 8
-
-/* Predicate is true if the current function is a 'noreturn' function, i.e. it
- * is qualified as volatile. */
-#define FUNC_IS_NORETURN_P(decl) (TREE_THIS_VOLATILE (decl))
-
-/* The following macros are used in crx_decompose_address () */
-
-/* Returns the factor of a scaled index address or -1 if invalid. */
-#define SCALE_FOR_INDEX_P(X) \
- (GET_CODE (X) == CONST_INT ? \
- (INTVAL (X) == 1 ? 1 : \
- INTVAL (X) == 2 ? 2 : \
- INTVAL (X) == 4 ? 4 : \
- INTVAL (X) == 8 ? 8 : \
- -1) : \
- -1)
-
-/* Nonzero if the rtx X is a signed const int of n bits */
-#define RTX_SIGNED_INT_FITS_N_BITS(X,n) \
- ((GET_CODE (X) == CONST_INT \
- && SIGNED_INT_FITS_N_BITS (INTVAL (X), n)) ? 1 : 0)
-
-/* Nonzero if the rtx X is an unsigned const int of n bits. */
-#define RTX_UNSIGNED_INT_FITS_N_BITS(X, n) \
- ((GET_CODE (X) == CONST_INT \
- && UNSIGNED_INT_FITS_N_BITS (INTVAL (X), n)) ? 1 : 0)
-
-/*****************************************************************************/
-/* STATIC VARIABLES */
-/*****************************************************************************/
-
-/* Nonzero if the last param processed is passed in a register. */
-static int last_parm_in_reg;
-
-/* Will hold the number of the last register the prologue saves, -1 if no
- * register is saved. */
-static int last_reg_to_save;
-
-/* Each object in the array is a register number. Mark 1 for registers that
- * need to be saved. */
-static int save_regs[FIRST_PSEUDO_REGISTER];
-
-/* Number of bytes saved on the stack for non-scratch registers */
-static int sum_regs = 0;
-
-/* Number of bytes saved on the stack for local variables. */
-static int local_vars_size;
-
-/* The sum of 2 sizes: locals vars and padding byte for saving the registers.
- * Used in expand_prologue () and expand_epilogue (). */
-static int size_for_adjusting_sp;
-
-/* In case of a POST_INC or POST_DEC memory reference, we must report the mode
- * of the memory reference from PRINT_OPERAND to PRINT_OPERAND_ADDRESS. */
-static enum machine_mode output_memory_reference_mode;
-
-/*****************************************************************************/
-/* TARGETM FUNCTION PROTOTYPES */
-/*****************************************************************************/
-
-static bool crx_fixed_condition_code_regs (unsigned int *, unsigned int *);
-static rtx crx_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
- int incoming ATTRIBUTE_UNUSED);
-static bool crx_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED);
-static int crx_address_cost (rtx, bool);
-static bool crx_legitimate_address_p (enum machine_mode, rtx, bool);
-static bool crx_can_eliminate (const int, const int);
-static rtx crx_function_arg (CUMULATIVE_ARGS *, enum machine_mode,
- const_tree, bool);
-static void crx_function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode,
- const_tree, bool);
-
-/*****************************************************************************/
-/* RTL VALIDITY */
-/*****************************************************************************/
-
-#undef TARGET_LEGITIMATE_ADDRESS_P
-#define TARGET_LEGITIMATE_ADDRESS_P crx_legitimate_address_p
-
-#undef TARGET_CAN_ELIMINATE
-#define TARGET_CAN_ELIMINATE crx_can_eliminate
-
-/*****************************************************************************/
-/* STACK LAYOUT AND CALLING CONVENTIONS */
-/*****************************************************************************/
-
-#undef TARGET_FIXED_CONDITION_CODE_REGS
-#define TARGET_FIXED_CONDITION_CODE_REGS crx_fixed_condition_code_regs
-
-#undef TARGET_STRUCT_VALUE_RTX
-#define TARGET_STRUCT_VALUE_RTX crx_struct_value_rtx
-
-#undef TARGET_RETURN_IN_MEMORY
-#define TARGET_RETURN_IN_MEMORY crx_return_in_memory
-
-/*****************************************************************************/
-/* PASSING FUNCTION ARGUMENTS */
-/*****************************************************************************/
-
-#undef TARGET_FUNCTION_ARG
-#define TARGET_FUNCTION_ARG crx_function_arg
-
-#undef TARGET_FUNCTION_ARG_ADVANCE
-#define TARGET_FUNCTION_ARG_ADVANCE crx_function_arg_advance
-
-/*****************************************************************************/
-/* RELATIVE COSTS OF OPERATIONS */
-/*****************************************************************************/
-
-#undef TARGET_ADDRESS_COST
-#define TARGET_ADDRESS_COST crx_address_cost
-
-/*****************************************************************************/
-/* TARGET-SPECIFIC USES OF `__attribute__' */
-/*****************************************************************************/
-
-#undef TARGET_ATTRIBUTE_TABLE
-#define TARGET_ATTRIBUTE_TABLE crx_attribute_table
-
-static const struct attribute_spec crx_attribute_table[] = {
- /* ISRs have special prologue and epilogue requirements. */
- {"interrupt", 0, 0, false, true, true, NULL, false},
- {NULL, 0, 0, false, false, false, NULL, false}
-};
-
-/* Option handling. */
-
-#undef TARGET_OPTION_OPTIMIZATION_TABLE
-#define TARGET_OPTION_OPTIMIZATION_TABLE crx_option_optimization_table
-
-static const struct default_options crx_option_optimization_table[] =
- {
- /* Put each function in its own section so that PAGE-instruction
- relaxation can do its best. */
- { OPT_LEVELS_1_PLUS, OPT_ffunction_sections, NULL, 1 },
- { OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1 },
- { OPT_LEVELS_NONE, 0, NULL, 0 }
- };
-
-/* Initialize 'targetm' variable which contains pointers to functions and data
- * relating to the target machine. */
-
-struct gcc_target targetm = TARGET_INITIALIZER;
-
-
-/*****************************************************************************/
-/* TARGET HOOK IMPLEMENTATIONS */
-/*****************************************************************************/
-
-/* Return the fixed registers used for condition codes. */
-
-static bool
-crx_fixed_condition_code_regs (unsigned int *p1, unsigned int *p2)
-{
- *p1 = CC_REGNUM;
- *p2 = INVALID_REGNUM;
- return true;
-}
-
-/* Implements hook TARGET_STRUCT_VALUE_RTX. */
-
-static rtx
-crx_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
- int incoming ATTRIBUTE_UNUSED)
-{
- return gen_rtx_REG (Pmode, CRX_STRUCT_VALUE_REGNUM);
-}
-
-/* Implements hook TARGET_RETURN_IN_MEMORY. */
-
-static bool
-crx_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
-{
- if (TYPE_MODE (type) == BLKmode)
- {
- HOST_WIDE_INT size = int_size_in_bytes (type);
- return (size == -1 || size > 8);
- }
- else
- return false;
-}
-
-
-/*****************************************************************************/
-/* MACRO IMPLEMENTATIONS */
-/*****************************************************************************/
-
-/* STACK LAYOUT AND CALLING CONVENTIONS ROUTINES */
-/* --------------------------------------------- */
-
-/* Return nonzero if the current function being compiled is an interrupt
- * function as specified by the "interrupt" attribute. */
-
-int
-crx_interrupt_function_p (void)
-{
- tree attributes;
-
- attributes = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
- return lookup_attribute ("interrupt", attributes) != NULL_TREE;
-}
-
-/* Compute values for the array save_regs and the variable sum_regs. The index
- * of save_regs is numbers of register, each will get 1 if we need to save it
- * in the current function, 0 if not. sum_regs is the total sum of the
- * registers being saved. */
-
-static void
-crx_compute_save_regs (void)
-{
- unsigned int regno;
-
- /* initialize here so in case the function is no-return it will be -1. */
- last_reg_to_save = -1;
-
- /* No need to save any registers if the function never returns. */
- if (FUNC_IS_NORETURN_P (current_function_decl))
- return;
-
- /* Initialize the number of bytes to be saved. */
- sum_regs = 0;
-
- for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
- {
- if (fixed_regs[regno])
- {
- save_regs[regno] = 0;
- continue;
- }
-
- /* If this reg is used and not call-used (except RA), save it. */
- if (crx_interrupt_function_p ())
- {
- if (!current_function_is_leaf && call_used_regs[regno])
- /* this is a volatile reg in a non-leaf interrupt routine - save it
- * for the sake of its sons. */
- save_regs[regno] = 1;
-
- else if (df_regs_ever_live_p (regno))
- /* This reg is used - save it. */
- save_regs[regno] = 1;
- else
- /* This reg is not used, and is not a volatile - don't save. */
- save_regs[regno] = 0;
- }
- else
- {
- /* If this reg is used and not call-used (except RA), save it. */
- if (df_regs_ever_live_p (regno)
- && (!call_used_regs[regno] || regno == RETURN_ADDRESS_REGNUM))
- save_regs[regno] = 1;
- else
- save_regs[regno] = 0;
- }
- }
-
- for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
- if (save_regs[regno] == 1)
- {
- last_reg_to_save = regno;
- sum_regs += UNITS_PER_WORD;
- }
-}
-
-/* Compute the size of the local area and the size to be adjusted by the
- * prologue and epilogue. */
-
-static void
-crx_compute_frame (void)
-{
- /* For aligning the local variables. */
- int stack_alignment = STACK_BOUNDARY / BITS_PER_UNIT;
- int padding_locals;
-
- /* Padding needed for each element of the frame. */
- local_vars_size = get_frame_size ();
-
- /* Align to the stack alignment. */
- padding_locals = local_vars_size % stack_alignment;
- if (padding_locals)
- padding_locals = stack_alignment - padding_locals;
-
- local_vars_size += padding_locals;
-
- size_for_adjusting_sp = local_vars_size + (ACCUMULATE_OUTGOING_ARGS ?
- crtl->outgoing_args_size : 0);
-}
-
-/* Worker function for TARGET_CAN_ELIMINATE. */
-
-bool
-crx_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
-{
- return (to == STACK_POINTER_REGNUM ? ! frame_pointer_needed : true);
-}
-
-/* Implements the macro INITIAL_ELIMINATION_OFFSET, return the OFFSET. */
-
-int
-crx_initial_elimination_offset (int from, int to)
-{
- /* Compute this since we need to use sum_regs. */
- crx_compute_save_regs ();
-
- /* Compute this since we need to use local_vars_size. */
- crx_compute_frame ();
-
- if ((from) == FRAME_POINTER_REGNUM && (to) == STACK_POINTER_REGNUM)
- return (ACCUMULATE_OUTGOING_ARGS ?
- crtl->outgoing_args_size : 0);
- else if ((from) == ARG_POINTER_REGNUM && (to) == FRAME_POINTER_REGNUM)
- return (sum_regs + local_vars_size);
- else if ((from) == ARG_POINTER_REGNUM && (to) == STACK_POINTER_REGNUM)
- return (sum_regs + local_vars_size +
- (ACCUMULATE_OUTGOING_ARGS ?
- crtl->outgoing_args_size : 0));
- else
- abort ();
-}
-
-/* REGISTER USAGE */
-/* -------------- */
-
-/* Return the class number of the smallest class containing reg number REGNO.
- * This could be a conditional expression or could index an array. */
-
-enum reg_class
-crx_regno_reg_class (int regno)
-{
- if (regno >= 0 && regno < SP_REGNUM)
- return NOSP_REGS;
-
- if (regno == SP_REGNUM)
- return GENERAL_REGS;
-
- if (regno == LO_REGNUM)
- return LO_REGS;
- if (regno == HI_REGNUM)
- return HI_REGS;
-
- return NO_REGS;
-}
-
-/* Transfer between HILO_REGS and memory via secondary reloading. */
-
-enum reg_class
-crx_secondary_reload_class (enum reg_class rclass,
- enum machine_mode mode ATTRIBUTE_UNUSED,
- rtx x ATTRIBUTE_UNUSED)
-{
- if (reg_classes_intersect_p (rclass, HILO_REGS)
- && true_regnum (x) == -1)
- return GENERAL_REGS;
-
- return NO_REGS;
-}
-
-/* Return 1 if hard register REGNO can hold a value of machine-mode MODE. */
-
-int
-crx_hard_regno_mode_ok (int regno, enum machine_mode mode)
-{
- /* CC can only hold CCmode values. */
- if (regno == CC_REGNUM)
- return GET_MODE_CLASS (mode) == MODE_CC;
- if (GET_MODE_CLASS (mode) == MODE_CC)
- return 0;
- /* HILO registers can only hold SImode and DImode */
- if (HILO_REGNO_P (regno))
- return mode == SImode || mode == DImode;
- return 1;
-}
-
-/* PASSING FUNCTION ARGUMENTS */
-/* -------------------------- */
-
-/* If enough param regs are available for passing the param of type TYPE return
- * the number of registers needed else 0. */
-
-static int
-enough_regs_for_param (CUMULATIVE_ARGS * cum, const_tree type,
- enum machine_mode mode)
-{
- int type_size;
- int remaining_size;
-
- if (mode != BLKmode)
- type_size = GET_MODE_BITSIZE (mode);
- else
- type_size = int_size_in_bytes (type) * BITS_PER_UNIT;
-
- remaining_size =
- BITS_PER_WORD * (MAX_REG_FOR_PASSING_ARGS -
- (MIN_REG_FOR_PASSING_ARGS + cum->ints) + 1);
-
- /* Any variable which is too big to pass in two registers, will pass on
- * stack. */
- if ((remaining_size >= type_size) && (type_size <= 2 * BITS_PER_WORD))
- return (type_size + BITS_PER_WORD - 1) / BITS_PER_WORD;
-
- return 0;
-}
-
-/* Implements TARGET_FUNCTION_ARG. */
-
-static rtx
-crx_function_arg (CUMULATIVE_ARGS * cum, enum machine_mode mode,
- const_tree type, bool named ATTRIBUTE_UNUSED)
-{
- last_parm_in_reg = 0;
-
- /* Function_arg () is called with this type just after all the args have had
- * their registers assigned. The rtx that function_arg returns from this type
- * is supposed to pass to 'gen_call' but currently it is not implemented (see
- * macro GEN_CALL). */
- if (type == void_type_node)
- return NULL_RTX;
-
- if (targetm.calls.must_pass_in_stack (mode, type) || (cum->ints < 0))
- return NULL_RTX;
-
- if (mode == BLKmode)
- {
- /* Enable structures that need padding bytes at the end to pass to a
- * function in registers. */
- if (enough_regs_for_param (cum, type, mode) != 0)
- {
- last_parm_in_reg = 1;
- return gen_rtx_REG (mode, MIN_REG_FOR_PASSING_ARGS + cum->ints);
- }
- }
-
- if (MIN_REG_FOR_PASSING_ARGS + cum->ints > MAX_REG_FOR_PASSING_ARGS)
- return NULL_RTX;
- else
- {
- if (enough_regs_for_param (cum, type, mode) != 0)
- {
- last_parm_in_reg = 1;
- return gen_rtx_REG (mode, MIN_REG_FOR_PASSING_ARGS + cum->ints);
- }
- }
-
- return NULL_RTX;
-}
-
-/* Implements the macro INIT_CUMULATIVE_ARGS defined in crx.h. */
-
-void
-crx_init_cumulative_args (CUMULATIVE_ARGS * cum, tree fntype,
- rtx libfunc ATTRIBUTE_UNUSED)
-{
- tree param, next_param;
-
- cum->ints = 0;
-
- /* Determine if this function has variable arguments. This is indicated by
- * the last argument being 'void_type_mode' if there are no variable
- * arguments. Change here for a different vararg. */
- for (param = (fntype) ? TYPE_ARG_TYPES (fntype) : 0;
- param != (tree) 0; param = next_param)
- {
- next_param = TREE_CHAIN (param);
- if (next_param == (tree) 0 && TREE_VALUE (param) != void_type_node)
- {
- cum->ints = -1;
- return;
- }
- }
-}
-
-/* Implements TARGET_FUNCTION_ARG_ADVANCE. */
-
-static void
-crx_function_arg_advance (CUMULATIVE_ARGS * cum, enum machine_mode mode,
- const_tree type, bool named ATTRIBUTE_UNUSED)
-{
- /* l holds the number of registers required */
- int l = GET_MODE_BITSIZE (mode) / BITS_PER_WORD;
-
- /* If the parameter isn't passed on a register don't advance cum. */
- if (!last_parm_in_reg)
- return;
-
- if (targetm.calls.must_pass_in_stack (mode, type) || (cum->ints < 0))
- return;
-
- if (mode == SImode || mode == HImode || mode == QImode || mode == DImode)
- {
- if (l <= 1)
- cum->ints += 1;
- else
- cum->ints += l;
- }
- else if (mode == SFmode || mode == DFmode)
- cum->ints += l;
- else if ((mode) == BLKmode)
- {
- if ((l = enough_regs_for_param (cum, type, mode)) != 0)
- cum->ints += l;
- }
-
-}
-
-/* Implements the macro FUNCTION_ARG_REGNO_P defined in crx.h. Return nonzero
- * if N is a register used for passing parameters. */
-
-int
-crx_function_arg_regno_p (int n)
-{
- return (n <= MAX_REG_FOR_PASSING_ARGS && n >= MIN_REG_FOR_PASSING_ARGS);
-}
-
-/* ADDRESSING MODES */
-/* ---------------- */
-
-/* Implements the hook for TARGET_LEGITIMATE_ADDRESS_P defined in crx.h.
- * The following addressing modes are supported on CRX:
- *
- * Relocations --> const | symbol_ref | label_ref
- * Absolute address --> 32-bit absolute
- * Post increment --> reg + 12-bit disp.
- * Post modify --> reg + 12-bit disp.
- * Register relative --> reg | 32-bit disp. + reg | 4 bit + reg
- * Scaled index --> reg + reg | 22-bit disp. + reg + reg |
- * 22-disp. + reg + reg + (2 | 4 | 8) */
-
-static rtx
-crx_addr_reg (rtx addr_reg)
-{
- if (GET_MODE (addr_reg) != Pmode)
- return NULL_RTX;
-
- if (REG_P (addr_reg))
- return addr_reg;
- else if (GET_CODE (addr_reg) == SUBREG
- && REG_P (SUBREG_REG (addr_reg))
- && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (addr_reg)))
- <= UNITS_PER_WORD))
- return SUBREG_REG (addr_reg);
- else
- return NULL_RTX;
-}
-
-enum crx_addrtype
-crx_decompose_address (rtx addr, struct crx_address *out)
-{
- rtx base = NULL_RTX, index = NULL_RTX, disp = NULL_RTX;
- rtx scale_rtx = NULL_RTX, side_effect = NULL_RTX;
- int scale = -1;
-
- enum crx_addrtype retval = CRX_INVALID;
-
- switch (GET_CODE (addr))
- {
- case CONST_INT:
- /* Absolute address (known at compile time) */
- retval = CRX_ABSOLUTE;
- disp = addr;
- if (!UNSIGNED_INT_FITS_N_BITS (INTVAL (disp), GET_MODE_BITSIZE (Pmode)))
- return CRX_INVALID;
- break;
-
- case CONST:
- case SYMBOL_REF:
- case LABEL_REF:
- /* Absolute address (known at link time) */
- retval = CRX_ABSOLUTE;
- disp = addr;
- break;
-
- case REG:
- case SUBREG:
- /* Register relative address */
- retval = CRX_REG_REL;
- base = addr;
- break;
-
- case PLUS:
- switch (GET_CODE (XEXP (addr, 0)))
- {
- case REG:
- case SUBREG:
- if (REG_P (XEXP (addr, 1)))
- {
- /* Scaled index with scale = 1 and disp. = 0 */
- retval = CRX_SCALED_INDX;
- base = XEXP (addr, 1);
- index = XEXP (addr, 0);
- scale = 1;
- }
- else if (RTX_SIGNED_INT_FITS_N_BITS (XEXP (addr, 1), 28))
- {
- /* Register relative address and <= 28-bit disp. */
- retval = CRX_REG_REL;
- base = XEXP (addr, 0);
- disp = XEXP (addr, 1);
- }
- else
- return CRX_INVALID;
- break;
-
- case PLUS:
- /* Scaled index and <= 22-bit disp. */
- retval = CRX_SCALED_INDX;
- base = XEXP (XEXP (addr, 0), 1);
- disp = XEXP (addr, 1);
- if (!RTX_SIGNED_INT_FITS_N_BITS (disp, 22))
- return CRX_INVALID;
- switch (GET_CODE (XEXP (XEXP (addr, 0), 0)))
- {
- case REG:
- /* Scaled index with scale = 0 and <= 22-bit disp. */
- index = XEXP (XEXP (addr, 0), 0);
- scale = 1;
- break;
-
- case MULT:
- /* Scaled index with scale >= 0 and <= 22-bit disp. */
- index = XEXP (XEXP (XEXP (addr, 0), 0), 0);
- scale_rtx = XEXP (XEXP (XEXP (addr, 0), 0), 1);
- if ((scale = SCALE_FOR_INDEX_P (scale_rtx)) == -1)
- return CRX_INVALID;
- break;
-
- default:
- return CRX_INVALID;
- }
- break;
-
- case MULT:
- /* Scaled index with scale >= 0 */
- retval = CRX_SCALED_INDX;
- base = XEXP (addr, 1);
- index = XEXP (XEXP (addr, 0), 0);
- scale_rtx = XEXP (XEXP (addr, 0), 1);
- /* Scaled index with scale >= 0 and <= 22-bit disp. */
- if ((scale = SCALE_FOR_INDEX_P (scale_rtx)) == -1)
- return CRX_INVALID;
- break;
-
- default:
- return CRX_INVALID;
- }
- break;
-
- case POST_INC:
- case POST_DEC:
- /* Simple post-increment */
- retval = CRX_POST_INC;
- base = XEXP (addr, 0);
- side_effect = addr;
- break;
-
- case POST_MODIFY:
- /* Generic post-increment with <= 12-bit disp. */
- retval = CRX_POST_INC;
- base = XEXP (addr, 0);
- side_effect = XEXP (addr, 1);
- if (base != XEXP (side_effect, 0))
- return CRX_INVALID;
- switch (GET_CODE (side_effect))
- {
- case PLUS:
- case MINUS:
- disp = XEXP (side_effect, 1);
- if (!RTX_SIGNED_INT_FITS_N_BITS (disp, 12))
- return CRX_INVALID;
- break;
-
- default:
- /* CRX only supports PLUS and MINUS */
- return CRX_INVALID;
- }
- break;
-
- default:
- return CRX_INVALID;
- }
-
- if (base)
- {
- base = crx_addr_reg (base);
- if (!base)
- return CRX_INVALID;
- }
- if (index)
- {
- index = crx_addr_reg (index);
- if (!index)
- return CRX_INVALID;
- }
-
- out->base = base;
- out->index = index;
- out->disp = disp;
- out->scale = scale;
- out->side_effect = side_effect;
-
- return retval;
-}
-
-bool
-crx_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
- rtx addr, bool strict)
-{
- enum crx_addrtype addrtype;
- struct crx_address address;
-
- if (TARGET_DEBUG_ADDR)
- {
- fprintf (stderr,
- "\n======\nGO_IF_LEGITIMATE_ADDRESS, mode = %s, strict = %d\n",
- GET_MODE_NAME (mode), strict);
- debug_rtx (addr);
- }
-
- addrtype = crx_decompose_address (addr, &address);
-
- if (addrtype == CRX_POST_INC && GET_MODE_SIZE (mode) > UNITS_PER_WORD)
- return FALSE;
-
- if (TARGET_DEBUG_ADDR)
- {
- const char *typestr;
- switch (addrtype)
- {
- case CRX_INVALID:
- typestr = "Invalid";
- break;
- case CRX_REG_REL:
- typestr = "Register relative";
- break;
- case CRX_POST_INC:
- typestr = "Post-increment";
- break;
- case CRX_SCALED_INDX:
- typestr = "Scaled index";
- break;
- case CRX_ABSOLUTE:
- typestr = "Absolute";
- break;
- default:
- abort ();
- }
- fprintf (stderr, "CRX Address type: %s\n", typestr);
- }
-
- if (addrtype == CRX_INVALID)
- return FALSE;
-
- if (strict)
- {
- if (address.base && !REGNO_OK_FOR_BASE_P (REGNO (address.base)))
- {
- if (TARGET_DEBUG_ADDR)
- fprintf (stderr, "Base register not strict\n");
- return FALSE;
- }
- if (address.index && !REGNO_OK_FOR_INDEX_P (REGNO (address.index)))
- {
- if (TARGET_DEBUG_ADDR)
- fprintf (stderr, "Index register not strict\n");
- return FALSE;
- }
- }
-
- return TRUE;
-}
-
-/* ROUTINES TO COMPUTE COSTS */
-/* ------------------------- */
-
-/* Return cost of the memory address x. */
-
-static int
-crx_address_cost (rtx addr, bool speed ATTRIBUTE_UNUSED)
-{
- enum crx_addrtype addrtype;
- struct crx_address address;
-
- int cost = 2;
-
- addrtype = crx_decompose_address (addr, &address);
-
- gcc_assert (addrtype != CRX_INVALID);
-
- /* An absolute address causes a 3-word instruction */
- if (addrtype == CRX_ABSOLUTE)
- cost+=2;
-
- /* Post-modifying addresses are more powerful. */
- if (addrtype == CRX_POST_INC)
- cost-=2;
-
- /* Attempt to minimize number of registers in the address. */
- if (address.base)
- cost++;
-
- if (address.index && address.scale == 1)
- cost+=5;
-
- if (address.disp && !INT_CST4 (INTVAL (address.disp)))
- cost+=2;
-
- if (TARGET_DEBUG_ADDR)
- {
- fprintf (stderr, "\n======\nTARGET_ADDRESS_COST = %d\n", cost);
- debug_rtx (addr);
- }
-
- return cost;
-}
-
-/* Return the cost of moving data of mode MODE between a register of class
- * RCLASS and memory; IN is zero if the value is to be written to memory,
- * nonzero if it is to be read in. This cost is relative to those in
- * REGISTER_MOVE_COST. */
-
-int
-crx_memory_move_cost (enum machine_mode mode,
- enum reg_class rclass ATTRIBUTE_UNUSED,
- int in ATTRIBUTE_UNUSED)
-{
- /* One LD or ST takes twice the time of a simple reg-reg move */
- if (reg_classes_intersect_p (rclass, GENERAL_REGS))
- {
- /* printf ("GENERAL_REGS LD/ST = %d\n", 4 * HARD_REGNO_NREGS (0, mode));*/
- return 4 * HARD_REGNO_NREGS (0, mode);
- }
- else if (reg_classes_intersect_p (rclass, HILO_REGS))
- {
- /* HILO to memory and vice versa */
- /* printf ("HILO_REGS %s = %d\n", in ? "LD" : "ST",
- (REGISTER_MOVE_COST (mode,
- in ? GENERAL_REGS : HILO_REGS,
- in ? HILO_REGS : GENERAL_REGS) + 4)
- * HARD_REGNO_NREGS (0, mode)); */
- return (REGISTER_MOVE_COST (mode,
- in ? GENERAL_REGS : HILO_REGS,
- in ? HILO_REGS : GENERAL_REGS) + 4)
- * HARD_REGNO_NREGS (0, mode);
- }
- else /* default (like in i386) */
- {
- /* printf ("ANYREGS = 100\n"); */
- return 100;
- }
-}
-
-/* INSTRUCTION OUTPUT */
-/* ------------------ */
-
-/* Check if a const_double is ok for crx store-immediate instructions */
-
-int
-crx_const_double_ok (rtx op)
-{
- if (GET_MODE (op) == DFmode)
- {
- REAL_VALUE_TYPE r;
- long l[2];
- REAL_VALUE_FROM_CONST_DOUBLE (r, op);
- REAL_VALUE_TO_TARGET_DOUBLE (r, l);
- return (UNSIGNED_INT_FITS_N_BITS (l[0], 4) &&
- UNSIGNED_INT_FITS_N_BITS (l[1], 4)) ? 1 : 0;
- }
-
- if (GET_MODE (op) == SFmode)
- {
- REAL_VALUE_TYPE r;
- long l;
- REAL_VALUE_FROM_CONST_DOUBLE (r, op);
- REAL_VALUE_TO_TARGET_SINGLE (r, l);
- return UNSIGNED_INT_FITS_N_BITS (l, 4) ? 1 : 0;
- }
-
- return (UNSIGNED_INT_FITS_N_BITS (CONST_DOUBLE_LOW (op), 4) &&
- UNSIGNED_INT_FITS_N_BITS (CONST_DOUBLE_HIGH (op), 4)) ? 1 : 0;
-}
-
-/* Implements the macro PRINT_OPERAND defined in crx.h. */
-
-void
-crx_print_operand (FILE * file, rtx x, int code)
-{
- switch (code)
- {
- case 'p' :
- if (GET_CODE (x) == REG) {
- if (GET_MODE (x) == DImode || GET_MODE (x) == DFmode)
- {
- int regno = REGNO (x);
- if (regno + 1 >= SP_REGNUM) abort ();
- fprintf (file, "{%s, %s}", reg_names[regno], reg_names[regno + 1]);
- return;
- }
- else
- {
- if (REGNO (x) >= SP_REGNUM) abort ();
- fprintf (file, "%s", reg_names[REGNO (x)]);
- return;
- }
- }
-
- case 'd' :
- {
- const char *crx_cmp_str;
- switch (GET_CODE (x))
- { /* MD: compare (reg, reg or imm) but CRX: cmp (reg or imm, reg)
- * -> swap all non symmetric ops */
- case EQ : crx_cmp_str = "eq"; break;
- case NE : crx_cmp_str = "ne"; break;
- case GT : crx_cmp_str = "lt"; break;
- case GTU : crx_cmp_str = "lo"; break;
- case LT : crx_cmp_str = "gt"; break;
- case LTU : crx_cmp_str = "hi"; break;
- case GE : crx_cmp_str = "le"; break;
- case GEU : crx_cmp_str = "ls"; break;
- case LE : crx_cmp_str = "ge"; break;
- case LEU : crx_cmp_str = "hs"; break;
- default : abort ();
- }
- fprintf (file, "%s", crx_cmp_str);
- return;
- }
-
- case 'H':
- /* Print high part of a double precision value. */
- switch (GET_CODE (x))
- {
- case CONST_DOUBLE:
- if (GET_MODE (x) == SFmode) abort ();
- if (GET_MODE (x) == DFmode)
- {
- /* High part of a DF const. */
- REAL_VALUE_TYPE r;
- long l[2];
-
- REAL_VALUE_FROM_CONST_DOUBLE (r, x);
- REAL_VALUE_TO_TARGET_DOUBLE (r, l);
-
- fprintf (file, "$0x%lx", l[1]);
- return;
- }
-
- /* -- Fallthrough to handle DI consts -- */
-
- case CONST_INT:
- {
- rtx high, low;
- split_double (x, &low, &high);
- putc ('$', file);
- output_addr_const (file, high);
- return;
- }
-
- case REG:
- if (REGNO (x) + 1 >= FIRST_PSEUDO_REGISTER) abort ();
- fprintf (file, "%s", reg_names[REGNO (x) + 1]);
- return;
-
- case MEM:
- /* Adjust memory address to high part. */
- {
- rtx adj_mem = x;
- adj_mem = adjust_address (adj_mem, GET_MODE (adj_mem), 4);
-
- output_memory_reference_mode = GET_MODE (adj_mem);
- output_address (XEXP (adj_mem, 0));
- return;
- }
-
- default:
- abort ();
- }
-
- case 'L':
- /* Print low part of a double precision value. */
- switch (GET_CODE (x))
- {
- case CONST_DOUBLE:
- if (GET_MODE (x) == SFmode) abort ();
- if (GET_MODE (x) == DFmode)
- {
- /* High part of a DF const. */
- REAL_VALUE_TYPE r;
- long l[2];
-
- REAL_VALUE_FROM_CONST_DOUBLE (r, x);
- REAL_VALUE_TO_TARGET_DOUBLE (r, l);
-
- fprintf (file, "$0x%lx", l[0]);
- return;
- }
-
- /* -- Fallthrough to handle DI consts -- */
-
- case CONST_INT:
- {
- rtx high, low;
- split_double (x, &low, &high);
- putc ('$', file);
- output_addr_const (file, low);
- return;
- }
-
- case REG:
- fprintf (file, "%s", reg_names[REGNO (x)]);
- return;
-
- case MEM:
- output_memory_reference_mode = GET_MODE (x);
- output_address (XEXP (x, 0));
- return;
-
- default:
- abort ();
- }
-
- case 0 : /* default */
- switch (GET_CODE (x))
- {
- case REG:
- fprintf (file, "%s", reg_names[REGNO (x)]);
- return;
-
- case MEM:
- output_memory_reference_mode = GET_MODE (x);
- output_address (XEXP (x, 0));
- return;
-
- case CONST_DOUBLE:
- {
- REAL_VALUE_TYPE r;
- long l;
-
- /* Always use H and L for double precision - see above */
- gcc_assert (GET_MODE (x) == SFmode);
-
- REAL_VALUE_FROM_CONST_DOUBLE (r, x);
- REAL_VALUE_TO_TARGET_SINGLE (r, l);
-
- fprintf (file, "$0x%lx", l);
- return;
- }
-
- default:
- putc ('$', file);
- output_addr_const (file, x);
- return;
- }
-
- default:
- output_operand_lossage ("invalid %%xn code");
- }
-
- abort ();
-}
-
-/* Implements the macro PRINT_OPERAND_ADDRESS defined in crx.h. */
-
-void
-crx_print_operand_address (FILE * file, rtx addr)
-{
- enum crx_addrtype addrtype;
- struct crx_address address;
-
- int offset;
-
- addrtype = crx_decompose_address (addr, &address);
-
- if (address.disp)
- offset = INTVAL (address.disp);
- else
- offset = 0;
-
- switch (addrtype)
- {
- case CRX_REG_REL:
- fprintf (file, "%d(%s)", offset, reg_names[REGNO (address.base)]);
- return;
-
- case CRX_POST_INC:
- switch (GET_CODE (address.side_effect))
- {
- case PLUS:
- break;
- case MINUS:
- offset = -offset;
- break;
- case POST_INC:
- offset = GET_MODE_SIZE (output_memory_reference_mode);
- break;
- case POST_DEC:
- offset = -GET_MODE_SIZE (output_memory_reference_mode);
- break;
- default:
- abort ();
- }
- fprintf (file, "%d(%s)+", offset, reg_names[REGNO (address.base)]);
- return;
-
- case CRX_SCALED_INDX:
- fprintf (file, "%d(%s, %s, %d)", offset, reg_names[REGNO (address.base)],
- reg_names[REGNO (address.index)], address.scale);
- return;
-
- case CRX_ABSOLUTE:
- output_addr_const (file, address.disp);
- return;
-
- default:
- abort ();
- }
-}
-
-
-/*****************************************************************************/
-/* MACHINE DESCRIPTION HELPER-FUNCTIONS */
-/*****************************************************************************/
-
-void crx_expand_movmem_single (rtx src, rtx srcbase, rtx dst, rtx dstbase,
- rtx tmp_reg, unsigned HOST_WIDE_INT *offset_p)
-{
- rtx addr, mem;
- unsigned HOST_WIDE_INT offset = *offset_p;
-
- /* Load */
- addr = plus_constant (src, offset);
- mem = adjust_automodify_address (srcbase, SImode, addr, offset);
- emit_move_insn (tmp_reg, mem);
-
- /* Store */
- addr = plus_constant (dst, offset);
- mem = adjust_automodify_address (dstbase, SImode, addr, offset);
- emit_move_insn (mem, tmp_reg);
-
- *offset_p = offset + 4;
-}
-
-int
-crx_expand_movmem (rtx dstbase, rtx srcbase, rtx count_exp, rtx align_exp)
-{
- unsigned HOST_WIDE_INT count = 0, offset, si_moves, i;
- HOST_WIDE_INT align = 0;
-
- rtx src, dst;
- rtx tmp_reg;
-
- if (GET_CODE (align_exp) == CONST_INT)
- { /* Only if aligned */
- align = INTVAL (align_exp);
- if (align & 3)
- return 0;
- }
-
- if (GET_CODE (count_exp) == CONST_INT)
- { /* No more than 16 SImode moves */
- count = INTVAL (count_exp);
- if (count > 64)
- return 0;
- }
-
- tmp_reg = gen_reg_rtx (SImode);
-
- /* Create psrs for the src and dest pointers */
- dst = copy_to_mode_reg (Pmode, XEXP (dstbase, 0));
- if (dst != XEXP (dstbase, 0))
- dstbase = replace_equiv_address_nv (dstbase, dst);
- src = copy_to_mode_reg (Pmode, XEXP (srcbase, 0));
- if (src != XEXP (srcbase, 0))
- srcbase = replace_equiv_address_nv (srcbase, src);
-
- offset = 0;
-
- /* Emit SImode moves */
- si_moves = count >> 2;
- for (i = 0; i < si_moves; i++)
- crx_expand_movmem_single (src, srcbase, dst, dstbase, tmp_reg, &offset);
-
- /* Special cases */
- if (count & 3)
- {
- offset = count - 4;
- crx_expand_movmem_single (src, srcbase, dst, dstbase, tmp_reg, &offset);
- }
-
- gcc_assert (offset == count);
-
- return 1;
-}
-
-static void
-mpushpop_str (char *stringbuffer, const char *mnemonic, char *mask)
-{
- if (strlen (mask) > 2 || crx_interrupt_function_p ()) /* needs 2-word instr. */
- sprintf (stringbuffer, "\n\t%s\tsp, {%s}", mnemonic, mask);
- else /* single word instruction */
- sprintf (stringbuffer, "\n\t%s\t%s", mnemonic, mask);
-}
-
-/* Called from crx.md. The return value depends on the parameter push_or_pop:
- * When push_or_pop is zero -> string for push instructions of prologue.
- * When push_or_pop is nonzero -> string for pop/popret/retx in epilogue.
- * Relies on the assumptions:
- * 1. RA is the last register to be saved.
- * 2. The maximal value of the counter is MAX_COUNT. */
-
-char *
-crx_prepare_push_pop_string (int push_or_pop)
-{
- /* j is the number of registers being saved, takes care that there won't be
- * more than 8 in one push/pop instruction */
-
- /* For the register mask string */
- static char mask_str[50];
-
- /* i is the index of save_regs[], going from 0 until last_reg_to_save */
- int i = 0;
-
- int ra_in_bitmask = 0;
-
- char *return_str;
-
- /* For reversing on the push instructions if there are more than one. */
- char *temp_str;
-
- return_str = (char *) xmalloc (120);
- temp_str = (char *) xmalloc (120);
-
- /* Initialize */
- memset (return_str, 0, 3);
-
- while (i <= last_reg_to_save)
- {
- /* Prepare mask for one instruction. */
- mask_str[0] = 0;
-
- if (i <= SP_REGNUM)
- { /* Add regs unit full or SP register reached */
- int j = 0;
- while (j < MAX_COUNT && i <= SP_REGNUM)
- {
- if (save_regs[i])
- {
- /* TODO to use ra_in_bitmask for detecting last pop is not
- * smart it prevents things like: popret r5 */
- if (i == RETURN_ADDRESS_REGNUM) ra_in_bitmask = 1;
- if (j > 0) strcat (mask_str, ", ");
- strcat (mask_str, reg_names[i]);
- ++j;
- }
- ++i;
- }
- }
- else
- {
- /* Handle hi/lo savings */
- while (i <= last_reg_to_save)
- {
- if (save_regs[i])
- {
- strcat (mask_str, "lo, hi");
- i = last_reg_to_save + 1;
- break;
- }
- ++i;
- }
- }
-
- if (strlen (mask_str) == 0) continue;
-
- if (push_or_pop == 1)
- {
- if (crx_interrupt_function_p ())
- mpushpop_str (temp_str, "popx", mask_str);
- else
- {
- if (ra_in_bitmask)
- {
- mpushpop_str (temp_str, "popret", mask_str);
- ra_in_bitmask = 0;
- }
- else mpushpop_str (temp_str, "pop", mask_str);
- }
-
- strcat (return_str, temp_str);
- }
- else
- {
- /* push - We need to reverse the order of the instructions if there
- * are more than one. (since the pop will not be reversed in the
- * epilogue */
- if (crx_interrupt_function_p ())
- mpushpop_str (temp_str, "pushx", mask_str);
- else
- mpushpop_str (temp_str, "push", mask_str);
- strcat (temp_str, return_str);
- strcpy (strcat (return_str, "\t"), temp_str);
- }
-
- }
-
- if (push_or_pop == 1)
- {
- /* pop */
- if (crx_interrupt_function_p ())
- strcat (return_str, "\n\tretx\n");
-
- else if (!FUNC_IS_NORETURN_P (current_function_decl)
- && !save_regs[RETURN_ADDRESS_REGNUM])
- strcat (return_str, "\n\tjump\tra\n");
- }
-
- /* Skip the newline and the tab in the start of return_str. */
- return_str += 2;
- return return_str;
-}
-
-/* CompactRISC CRX Architecture stack layout:
-
- 0 +---------------------
- |
- .
- .
- |
- +==================== Sp(x)=Ap(x+1)
- A | Args for functions
- | | called by X and Dynamically
- | | Dynamic allocations allocated and
- | | (alloca, variable deallocated
- Stack | length arrays).
- grows +-------------------- Fp(x)
- down| | Local variables of X
- ward| +--------------------
- | | Regs saved for X-1
- | +==================== Sp(x-1)=Ap(x)
- | Args for func X
- | pushed by X-1
- +-------------------- Fp(x-1)
- |
- |
- V
-
-*/
-
-void
-crx_expand_prologue (void)
-{
- crx_compute_frame ();
- crx_compute_save_regs ();
-
- /* If there is no need in push and adjustment to sp, return. */
- if (size_for_adjusting_sp + sum_regs == 0)
- return;
-
- if (last_reg_to_save != -1)
- /* If there are registers to push. */
- emit_insn (gen_push_for_prologue (GEN_INT (sum_regs)));
-
- if (size_for_adjusting_sp > 0)
- emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
- GEN_INT (-size_for_adjusting_sp)));
-
- if (frame_pointer_needed)
- /* Initialize the frame pointer with the value of the stack pointer
- * pointing now to the locals. */
- emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
-}
-
-/* Generate insn that updates the stack for local variables and padding for
- * registers we save. - Generate the appropriate return insn. */
-
-void
-crx_expand_epilogue (void)
-{
- /* Nonzero if we need to return and pop only RA. This will generate a
- * different insn. This differentiate is for the peepholes for call as last
- * statement in function. */
- int only_popret_RA = (save_regs[RETURN_ADDRESS_REGNUM]
- && (sum_regs == UNITS_PER_WORD));
-
- if (frame_pointer_needed)
- /* Restore the stack pointer with the frame pointers value */
- emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
-
- if (size_for_adjusting_sp > 0)
- emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
- GEN_INT (size_for_adjusting_sp)));
-
- if (crx_interrupt_function_p ())
- emit_jump_insn (gen_interrupt_return ());
- else if (last_reg_to_save == -1)
- /* Nothing to pop */
- /* Don't output jump for interrupt routine, only retx. */
- emit_jump_insn (gen_indirect_jump_return ());
- else if (only_popret_RA)
- emit_jump_insn (gen_popret_RA_return ());
- else
- emit_jump_insn (gen_pop_and_popret_return (GEN_INT (sum_regs)));
-}
+++ /dev/null
-/* Definitions of target machine for GNU compiler, for CRX.
- Copyright (C) 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
- Free Software Foundation, Inc.
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
- <http://www.gnu.org/licenses/>. */
-
-#ifndef GCC_CRX_H
-#define GCC_CRX_H
-
-/*****************************************************************************/
-/* CONTROLLING THE DRIVER */
-/*****************************************************************************/
-
-#define CC1PLUS_SPEC "%{!frtti:-fno-rtti} \
- %{!fenforce-eh-specs:-fno-enforce-eh-specs} \
- %{!fexceptions:-fno-exceptions} \
- %{!fthreadsafe-statics:-fno-threadsafe-statics}"
-
-#undef STARTFILE_SPEC
-#define STARTFILE_SPEC "crti.o%s crtbegin.o%s"
-
-#undef ENDFILE_SPEC
-#define ENDFILE_SPEC "crtend.o%s crtn.o%s"
-
-#undef MATH_LIBRARY
-#define MATH_LIBRARY ""
-
-/*****************************************************************************/
-/* RUN-TIME TARGET SPECIFICATION */
-/*****************************************************************************/
-
-#ifndef TARGET_CPU_CPP_BUILTINS
-#define TARGET_CPU_CPP_BUILTINS() \
-do { \
- builtin_define("__CRX__"); \
- builtin_define("__CR__"); \
-} while (0)
-#endif
-
-#define TARGET_VERSION fputs (" (CRX/ELF)", stderr);
-
-/*****************************************************************************/
-/* STORAGE LAYOUT */
-/*****************************************************************************/
-
-#define BITS_BIG_ENDIAN 0
-
-#define BYTES_BIG_ENDIAN 0
-
-#define WORDS_BIG_ENDIAN 0
-
-#define UNITS_PER_WORD 4
-
-#define POINTER_SIZE 32
-
-#define PARM_BOUNDARY 32
-
-#define STACK_BOUNDARY 32
-
-#define FUNCTION_BOUNDARY 32
-
-#define STRUCTURE_SIZE_BOUNDARY 32
-
-#define BIGGEST_ALIGNMENT 32
-
-/* In CRX arrays of chars are word-aligned, so strcpy() will be faster. */
-#define DATA_ALIGNMENT(TYPE, ALIGN) \
- (TREE_CODE (TYPE) == ARRAY_TYPE && TYPE_MODE (TREE_TYPE (TYPE)) == QImode \
- && (ALIGN) < BITS_PER_WORD \
- ? (BITS_PER_WORD) : (ALIGN))
-
-/* In CRX strings are word-aligned so strcpy from constants will be faster. */
-#define CONSTANT_ALIGNMENT(CONSTANT, ALIGN) \
- (TREE_CODE (CONSTANT) == STRING_CST && (ALIGN) < BITS_PER_WORD \
- ? (BITS_PER_WORD) : (ALIGN))
-
-#define STRICT_ALIGNMENT 0
-
-#define PCC_BITFIELD_TYPE_MATTERS 1
-
-/*****************************************************************************/
-/* LAYOUT OF SOURCE LANGUAGE DATA TYPES */
-/*****************************************************************************/
-
-#define INT_TYPE_SIZE 32
-
-#define SHORT_TYPE_SIZE 16
-
-#define LONG_TYPE_SIZE 32
-
-#define LONG_LONG_TYPE_SIZE 64
-
-#define FLOAT_TYPE_SIZE 32
-
-#define DOUBLE_TYPE_SIZE 64
-
-#define LONG_DOUBLE_TYPE_SIZE 64
-
-#define DEFAULT_SIGNED_CHAR 1
-
-#define SIZE_TYPE "unsigned int"
-
-#define PTRDIFF_TYPE "int"
-
-/*****************************************************************************/
-/* REGISTER USAGE. */
-/*****************************************************************************/
-
-#define FIRST_PSEUDO_REGISTER 19
-
-/* On the CRX, only the stack pointer (r15) is such. */
-#define FIXED_REGISTERS \
- { \
- /* r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 */ \
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
- /* r11 r12 r13 ra sp r16 r17 cc */ \
- 0, 0, 0, 0, 1, 0, 0, 1 \
- }
-
-/* On the CRX, calls clobbers r0-r6 (scratch registers), ra (the return address)
- * and sp - (the stack pointer which is fixed). */
-#define CALL_USED_REGISTERS \
- { \
- /* r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 */ \
- 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, \
- /* r11 r12 r13 ra sp r16 r17 cc */ \
- 0, 0, 0, 1, 1, 1, 1, 1 \
- }
-
-#define HARD_REGNO_NREGS(REGNO, MODE) \
- ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
-
-/* On the CRX architecture, HILO regs can only hold SI mode. */
-#define HARD_REGNO_MODE_OK(REGNO, MODE) crx_hard_regno_mode_ok(REGNO, MODE)
-
-/* So far no patterns for moving CCMODE data are available */
-#define AVOID_CCMODE_COPIES
-
-/* Interrupt functions can only use registers that have already been saved by
- * the prologue, even if they would normally be call-clobbered. */
-#define HARD_REGNO_RENAME_OK(SRC, DEST) \
- (!crx_interrupt_function_p () || df_regs_ever_live_p (DEST))
-
-#define MODES_TIEABLE_P(MODE1, MODE2) 1
-
-enum reg_class
-{
- NO_REGS,
- LO_REGS,
- HI_REGS,
- HILO_REGS,
- NOSP_REGS,
- GENERAL_REGS,
- ALL_REGS,
- LIM_REG_CLASSES
-};
-
-#define N_REG_CLASSES (int) LIM_REG_CLASSES
-
-/* The following macro defines cover classes for Integrated Register
- Allocator. Cover classes is a set of non-intersected register
- classes covering all hard registers used for register allocation
- purpose. Any move between two registers of a cover class should be
- cheaper than load or store of the registers. The macro value is
- array of register classes with LIM_REG_CLASSES used as the end
- marker. */
-
-#define IRA_COVER_CLASSES \
-{ \
- GENERAL_REGS, LIM_REG_CLASSES \
-}
-
-#define REG_CLASS_NAMES \
- { \
- "NO_REGS", \
- "LO_REGS", \
- "HI_REGS", \
- "HILO_REGS", \
- "NOSP_REGS", \
- "GENERAL_REGS", \
- "ALL_REGS" \
- }
-
-#define REG_CLASS_CONTENTS \
- { \
- {0x00000000}, /* NO_REGS */ \
- {0x00010000}, /* LO_REGS : 16 */ \
- {0x00020000}, /* HI_REGS : 17 */ \
- {0x00030000}, /* HILO_REGS : 16, 17 */ \
- {0x00007fff}, /* NOSP_REGS : 0 - 14 */ \
- {0x0000ffff}, /* GENERAL_REGS : 0 - 15 */ \
- {0x0007ffff} /* ALL_REGS : 0 - 18 */ \
- }
-
-#define REGNO_REG_CLASS(REGNO) crx_regno_reg_class(REGNO)
-
-#define BASE_REG_CLASS GENERAL_REGS
-
-#define INDEX_REG_CLASS GENERAL_REGS
-
-#define REG_CLASS_FROM_LETTER(C) \
- ((C) == 'b' ? NOSP_REGS : \
- (C) == 'l' ? LO_REGS : \
- (C) == 'h' ? HI_REGS : \
- (C) == 'k' ? HILO_REGS : \
- NO_REGS)
-
-#define REGNO_OK_FOR_BASE_P(REGNO) \
- ((REGNO) < 16 \
- || (reg_renumber && (unsigned)reg_renumber[REGNO] < 16))
-
-#define REGNO_OK_FOR_INDEX_P(REGNO) REGNO_OK_FOR_BASE_P(REGNO)
-
-#define SECONDARY_RELOAD_CLASS(CLASS, MODE, X) \
- crx_secondary_reload_class (CLASS, MODE, X)
-
-#define CLASS_MAX_NREGS(CLASS, MODE) \
- (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD
-
-#define SIGNED_INT_FITS_N_BITS(imm, N) \
- ((((imm) < ((long long)1<<((N)-1))) && ((imm) >= -((long long)1<<((N)-1)))) ? 1 : 0)
-
-#define UNSIGNED_INT_FITS_N_BITS(imm, N) \
- (((imm) < ((long long)1<<(N)) && (imm) >= (long long)0) ? 1 : 0)
-
-#define HILO_REGNO_P(regno) \
- (reg_classes_intersect_p(REGNO_REG_CLASS(regno), HILO_REGS))
-
-#define INT_CST4(VALUE) \
- (((VALUE) >= -1 && (VALUE) <= 4) || (VALUE) == -4 \
- || (VALUE) == 7 || (VALUE) == 8 || (VALUE) == 16 || (VALUE) == 32 \
- || (VALUE) == 20 || (VALUE) == 12 || (VALUE) == 48)
-
-#define CONST_OK_FOR_LETTER_P(VALUE, C) \
- /* Legal const for store immediate instructions */ \
- ((C) == 'I' ? UNSIGNED_INT_FITS_N_BITS(VALUE, 3) : \
- (C) == 'J' ? UNSIGNED_INT_FITS_N_BITS(VALUE, 4) : \
- (C) == 'K' ? UNSIGNED_INT_FITS_N_BITS(VALUE, 5) : \
- (C) == 'L' ? INT_CST4(VALUE) : \
- 0)
-
-#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \
- ((C) == 'G' ? crx_const_double_ok (VALUE) : \
- 0)
-
-/*****************************************************************************/
-/* STACK LAYOUT AND CALLING CONVENTIONS. */
-/*****************************************************************************/
-
-#define STACK_GROWS_DOWNWARD
-
-#define STARTING_FRAME_OFFSET 0
-
-#define STACK_POINTER_REGNUM 15
-
-#define FRAME_POINTER_REGNUM 13
-
-#define ARG_POINTER_REGNUM 12
-
-#define STATIC_CHAIN_REGNUM 1
-
-#define RETURN_ADDRESS_REGNUM 14
-
-#define FIRST_PARM_OFFSET(FNDECL) 0
-
-#define ELIMINABLE_REGS \
- { \
- { ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
- { ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \
- { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM} \
- }
-
-#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
- do { \
- (OFFSET) = crx_initial_elimination_offset ((FROM), (TO)); \
- } while (0)
-
-/*****************************************************************************/
-/* PASSING FUNCTION ARGUMENTS */
-/*****************************************************************************/
-
-#define ACCUMULATE_OUTGOING_ARGS (TARGET_NO_PUSH_ARGS)
-
-#define PUSH_ARGS (!TARGET_NO_PUSH_ARGS)
-
-#define PUSH_ROUNDING(BYTES) (((BYTES) + 3) & ~3)
-
-#ifndef CUMULATIVE_ARGS
-struct cumulative_args
-{
- int ints;
-};
-
-#define CUMULATIVE_ARGS struct cumulative_args
-#endif
-
-/* On the CRX architecture, Varargs routines should receive their parameters on
- * the stack. */
-
-#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, FNDECL, N_NAMED_ARGS) \
- crx_init_cumulative_args(&(CUM), (FNTYPE), (LIBNAME))
-
-#define FUNCTION_ARG_REGNO_P(REGNO) crx_function_arg_regno_p(REGNO)
-
-/*****************************************************************************/
-/* RETURNING FUNCTION VALUE */
-/*****************************************************************************/
-
-/* On the CRX, the return value is in R0 */
-
-#define FUNCTION_VALUE(VALTYPE, FUNC) \
- gen_rtx_REG(TYPE_MODE (VALTYPE), 0)
-
-#define LIBCALL_VALUE(MODE) gen_rtx_REG (MODE, 0)
-
-#define FUNCTION_VALUE_REGNO_P(N) ((N) == 0)
-
-#define CRX_STRUCT_VALUE_REGNUM 0
-
-/*****************************************************************************/
-/* GENERATING CODE FOR PROFILING - NOT IMPLEMENTED */
-/*****************************************************************************/
-
-#undef FUNCTION_PROFILER
-#define FUNCTION_PROFILER(STREAM, LABELNO) \
-{ \
- sorry ("profiler support for CRX"); \
-}
-
-/*****************************************************************************/
-/* TRAMPOLINES FOR NESTED FUNCTIONS - NOT SUPPORTED */
-/*****************************************************************************/
-
-#define TRAMPOLINE_SIZE 32
-
-/*****************************************************************************/
-/* ADDRESSING MODES */
-/*****************************************************************************/
-
-#define CONSTANT_ADDRESS_P(X) \
- (GET_CODE (X) == LABEL_REF \
- || GET_CODE (X) == SYMBOL_REF \
- || GET_CODE (X) == CONST \
- || GET_CODE (X) == CONST_INT)
-
-#define MAX_REGS_PER_ADDRESS 2
-
-#define HAVE_POST_INCREMENT 1
-#define HAVE_POST_DECREMENT 1
-#define HAVE_POST_MODIFY_DISP 1
-#define HAVE_POST_MODIFY_REG 0
-
-#ifdef REG_OK_STRICT
-#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
-#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X))
-#else
-#define REG_OK_FOR_BASE_P(X) 1
-#define REG_OK_FOR_INDEX_P(X) 1
-#endif /* REG_OK_STRICT */
-
-#define LEGITIMATE_CONSTANT_P(X) 1
-
-/*****************************************************************************/
-/* CONDITION CODE STATUS */
-/*****************************************************************************/
-
-/*****************************************************************************/
-/* RELATIVE COSTS OF OPERATIONS */
-/*****************************************************************************/
-
-#define MEMORY_MOVE_COST(MODE, CLASS, IN) crx_memory_move_cost(MODE, CLASS, IN)
-/* Moving to processor register flushes pipeline - thus asymmetric */
-#define REGISTER_MOVE_COST(MODE, FROM, TO) ((TO != GENERAL_REGS) ? 8 : 2)
-/* Assume best case (branch predicted) */
-#define BRANCH_COST(speed_p, predictable_p) 2
-
-#define SLOW_BYTE_ACCESS 1
-
-/*****************************************************************************/
-/* DIVIDING THE OUTPUT INTO SECTIONS */
-/*****************************************************************************/
-
-#define TEXT_SECTION_ASM_OP "\t.section\t.text"
-
-#define DATA_SECTION_ASM_OP "\t.section\t.data"
-
-#define BSS_SECTION_ASM_OP "\t.section\t.bss"
-
-/*****************************************************************************/
-/* POSITION INDEPENDENT CODE */
-/*****************************************************************************/
-
-#define PIC_OFFSET_TABLE_REGNUM 12
-
-#define LEGITIMATE_PIC_OPERAND_P(X) 1
-
-/*****************************************************************************/
-/* ASSEMBLER FORMAT */
-/*****************************************************************************/
-
-#define GLOBAL_ASM_OP "\t.globl\t"
-
-#undef USER_LABEL_PREFIX
-#define USER_LABEL_PREFIX "_"
-
-#undef ASM_OUTPUT_LABELREF
-#define ASM_OUTPUT_LABELREF(STREAM, NAME) \
- asm_fprintf (STREAM, "%U%s", (*targetm.strip_name_encoding) (NAME));
-
-#undef ASM_APP_ON
-#define ASM_APP_ON "#APP\n"
-
-#undef ASM_APP_OFF
-#define ASM_APP_OFF "#NO_APP\n"
-
-/*****************************************************************************/
-/* INSTRUCTION OUTPUT */
-/*****************************************************************************/
-
-#define REGISTER_NAMES \
- { \
- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
- "r8", "r9", "r10", "r11", "r12", "r13", "ra", "sp", \
- "lo", "hi", "cc" \
- }
-
-#define PRINT_OPERAND(STREAM, X, CODE) \
- crx_print_operand(STREAM, X, CODE)
-
-#define PRINT_OPERAND_ADDRESS(STREAM, ADDR) \
- crx_print_operand_address(STREAM, ADDR)
-
-/*****************************************************************************/
-/* OUTPUT OF DISPATCH TABLES */
-/*****************************************************************************/
-
-#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM, VALUE) \
- asm_fprintf ((STREAM), "\t.long\t.L%d\n", (VALUE))
-
-/*****************************************************************************/
-/* ALIGNMENT IN ASSEMBLER FILE */
-/*****************************************************************************/
-
-#define ASM_OUTPUT_ALIGN(STREAM, POWER) \
- asm_fprintf ((STREAM), "\t.align\t%d\n", 1 << (POWER))
-
-/*****************************************************************************/
-/* MISCELLANEOUS PARAMETERS */
-/*****************************************************************************/
-
-#define CASE_VECTOR_MODE Pmode
-
-#define MOVE_MAX 4
-
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
-
-#define STORE_FLAG_VALUE 1
-
-#define Pmode SImode
-
-#define FUNCTION_MODE QImode
-
-#endif /* ! GCC_CRX_H */
+++ /dev/null
-;; GCC machine description for CRX.
-;; Copyright (C) 1988, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-;; 2001, 2002, 2003, 2004, 2007
-;; Free Software Foundation, Inc.
-;;
-;; This file is part of GCC.
-;;
-;; GCC is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 3, or (at your option)
-;; any later version.
-;;
-;; GCC is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with GCC; see the file COPYING3. If not see
-;; <http://www.gnu.org/licenses/>. */
-
-;; Register numbers
-
-(define_constants
- [(SP_REGNUM 15) ; Stack pointer
- (RA_REGNUM 14) ; Return address
- (LO_REGNUM 16) ; LO register
- (HI_REGNUM 17) ; HI register
- (CC_REGNUM 18) ; Condition code register
- ]
-)
-
-(define_attr "length" "" ( const_int 6 ))
-
-(define_asm_attributes
- [(set_attr "length" "6")]
-)
-
-;; Predicates
-
-(define_predicate "u4bits_operand"
- (match_code "const_int,const_double")
- {
- if (GET_CODE (op) == CONST_DOUBLE)
- return crx_const_double_ok (op);
- return (UNSIGNED_INT_FITS_N_BITS(INTVAL(op), 4)) ? 1 : 0;
- }
-)
-
-(define_predicate "cst4_operand"
- (and (match_code "const_int")
- (match_test "INT_CST4(INTVAL(op))")))
-
-(define_predicate "reg_or_u4bits_operand"
- (ior (match_operand 0 "u4bits_operand")
- (match_operand 0 "register_operand")))
-
-(define_predicate "reg_or_cst4_operand"
- (ior (match_operand 0 "cst4_operand")
- (match_operand 0 "register_operand")))
-
-(define_predicate "reg_or_sym_operand"
- (ior (match_code "symbol_ref")
- (match_operand 0 "register_operand")))
-
-(define_predicate "cc_reg_operand"
- (and (match_code "reg")
- (match_test "REGNO (op) == CC_REGNUM")))
-
-(define_predicate "nosp_reg_operand"
- (and (match_operand 0 "register_operand")
- (match_test "REGNO (op) != SP_REGNUM")))
-
-(define_predicate "store_operand"
- (and (match_operand 0 "memory_operand")
- (not (match_operand 0 "push_operand"))))
-
-;; Mode Macro Definitions
-
-(define_mode_iterator ALLMT [QI HI SI SF DI DF])
-(define_mode_iterator CRXMM [QI HI SI SF])
-(define_mode_iterator CRXIM [QI HI SI])
-(define_mode_iterator DIDFM [DI DF])
-(define_mode_iterator SISFM [SI SF])
-(define_mode_iterator SHORT [QI HI])
-
-(define_mode_attr tIsa [(QI "b") (HI "w") (SI "d") (SF "d")])
-(define_mode_attr lImmArith [(QI "4") (HI "4") (SI "6")])
-(define_mode_attr lImmRotl [(QI "2") (HI "2") (SI "4")])
-(define_mode_attr IJK [(QI "I") (HI "J") (SI "K")])
-(define_mode_attr iF [(QI "i") (HI "i") (SI "i") (DI "i") (SF "F") (DF "F")])
-(define_mode_attr JG [(QI "J") (HI "J") (SI "J") (DI "J") (SF "G") (DF "G")])
-; In HI or QI mode we push 4 bytes.
-(define_mode_attr pushCnstr [(QI "X") (HI "X") (SI "<") (SF "<") (DI "<") (DF "<")])
-(define_mode_attr tpush [(QI "") (HI "") (SI "") (SF "") (DI "sp, ") (DF "sp, ")])
-(define_mode_attr lpush [(QI "2") (HI "2") (SI "2") (SF "2") (DI "4") (DF "4")])
-
-
-;; Code Macro Definitions
-
-(define_code_iterator sz_xtnd [sign_extend zero_extend])
-(define_code_attr sIsa [(sign_extend "") (zero_extend "u")])
-(define_code_attr sPat [(sign_extend "s") (zero_extend "u")])
-(define_code_attr szPat [(sign_extend "") (zero_extend "zero_")])
-(define_code_attr szIsa [(sign_extend "s") (zero_extend "z")])
-
-(define_code_iterator sh_oprnd [ashift ashiftrt lshiftrt])
-(define_code_attr shIsa [(ashift "ll") (ashiftrt "ra") (lshiftrt "rl")])
-(define_code_attr shPat [(ashift "ashl") (ashiftrt "ashr") (lshiftrt "lshr")])
-
-(define_code_iterator mima_oprnd [smax umax smin umin])
-(define_code_attr mimaIsa [(smax "maxs") (umax "maxu") (smin "mins") (umin "minu")])
-
-;; Addition Instructions
-
-(define_insn "adddi3"
- [(set (match_operand:DI 0 "register_operand" "=r,r")
- (plus:DI (match_operand:DI 1 "register_operand" "%0,0")
- (match_operand:DI 2 "nonmemory_operand" "r,i")))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "addd\t%L2, %L1\;addcd\t%H2, %H1"
- [(set_attr "length" "4,12")]
-)
-
-(define_insn "add<mode>3"
- [(set (match_operand:CRXIM 0 "register_operand" "=r,r")
- (plus:CRXIM (match_operand:CRXIM 1 "register_operand" "%0,0")
- (match_operand:CRXIM 2 "nonmemory_operand" "r,i")))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "add<tIsa>\t%2, %0"
- [(set_attr "length" "2,<lImmArith>")]
-)
-
-;; Subtract Instructions
-
-(define_insn "subdi3"
- [(set (match_operand:DI 0 "register_operand" "=r,r")
- (minus:DI (match_operand:DI 1 "register_operand" "0,0")
- (match_operand:DI 2 "nonmemory_operand" "r,i")))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "subd\t%L2, %L1\;subcd\t%H2, %H1"
- [(set_attr "length" "4,12")]
-)
-
-(define_insn "sub<mode>3"
- [(set (match_operand:CRXIM 0 "register_operand" "=r,r")
- (minus:CRXIM (match_operand:CRXIM 1 "register_operand" "0,0")
- (match_operand:CRXIM 2 "nonmemory_operand" "r,i")))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "sub<tIsa>\t%2, %0"
- [(set_attr "length" "2,<lImmArith>")]
-)
-
-;; Multiply Instructions
-
-(define_insn "mul<mode>3"
- [(set (match_operand:CRXIM 0 "register_operand" "=r,r")
- (mult:CRXIM (match_operand:CRXIM 1 "register_operand" "%0,0")
- (match_operand:CRXIM 2 "nonmemory_operand" "r,i")))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "mul<tIsa>\t%2, %0"
- [(set_attr "length" "2,<lImmArith>")]
-)
-
-;; Widening-multiplication Instructions
-
-(define_insn "<sIsa>mulsidi3"
- [(set (match_operand:DI 0 "register_operand" "=k")
- (mult:DI (sz_xtnd:DI (match_operand:SI 1 "register_operand" "%r"))
- (sz_xtnd:DI (match_operand:SI 2 "register_operand" "r"))))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "mull<sPat>d\t%2, %1"
- [(set_attr "length" "4")]
-)
-
-(define_insn "<sIsa>mulhisi3"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (mult:SI (sz_xtnd:SI (match_operand:HI 1 "register_operand" "%0"))
- (sz_xtnd:SI (match_operand:HI 2 "register_operand" "r"))))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "mul<sPat>wd\t%2, %0"
- [(set_attr "length" "4")]
-)
-
-(define_insn "<sIsa>mulqihi3"
- [(set (match_operand:HI 0 "register_operand" "=r")
- (mult:HI (sz_xtnd:HI (match_operand:QI 1 "register_operand" "%0"))
- (sz_xtnd:HI (match_operand:QI 2 "register_operand" "r"))))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "mul<sPat>bw\t%2, %0"
- [(set_attr "length" "4")]
-)
-
-;; Logical Instructions - and
-
-(define_insn "and<mode>3"
- [(set (match_operand:CRXIM 0 "register_operand" "=r,r")
- (and:CRXIM (match_operand:CRXIM 1 "register_operand" "%0,0")
- (match_operand:CRXIM 2 "nonmemory_operand" "r,i")))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "and<tIsa>\t%2, %0"
- [(set_attr "length" "2,<lImmArith>")]
-)
-
-;; Logical Instructions - or
-
-(define_insn "ior<mode>3"
- [(set (match_operand:CRXIM 0 "register_operand" "=r,r")
- (ior:CRXIM (match_operand:CRXIM 1 "register_operand" "%0,0")
- (match_operand:CRXIM 2 "nonmemory_operand" "r,i")))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "or<tIsa>\t%2, %0"
- [(set_attr "length" "2,<lImmArith>")]
-)
-
-;; Logical Instructions - xor
-
-(define_insn "xor<mode>3"
- [(set (match_operand:CRXIM 0 "register_operand" "=r,r")
- (xor:CRXIM (match_operand:CRXIM 1 "register_operand" "%0,0")
- (match_operand:CRXIM 2 "nonmemory_operand" "r,i")))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "xor<tIsa>\t%2, %0"
- [(set_attr "length" "2,<lImmArith>")]
-)
-
-;; Sign and Zero Extend Instructions
-
-(define_insn "<szPat>extendhisi2"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (sz_xtnd:SI (match_operand:HI 1 "register_operand" "r")))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "<szIsa>extwd\t%1, %0"
- [(set_attr "length" "4")]
-)
-
-(define_insn "<szPat>extendqisi2"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (sz_xtnd:SI (match_operand:QI 1 "register_operand" "r")))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "<szIsa>extbd\t%1, %0"
- [(set_attr "length" "4")]
-)
-
-(define_insn "<szPat>extendqihi2"
- [(set (match_operand:HI 0 "register_operand" "=r")
- (sz_xtnd:HI (match_operand:QI 1 "register_operand" "r")))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "<szIsa>extbw\t%1, %0"
- [(set_attr "length" "4")]
-)
-
-;; Negation Instructions
-
-(define_insn "neg<mode>2"
- [(set (match_operand:CRXIM 0 "register_operand" "=r")
- (neg:CRXIM (match_operand:CRXIM 1 "register_operand" "r")))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "neg<tIsa>\t%1, %0"
- [(set_attr "length" "4")]
-)
-
-;; Absolute Instructions
-
-(define_insn "abs<mode>2"
- [(set (match_operand:CRXIM 0 "register_operand" "=r")
- (abs:CRXIM (match_operand:CRXIM 1 "register_operand" "r")))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "abs<tIsa>\t%1, %0"
- [(set_attr "length" "4")]
-)
-
-;; Max and Min Instructions
-
-(define_insn "<code><mode>3"
- [(set (match_operand:CRXIM 0 "register_operand" "=r")
- (mima_oprnd:CRXIM (match_operand:CRXIM 1 "register_operand" "%0")
- (match_operand:CRXIM 2 "register_operand" "r")))]
- ""
- "<mimaIsa><tIsa>\t%2, %0"
- [(set_attr "length" "4")]
-)
-
-;; One's Complement
-
-(define_insn "one_cmpl<mode>2"
- [(set (match_operand:CRXIM 0 "register_operand" "=r")
- (not:CRXIM (match_operand:CRXIM 1 "register_operand" "0")))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "xor<tIsa>\t$-1, %0"
- [(set_attr "length" "2")]
-)
-
-;; Rotate Instructions
-
-(define_insn "rotl<mode>3"
- [(set (match_operand:CRXIM 0 "register_operand" "=r,r")
- (rotate:CRXIM (match_operand:CRXIM 1 "register_operand" "0,0")
- (match_operand:CRXIM 2 "nonmemory_operand" "r,<IJK>")))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "@
- rotl<tIsa>\t%2, %0
- rot<tIsa>\t%2, %0"
- [(set_attr "length" "4,<lImmRotl>")]
-)
-
-(define_insn "rotr<mode>3"
- [(set (match_operand:CRXIM 0 "register_operand" "=r")
- (rotatert:CRXIM (match_operand:CRXIM 1 "register_operand" "0")
- (match_operand:CRXIM 2 "register_operand" "r")))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "rotr<tIsa>\t%2, %0"
- [(set_attr "length" "4")]
-)
-
-;; Arithmetic Left and Right Shift Instructions
-
-(define_insn "<shPat><mode>3"
- [(set (match_operand:CRXIM 0 "register_operand" "=r,r")
- (sh_oprnd:CRXIM (match_operand:CRXIM 1 "register_operand" "0,0")
- (match_operand:QI 2 "nonmemory_operand" "r,<IJK>")))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "s<shIsa><tIsa>\t%2, %0"
- [(set_attr "length" "2,2")]
-)
-
-;; Bit Set Instructions
-
-(define_insn "extv"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (sign_extract:SI (match_operand:SI 1 "register_operand" "r")
- (match_operand:SI 2 "const_int_operand" "n")
- (match_operand:SI 3 "const_int_operand" "n")))]
- ""
- {
- static char buf[100];
- int strpntr;
- int size = INTVAL (operands[2]);
- int pos = INTVAL (operands[3]);
- strpntr = sprintf (buf, "ram\t$%d, $31, $%d, %%1, %%0\;",
- BITS_PER_WORD - (size + pos), BITS_PER_WORD - size);
- sprintf (buf + strpntr, "srad\t$%d, %%0", BITS_PER_WORD - size);
- return buf;
- }
- [(set_attr "length" "6")]
-)
-
-(define_insn "extzv"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (zero_extract:SI (match_operand:SI 1 "register_operand" "r")
- (match_operand:SI 2 "const_int_operand" "n")
- (match_operand:SI 3 "const_int_operand" "n")))]
- ""
- {
- static char buf[40];
- int size = INTVAL (operands[2]);
- int pos = INTVAL (operands[3]);
- sprintf (buf, "ram\t$%d, $%d, $0, %%1, %%0",
- (BITS_PER_WORD - pos) % BITS_PER_WORD, size - 1);
- return buf;
- }
- [(set_attr "length" "4")]
-)
-
-(define_insn "insv"
- [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
- (match_operand:SI 1 "const_int_operand" "n")
- (match_operand:SI 2 "const_int_operand" "n"))
- (match_operand:SI 3 "register_operand" "r"))]
- ""
- {
- static char buf[40];
- int size = INTVAL (operands[1]);
- int pos = INTVAL (operands[2]);
- sprintf (buf, "rim\t$%d, $%d, $%d, %%3, %%0",
- pos, size + pos - 1, pos);
- return buf;
- }
- [(set_attr "length" "4")]
-)
-
-;; Move Instructions
-
-(define_expand "mov<mode>"
- [(set (match_operand:ALLMT 0 "nonimmediate_operand" "")
- (match_operand:ALLMT 1 "general_operand" ""))]
- ""
- {
- if (!(reload_in_progress || reload_completed))
- {
- if (!register_operand (operands[0], <MODE>mode))
- {
- if (push_operand (operands[0], <MODE>mode) ?
- !nosp_reg_operand (operands[1], <MODE>mode) :
- !reg_or_u4bits_operand (operands[1], <MODE>mode))
- {
- operands[1] = copy_to_mode_reg (<MODE>mode, operands[1]);
- }
- }
- }
- }
-)
-
-(define_insn "push<mode>_internal"
- [(set (match_operand:ALLMT 0 "push_operand" "=<pushCnstr>")
- (match_operand:ALLMT 1 "nosp_reg_operand" "b"))]
- ""
- "push\t<tpush>%p1"
- [(set_attr "length" "<lpush>")]
-)
-
-(define_insn "mov<mode>_regs"
- [(set (match_operand:SISFM 0 "register_operand" "=r, r, r, k")
- (match_operand:SISFM 1 "nonmemory_operand" "r, <iF>, k, r"))]
- ""
- "@
- movd\t%1, %0
- movd\t%1, %0
- mfpr\t%1, %0
- mtpr\t%1, %0"
- [(set_attr "length" "2,6,4,4")]
-)
-
-(define_insn "mov<mode>_regs"
- [(set (match_operand:DIDFM 0 "register_operand" "=r, r, r, k")
- (match_operand:DIDFM 1 "nonmemory_operand" "r, <iF>, k, r"))]
- ""
- {
- switch (which_alternative)
- {
- case 0: if (REGNO (operands[0]) > REGNO (operands[1]))
- return "movd\t%H1, %H0\;movd\t%L1, %L0";
- else
- return "movd\t%L1, %L0\;movd\t%H1, %H0";
- case 1: return "movd\t%H1, %H0\;movd\t%L1, %L0";
- case 2: return "mfpr\t%H1, %H0\;mfpr\t%L1, %L0";
- case 3: return "mtpr\t%H1, %H0\;mtpr\t%L1, %L0";
- default: gcc_unreachable ();
- }
- }
- [(set_attr "length" "4,12,8,8")]
-)
-
-(define_insn "mov<mode>_regs" ; no HI/QI mode in HILO regs
- [(set (match_operand:SHORT 0 "register_operand" "=r, r")
- (match_operand:SHORT 1 "nonmemory_operand" "r, i"))]
- ""
- "mov<tIsa>\t%1, %0"
- [(set_attr "length" "2,<lImmArith>")]
-)
-
-(define_insn "mov<mode>_load"
- [(set (match_operand:CRXMM 0 "register_operand" "=r")
- (match_operand:CRXMM 1 "memory_operand" "m"))]
- ""
- "load<tIsa>\t%1, %0"
- [(set_attr "length" "6")]
-)
-
-(define_insn "mov<mode>_load"
- [(set (match_operand:DIDFM 0 "register_operand" "=r")
- (match_operand:DIDFM 1 "memory_operand" "m"))]
- ""
- {
- rtx first_dest_reg = gen_rtx_REG (SImode, REGNO (operands[0]));
- if (reg_overlap_mentioned_p (first_dest_reg, operands[1]))
- return "loadd\t%H1, %H0\;loadd\t%L1, %L0";
- return "loadd\t%L1, %L0\;loadd\t%H1, %H0";
- }
- [(set_attr "length" "12")]
-)
-
-(define_insn "mov<mode>_store"
- [(set (match_operand:CRXMM 0 "store_operand" "=m, m")
- (match_operand:CRXMM 1 "reg_or_u4bits_operand" "r, <JG>"))]
- ""
- "stor<tIsa>\t%1, %0"
- [(set_attr "length" "6")]
-)
-
-(define_insn "mov<mode>_store"
- [(set (match_operand:DIDFM 0 "store_operand" "=m, m")
- (match_operand:DIDFM 1 "reg_or_u4bits_operand" "r, <JG>"))]
- ""
- "stord\t%H1, %H0\;stord\t%L1, %L0"
- [(set_attr "length" "12")]
-)
-
-;; Movmem Instruction
-
-(define_expand "movmemsi"
- [(use (match_operand:BLK 0 "memory_operand" ""))
- (use (match_operand:BLK 1 "memory_operand" ""))
- (use (match_operand:SI 2 "nonmemory_operand" ""))
- (use (match_operand:SI 3 "const_int_operand" ""))]
- ""
- {
- if (crx_expand_movmem (operands[0], operands[1], operands[2], operands[3]))
- DONE;
- else
- FAIL;
- }
-)
-
-;; Compare and Branch Instructions
-
-(define_insn "cbranchcc4"
- [(set (pc)
- (if_then_else (match_operator 0 "ordered_comparison_operator"
- [(match_operand:CC 1 "cc_reg_operand" "r")
- (match_operand 2 "cst4_operand" "L")])
- (label_ref (match_operand 3 ""))
- (pc)))]
- ""
- "b%d0\t%l3"
- [(set_attr "length" "6")]
-)
-
-(define_insn "cbranch<mode>4"
- [(set (pc)
- (if_then_else (match_operator 0 "ordered_comparison_operator"
- [(match_operand:CRXIM 1 "register_operand" "r")
- (match_operand:CRXIM 2 "reg_or_cst4_operand" "rL")])
- (label_ref (match_operand 3 "" ""))
- (pc)))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "cmpb%d0<tIsa>\t%2, %1, %l3"
- [(set_attr "length" "6")]
-)
-
-
-;; Scond Instructions
-
-(define_expand "cstore<mode>4"
- [(set (reg:CC CC_REGNUM)
- (compare:CC (match_operand:CRXIM 2 "register_operand" "")
- (match_operand:CRXIM 3 "nonmemory_operand" "")))
- (set (match_operand:SI 0 "register_operand")
- (match_operator:SI 1 "ordered_comparison_operator"
- [(reg:CC CC_REGNUM) (const_int 0)]))]
- ""
- ""
-)
-
-(define_insn "cmp<mode>_internal"
- [(set (reg:CC CC_REGNUM)
- (compare:CC (match_operand:CRXIM 0 "register_operand" "r,r")
- (match_operand:CRXIM 1 "nonmemory_operand" "r,i")))]
- ""
- "cmp<tIsa>\t%1, %0"
- [(set_attr "length" "2,<lImmArith>")]
-)
-
-(define_insn "sCOND_internal"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (match_operator:SI 1 "ordered_comparison_operator"
- [(reg:CC CC_REGNUM) (const_int 0)]))]
- ""
- "s%d1\t%0"
- [(set_attr "length" "2")]
-)
-
-;; Jumps and Branches
-
-(define_insn "indirect_jump_return"
- [(parallel
- [(set (pc)
- (reg:SI RA_REGNUM))
- (return)])
- ]
- "reload_completed"
- "jump\tra"
- [(set_attr "length" "2")]
-)
-
-(define_insn "indirect_jump"
- [(set (pc)
- (match_operand:SI 0 "reg_or_sym_operand" "r,i"))]
- ""
- "@
- jump\t%0
- br\t%a0"
- [(set_attr "length" "2,6")]
-)
-
-(define_insn "interrupt_return"
- [(parallel
- [(unspec_volatile [(const_int 0)] 0)
- (return)])]
- ""
- {
- return crx_prepare_push_pop_string (1);
- }
- [(set_attr "length" "14")]
-)
-
-(define_insn "jump_to_imm"
- [(set (pc)
- (match_operand 0 "immediate_operand" "i"))]
- ""
- "br\t%c0"
- [(set_attr "length" "6")]
-)
-
-(define_insn "jump"
- [(set (pc)
- (label_ref (match_operand 0 "" "")))]
- ""
- "br\t%l0"
- [(set_attr "length" "6")]
-)
-
-;; Function Prologue and Epilogue
-
-(define_expand "prologue"
- [(const_int 0)]
- ""
- {
- crx_expand_prologue ();
- DONE;
- }
-)
-
-(define_insn "push_for_prologue"
- [(parallel
- [(set (reg:SI SP_REGNUM)
- (minus:SI (reg:SI SP_REGNUM)
- (match_operand:SI 0 "immediate_operand" "i")))])]
- "reload_completed"
- {
- return crx_prepare_push_pop_string (0);
- }
- [(set_attr "length" "4")]
-)
-
-(define_expand "epilogue"
- [(return)]
- ""
- {
- crx_expand_epilogue ();
- DONE;
- }
-)
-
-(define_insn "pop_and_popret_return"
- [(parallel
- [(set (reg:SI SP_REGNUM)
- (plus:SI (reg:SI SP_REGNUM)
- (match_operand:SI 0 "immediate_operand" "i")))
- (use (reg:SI RA_REGNUM))
- (return)])
- ]
- "reload_completed"
- {
- return crx_prepare_push_pop_string (1);
- }
- [(set_attr "length" "4")]
-)
-
-(define_insn "popret_RA_return"
- [(parallel
- [(use (reg:SI RA_REGNUM))
- (return)])
- ]
- "reload_completed"
- "popret\tra"
- [(set_attr "length" "2")]
-)
-
-;; Table Jump
-
-(define_insn "tablejump"
- [(set (pc)
- (match_operand:SI 0 "register_operand" "r"))
- (use (label_ref:SI (match_operand 1 "" "" )))]
- ""
- "jump\t%0"
- [(set_attr "length" "2")]
-)
-
-;; Call Instructions
-
-(define_expand "call"
- [(call (match_operand:QI 0 "memory_operand" "")
- (match_operand 1 "" ""))]
- ""
- {
- emit_call_insn (gen_crx_call (operands[0], operands[1]));
- DONE;
- }
-)
-
-(define_expand "crx_call"
- [(parallel
- [(call (match_operand:QI 0 "memory_operand" "")
- (match_operand 1 "" ""))
- (clobber (reg:SI RA_REGNUM))])]
- ""
- ""
-)
-
-(define_insn "crx_call_insn_branch"
- [(call (mem:QI (match_operand:SI 0 "immediate_operand" "i"))
- (match_operand 1 "" ""))
- (clobber (match_operand:SI 2 "register_operand" "+r"))]
- ""
- "bal\tra, %a0"
- [(set_attr "length" "6")]
-)
-
-(define_insn "crx_call_insn_jump"
- [(call (mem:QI (match_operand:SI 0 "register_operand" "r"))
- (match_operand 1 "" ""))
- (clobber (match_operand:SI 2 "register_operand" "+r"))]
- ""
- "jal\t%0"
- [(set_attr "length" "2")]
-)
-
-(define_insn "crx_call_insn_jalid"
- [(call (mem:QI (mem:SI (plus:SI
- (match_operand:SI 0 "register_operand" "r")
- (match_operand:SI 1 "register_operand" "r"))))
- (match_operand 2 "" ""))
- (clobber (match_operand:SI 3 "register_operand" "+r"))]
- ""
- "jalid\t%0, %1"
- [(set_attr "length" "4")]
-)
-
-;; Call Value Instructions
-
-(define_expand "call_value"
- [(set (match_operand 0 "general_operand" "")
- (call (match_operand:QI 1 "memory_operand" "")
- (match_operand 2 "" "")))]
- ""
- {
- emit_call_insn (gen_crx_call_value (operands[0], operands[1], operands[2]));
- DONE;
- }
-)
-
-(define_expand "crx_call_value"
- [(parallel
- [(set (match_operand 0 "general_operand" "")
- (call (match_operand 1 "memory_operand" "")
- (match_operand 2 "" "")))
- (clobber (reg:SI RA_REGNUM))])]
- ""
- ""
-)
-
-(define_insn "crx_call_value_insn_branch"
- [(set (match_operand 0 "" "=g")
- (call (mem:QI (match_operand:SI 1 "immediate_operand" "i"))
- (match_operand 2 "" "")))
- (clobber (match_operand:SI 3 "register_operand" "+r"))]
- ""
- "bal\tra, %a1"
- [(set_attr "length" "6")]
-)
-
-(define_insn "crx_call_value_insn_jump"
- [(set (match_operand 0 "" "=g")
- (call (mem:QI (match_operand:SI 1 "register_operand" "r"))
- (match_operand 2 "" "")))
- (clobber (match_operand:SI 3 "register_operand" "+r"))]
- ""
- "jal\t%1"
- [(set_attr "length" "2")]
-)
-
-(define_insn "crx_call_value_insn_jalid"
- [(set (match_operand 0 "" "=g")
- (call (mem:QI (mem:SI (plus:SI
- (match_operand:SI 1 "register_operand" "r")
- (match_operand:SI 2 "register_operand" "r"))))
- (match_operand 3 "" "")))
- (clobber (match_operand:SI 4 "register_operand" "+r"))]
- ""
- "jalid\t%0, %1"
- [(set_attr "length" "4")]
-)
-
-;; Nop
-
-(define_insn "nop"
- [(const_int 0)]
- ""
- ""
-)
-
-;; Multiply and Accumulate Instructions
-
-(define_insn "<sPat>madsidi3"
- [(set (match_operand:DI 0 "register_operand" "+k")
- (plus:DI
- (mult:DI (sz_xtnd:DI (match_operand:SI 1 "register_operand" "%r"))
- (sz_xtnd:DI (match_operand:SI 2 "register_operand" "r")))
- (match_dup 0)))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_MAC"
- "mac<sPat>d\t%2, %1"
- [(set_attr "length" "4")]
-)
-
-(define_insn "<sPat>madhisi3"
- [(set (match_operand:SI 0 "register_operand" "+l")
- (plus:SI
- (mult:SI (sz_xtnd:SI (match_operand:HI 1 "register_operand" "%r"))
- (sz_xtnd:SI (match_operand:HI 2 "register_operand" "r")))
- (match_dup 0)))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_MAC"
- "mac<sPat>w\t%2, %1"
- [(set_attr "length" "4")]
-)
-
-(define_insn "<sPat>madqihi3"
- [(set (match_operand:HI 0 "register_operand" "+l")
- (plus:HI
- (mult:HI (sz_xtnd:HI (match_operand:QI 1 "register_operand" "%r"))
- (sz_xtnd:HI (match_operand:QI 2 "register_operand" "r")))
- (match_dup 0)))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_MAC"
- "mac<sPat>b\t%2, %1"
- [(set_attr "length" "4")]
-)
-
-;; Loop Instructions
-
-(define_expand "doloop_end"
- [(use (match_operand 0 "" "")) ; loop pseudo
- (use (match_operand 1 "" "")) ; iterations; zero if unknown
- (use (match_operand 2 "" "")) ; max iterations
- (use (match_operand 3 "" "")) ; loop level
- (use (match_operand 4 "" ""))] ; label
- ""
- {
- if (INTVAL (operands[3]) > crx_loop_nesting)
- FAIL;
- switch (GET_MODE (operands[0]))
- {
- case SImode:
- emit_jump_insn (gen_doloop_end_si (operands[4], operands[0]));
- break;
- case HImode:
- emit_jump_insn (gen_doloop_end_hi (operands[4], operands[0]));
- break;
- case QImode:
- emit_jump_insn (gen_doloop_end_qi (operands[4], operands[0]));
- break;
- default:
- FAIL;
- }
- DONE;
- }
-)
-
-; CRX dbnz[bwd] used explicitly (see above) but also by the combiner.
-
-(define_insn "doloop_end_<mode>"
- [(set (pc)
- (if_then_else (ne (match_operand:CRXIM 1 "register_operand" "+r,!m")
- (const_int 1))
- (label_ref (match_operand 0 "" ""))
- (pc)))
- (set (match_dup 1) (plus:CRXIM (match_dup 1) (const_int -1)))
- (clobber (match_scratch:CRXIM 2 "=X,r"))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "@
- dbnz<tIsa>\t%1, %l0
- load<tIsa>\t%1, %2\;add<tIsa>\t$-1, %2\;stor<tIsa>\t%2, %1\;bne\t%l0"
- [(set_attr "length" "6, 12")]
-)
+++ /dev/null
-; Options for the National Semiconductor CRX port of the compiler.
-
-; Copyright (C) 2005, 2007 Free Software Foundation, Inc.
-;
-; This file is part of GCC.
-;
-; GCC is free software; you can redistribute it and/or modify it under
-; the terms of the GNU General Public License as published by the Free
-; Software Foundation; either version 3, or (at your option) any later
-; version.
-;
-; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-; WARRANTY; without even the implied warranty of MERCHANTABILITY or
-; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-; for more details.
-;
-; You should have received a copy of the GNU General Public License
-; along with GCC; see the file COPYING3. If not see
-; <http://www.gnu.org/licenses/>.
-
-mmac
-Target Report Mask(MAC)
-Support multiply accumulate instructions
-
-mno-push-args
-Target Report RejectNegative Mask(NO_PUSH_ARGS)
-Do not use push to store function arguments
-
-mloop-nesting=
-Common RejectNegative Joined UInteger Var(crx_loop_nesting) Init(12)
-Restrict doloop to the given nesting level
-
-mdebug-addr
-Target RejectNegative Var(TARGET_DEBUG_ADDR) Undocumented
+++ /dev/null
-# CRX Target Makefile
-#
-# Copyright (C) 2005 Free Software Foundation, Inc.
-#
-# This file is part of GCC.
-#
-# GCC is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3, or (at your option)
-# any later version.
-#
-# GCC is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with GCC; see the file COPYING3. If not see
-# <http://www.gnu.org/licenses/>.
-
-# Mingw specific compilation fixes
-USE_COLLECT2 =
-STMP_FIXINC =
-
-# Software emulation for integer div and mod
-LIB2FUNCS_EXTRA = $(srcdir)/config/udivmodsi4.c $(srcdir)/config/udivmod.c $(srcdir)/config/divmod.c
-
-# Build the floating point emulation libraries.
-FPBIT = fp-bit.c
-DPBIT = dp-bit.c
-
-fp-bit.c: $(srcdir)/config/fp-bit.c
- echo '#define FLOAT' > fp-bit.c
- cat $(srcdir)/config/fp-bit.c >> fp-bit.c
-
-dp-bit.c: $(srcdir)/config/fp-bit.c
- cat $(srcdir)/config/fp-bit.c > dp-bit.c
+++ /dev/null
-/* Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
- 2004 Free Software Foundation, Inc.
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 3, or (at your option) any later
-version.
-
-GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-for more details.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-#define TARGET_OS_CPP_BUILTINS() \
- do \
- { \
- NETBSD_OS_CPP_BUILTINS_AOUT(); \
- } \
- while (0)
-
-#define TARGET_VERSION fprintf (stderr, " (NetBSD/i386 a.out)");
-
-/* 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)
-
-#undef SUBTARGET_EXTRA_SPECS
-#define SUBTARGET_EXTRA_SPECS \
- { "netbsd_cpp_spec", NETBSD_CPP_SPEC },
-
-#undef CPP_SPEC
-#define CPP_SPEC "%(netbsd_cpp_spec)"
-
-\f
-#undef SIZE_TYPE
-#define SIZE_TYPE "unsigned int"
-
-#undef PTRDIFF_TYPE
-#define PTRDIFF_TYPE "int"
-
-#undef ASM_APP_ON
-#define ASM_APP_ON "#APP\n"
-
-#undef ASM_APP_OFF
-#define ASM_APP_OFF "#NO_APP\n"
-
-/* 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
-\f
-/* i386 netbsd 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. */
-
-/* Redefine this to use %eax instead of %edx. */
-#undef FUNCTION_PROFILER
-#define FUNCTION_PROFILER(FILE, LABELNO) \
-{ \
- if (flag_pic) \
- { \
- fprintf (FILE, "\tcall mcount@PLT\n"); \
- } \
- else \
- { \
- fprintf (FILE, "\tcall mcount\n"); \
- } \
-}
-
-/* Until they use ELF or something that handles dwarf2 unwinds
- and initialization stuff better. */
-#define DWARF2_UNWIND_INFO 0
-
-/* Redefine this so that it becomes "_GLOBAL_OFFSET_TABLE_" when the label
- prefix is added. */
-#undef GOT_SYMBOL_NAME
-#define GOT_SYMBOL_NAME "GLOBAL_OFFSET_TABLE_"
-
-/* Attempt to enable execute permissions on the stack. */
-#define ENABLE_EXECUTE_STACK NETBSD_ENABLE_EXECUTE_STACK
+++ /dev/null
-/* libgcc routines for M68HC11 & M68HC12.
- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2008, 2009
- Free Software Foundation, Inc.
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3, or (at your option) any
-later version.
-
-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.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-#ifdef __HAVE_SHORT_INT__
- .mode mshort
-#else
- .mode mlong
-#endif
-
- .macro declare_near name
- .globl \name
- .type \name,@function
- .size \name,.Lend-\name
-\name:
- .endm
-
-#if defined(__USE_RTC__)
-# define ARG(N) N+1
-
- .macro ret
-#if defined(mc68hc12)
- rtc
-#else
- jmp __return_32
-#endif
- .endm
-
- .macro declare name
- .globl \name
- .type \name,@function
- .size \name,.Lend-\name
- .far \name
-\name:
- .endm
-
- .macro farsym name
- .far NAME
- .endm
-
-#else
-# define ARG(N) N
-
- .macro ret
- rts
- .endm
-
- .macro farsym name
- .endm
-
- .macro declare name
- .globl \name
- .type \name,@function
- .size \name,.Lend-\name
-\name:
- .endm
-
-#endif
-
- .sect .text
-
-
-#define REG(NAME) \
-NAME: .dc.w 1; \
- .type NAME,@object ; \
- .size NAME,2
-
-#ifdef L_regs_min
-/* Pseudo hard registers used by gcc.
- They should be located in page0. */
-
- .sect .softregs
- .globl _.tmp
- .globl _.z,_.xy
-REG(_.tmp)
-REG(_.z)
-REG(_.xy)
-
-#endif
-
-#ifdef L_regs_frame
- .sect .softregs
- .globl _.frame
-REG(_.frame)
-#endif
-
-#ifdef L_regs_d1_2
- .sect .softregs
- .globl _.d1,_.d2
-REG(_.d1)
-REG(_.d2)
-#endif
-
-#ifdef L_regs_d3_4
- .sect .softregs
- .globl _.d3,_.d4
-REG(_.d3)
-REG(_.d4)
-#endif
-
-#ifdef L_regs_d5_6
- .sect .softregs
- .globl _.d5,_.d6
-REG(_.d5)
-REG(_.d6)
-#endif
-
-#ifdef L_regs_d7_8
- .sect .softregs
- .globl _.d7,_.d8
-REG(_.d7)
-REG(_.d8)
-#endif
-
-#ifdef L_regs_d9_16
-/* Pseudo hard registers used by gcc.
- They should be located in page0. */
- .sect .softregs
- .globl _.d9,_.d10,_.d11,_.d12,_.d13,_.d14
- .globl _.d15,_.d16
-REG(_.d9)
-REG(_.d10)
-REG(_.d11)
-REG(_.d12)
-REG(_.d13)
-REG(_.d14)
-REG(_.d15)
-REG(_.d16)
-
-#endif
-
-#ifdef L_regs_d17_32
-/* Pseudo hard registers used by gcc.
- They should be located in page0. */
- .sect .softregs
- .globl _.d17,_.d18,_.d19,_.d20,_.d21,_.d22
- .globl _.d23,_.d24,_.d25,_.d26,_.d27,_.d28
- .globl _.d29,_.d30,_.d31,_.d32
-REG(_.d17)
-REG(_.d18)
-REG(_.d19)
-REG(_.d20)
-REG(_.d21)
-REG(_.d22)
-REG(_.d23)
-REG(_.d24)
-REG(_.d25)
-REG(_.d26)
-REG(_.d27)
-REG(_.d28)
-REG(_.d29)
-REG(_.d30)
-REG(_.d31)
-REG(_.d32)
-#endif
-
-#ifdef L_premain
-;;
-;; Specific initialization for 68hc11 before the main.
-;; Nothing special for a generic routine; Just enable interrupts.
-;;
- declare_near __premain
- clra
- tap ; Clear both I and X.
- rts
-#endif
-
-#ifdef L__exit
-;;
-;; Exit operation. Just loop forever and wait for interrupts.
-;; (no other place to go)
-;; This operation is split in several pieces collected together by
-;; the linker script. This allows to support destructors at the
-;; exit stage while not impacting program sizes when there is no
-;; destructors.
-;;
-;; _exit:
-;; *(.fini0) /* Beginning of finish code (_exit symbol). */
-;; *(.fini1) /* Place holder for applications. */
-;; *(.fini2) /* C++ destructors. */
-;; *(.fini3) /* Place holder for applications. */
-;; *(.fini4) /* Runtime exit. */
-;;
- .sect .fini0,"ax",@progbits
- .globl _exit
- .globl exit
- .weak exit
- farsym exit
- farsym _exit
-exit:
-_exit:
-
- .sect .fini4,"ax",@progbits
-fatal:
- cli
- wai
- bra fatal
-#endif
-
-#ifdef L_abort
-;;
-;; Abort operation. This is defined for the GCC testsuite.
-;;
- declare abort
-
- ldd #255 ;
-#ifdef mc68hc12
- trap #0x30
-#else
- .byte 0xCD ; Generate an illegal instruction trap
- .byte 0x03 ; The simulator catches this and stops.
-#endif
- jmp _exit
-#endif
-
-#ifdef L_cleanup
-;;
-;; Cleanup operation used by exit().
-;;
- declare _cleanup
-
- ret
-#endif
-
-;-----------------------------------------
-; required gcclib code
-;-----------------------------------------
-#ifdef L_memcpy
- declare memcpy
- declare __memcpy
-
- .weak memcpy
-;;;
-;;; void* memcpy(void*, const void*, size_t)
-;;;
-;;; D = dst Pmode
-;;; 2,sp = src Pmode
-;;; 4,sp = size HImode (size_t)
-;;;
-#ifdef mc68hc12
- ldx ARG(2),sp
- ldy ARG(4),sp
- pshd
- xgdy
- lsrd
- bcc Start
- movb 1,x+,1,y+
-Start:
- beq Done
-Loop:
- movw 2,x+,2,y+
- dbne d,Loop
-Done:
- puld
- ret
-#else
- xgdy
- tsx
- ldd ARG(4),x
- ldx ARG(2),x ; SRC = X, DST = Y
- cpd #0
- beq End
- pshy
- inca ; Correction for the deca below
-L0:
- psha ; Save high-counter part
-L1:
- ldaa 0,x ; Copy up to 256 bytes
- staa 0,y
- inx
- iny
- decb
- bne L1
- pula
- deca
- bne L0
- puly ; Restore Y to return the DST
-End:
- xgdy
- ret
-#endif
-#endif
-
-#ifdef L_memset
- declare memset
- declare __memset
-;;;
-;;; void* memset(void*, int value, size_t)
-;;;
-#ifndef __HAVE_SHORT_INT__
-;;; D = dst Pmode
-;;; 2,sp = src SImode
-;;; 6,sp = size HImode (size_t)
- val = ARG(5)
- size = ARG(6)
-#else
-;;; D = dst Pmode
-;;; 2,sp = src SImode
-;;; 6,sp = size HImode (size_t)
- val = ARG(3)
- size = ARG(4)
-#endif
-#ifdef mc68hc12
- xgdx
- ldab val,sp
- ldy size,sp
- pshx
- beq End
-Loop:
- stab 1,x+
- dbne y,Loop
-End:
- puld
- ret
-#else
- xgdx
- tsy
- ldab val,y
- ldy size,y ; DST = X, CNT = Y
- beq End
- pshx
-L0:
- stab 0,x ; Fill up to 256 bytes
- inx
- dey
- bne L0
- pulx ; Restore X to return the DST
-End:
- xgdx
- ret
-#endif
-#endif
-
-#ifdef L_adddi3
- declare ___adddi3
-
- tsx
- xgdy
- ldd ARG(8),x ; Add LSB
- addd ARG(16),x
- std 6,y ; Save (carry preserved)
-
- ldd ARG(6),x
- adcb ARG(15),x
- adca ARG(14),x
- std 4,y
-
- ldd ARG(4),x
- adcb ARG(13),x
- adca ARG(12),x
- std 2,y
-
- ldd ARG(2),x
- adcb ARG(11),x ; Add MSB
- adca ARG(10),x
- std 0,y
-
- xgdy
- ret
-#endif
-
-#ifdef L_subdi3
- declare ___subdi3
-
- tsx
- xgdy
- ldd ARG(8),x ; Subtract LSB
- subd ARG(16),x
- std 6,y ; Save, borrow preserved
-
- ldd ARG(6),x
- sbcb ARG(15),x
- sbca ARG(14),x
- std 4,y
-
- ldd ARG(4),x
- sbcb ARG(13),x
- sbca ARG(12),x
- std 2,y
-
- ldd ARG(2),x ; Subtract MSB
- sbcb ARG(11),x
- sbca ARG(10),x
- std 0,y
-
- xgdy ;
- ret
-#endif
-
-#ifdef L_notdi2
- declare ___notdi2
-
- tsy
- xgdx
- ldd ARG(8),y
- coma
- comb
- std 6,x
-
- ldd ARG(6),y
- coma
- comb
- std 4,x
-
- ldd ARG(4),y
- coma
- comb
- std 2,x
-
- ldd ARG(2),y
- coma
- comb
- std 0,x
- xgdx
- ret
-#endif
-
-#ifdef L_negsi2
- declare_near ___negsi2
-
- comb
- coma
- xgdx
- comb
- coma
- inx
- xgdx
- bne done
- inx
-done:
- rts
-#endif
-
-#ifdef L_one_cmplsi2
- declare_near ___one_cmplsi2
-
- comb
- coma
- xgdx
- comb
- coma
- xgdx
- rts
-#endif
-
-#ifdef L_ashlsi3
- declare_near ___ashlsi3
-
- xgdy
- clra
- andb #0x1f
- xgdy
- beq Return
-Loop:
- lsld
- xgdx
- rolb
- rola
- xgdx
- dey
- bne Loop
-Return:
- rts
-#endif
-
-#ifdef L_ashrsi3
- declare_near ___ashrsi3
-
- xgdy
- clra
- andb #0x1f
- xgdy
- beq Return
-Loop:
- xgdx
- asra
- rorb
- xgdx
- rora
- rorb
- dey
- bne Loop
-Return:
- rts
-#endif
-
-#ifdef L_lshrsi3
- declare_near ___lshrsi3
-
- xgdy
- clra
- andb #0x1f
- xgdy
- beq Return
-Loop:
- xgdx
- lsrd
- xgdx
- rora
- rorb
- dey
- bne Loop
-Return:
- rts
-#endif
-
-#ifdef L_lshrhi3
- declare_near ___lshrhi3
-
- cpx #16
- bge Return_zero
- cpx #0
- beq Return
-Loop:
- lsrd
- dex
- bne Loop
-Return:
- rts
-Return_zero:
- clra
- clrb
- rts
-#endif
-
-#ifdef L_lshlhi3
- declare_near ___lshlhi3
-
- cpx #16
- bge Return_zero
- cpx #0
- beq Return
-Loop:
- lsld
- dex
- bne Loop
-Return:
- rts
-Return_zero:
- clra
- clrb
- rts
-#endif
-
-#ifdef L_rotrhi3
- declare_near ___rotrhi3
-
-___rotrhi3:
- xgdx
- clra
- andb #0x0f
- xgdx
- beq Return
-Loop:
- tap
- rorb
- rora
- dex
- bne Loop
-Return:
- rts
-#endif
-
-#ifdef L_rotlhi3
- declare_near ___rotlhi3
-
-___rotlhi3:
- xgdx
- clra
- andb #0x0f
- xgdx
- beq Return
-Loop:
- asrb
- rolb
- rola
- rolb
- dex
- bne Loop
-Return:
- rts
-#endif
-
-#ifdef L_ashrhi3
- declare_near ___ashrhi3
-
- cpx #16
- bge Return_minus_1_or_zero
- cpx #0
- beq Return
-Loop:
- asra
- rorb
- dex
- bne Loop
-Return:
- rts
-Return_minus_1_or_zero:
- clrb
- tsta
- bpl Return_zero
- comb
-Return_zero:
- tba
- rts
-#endif
-
-#ifdef L_ashrqi3
- declare_near ___ashrqi3
-
- cmpa #8
- bge Return_minus_1_or_zero
- tsta
- beq Return
-Loop:
- asrb
- deca
- bne Loop
-Return:
- rts
-Return_minus_1_or_zero:
- clrb
- tstb
- bpl Return_zero
- coma
-Return_zero:
- tab
- rts
-#endif
-
-#ifdef L_lshlqi3
- declare_near ___lshlqi3
-
- cmpa #8
- bge Return_zero
- tsta
- beq Return
-Loop:
- lslb
- deca
- bne Loop
-Return:
- rts
-Return_zero:
- clrb
- rts
-#endif
-
-#ifdef L_divmodhi4
-#ifndef mc68hc12
-/* 68HC12 signed divisions are generated inline (idivs). */
-
- declare_near __divmodhi4
-
-;
-;; D = numerator
-;; X = denominator
-;;
-;; Result: D = D / X
-;; X = D % X
-;;
- tsta
- bpl Numerator_pos
- comb ; D = -D <=> D = (~D) + 1
- coma
- xgdx
- inx
- tsta
- bpl Numerator_neg_denominator_pos
-Numerator_neg_denominator_neg:
- comb ; X = -X
- coma
- addd #1
- xgdx
- idiv
- coma
- comb
- xgdx ; Remainder <= 0 and result >= 0
- inx
- rts
-
-Numerator_pos_denominator_pos:
- xgdx
- idiv
- xgdx ; Both values are >= 0
- rts
-
-Numerator_pos:
- xgdx
- tsta
- bpl Numerator_pos_denominator_pos
-Numerator_pos_denominator_neg:
- coma ; X = -X
- comb
- xgdx
- inx
- idiv
- xgdx ; Remainder >= 0 but result <= 0
- coma
- comb
- addd #1
- rts
-
-Numerator_neg_denominator_pos:
- xgdx
- idiv
- coma ; One value is > 0 and the other < 0
- comb ; Change the sign of result and remainder
- xgdx
- inx
- coma
- comb
- addd #1
- rts
-#endif /* !mc68hc12 */
-#endif
-
-#ifdef L_mulqi3
- declare_near ___mulqi3
-
-;
-; short __mulqi3(signed char a, signed char b);
-;
-; signed char a -> register A
-; signed char b -> register B
-;
-; returns the signed result of A * B in register D.
-;
- tsta
- bmi A_neg
- tstb
- bmi B_neg
- mul
- rts
-B_neg:
- negb
- bra A_or_B_neg
-A_neg:
- nega
- tstb
- bmi AB_neg
-A_or_B_neg:
- mul
- coma
- comb
- addd #1
- rts
-AB_neg:
- negb
- mul
- rts
-#endif
-
-#ifdef L_mulhi3
- declare_near ___mulhi3
-
-;
-;
-; unsigned short ___mulhi3(unsigned short a, unsigned short b)
-;
-; a = register D
-; b = register X
-;
-#ifdef mc68hc12
- pshx ; Preserve X
- exg x,y
- emul
- exg x,y
- pulx
- rts
-#else
-#ifdef NO_TMP
- ;
- ; 16-bit multiplication without temp memory location.
- ; (smaller but slower)
- ;
- pshx ; (4)
- ins ; (3)
- pshb ; (3)
- psha ; (3)
- pshx ; (4)
- pula ; (4)
- pulx ; (5)
- mul ; (10) B.high * A.low
- xgdx ; (3)
- mul ; (10) B.low * A.high
- abx ; (3)
- pula ; (4)
- pulb ; (4)
- mul ; (10) B.low * A.low
- pshx ; (4)
- tsx ; (3)
- adda 1,x ; (4)
- pulx ; (5)
- rts ; (5) 20 bytes
- ; ---
- ; 91 cycles
-#else
- stx *_.tmp ; (4)
- pshb ; (3)
- ldab *_.tmp+1 ; (3)
- mul ; (10) A.high * B.low
- ldaa *_.tmp ; (3)
- stab *_.tmp ; (3)
- pulb ; (4)
- pshb ; (4)
- mul ; (10) A.low * B.high
- addb *_.tmp ; (4)
- stab *_.tmp ; (3)
- ldaa *_.tmp+1 ; (3)
- pulb ; (4)
- mul ; (10) A.low * B.low
- adda *_.tmp ; (4)
- rts ; (5) 24/32 bytes
- ; 77/85 cycles
-#endif
-#endif
-#endif
-
-#ifdef L_mulhi32
-
-;
-;
-; unsigned long __mulhi32(unsigned short a, unsigned short b)
-;
-; a = register D
-; b = value on stack
-;
-; +---------------+
-; | B low | <- 7,x
-; +---------------+
-; | B high | <- 6,x
-; +---------------+
-; | PC low |
-; +---------------+
-; | PC high |
-; +---------------+
-; | Tmp low |
-; +---------------+
-; | Tmp high |
-; +---------------+
-; | A low |
-; +---------------+
-; | A high |
-; +---------------+ <- 0,x
-;
-;
-; <B-low> 5,x
-; <B-high> 4,x
-; <ret> 2,x
-; <A-low> 1,x
-; <A-high> 0,x
-;
- declare_near __mulhi32
-
-#ifdef mc68hc12
- ldy 2,sp
- emul
- exg x,y
- rts
-#else
- pshx ; Room for temp value
- pshb
- psha
- tsx
- ldab 6,x
- mul
- xgdy ; A.high * B.high
- ldab 7,x
- pula
- mul ; A.high * B.low
- std 2,x
- ldaa 1,x
- ldab 6,x
- mul ; A.low * B.high
- addd 2,x
- stab 2,x
- tab
- aby
- bcc N
- ldab #0xff
- aby
- iny
-N:
- ldab 7,x
- pula
- mul ; A.low * B.low
- adda 2,x
- pulx ; Drop temp location
- pshy ; Put high part in X
- pulx
- bcc Ret
- inx
-Ret:
- rts
-#endif
-#endif
-
-#ifdef L_mulsi3
-
-;
-; <B-low> 8,y
-; <B-high> 6,y
-; <ret> 4,y
-; <tmp> 2,y
-; <A-low> 0,y
-;
-; D,X -> A
-; Stack -> B
-;
-; The result is:
-;
-; (((A.low * B.high) + (A.high * B.low)) << 16) + (A.low * B.low)
-;
-;
-;
-
- declare __mulsi3
-
-#ifdef mc68hc12
- pshd ; Save A.low
- ldy ARG(4),sp
- emul ; A.low * B.high
- ldy ARG(6),sp
- exg x,d
- emul ; A.high * B.low
- leax d,x
- ldy ARG(6),sp
- puld
- emul ; A.low * B.low
- exg d,y
- leax d,x
- exg d,y
- ret
-#else
-B_low = ARG(8)
-B_high = ARG(6)
-A_low = 0
-A_high = 2
- pshx
- pshb
- psha
- tsy
-;
-; If B.low is 0, optimize into: (A.low * B.high) << 16
-;
- ldd B_low,y
- beq B_low_zero
-;
-; If A.high is 0, optimize into: (A.low * B.high) << 16 + (A.low * B.low)
-;
- cpx #0
- beq A_high_zero
- bsr ___mulhi3 ; A.high * B.low
-;
-; If A.low is 0, optimize into: (A.high * B.low) << 16
-;
- ldx A_low,y
- beq A_low_zero ; X = 0, D = A.high * B.low
- std 2,y
-;
-; If B.high is 0, we can avoid the (A.low * B.high) << 16 term.
-;
- ldd B_high,y
- beq B_high_zero
- bsr ___mulhi3 ; A.low * B.high
- addd 2,y
- std 2,y
-;
-; Here, we know that A.low and B.low are not 0.
-;
-B_high_zero:
- ldd B_low,y ; A.low is on the stack
- bsr __mulhi32 ; A.low * B.low
- xgdx
- tsy ; Y was clobbered, get it back
- addd 2,y
-A_low_zero: ; See A_low_zero_non_optimized below
- xgdx
-Return:
- ins
- ins
- ins
- ins
- ret
-;
-;
-; A_low_zero_non_optimized:
-;
-; At this step, X = 0 and D = (A.high * B.low)
-; Optimize into: (A.high * B.low) << 16
-;
-; xgdx
-; clra ; Since X was 0, clearing D is superfuous.
-; clrb
-; bra Return
-; ----------------
-; B.low == 0, the result is: (A.low * B.high) << 16
-;
-; At this step:
-; D = B.low = 0
-; X = A.high ?
-; A.low is at A_low,y ?
-; B.low is at B_low,y ?
-;
-B_low_zero:
- ldd A_low,y
- beq Zero1
- ldx B_high,y
- beq Zero2
- bsr ___mulhi3
-Zero1:
- xgdx
-Zero2:
- clra
- clrb
- bra Return
-; ----------------
-; A.high is 0, optimize into: (A.low * B.high) << 16 + (A.low * B.low)
-;
-; At this step:
-; D = B.low != 0
-; X = A.high = 0
-; A.low is at A_low,y ?
-; B.low is at B_low,y ?
-;
-A_high_zero:
- ldd A_low,y ; A.low
- beq Zero1
- ldx B_high,y ; B.high
- beq A_low_B_low
- bsr ___mulhi3
- std 2,y
- bra B_high_zero ; Do the (A.low * B.low) and the add.
-
-; ----------------
-; A.high and B.high are 0 optimize into: (A.low * B.low)
-;
-; At this step:
-; D = B.high = 0
-; X = A.low != 0
-; A.low is at A_low,y != 0
-; B.high is at B_high,y = 0
-;
-A_low_B_low:
- ldd B_low,y ; A.low is on the stack
- bsr __mulhi32
- bra Return
-#endif
-#endif
-
-#ifdef L_map_data
-
- .sect .install2,"ax",@progbits
- .globl __map_data_section
- .globl __data_image
-#ifdef mc68hc12
- .globl __data_section_size
-#endif
-__map_data_section:
-#ifdef mc68hc12
- ldx #__data_image
- ldy #__data_section_start
- ldd #__data_section_size
- beq Done
-Loop:
- movb 1,x+,1,y+
- dbne d,Loop
-#else
- ldx #__data_image
- ldy #__data_section_start
- bra Start_map
-Loop:
- ldaa 0,x
- staa 0,y
- inx
- iny
-Start_map:
- cpx #__data_image_end
- blo Loop
-#endif
-Done:
-
-#endif
-
-#ifdef L_init_bss
-
- .sect .install2,"ax",@progbits
- .globl __init_bss_section
-
-__init_bss_section:
- ldd #__bss_size
- beq Done
- ldx #__bss_start
-Loop:
-#ifdef mc68hc12
- clr 1,x+
- dbne d,Loop
-#else
- clr 0,x
- inx
- subd #1
- bne Loop
-#endif
-Done:
-
-#endif
-
-#ifdef L_ctor
-
-; End of constructor table
- .sect .install3,"ax",@progbits
- .globl __do_global_ctors
-
-__do_global_ctors:
- ; Start from the end - sizeof(void*)
- ldx #__CTOR_END__-2
-ctors_loop:
- cpx #__CTOR_LIST__
- blo ctors_done
- pshx
- ldx 0,x
- jsr 0,x
- pulx
- dex
- dex
- bra ctors_loop
-ctors_done:
-
-#endif
-
-#ifdef L_dtor
-
- .sect .fini3,"ax",@progbits
- .globl __do_global_dtors
-
-;;
-;; This piece of code is inserted in the _exit() code by the linker.
-;;
-__do_global_dtors:
- pshb ; Save exit code
- psha
- ldx #__DTOR_LIST__
-dtors_loop:
- cpx #__DTOR_END__
- bhs dtors_done
- pshx
- ldx 0,x
- jsr 0,x
- pulx
- inx
- inx
- bra dtors_loop
-dtors_done:
- pula ; Restore exit code
- pulb
-
-#endif
-
-#ifdef L_far_tramp
-#ifdef mc68hc12
- .sect .tramp,"ax",@progbits
- .globl __far_trampoline
-
-;; This is a trampoline used by the linker to invoke a function
-;; using rtc to return and being called with jsr/bsr.
-;; The trampoline generated is:
-;;
-;; foo_tramp:
-;; ldy #foo
-;; call __far_trampoline,page(foo)
-;;
-;; The linker transforms:
-;;
-;; jsr foo
-;;
-;; into
-;; jsr foo_tramp
-;;
-;; The linker generated trampoline and _far_trampoline must be in
-;; non-banked memory.
-;;
-__far_trampoline:
- movb 0,sp, 2,sp ; Copy page register below the caller's return
- leas 2,sp ; address.
- jmp 0,y ; We have a 'call/rtc' stack layout now
- ; and can jump to the far handler
- ; (whose memory bank is mapped due to the
- ; call to the trampoline).
-#endif
-
-#ifdef mc68hc11
- .sect .tramp,"ax",@progbits
- .globl __far_trampoline
-
-;; Trampoline generated by gcc for 68HC11:
-;;
-;; pshb
-;; ldab #%page(func)
-;; ldy #%addr(func)
-;; jmp __far_trampoline
-;;
-__far_trampoline:
- psha ; (2) Save function parameter (high)
- ;; <Read current page in A>
- psha ; (2)
- ;; <Set currenge page from B>
- pshx ; (4)
- tsx ; (3)
- ldab 4,x ; (4) Restore function parameter (low)
- ldaa 2,x ; (4) Get saved page number
- staa 4,x ; (4) Save it below return PC
- pulx ; (5)
- pula ; (3)
- pula ; (3) Restore function parameter (high)
- jmp 0,y ; (4)
-#endif
-#endif
-
-#ifdef L_call_far
-#ifdef mc68hc11
- .sect .tramp,"ax",@progbits
- .globl __call_a16
- .globl __call_a32
-;;
-;; The call methods are used for 68HC11 to support memory bank switching.
-;; Every far call is redirected to these call methods. Its purpose is to:
-;;
-;; 1/ Save the current page on the stack (1 byte to follow 68HC12 call frame)
-;; 2/ Install the new page
-;; 3/ Jump to the real function
-;;
-;; The page switching (get/save) is board dependent. The default provided
-;; here does nothing (just create the appropriate call frame).
-;;
-;; Call sequence (10 bytes, 13 cycles):
-;;
-;; ldx #page ; (3)
-;; ldy #func ; (4)
-;; jsr __call_a16 ; (6)
-;;
-;; Call trampoline (11 bytes, 19 cycles):
-;;
-__call_a16:
- ;; xgdx ; (3)
- ;; <Read current page in A> ; (3) ldaa _current_page
- psha ; (2)
- ;; <Set current page from B> ; (4) staa _current_page
- ;; xgdx ; (3)
- jmp 0,y ; (4)
-
-;;
-;; Call sequence (10 bytes, 14 cycles):
-;;
-;; pshb ; (2)
-;; ldab #page ; (2)
-;; ldy #func ; (4)
-;; jsr __call_a32 ; (6)
-;;
-;; Call trampoline (87 bytes, 57 cycles):
-;;
-__call_a32:
- pshx ; (4)
- psha ; (2)
- ;; <Read current page in A> ; (3) ldaa _current_page
- psha ; (2)
- ;; <Set current page from B> ; (4) staa _current_page
- tsx ; (3)
- ldab 6,x ; (4) Restore function parameter
- ldaa 5,x ; (4) Move PC return at good place
- staa 6,x ; (4)
- ldaa 4,x ; (4)
- staa 5,x ; (4)
- pula ; (3)
- staa 4,x ; (4)
- pula ; (3)
- pulx ; (5)
- jmp 0,y ; (4)
-#endif
-#endif
-
-#ifdef L_return_far
-#ifdef mc68hc11
- .sect .tramp,"ax",@progbits
- .globl __return_void
- .globl __return_16
- .globl __return_32
-
-__return_void:
- ;; pulb
- ;; <Set current page from B> (Board specific)
- ;; rts
-__return_16:
- ;; xgdx
- ;; pulb
- ;; <Set current page from B> (Board specific)
- ;; xgdx
- ;; rts
-__return_32:
- ;; xgdy
- ;; pulb
- ;; <Set current page from B> (Board specific)
- ;; xgdy
- ;; rts
- ins
- rts
-#endif
-#endif
-.Lend:
-;-----------------------------------------
-; end required gcclib code
-;-----------------------------------------
+++ /dev/null
-/* Startup code for M68HC11.
- Copyright (C) 1999, 2000, 2002, 2008, 2009 Free Software Foundation, Inc.
-
-This file is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3, or (at your option) any
-later version.
-
-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.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-;-----------------------------------------
-; startup code
-;-----------------------------------------
-
-#ifdef __HAVE_SHORT_INT__
- .mode mshort
-#else
- .mode mlong
-#endif
-
-#if defined(__USE_RTC__) && defined(mc68hc12)
- .macro jsr name
- call \name
- .endm
-#endif
-;;
-;;
-;; The linker concatenate the .install* sections in the following order:
-;;
-;; .install0 Setup the stack pointer
-;; .install1 Place holder for applications
-;; .install2 Optional installation of data section in memory
-;; .install3 Place holder for applications
-;; .install4 Invokes the main
-;;
- .sect .install0,"ax",@progbits
- .globl _start
-
-_start:
-;;
-;; At this step, the stack is not initialized and interrupts are masked.
-;; Applications only have 64 cycles to initialize some registers.
-;;
-;; To have a generic/configurable startup, initialize the stack to
-;; the end of some memory region. The _stack symbol is defined by
-;; the linker.
-;;
- lds #_stack
-
- .sect .install2,"ax",@progbits
-;;
-;; Call a specific initialization operation. The default is empty.
-;; It can be overridden by applications. It is intended to initialize
-;; the 68hc11 registers. Function prototype is:
-;;
-;; int __premain(void);
-;;
- jsr __premain
-
-;;
-;;
-;;
- .sect .install4,"ax",@progbits
- jsr main
-fatal:
- jsr exit
- bra fatal
-
-;-----------------------------------------
-; end startup code
-;-----------------------------------------
-;; Force loading of data section mapping and bss clear
- .2byte __map_data_section
- .2byte __init_bss_section
+++ /dev/null
-/* Prototypes for exported functions defined in m68hc11.c
- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2009, 2010
- Free Software Foundation, Inc.
- Contributed by Stephane Carrez (stcarrez@nerim.fr)
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-
-extern int hard_regno_mode_ok (int, enum machine_mode);
-extern int m68hc11_hard_regno_rename_ok (int, int);
-
-extern int m68hc11_total_frame_size (void);
-extern int m68hc11_initial_frame_pointer_offset (void);
-extern int m68hc11_initial_elimination_offset (int, int);
-
-extern void expand_prologue (void);
-extern void expand_epilogue (void);
-
-#ifdef RTX_CODE
-extern int m68hc11_auto_inc_p (rtx);
-
-extern rtx m68hc11_expand_compare_and_branch (enum rtx_code, rtx, rtx, rtx);
-extern enum reg_class preferred_reload_class (rtx, enum reg_class);
-
-extern void m68hc11_notice_update_cc (rtx, rtx);
-extern void m68hc11_notice_keep_cc (rtx);
-
-extern void m68hc11_gen_movqi (rtx, rtx*);
-extern void m68hc11_gen_movhi (rtx, rtx*);
-extern void m68hc11_gen_rotate (enum rtx_code, rtx, rtx*);
-
-extern void m68hc11_output_swap (rtx, rtx*);
-
-extern int next_insn_test_reg (rtx, rtx);
-
-extern int m68hc11_reload_operands (rtx*);
-
-extern int dead_register_here (rtx, rtx);
-
-extern int push_pop_operand_p (rtx);
-extern void m68hc11_split_move (rtx, rtx, rtx);
-extern void m68hc11_split_compare_and_branch (enum rtx_code,
- rtx, rtx, rtx);
-
-extern rtx m68hc11_gen_lowpart (enum machine_mode, rtx);
-extern rtx m68hc11_gen_highpart (enum machine_mode, rtx);
-
-#ifdef HAVE_MACHINE_MODES
-extern int m68hc11_memory_move_cost (enum machine_mode, enum reg_class, int);
-extern int m68hc11_register_move_cost (enum machine_mode,
- enum reg_class, enum reg_class);
-
-extern void m68hc11_emit_libcall (const char*, enum rtx_code,
- enum machine_mode, enum machine_mode,
- int, rtx*);
-extern int m68hc11_small_indexed_indirect_p (rtx, enum machine_mode);
-extern int m68hc11_symbolic_p (rtx, enum machine_mode);
-extern int m68hc11_indirect_p (rtx, enum machine_mode);
-extern int go_if_legitimate_address2 (rtx, enum machine_mode, int);
-
-extern int reg_or_indexed_operand (rtx,enum machine_mode);
-extern int memory_indexed_operand (rtx, enum machine_mode);
-
-#ifdef RTX_CODE
-extern void m68hc11_split_logical (enum machine_mode, enum rtx_code, rtx*);
-#endif
-
-extern int m68hc11_register_indirect_p (rtx, enum machine_mode);
-extern int m68hc11_valid_addressing_p (rtx, enum machine_mode, int);
-
-extern int symbolic_memory_operand (rtx, enum machine_mode);
-
-extern int memory_reload_operand (rtx, enum machine_mode);
-extern int arith_src_operand (rtx, enum machine_mode);
-extern int soft_reg_operand (rtx, enum machine_mode);
-
-extern void m68hc11_init_cumulative_args (CUMULATIVE_ARGS*, tree, rtx);
-
-#ifdef ARGS_SIZE_RTX
-extern enum direction m68hc11_function_arg_padding (enum machine_mode,
- const_tree);
-#endif
-
-extern void m68hc11_function_epilogue (FILE*,int);
-
-extern int m68hc11_is_far_symbol (rtx);
-extern int m68hc11_is_trap_symbol (rtx);
-extern int m68hc11_page0_symbol_p (rtx x);
-
-extern HOST_WIDE_INT m68hc11_min_offset;
-extern HOST_WIDE_INT m68hc11_max_offset;
-extern int m68hc11_addr_mode;
-
-#endif /* HAVE_MACHINE_MODES */
-#endif /* RTX_CODE */
+++ /dev/null
-/* Subroutines for code generation on Motorola 68HC11 and 68HC12.
- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
- 2009, 2010 Free Software Foundation, Inc.
- Contributed by Stephane Carrez (stcarrez@nerim.fr)
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>.
-
-Note:
- A first 68HC11 port was made by Otto Lind (otto@coactive.com)
- on gcc 2.6.3. I have used it as a starting point for this port.
- However, this new port is a complete re-write. Its internal
- design is completely different. The generated code is not
- compatible with the gcc 2.6.3 port.
-
- The gcc 2.6.3 port is available at:
-
- ftp.unina.it/pub/electronics/motorola/68hc11/gcc/gcc-6811-fsf.tar.gz
-
-*/
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "tm.h"
-#include "rtl.h"
-#include "tree.h"
-#include "expr.h"
-#include "tm_p.h"
-#include "regs.h"
-#include "hard-reg-set.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 "libfuncs.h"
-#include "diagnostic-core.h"
-#include "basic-block.h"
-#include "function.h"
-#include "ggc.h"
-#include "reload.h"
-#include "target.h"
-#include "target-def.h"
-#include "df.h"
-
-static void m68hc11_option_override (void);
-static void emit_move_after_reload (rtx, rtx, rtx);
-static rtx simplify_logical (enum machine_mode, int, rtx, rtx *);
-static void m68hc11_emit_logical (enum machine_mode, enum rtx_code, rtx *);
-static void m68hc11_reorg (void);
-static bool m68hc11_legitimate_address_p_1 (enum machine_mode, rtx, bool);
-static bool m68hc11_legitimate_address_p (enum machine_mode, rtx, bool);
-static rtx m68hc11_expand_compare (enum rtx_code, rtx, rtx);
-static int must_parenthesize (rtx);
-static int m68hc11_address_cost (rtx, bool);
-static int m68hc11_shift_cost (enum machine_mode, rtx, int);
-static int m68hc11_rtx_costs_1 (rtx, enum rtx_code, enum rtx_code);
-static bool m68hc11_rtx_costs (rtx, int, int, int *, bool);
-static tree m68hc11_handle_fntype_attribute (tree *, tree, tree, int, bool *);
-static tree m68hc11_handle_page0_attribute (tree *, tree, tree, int, bool *);
-static bool m68hc11_class_likely_spilled_p (reg_class_t);
-
-void create_regs_rtx (void);
-
-static void asm_print_register (FILE *, int);
-static void m68hc11_print_operand (FILE *, rtx, int);
-static void m68hc11_print_operand_address (FILE *, rtx);
-static void m68hc11_output_function_epilogue (FILE *, HOST_WIDE_INT);
-static void m68hc11_asm_out_constructor (rtx, int);
-static void m68hc11_asm_out_destructor (rtx, int);
-static void m68hc11_file_start (void);
-static void m68hc11_encode_section_info (tree, rtx, int);
-static const char *m68hc11_strip_name_encoding (const char* str);
-static unsigned int m68hc11_section_type_flags (tree, const char*, int);
-static int autoinc_mode (rtx);
-static int m68hc11_make_autoinc_notes (rtx *, void *);
-static void m68hc11_init_libfuncs (void);
-static rtx m68hc11_struct_value_rtx (tree, int);
-static bool m68hc11_return_in_memory (const_tree, const_tree);
-static bool m68hc11_can_eliminate (const int, const int);
-static void m68hc11_conditional_register_usage (void);
-static void m68hc11_trampoline_init (rtx, tree, rtx);
-
-static rtx m68hc11_function_arg (CUMULATIVE_ARGS*, enum machine_mode,
- const_tree, bool);
-static void m68hc11_function_arg_advance (CUMULATIVE_ARGS*, enum machine_mode,
- const_tree, bool);
-
-/* Must be set to 1 to produce debug messages. */
-int debug_m6811 = 0;
-
-extern FILE *asm_out_file;
-
-rtx ix_reg;
-rtx iy_reg;
-rtx d_reg;
-rtx m68hc11_soft_tmp_reg;
-static GTY(()) rtx stack_push_word;
-static GTY(()) rtx stack_pop_word;
-static GTY(()) rtx z_reg;
-static GTY(()) rtx z_reg_qi;
-static int regs_inited = 0;
-
-/* Set to 1 by expand_prologue() when the function is an interrupt handler. */
-int current_function_interrupt;
-
-/* Set to 1 by expand_prologue() when the function is a trap handler. */
-int current_function_trap;
-
-/* Set to 1 when the current function is placed in 68HC12 banked
- memory and must return with rtc. */
-int current_function_far;
-
-/* Min offset that is valid for the indirect addressing mode. */
-HOST_WIDE_INT m68hc11_min_offset = 0;
-
-/* Max offset that is valid for the indirect addressing mode. */
-HOST_WIDE_INT m68hc11_max_offset = 256;
-
-/* The class value for base registers. */
-enum reg_class m68hc11_base_reg_class = A_REGS;
-
-/* The class value for index registers. This is NO_REGS for 68HC11. */
-enum reg_class m68hc11_index_reg_class = NO_REGS;
-
-enum reg_class m68hc11_tmp_regs_class = NO_REGS;
-
-/* Tables that tell whether a given hard register is valid for
- a base or an index register. It is filled at init time depending
- on the target processor. */
-unsigned char m68hc11_reg_valid_for_base[FIRST_PSEUDO_REGISTER];
-unsigned char m68hc11_reg_valid_for_index[FIRST_PSEUDO_REGISTER];
-
-/* A correction offset which is applied to the stack pointer.
- This is 1 for 68HC11 and 0 for 68HC12. */
-int m68hc11_sp_correction;
-
-int m68hc11_addr_mode;
-int m68hc11_mov_addr_mode;
-\f
-
-const struct processor_costs *m68hc11_cost;
-
-/* Costs for a 68HC11. */
-static const struct processor_costs m6811_cost = {
- /* add */
- COSTS_N_INSNS (2),
- /* logical */
- COSTS_N_INSNS (2),
- /* non-constant shift */
- COSTS_N_INSNS (20),
- /* shiftQI const */
- { COSTS_N_INSNS (0), COSTS_N_INSNS (1), COSTS_N_INSNS (2),
- COSTS_N_INSNS (3), COSTS_N_INSNS (4), COSTS_N_INSNS (3),
- COSTS_N_INSNS (2), COSTS_N_INSNS (1) },
-
- /* shiftHI const */
- { COSTS_N_INSNS (0), COSTS_N_INSNS (1), COSTS_N_INSNS (4),
- COSTS_N_INSNS (6), COSTS_N_INSNS (8), COSTS_N_INSNS (6),
- COSTS_N_INSNS (4), COSTS_N_INSNS (2),
- COSTS_N_INSNS (2), COSTS_N_INSNS (4),
- COSTS_N_INSNS (6), COSTS_N_INSNS (8), COSTS_N_INSNS (10),
- COSTS_N_INSNS (8), COSTS_N_INSNS (6), COSTS_N_INSNS (4)
- },
- /* mulQI */
- COSTS_N_INSNS (20),
- /* mulHI */
- COSTS_N_INSNS (20 * 4),
- /* mulSI */
- COSTS_N_INSNS (20 * 16),
- /* divQI */
- COSTS_N_INSNS (20),
- /* divHI */
- COSTS_N_INSNS (80),
- /* divSI */
- COSTS_N_INSNS (100)
-};
-
-/* Costs for a 68HC12. */
-static const struct processor_costs m6812_cost = {
- /* add */
- COSTS_N_INSNS (2),
- /* logical */
- COSTS_N_INSNS (2),
- /* non-constant shift */
- COSTS_N_INSNS (20),
- /* shiftQI const */
- { COSTS_N_INSNS (0), COSTS_N_INSNS (1), COSTS_N_INSNS (2),
- COSTS_N_INSNS (3), COSTS_N_INSNS (4), COSTS_N_INSNS (3),
- COSTS_N_INSNS (2), COSTS_N_INSNS (1) },
-
- /* shiftHI const */
- { COSTS_N_INSNS (0), COSTS_N_INSNS (1), COSTS_N_INSNS (4),
- COSTS_N_INSNS (6), COSTS_N_INSNS (8), COSTS_N_INSNS (6),
- COSTS_N_INSNS (4), COSTS_N_INSNS (2),
- COSTS_N_INSNS (2), COSTS_N_INSNS (4), COSTS_N_INSNS (6),
- COSTS_N_INSNS (8), COSTS_N_INSNS (10), COSTS_N_INSNS (8),
- COSTS_N_INSNS (6), COSTS_N_INSNS (4)
- },
- /* mulQI */
- COSTS_N_INSNS (3),
- /* mulHI */
- COSTS_N_INSNS (3),
- /* mulSI */
- COSTS_N_INSNS (3 * 4),
- /* divQI */
- COSTS_N_INSNS (12),
- /* divHI */
- COSTS_N_INSNS (12),
- /* divSI */
- COSTS_N_INSNS (100)
-};
-\f
-/* M68HC11 specific attributes. */
-
-static const struct attribute_spec m68hc11_attribute_table[] =
-{
- /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
- affects_type_identity } */
- { "interrupt", 0, 0, false, true, true, m68hc11_handle_fntype_attribute,
- false },
- { "trap", 0, 0, false, true, true, m68hc11_handle_fntype_attribute,
- false },
- { "far", 0, 0, false, true, true, m68hc11_handle_fntype_attribute,
- false },
- { "near", 0, 0, false, true, true, m68hc11_handle_fntype_attribute,
- false },
- { "page0", 0, 0, false, false, false, m68hc11_handle_page0_attribute,
- false },
- { NULL, 0, 0, false, false, false, NULL, false }
-};
-\f
-/* Initialize the GCC target structure. */
-#undef TARGET_ATTRIBUTE_TABLE
-#define TARGET_ATTRIBUTE_TABLE m68hc11_attribute_table
-
-#undef TARGET_ASM_ALIGNED_HI_OP
-#define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
-
-#undef TARGET_PRINT_OPERAND
-#define TARGET_PRINT_OPERAND m68hc11_print_operand
-#undef TARGET_PRINT_OPERAND_ADDRESS
-#define TARGET_PRINT_OPERAND_ADDRESS m68hc11_print_operand_address
-
-#undef TARGET_ASM_FUNCTION_EPILOGUE
-#define TARGET_ASM_FUNCTION_EPILOGUE m68hc11_output_function_epilogue
-
-#undef TARGET_ASM_FILE_START
-#define TARGET_ASM_FILE_START m68hc11_file_start
-#undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
-#define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
-
-#undef TARGET_DEFAULT_TARGET_FLAGS
-#define TARGET_DEFAULT_TARGET_FLAGS TARGET_DEFAULT
-
-#undef TARGET_ENCODE_SECTION_INFO
-#define TARGET_ENCODE_SECTION_INFO m68hc11_encode_section_info
-
-#undef TARGET_SECTION_TYPE_FLAGS
-#define TARGET_SECTION_TYPE_FLAGS m68hc11_section_type_flags
-
-#undef TARGET_RTX_COSTS
-#define TARGET_RTX_COSTS m68hc11_rtx_costs
-#undef TARGET_ADDRESS_COST
-#define TARGET_ADDRESS_COST m68hc11_address_cost
-
-#undef TARGET_MACHINE_DEPENDENT_REORG
-#define TARGET_MACHINE_DEPENDENT_REORG m68hc11_reorg
-
-#undef TARGET_INIT_LIBFUNCS
-#define TARGET_INIT_LIBFUNCS m68hc11_init_libfuncs
-
-#undef TARGET_FUNCTION_ARG
-#define TARGET_FUNCTION_ARG m68hc11_function_arg
-#undef TARGET_FUNCTION_ARG_ADVANCE
-#define TARGET_FUNCTION_ARG_ADVANCE m68hc11_function_arg_advance
-
-#undef TARGET_STRUCT_VALUE_RTX
-#define TARGET_STRUCT_VALUE_RTX m68hc11_struct_value_rtx
-#undef TARGET_RETURN_IN_MEMORY
-#define TARGET_RETURN_IN_MEMORY m68hc11_return_in_memory
-#undef TARGET_CALLEE_COPIES
-#define TARGET_CALLEE_COPIES hook_callee_copies_named
-
-#undef TARGET_STRIP_NAME_ENCODING
-#define TARGET_STRIP_NAME_ENCODING m68hc11_strip_name_encoding
-
-#undef TARGET_LEGITIMATE_ADDRESS_P
-#define TARGET_LEGITIMATE_ADDRESS_P m68hc11_legitimate_address_p
-
-#undef TARGET_CAN_ELIMINATE
-#define TARGET_CAN_ELIMINATE m68hc11_can_eliminate
-
-#undef TARGET_CONDITIONAL_REGISTER_USAGE
-#define TARGET_CONDITIONAL_REGISTER_USAGE m68hc11_conditional_register_usage
-
-#undef TARGET_CLASS_LIKELY_SPILLED_P
-#define TARGET_CLASS_LIKELY_SPILLED_P m68hc11_class_likely_spilled_p
-
-#undef TARGET_TRAMPOLINE_INIT
-#define TARGET_TRAMPOLINE_INIT m68hc11_trampoline_init
-
-#undef TARGET_OPTION_OVERRIDE
-#define TARGET_OPTION_OVERRIDE m68hc11_option_override
-
-struct gcc_target targetm = TARGET_INITIALIZER;
-\f
-static void
-m68hc11_option_override (void)
-{
- memset (m68hc11_reg_valid_for_index, 0,
- sizeof (m68hc11_reg_valid_for_index));
- memset (m68hc11_reg_valid_for_base, 0, sizeof (m68hc11_reg_valid_for_base));
-
- /* Compilation with -fpic generates a wrong code. */
- if (flag_pic)
- {
- warning (0, "-f%s ignored for 68HC11/68HC12 (not supported)",
- (flag_pic > 1) ? "PIC" : "pic");
- flag_pic = 0;
- }
-
- /* Do not enable -fweb because it breaks the 32-bit shift patterns
- by breaking the match_dup of those patterns. The shift patterns
- will no longer be recognized after that. */
- flag_web = 0;
-
- /* Configure for a 68hc11 processor. */
- if (TARGET_M6811)
- {
- target_flags &= ~(TARGET_AUTO_INC_DEC | TARGET_MIN_MAX);
- m68hc11_cost = &m6811_cost;
- m68hc11_min_offset = 0;
- m68hc11_max_offset = 256;
- m68hc11_index_reg_class = NO_REGS;
- m68hc11_base_reg_class = A_REGS;
- m68hc11_reg_valid_for_base[HARD_X_REGNUM] = 1;
- m68hc11_reg_valid_for_base[HARD_Y_REGNUM] = 1;
- m68hc11_reg_valid_for_base[HARD_Z_REGNUM] = 1;
- m68hc11_sp_correction = 1;
- m68hc11_tmp_regs_class = D_REGS;
- m68hc11_addr_mode = ADDR_OFFSET;
- m68hc11_mov_addr_mode = 0;
- if (m68hc11_soft_reg_count < 0)
- m68hc11_soft_reg_count = 4;
- }
-
- /* Configure for a 68hc12 processor. */
- if (TARGET_M6812)
- {
- m68hc11_cost = &m6812_cost;
- m68hc11_min_offset = -65536;
- m68hc11_max_offset = 65536;
- m68hc11_index_reg_class = D_REGS;
- m68hc11_base_reg_class = A_OR_SP_REGS;
- m68hc11_reg_valid_for_base[HARD_X_REGNUM] = 1;
- m68hc11_reg_valid_for_base[HARD_Y_REGNUM] = 1;
- m68hc11_reg_valid_for_base[HARD_Z_REGNUM] = 1;
- m68hc11_reg_valid_for_base[HARD_SP_REGNUM] = 1;
- m68hc11_reg_valid_for_index[HARD_D_REGNUM] = 1;
- m68hc11_sp_correction = 0;
- m68hc11_tmp_regs_class = TMP_REGS;
- m68hc11_addr_mode = ADDR_INDIRECT | ADDR_OFFSET | ADDR_CONST
- | (TARGET_AUTO_INC_DEC ? ADDR_INCDEC : 0);
- m68hc11_mov_addr_mode = ADDR_OFFSET | ADDR_CONST
- | (TARGET_AUTO_INC_DEC ? ADDR_INCDEC : 0);
- target_flags |= MASK_NO_DIRECT_MODE;
- if (m68hc11_soft_reg_count < 0)
- m68hc11_soft_reg_count = 0;
-
- if (TARGET_LONG_CALLS)
- current_function_far = 1;
- }
-}
-
-
-/* The soft-registers are disabled or enabled according to the
- -msoft-reg-count=<n> option. */
-
-static void
-m68hc11_conditional_register_usage (void)
-{
- int i;
-
- if (m68hc11_soft_reg_count > SOFT_REG_LAST - SOFT_REG_FIRST)
- m68hc11_soft_reg_count = SOFT_REG_LAST - SOFT_REG_FIRST;
-
- for (i = SOFT_REG_FIRST + m68hc11_soft_reg_count; i < SOFT_REG_LAST; i++)
- {
- fixed_regs[i] = 1;
- call_used_regs[i] = 1;
- }
-
- /* For 68HC12, the Z register emulation is not necessary when the
- frame pointer is not used. The frame pointer is eliminated and
- replaced by the stack register (which is a BASE_REG_CLASS). */
- if (TARGET_M6812 && flag_omit_frame_pointer && optimize)
- {
- fixed_regs[HARD_Z_REGNUM] = 1;
- }
-}
-\f
-
-/* Reload and register operations. */
-
-
-void
-create_regs_rtx (void)
-{
- /* regs_inited = 1; */
- ix_reg = gen_rtx_REG (HImode, HARD_X_REGNUM);
- iy_reg = gen_rtx_REG (HImode, HARD_Y_REGNUM);
- d_reg = gen_rtx_REG (HImode, HARD_D_REGNUM);
- m68hc11_soft_tmp_reg = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
-
- stack_push_word = gen_rtx_MEM (HImode,
- gen_rtx_PRE_DEC (HImode,
- gen_rtx_REG (HImode, HARD_SP_REGNUM)));
- stack_pop_word = gen_rtx_MEM (HImode,
- gen_rtx_POST_INC (HImode,
- gen_rtx_REG (HImode, HARD_SP_REGNUM)));
-
-}
-
-/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
- - 8-bit values are stored anywhere (except the SP register).
- - 16-bit values can be stored in any register whose mode is 16
- - 32-bit values can be stored in D, X registers or in a soft register
- (except the last one because we need 2 soft registers)
- - Values whose size is > 32 bit are not stored in real hard
- registers. They may be stored in soft registers if there are
- enough of them. */
-int
-hard_regno_mode_ok (int regno, enum machine_mode mode)
-{
- switch (GET_MODE_SIZE (mode))
- {
- case 8:
- return S_REGNO_P (regno) && m68hc11_soft_reg_count >= 4;
-
- case 4:
- return (X_REGNO_P (regno)
- || (S_REGNO_P (regno) && m68hc11_soft_reg_count >= 2));
-
- case 2:
- return G_REGNO_P (regno);
-
- case 1:
- /* We have to accept a QImode in X or Y registers. Otherwise, the
- reload pass will fail when some (SUBREG:QI (REG:HI X)) are defined
- in the insns. Reload fails if the insn rejects the register class 'a'
- as well as if it accepts it. Patterns that failed were
- zero_extend_qihi2 and iorqi3. */
-
- return G_REGNO_P (regno) && !SP_REGNO_P (regno);
-
- default:
- return 0;
- }
-}
-
-int
-m68hc11_hard_regno_rename_ok (int reg1, int reg2)
-{
- /* Don't accept renaming to Z register. We will replace it to
- X,Y or D during machine reorg pass. */
- if (reg2 == HARD_Z_REGNUM)
- return 0;
-
- /* Don't accept renaming D,X to Y register as the code will be bigger. */
- if (TARGET_M6811 && reg2 == HARD_Y_REGNUM
- && (D_REGNO_P (reg1) || X_REGNO_P (reg1)))
- return 0;
-
- return 1;
-}
-
-enum reg_class
-preferred_reload_class (rtx operand, enum reg_class rclass)
-{
- enum machine_mode mode;
-
- mode = GET_MODE (operand);
-
- if (debug_m6811)
- {
- printf ("Preferred reload: (class=%s): ", reg_class_names[rclass]);
- }
-
- if (rclass == D_OR_A_OR_S_REGS && SP_REG_P (operand))
- return m68hc11_base_reg_class;
-
- if (rclass >= S_REGS && (GET_CODE (operand) == MEM
- || GET_CODE (operand) == CONST_INT))
- {
- /* S_REGS class must not be used. The movhi template does not
- work to move a memory to a soft register.
- Restrict to a hard reg. */
- switch (rclass)
- {
- default:
- case G_REGS:
- case D_OR_A_OR_S_REGS:
- rclass = A_OR_D_REGS;
- break;
- case A_OR_S_REGS:
- rclass = A_REGS;
- break;
- case D_OR_SP_OR_S_REGS:
- rclass = D_OR_SP_REGS;
- break;
- case D_OR_Y_OR_S_REGS:
- rclass = D_OR_Y_REGS;
- break;
- case D_OR_X_OR_S_REGS:
- rclass = D_OR_X_REGS;
- break;
- case SP_OR_S_REGS:
- rclass = SP_REGS;
- break;
- case Y_OR_S_REGS:
- rclass = Y_REGS;
- break;
- case X_OR_S_REGS:
- rclass = X_REGS;
- break;
- case D_OR_S_REGS:
- rclass = D_REGS;
- }
- }
- else if (rclass == Y_REGS && GET_CODE (operand) == MEM)
- {
- rclass = Y_REGS;
- }
- else if (rclass == A_OR_D_REGS && GET_MODE_SIZE (mode) == 4)
- {
- rclass = D_OR_X_REGS;
- }
- else if (rclass >= S_REGS && S_REG_P (operand))
- {
- switch (rclass)
- {
- default:
- case G_REGS:
- case D_OR_A_OR_S_REGS:
- rclass = A_OR_D_REGS;
- break;
- case A_OR_S_REGS:
- rclass = A_REGS;
- break;
- case D_OR_SP_OR_S_REGS:
- rclass = D_OR_SP_REGS;
- break;
- case D_OR_Y_OR_S_REGS:
- rclass = D_OR_Y_REGS;
- break;
- case D_OR_X_OR_S_REGS:
- rclass = D_OR_X_REGS;
- break;
- case SP_OR_S_REGS:
- rclass = SP_REGS;
- break;
- case Y_OR_S_REGS:
- rclass = Y_REGS;
- break;
- case X_OR_S_REGS:
- rclass = X_REGS;
- break;
- case D_OR_S_REGS:
- rclass = D_REGS;
- }
- }
- else if (rclass >= S_REGS)
- {
- if (debug_m6811)
- {
- printf ("Class = %s for: ", reg_class_names[rclass]);
- fflush (stdout);
- debug_rtx (operand);
- }
- }
-
- if (debug_m6811)
- {
- printf (" => class=%s\n", reg_class_names[rclass]);
- fflush (stdout);
- debug_rtx (operand);
- }
-
- return rclass;
-}
-
-/* Implement TARGET_CLASS_LIKELY_SPILLED_P. */
-
-static bool
-m68hc11_class_likely_spilled_p (reg_class_t rclass)
-{
- switch (rclass)
- {
- case D_REGS:
- case X_REGS:
- case Y_REGS:
- case A_REGS:
- case SP_REGS:
- case D_OR_X_REGS:
- case D_OR_Y_REGS:
- case X_OR_SP_REGS:
- case Y_OR_SP_REGS:
- case D_OR_SP_REGS:
- return true;
-
- default:
- break;
- }
-
- return false;
-}
-
-/* Return 1 if the operand is a valid indexed addressing mode.
- For 68hc11: n,r with n in [0..255] and r in A_REGS class
- For 68hc12: n,r no constraint on the constant, r in A_REGS class. */
-int
-m68hc11_valid_addressing_p (rtx operand, enum machine_mode mode, int addr_mode)
-{
- rtx base, offset;
-
- switch (GET_CODE (operand))
- {
- case MEM:
- if ((addr_mode & ADDR_INDIRECT) && GET_MODE_SIZE (mode) <= 2)
- return m68hc11_valid_addressing_p (XEXP (operand, 0), mode,
- addr_mode & (ADDR_STRICT | ADDR_OFFSET));
- return 0;
-
- case POST_INC:
- case PRE_INC:
- case POST_DEC:
- case PRE_DEC:
- if (addr_mode & ADDR_INCDEC)
- return m68hc11_valid_addressing_p (XEXP (operand, 0), mode,
- addr_mode & ADDR_STRICT);
- return 0;
-
- case PLUS:
- base = XEXP (operand, 0);
- if (GET_CODE (base) == MEM)
- return 0;
-
- offset = XEXP (operand, 1);
- if (GET_CODE (offset) == MEM)
- return 0;
-
- /* Indexed addressing mode with 2 registers. */
- if (GET_CODE (base) == REG && GET_CODE (offset) == REG)
- {
- if (!(addr_mode & ADDR_INDEXED))
- return 0;
-
- addr_mode &= ADDR_STRICT;
- if (REGNO_OK_FOR_BASE_P2 (REGNO (base), addr_mode)
- && REGNO_OK_FOR_INDEX_P2 (REGNO (offset), addr_mode))
- return 1;
-
- if (REGNO_OK_FOR_BASE_P2 (REGNO (offset), addr_mode)
- && REGNO_OK_FOR_INDEX_P2 (REGNO (base), addr_mode))
- return 1;
-
- return 0;
- }
-
- if (!(addr_mode & ADDR_OFFSET))
- return 0;
-
- if (GET_CODE (base) == REG)
- {
- if (!VALID_CONSTANT_OFFSET_P (offset, mode))
- return 0;
-
- if (!(addr_mode & ADDR_STRICT))
- return 1;
-
- return REGNO_OK_FOR_BASE_P2 (REGNO (base), 1);
- }
-
- if (GET_CODE (offset) == REG)
- {
- if (!VALID_CONSTANT_OFFSET_P (base, mode))
- return 0;
-
- if (!(addr_mode & ADDR_STRICT))
- return 1;
-
- return REGNO_OK_FOR_BASE_P2 (REGNO (offset), 1);
- }
- return 0;
-
- case REG:
- return REGNO_OK_FOR_BASE_P2 (REGNO (operand), addr_mode & ADDR_STRICT);
-
- case CONST_INT:
- if (addr_mode & ADDR_CONST)
- return VALID_CONSTANT_OFFSET_P (operand, mode);
- return 0;
-
- default:
- return 0;
- }
-}
-
-/* Returns 1 if the operand fits in a 68HC11 indirect mode or in
- a 68HC12 1-byte index addressing mode. */
-int
-m68hc11_small_indexed_indirect_p (rtx operand, enum machine_mode mode)
-{
- rtx base, offset;
- int addr_mode;
-
- if (GET_CODE (operand) == REG && reload_in_progress
- && REGNO (operand) >= FIRST_PSEUDO_REGISTER
- && reg_equiv_memory_loc[REGNO (operand)])
- {
- operand = reg_equiv_memory_loc[REGNO (operand)];
- operand = eliminate_regs (operand, VOIDmode, NULL_RTX);
- }
-
- if (GET_CODE (operand) != MEM)
- return 0;
-
- operand = XEXP (operand, 0);
- if (CONSTANT_ADDRESS_P (operand))
- return 1;
-
- if (PUSH_POP_ADDRESS_P (operand))
- return 1;
-
- addr_mode = m68hc11_mov_addr_mode | (reload_completed ? ADDR_STRICT : 0);
- if (!m68hc11_valid_addressing_p (operand, mode, addr_mode))
- return 0;
-
- if (TARGET_M6812 && GET_CODE (operand) == PLUS
- && (reload_completed | reload_in_progress))
- {
- base = XEXP (operand, 0);
- offset = XEXP (operand, 1);
-
- /* The offset can be a symbol address and this is too big
- for the operand constraint. */
- if (GET_CODE (base) != CONST_INT && GET_CODE (offset) != CONST_INT)
- return 0;
-
- if (GET_CODE (base) == CONST_INT)
- offset = base;
-
- switch (GET_MODE_SIZE (mode))
- {
- case 8:
- if (INTVAL (offset) < -16 + 6 || INTVAL (offset) > 15 - 6)
- return 0;
- break;
-
- case 4:
- if (INTVAL (offset) < -16 + 2 || INTVAL (offset) > 15 - 2)
- return 0;
- break;
-
- default:
- if (INTVAL (offset) < -16 || INTVAL (offset) > 15)
- return 0;
- break;
- }
- }
- return 1;
-}
-
-int
-m68hc11_register_indirect_p (rtx operand, enum machine_mode mode)
-{
- int addr_mode;
-
- if (GET_CODE (operand) == REG && reload_in_progress
- && REGNO (operand) >= FIRST_PSEUDO_REGISTER
- && reg_equiv_memory_loc[REGNO (operand)])
- {
- operand = reg_equiv_memory_loc[REGNO (operand)];
- operand = eliminate_regs (operand, VOIDmode, NULL_RTX);
- }
- if (GET_CODE (operand) != MEM)
- return 0;
-
- operand = XEXP (operand, 0);
- addr_mode = m68hc11_addr_mode | (reload_completed ? ADDR_STRICT : 0);
- return m68hc11_valid_addressing_p (operand, mode, addr_mode);
-}
-
-static bool
-m68hc11_legitimate_address_p_1 (enum machine_mode mode, rtx operand,
- bool strict)
-{
- int addr_mode;
-
- if (CONSTANT_ADDRESS_P (operand) && TARGET_M6812)
- {
- /* Reject the global variables if they are too wide. This forces
- a load of their address in a register and generates smaller code. */
- if (GET_MODE_SIZE (mode) == 8)
- return 0;
-
- return 1;
- }
- addr_mode = m68hc11_addr_mode | (strict ? ADDR_STRICT : 0);
- if (m68hc11_valid_addressing_p (operand, mode, addr_mode))
- {
- return 1;
- }
- if (PUSH_POP_ADDRESS_P (operand))
- {
- return 1;
- }
- if (symbolic_memory_operand (operand, mode))
- {
- return 1;
- }
- return 0;
-}
-
-bool
-m68hc11_legitimate_address_p (enum machine_mode mode, rtx operand,
- bool strict)
-{
- int result;
-
- if (debug_m6811)
- {
- printf ("Checking: ");
- fflush (stdout);
- debug_rtx (operand);
- }
-
- result = m68hc11_legitimate_address_p_1 (mode, operand, strict);
-
- if (debug_m6811)
- {
- printf (" -> %s\n", result == 0 ? "NO" : "YES");
- }
-
- if (result == 0)
- {
- if (debug_m6811)
- {
- printf ("go_if_legitimate%s, ret 0: %d:",
- (strict ? "_strict" : ""), mode);
- fflush (stdout);
- debug_rtx (operand);
- }
- }
- return result;
-}
-
-
-int
-m68hc11_reload_operands (rtx operands[])
-{
- enum machine_mode mode;
-
- if (regs_inited == 0)
- create_regs_rtx ();
-
- mode = GET_MODE (operands[1]);
-
- /* Input reload of indirect addressing (MEM (PLUS (REG) (CONST))). */
- if (A_REG_P (operands[0]) && memory_reload_operand (operands[1], mode))
- {
- rtx big_offset = XEXP (XEXP (operands[1], 0), 1);
- rtx base = XEXP (XEXP (operands[1], 0), 0);
-
- if (GET_CODE (base) != REG)
- {
- rtx tmp = base;
- base = big_offset;
- big_offset = tmp;
- }
-
- /* If the offset is out of range, we have to compute the address
- with a separate add instruction. We try to do this with an 8-bit
- add on the A register. This is possible only if the lowest part
- of the offset (i.e., big_offset % 256) is a valid constant offset
- with respect to the mode. If it's not, we have to generate a
- 16-bit add on the D register. From:
-
- (SET (REG X (MEM (PLUS (REG X) (CONST_INT 1000)))))
-
- we generate:
-
- [(SET (REG D) (REG X)) (SET (REG X) (REG D))]
- (SET (REG A) (PLUS (REG A) (CONST_INT 1000 / 256)))
- [(SET (REG D) (REG X)) (SET (REG X) (REG D))]
- (SET (REG X) (MEM (PLUS (REG X) (CONST_INT 1000 % 256)))
-
- (SET (REG X) (PLUS (REG X) (CONST_INT 1000 / 256 * 256)))
- (SET (REG X) (MEM (PLUS (REG X) (CONST_INT 1000 % 256))))
-
- */
- if (!VALID_CONSTANT_OFFSET_P (big_offset, mode))
- {
- int vh, vl;
- rtx reg = operands[0];
- rtx offset;
- int val = INTVAL (big_offset);
-
-
- /* We use the 'operands[0]' as a scratch register to compute the
- address. Make sure 'base' is in that register. */
- if (!rtx_equal_p (base, operands[0]))
- {
- emit_move_insn (reg, base);
- }
-
- if (val > 0)
- {
- vh = val >> 8;
- vl = val & 0x0FF;
- }
- else
- {
- vh = (val >> 8) & 0x0FF;
- vl = val & 0x0FF;
- }
-
- /* Create the lowest part offset that still remains to be added.
- If it's not a valid offset, do a 16-bit add. */
- offset = GEN_INT (vl);
- if (!VALID_CONSTANT_OFFSET_P (offset, mode))
- {
- emit_insn (gen_rtx_SET (VOIDmode, reg,
- gen_rtx_PLUS (HImode, reg, big_offset)));
- offset = const0_rtx;
- }
- else
- {
- emit_insn (gen_rtx_SET (VOIDmode, reg,
- gen_rtx_PLUS (HImode, reg,
- GEN_INT (vh << 8))));
- }
- emit_move_insn (operands[0],
- gen_rtx_MEM (GET_MODE (operands[1]),
- gen_rtx_PLUS (Pmode, reg, offset)));
- return 1;
- }
- }
-
- /* Use the normal gen_movhi pattern. */
- return 0;
-}
-
-void
-m68hc11_emit_libcall (const char *name, enum rtx_code code,
- enum machine_mode dmode, enum machine_mode smode,
- int noperands, rtx *operands)
-{
- rtx ret;
- rtx insns;
- rtx libcall;
- rtx equiv;
-
- start_sequence ();
- libcall = gen_rtx_SYMBOL_REF (Pmode, name);
- switch (noperands)
- {
- case 2:
- ret = emit_library_call_value (libcall, NULL_RTX, LCT_CONST,
- dmode, 1, operands[1], smode);
- equiv = gen_rtx_fmt_e (code, dmode, operands[1]);
- break;
-
- case 3:
- ret = emit_library_call_value (libcall, NULL_RTX,
- LCT_CONST, dmode, 2,
- operands[1], smode, operands[2],
- smode);
- equiv = gen_rtx_fmt_ee (code, dmode, operands[1], operands[2]);
- break;
-
- default:
- gcc_unreachable ();
- }
-
- insns = get_insns ();
- end_sequence ();
- emit_libcall_block (insns, operands[0], ret, equiv);
-}
-
-/* Returns true if X is a PRE/POST increment decrement
- (same as auto_inc_p() in rtlanal.c but do not take into
- account the stack). */
-int
-m68hc11_auto_inc_p (rtx x)
-{
- return GET_CODE (x) == PRE_DEC
- || GET_CODE (x) == POST_INC
- || GET_CODE (x) == POST_DEC || GET_CODE (x) == PRE_INC;
-}
-\f
-
-/* Predicates for machine description. */
-
-int
-memory_reload_operand (rtx operand, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return GET_CODE (operand) == MEM
- && GET_CODE (XEXP (operand, 0)) == PLUS
- && ((GET_CODE (XEXP (XEXP (operand, 0), 0)) == REG
- && GET_CODE (XEXP (XEXP (operand, 0), 1)) == CONST_INT)
- || (GET_CODE (XEXP (XEXP (operand, 0), 1)) == REG
- && GET_CODE (XEXP (XEXP (operand, 0), 0)) == CONST_INT));
-}
-
-int
-m68hc11_symbolic_p (rtx operand, enum machine_mode mode)
-{
- if (GET_CODE (operand) == MEM)
- {
- rtx op = XEXP (operand, 0);
-
- if (symbolic_memory_operand (op, mode))
- return 1;
- }
- return 0;
-}
-
-int
-m68hc11_indirect_p (rtx operand, enum machine_mode mode)
-{
- if (GET_CODE (operand) == MEM && GET_MODE (operand) == mode)
- {
- rtx op = XEXP (operand, 0);
- int addr_mode;
-
- if (m68hc11_page0_symbol_p (op))
- return 1;
-
- if (symbolic_memory_operand (op, mode))
- return TARGET_M6812;
-
- if (reload_in_progress)
- return 1;
-
- operand = XEXP (operand, 0);
- addr_mode = m68hc11_addr_mode | (reload_completed ? ADDR_STRICT : 0);
- return m68hc11_valid_addressing_p (operand, mode, addr_mode);
- }
- return 0;
-}
-
-int
-memory_indexed_operand (rtx operand, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- if (GET_CODE (operand) != MEM)
- return 0;
-
- operand = XEXP (operand, 0);
- if (GET_CODE (operand) == PLUS)
- {
- if (GET_CODE (XEXP (operand, 0)) == REG)
- operand = XEXP (operand, 0);
- else if (GET_CODE (XEXP (operand, 1)) == REG)
- operand = XEXP (operand, 1);
- }
- return GET_CODE (operand) == REG
- && (REGNO (operand) >= FIRST_PSEUDO_REGISTER
- || A_REGNO_P (REGNO (operand)));
-}
-
-int
-push_pop_operand_p (rtx operand)
-{
- if (GET_CODE (operand) != MEM)
- {
- return 0;
- }
- operand = XEXP (operand, 0);
- return PUSH_POP_ADDRESS_P (operand);
-}
-
-/* Returns 1 if OP is either a symbol reference or a sum of a symbol
- reference and a constant. */
-
-int
-symbolic_memory_operand (rtx op, enum machine_mode mode)
-{
- 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);
-
- /* ??? This clause seems to be irrelevant. */
- case CONST_DOUBLE:
- return GET_MODE (op) == mode;
-
- case PLUS:
- return symbolic_memory_operand (XEXP (op, 0), mode)
- && symbolic_memory_operand (XEXP (op, 1), mode);
-
- default:
- return 0;
- }
-}
-\f
-/* Emit the code to build the trampoline used to call a nested function.
-
- 68HC11 68HC12
-
- ldy #&CXT movw #&CXT,*_.d1
- sty *_.d1 jmp FNADDR
- jmp FNADDR
-
-*/
-static void
-m68hc11_trampoline_init (rtx m_tramp, tree fndecl, rtx cxt)
-{
- const char *static_chain_reg = reg_names[STATIC_CHAIN_REGNUM];
- rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
- rtx mem;
-
- /* Skip the '*'. */
- if (*static_chain_reg == '*')
- static_chain_reg++;
- if (TARGET_M6811)
- {
- mem = adjust_address (m_tramp, HImode, 0);
- emit_move_insn (mem, GEN_INT (0x18ce));
- mem = adjust_address (m_tramp, HImode, 2);
- emit_move_insn (mem, cxt);
- mem = adjust_address (m_tramp, HImode, 4);
- emit_move_insn (mem, GEN_INT (0x18df));
- mem = adjust_address (m_tramp, QImode, 6);
- emit_move_insn (mem,
- gen_rtx_CONST (QImode,
- gen_rtx_SYMBOL_REF (Pmode,
- static_chain_reg)));
- mem = adjust_address (m_tramp, QImode, 7);
- emit_move_insn (mem, GEN_INT (0x7e));
- mem = adjust_address (m_tramp, HImode, 8);
- emit_move_insn (mem, fnaddr);
- }
- else
- {
- mem = adjust_address (m_tramp, HImode, 0);
- emit_move_insn (mem, GEN_INT (0x1803));
- mem = adjust_address (m_tramp, HImode, 2);
- emit_move_insn (mem, cxt);
- mem = adjust_address (m_tramp, HImode, 4);
- emit_move_insn (mem,
- gen_rtx_CONST (HImode,
- gen_rtx_SYMBOL_REF (Pmode,
- static_chain_reg)));
- mem = adjust_address (m_tramp, QImode, 6);
- emit_move_insn (mem, GEN_INT (0x06));
- mem = adjust_address (m_tramp, HImode, 7);
- emit_move_insn (mem, fnaddr);
- }
-}
-\f
-/* Declaration of types. */
-
-/* Handle an "tiny_data" attribute; arguments as in
- struct attribute_spec.handler. */
-static tree
-m68hc11_handle_page0_attribute (tree *node, tree name,
- tree args ATTRIBUTE_UNUSED,
- int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
-{
- tree decl = *node;
-
- if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
- {
- DECL_SECTION_NAME (decl) = build_string (6, ".page0");
- }
- else
- {
- warning (OPT_Wattributes, "%qE attribute ignored",
- name);
- *no_add_attrs = true;
- }
-
- return NULL_TREE;
-}
-
-/* Keep track of the symbol which has a `trap' attribute and which uses
- the `swi' calling convention. Since there is only one trap, we only
- record one such symbol. If there are several, a warning is reported. */
-static rtx trap_handler_symbol = 0;
-
-/* Handle an attribute requiring a FUNCTION_TYPE, FIELD_DECL or TYPE_DECL;
- arguments as in struct attribute_spec.handler. */
-static tree
-m68hc11_handle_fntype_attribute (tree *node, tree name,
- tree args ATTRIBUTE_UNUSED,
- int flags ATTRIBUTE_UNUSED,
- bool *no_add_attrs)
-{
- if (TREE_CODE (*node) != FUNCTION_TYPE
- && TREE_CODE (*node) != METHOD_TYPE
- && TREE_CODE (*node) != FIELD_DECL
- && TREE_CODE (*node) != TYPE_DECL)
- {
- warning (OPT_Wattributes, "%qE attribute only applies to functions",
- name);
- *no_add_attrs = true;
- }
-
- return NULL_TREE;
-}
-/* Undo the effects of the above. */
-
-static const char *
-m68hc11_strip_name_encoding (const char *str)
-{
- return str + (*str == '*' || *str == '@' || *str == '&');
-}
-
-static void
-m68hc11_encode_label (tree decl)
-{
- const char *str = XSTR (XEXP (DECL_RTL (decl), 0), 0);
- int len = strlen (str);
- char *newstr = XALLOCAVEC (char, len + 2);
-
- newstr[0] = '@';
- strcpy (&newstr[1], str);
-
- XSTR (XEXP (DECL_RTL (decl), 0), 0) = ggc_alloc_string (newstr, len + 1);
-}
-
-/* Return 1 if this is a symbol in page0 */
-int
-m68hc11_page0_symbol_p (rtx x)
-{
- switch (GET_CODE (x))
- {
- case SYMBOL_REF:
- return XSTR (x, 0) != 0 && XSTR (x, 0)[0] == '@';
-
- case CONST:
- return m68hc11_page0_symbol_p (XEXP (x, 0));
-
- case PLUS:
- if (!m68hc11_page0_symbol_p (XEXP (x, 0)))
- return 0;
-
- return GET_CODE (XEXP (x, 1)) == CONST_INT
- && INTVAL (XEXP (x, 1)) < 256
- && INTVAL (XEXP (x, 1)) >= 0;
-
- default:
- return 0;
- }
-}
-
-/* We want to recognize trap handlers so that we handle calls to traps
- in a special manner (by issuing the trap). This information is stored
- in SYMBOL_REF_FLAG. */
-
-static void
-m68hc11_encode_section_info (tree decl, rtx rtl, int first ATTRIBUTE_UNUSED)
-{
- tree func_attr;
- int trap_handler;
- int is_far = 0;
-
- if (TREE_CODE (decl) == VAR_DECL)
- {
- if (lookup_attribute ("page0", DECL_ATTRIBUTES (decl)) != 0)
- m68hc11_encode_label (decl);
- return;
- }
-
- if (TREE_CODE (decl) != FUNCTION_DECL)
- return;
-
- func_attr = TYPE_ATTRIBUTES (TREE_TYPE (decl));
-
-
- if (lookup_attribute ("far", func_attr) != NULL_TREE)
- is_far = 1;
- else if (lookup_attribute ("near", func_attr) == NULL_TREE)
- is_far = TARGET_LONG_CALLS != 0;
-
- trap_handler = lookup_attribute ("trap", func_attr) != NULL_TREE;
- if (trap_handler && is_far)
- {
- warning (OPT_Wattributes, "%<trap%> and %<far%> attributes are "
- "not compatible, ignoring %<far%>");
- trap_handler = 0;
- }
- if (trap_handler)
- {
- if (trap_handler_symbol != 0)
- warning (OPT_Wattributes, "%<trap%> attribute is already used");
- else
- trap_handler_symbol = XEXP (rtl, 0);
- }
- SYMBOL_REF_FLAG (XEXP (rtl, 0)) = is_far;
-}
-
-static unsigned int
-m68hc11_section_type_flags (tree decl, const char *name, int reloc)
-{
- unsigned int flags = default_section_type_flags (decl, name, reloc);
-
- if (strncmp (name, ".eeprom", 7) == 0)
- {
- flags |= SECTION_WRITE | SECTION_CODE | SECTION_OVERRIDE;
- }
-
- return flags;
-}
-
-int
-m68hc11_is_far_symbol (rtx sym)
-{
- if (GET_CODE (sym) == MEM)
- sym = XEXP (sym, 0);
-
- return SYMBOL_REF_FLAG (sym);
-}
-
-int
-m68hc11_is_trap_symbol (rtx sym)
-{
- if (GET_CODE (sym) == MEM)
- sym = XEXP (sym, 0);
-
- return trap_handler_symbol != 0 && rtx_equal_p (trap_handler_symbol, sym);
-}
-\f
-
-/* Argument support functions. */
-
-/* Given FROM and TO register numbers, say whether this elimination is
- allowed. Frame pointer elimination is automatically handled.
-
- All other eliminations are valid. */
-
-bool
-m68hc11_can_eliminate (const int from, const int to)
-{
- return (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM
- ? ! frame_pointer_needed
- : true);
-}
-
-/* Define the offset between two registers, one to be eliminated, and the
- other its replacement, at the start of a routine. */
-int
-m68hc11_initial_elimination_offset (int from, int to)
-{
- int trap_handler;
- tree func_attr;
- int size;
- int regno;
-
- /* For a trap handler, we must take into account the registers which
- are pushed on the stack during the trap (except the PC). */
- func_attr = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
- current_function_interrupt = lookup_attribute ("interrupt",
- func_attr) != NULL_TREE;
- trap_handler = lookup_attribute ("trap", func_attr) != NULL_TREE;
-
- if (lookup_attribute ("far", func_attr) != 0)
- current_function_far = 1;
- else if (lookup_attribute ("near", func_attr) != 0)
- current_function_far = 0;
- else
- current_function_far = (TARGET_LONG_CALLS != 0
- && !current_function_interrupt
- && !trap_handler);
-
- if (trap_handler && from == ARG_POINTER_REGNUM)
- size = 7;
-
- /* For a function using 'call/rtc' we must take into account the
- page register which is pushed in the call. */
- else if (current_function_far && from == ARG_POINTER_REGNUM)
- size = 1;
- else
- size = 0;
-
- if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
- {
- /* 2 is for the saved frame.
- 1 is for the 'sts' correction when creating the frame. */
- return get_frame_size () + 2 + m68hc11_sp_correction + size;
- }
-
- if (from == FRAME_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
- {
- return m68hc11_sp_correction;
- }
-
- /* Push any 2 byte pseudo hard registers that we need to save. */
- for (regno = SOFT_REG_FIRST; regno < SOFT_REG_LAST; regno++)
- {
- if (df_regs_ever_live_p (regno) && !call_used_regs[regno])
- {
- size += 2;
- }
- }
-
- if (from == ARG_POINTER_REGNUM && to == HARD_SP_REGNUM)
- {
- return get_frame_size () + size;
- }
-
- if (from == FRAME_POINTER_REGNUM && to == HARD_SP_REGNUM)
- {
- return size;
- }
- return 0;
-}
-
-/* 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. */
-
-void
-m68hc11_init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, rtx libname)
-{
- tree ret_type;
-
- z_replacement_completed = 0;
- cum->words = 0;
- cum->nregs = 0;
-
- /* For a library call, we must find out the type of the return value.
- When the return value is bigger than 4 bytes, it is returned in
- memory. In that case, the first argument of the library call is a
- pointer to the memory location. Because the first argument is passed in
- register D, we have to identify this, so that the first function
- parameter is not passed in D either. */
- if (fntype == 0)
- {
- const char *name;
- size_t len;
-
- if (libname == 0 || GET_CODE (libname) != SYMBOL_REF)
- return;
-
- /* If the library ends in 'di' or in 'df', we assume it's
- returning some DImode or some DFmode which are 64-bit wide. */
- name = XSTR (libname, 0);
- len = strlen (name);
- if (len > 3
- && ((name[len - 2] == 'd'
- && (name[len - 1] == 'f' || name[len - 1] == 'i'))
- || (name[len - 3] == 'd'
- && (name[len - 2] == 'i' || name[len - 2] == 'f'))))
- {
- /* We are in. Mark the first parameter register as already used. */
- cum->words = 1;
- cum->nregs = 1;
- }
- return;
- }
-
- ret_type = TREE_TYPE (fntype);
-
- if (ret_type && aggregate_value_p (ret_type, fntype))
- {
- cum->words = 1;
- cum->nregs = 1;
- }
-}
-
-/* Update the data in CUM to advance over an argument
- of mode MODE and data type TYPE.
- (TYPE is null for libcalls where that information may not be available.) */
-
-static void
-m68hc11_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
- const_tree type, bool named ATTRIBUTE_UNUSED)
-{
- if (mode != BLKmode)
- {
- if (cum->words == 0 && GET_MODE_SIZE (mode) == 4)
- {
- cum->nregs = 2;
- cum->words = GET_MODE_SIZE (mode);
- }
- else
- {
- cum->words += GET_MODE_SIZE (mode);
- if (cum->words <= HARD_REG_SIZE)
- cum->nregs = 1;
- }
- }
- else
- {
- cum->words += int_size_in_bytes (type);
- }
- return;
-}
-
-/* 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). */
-
-static rtx
-m68hc11_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
- const_tree type ATTRIBUTE_UNUSED,
- bool named ATTRIBUTE_UNUSED)
-{
- if (cum->words != 0)
- {
- return NULL_RTX;
- }
-
- if (mode != BLKmode)
- {
- if (GET_MODE_SIZE (mode) == 2 * HARD_REG_SIZE)
- return gen_rtx_REG (mode, HARD_X_REGNUM);
-
- if (GET_MODE_SIZE (mode) > HARD_REG_SIZE)
- {
- return NULL_RTX;
- }
- return gen_rtx_REG (mode, HARD_D_REGNUM);
- }
- return NULL_RTX;
-}
-
-/* If defined, a C expression which determines whether, and in which direction,
- to pad out an argument with extra space. The value should be of type
- `enum direction': either `upward' to pad above the argument,
- `downward' to pad below, or `none' to inhibit padding.
-
- Structures are stored left shifted in their argument slot. */
-enum direction
-m68hc11_function_arg_padding (enum machine_mode mode, const_tree type)
-{
- if (type != 0 && AGGREGATE_TYPE_P (type))
- return upward;
-
- /* Fall back to the default. */
- return DEFAULT_FUNCTION_ARG_PADDING (mode, type);
-}
-\f
-
-/* Function prologue and epilogue. */
-
-/* Emit a move after the reload pass has completed. This is used to
- emit the prologue and epilogue. */
-static void
-emit_move_after_reload (rtx to, rtx from, rtx scratch)
-{
- rtx insn;
-
- if (TARGET_M6812 || H_REG_P (to) || H_REG_P (from))
- {
- insn = emit_move_insn (to, from);
- }
- else
- {
- emit_move_insn (scratch, from);
- insn = emit_move_insn (to, scratch);
- }
-
- /* Put a REG_INC note to tell the flow analysis that the instruction
- is necessary. */
- if (IS_STACK_PUSH (to))
- add_reg_note (insn, REG_INC, XEXP (XEXP (to, 0), 0));
- else if (IS_STACK_POP (from))
- add_reg_note (insn, REG_INC, XEXP (XEXP (from, 0), 0));
-
- /* For 68HC11, put a REG_INC note on `sts _.frame' to prevent the cse-reg
- to think that sp == _.frame and later replace a x = sp with x = _.frame.
- The problem is that we are lying to gcc and use `txs' for x = sp
- (which is not really true because txs is really x = sp + 1). */
- else if (TARGET_M6811 && SP_REG_P (from))
- add_reg_note (insn, REG_INC, from);
-}
-
-int
-m68hc11_total_frame_size (void)
-{
- int size;
- int regno;
-
- size = get_frame_size ();
- if (current_function_interrupt)
- {
- size += 3 * HARD_REG_SIZE;
- }
- if (frame_pointer_needed)
- size += HARD_REG_SIZE;
-
- for (regno = SOFT_REG_FIRST; regno <= SOFT_REG_LAST; regno++)
- if (df_regs_ever_live_p (regno) && !call_used_regs[regno])
- size += HARD_REG_SIZE;
-
- return size;
-}
-
-static void
-m68hc11_output_function_epilogue (FILE *out ATTRIBUTE_UNUSED,
- HOST_WIDE_INT size ATTRIBUTE_UNUSED)
-{
- /* We catch the function epilogue generation to have a chance
- to clear the z_replacement_completed flag. */
- z_replacement_completed = 0;
-}
-
-void
-expand_prologue (void)
-{
- tree func_attr;
- int size;
- int regno;
- rtx scratch;
-
- gcc_assert (reload_completed == 1);
-
- size = get_frame_size ();
-
- create_regs_rtx ();
-
- /* Generate specific prologue for interrupt handlers. */
- func_attr = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
- current_function_interrupt = lookup_attribute ("interrupt",
- func_attr) != NULL_TREE;
- current_function_trap = lookup_attribute ("trap", func_attr) != NULL_TREE;
- if (lookup_attribute ("far", func_attr) != NULL_TREE)
- current_function_far = 1;
- else if (lookup_attribute ("near", func_attr) != NULL_TREE)
- current_function_far = 0;
- else
- current_function_far = (TARGET_LONG_CALLS != 0
- && !current_function_interrupt
- && !current_function_trap);
-
- /* Get the scratch register to build the frame and push registers.
- If the first argument is a 32-bit quantity, the D+X registers
- are used. Use Y to compute the frame. Otherwise, X is cheaper.
- For 68HC12, this scratch register is not used. */
- if (crtl->args.info.nregs == 2)
- scratch = iy_reg;
- else
- scratch = ix_reg;
-
- /* Save current stack frame. */
- if (frame_pointer_needed)
- emit_move_after_reload (stack_push_word, hard_frame_pointer_rtx, scratch);
-
- /* For an interrupt handler, we must preserve _.tmp, _.z and _.xy.
- Other soft registers in page0 need not to be saved because they
- will be restored by C functions. For a trap handler, we don't
- need to preserve these registers because this is a synchronous call. */
- if (current_function_interrupt)
- {
- emit_move_after_reload (stack_push_word, m68hc11_soft_tmp_reg, scratch);
- emit_move_after_reload (stack_push_word,
- gen_rtx_REG (HImode, SOFT_Z_REGNUM), scratch);
- emit_move_after_reload (stack_push_word,
- gen_rtx_REG (HImode, SOFT_SAVED_XY_REGNUM),
- scratch);
- }
-
- /* Allocate local variables. */
- if (TARGET_M6812 && (size > 4 || size == 3))
- {
- emit_insn (gen_addhi3 (stack_pointer_rtx,
- stack_pointer_rtx, GEN_INT (-size)));
- }
- else if ((!optimize_size && size > 8) || (optimize_size && size > 10))
- {
- rtx insn;
-
- insn = gen_rtx_PARALLEL
- (VOIDmode,
- gen_rtvec (2,
- gen_rtx_SET (VOIDmode,
- stack_pointer_rtx,
- gen_rtx_PLUS (HImode,
- stack_pointer_rtx,
- GEN_INT (-size))),
- gen_rtx_CLOBBER (VOIDmode, scratch)));
- emit_insn (insn);
- }
- else
- {
- int i;
-
- /* Allocate by pushing scratch values. */
- for (i = 2; i <= size; i += 2)
- emit_move_after_reload (stack_push_word, ix_reg, 0);
-
- if (size & 1)
- emit_insn (gen_addhi3 (stack_pointer_rtx,
- stack_pointer_rtx, constm1_rtx));
- }
-
- /* Create the frame pointer. */
- if (frame_pointer_needed)
- emit_move_after_reload (hard_frame_pointer_rtx,
- stack_pointer_rtx, scratch);
-
- /* Push any 2 byte pseudo hard registers that we need to save. */
- for (regno = SOFT_REG_FIRST; regno <= SOFT_REG_LAST; regno++)
- {
- if (df_regs_ever_live_p (regno) && !call_used_regs[regno])
- {
- emit_move_after_reload (stack_push_word,
- gen_rtx_REG (HImode, regno), scratch);
- }
- }
-}
-
-void
-expand_epilogue (void)
-{
- int size;
- register int regno;
- int return_size;
- rtx scratch;
-
- gcc_assert (reload_completed == 1);
-
- size = get_frame_size ();
-
- /* If we are returning a value in two registers, we have to preserve the
- X register and use the Y register to restore the stack and the saved
- registers. Otherwise, use X because it's faster (and smaller). */
- if (crtl->return_rtx == 0)
- return_size = 0;
- else if (GET_CODE (crtl->return_rtx) == MEM)
- return_size = HARD_REG_SIZE;
- else
- return_size = GET_MODE_SIZE (GET_MODE (crtl->return_rtx));
-
- if (return_size > HARD_REG_SIZE && return_size <= 2 * HARD_REG_SIZE)
- scratch = iy_reg;
- else
- scratch = ix_reg;
-
- /* Pop any 2 byte pseudo hard registers that we saved. */
- for (regno = SOFT_REG_LAST; regno >= SOFT_REG_FIRST; regno--)
- {
- if (df_regs_ever_live_p (regno) && !call_used_regs[regno])
- {
- emit_move_after_reload (gen_rtx_REG (HImode, regno),
- stack_pop_word, scratch);
- }
- }
-
- /* de-allocate auto variables */
- if (TARGET_M6812 && (size > 4 || size == 3))
- {
- emit_insn (gen_addhi3 (stack_pointer_rtx,
- stack_pointer_rtx, GEN_INT (size)));
- }
- else if ((!optimize_size && size > 8) || (optimize_size && size > 10))
- {
- rtx insn;
-
- insn = gen_rtx_PARALLEL
- (VOIDmode,
- gen_rtvec (2,
- gen_rtx_SET (VOIDmode,
- stack_pointer_rtx,
- gen_rtx_PLUS (HImode,
- stack_pointer_rtx,
- GEN_INT (size))),
- gen_rtx_CLOBBER (VOIDmode, scratch)));
- emit_insn (insn);
- }
- else
- {
- int i;
-
- for (i = 2; i <= size; i += 2)
- emit_move_after_reload (scratch, stack_pop_word, scratch);
- if (size & 1)
- emit_insn (gen_addhi3 (stack_pointer_rtx,
- stack_pointer_rtx, const1_rtx));
- }
-
- /* For an interrupt handler, restore ZTMP, ZREG and XYREG. */
- if (current_function_interrupt)
- {
- emit_move_after_reload (gen_rtx_REG (HImode, SOFT_SAVED_XY_REGNUM),
- stack_pop_word, scratch);
- emit_move_after_reload (gen_rtx_REG (HImode, SOFT_Z_REGNUM),
- stack_pop_word, scratch);
- emit_move_after_reload (m68hc11_soft_tmp_reg, stack_pop_word, scratch);
- }
-
- /* Restore previous frame pointer. */
- if (frame_pointer_needed)
- emit_move_after_reload (hard_frame_pointer_rtx, stack_pop_word, scratch);
-
- /* If the trap handler returns some value, copy the value
- in D, X onto the stack so that the rti will pop the return value
- correctly. */
- else if (current_function_trap && return_size != 0)
- {
- rtx addr_reg = stack_pointer_rtx;
-
- if (!TARGET_M6812)
- {
- emit_move_after_reload (scratch, stack_pointer_rtx, 0);
- addr_reg = scratch;
- }
- emit_move_after_reload (gen_rtx_MEM (HImode,
- gen_rtx_PLUS (HImode, addr_reg,
- const1_rtx)), d_reg, 0);
- if (return_size > HARD_REG_SIZE)
- emit_move_after_reload (gen_rtx_MEM (HImode,
- gen_rtx_PLUS (HImode, addr_reg,
- GEN_INT (3))), ix_reg, 0);
- }
-
- emit_jump_insn (gen_return ());
-}
-\f
-
-/* Low and High part extraction for 68HC11. These routines are
- similar to gen_lowpart and gen_highpart but they have been
- fixed to work for constants and 68HC11 specific registers. */
-
-rtx
-m68hc11_gen_lowpart (enum machine_mode mode, rtx x)
-{
- /* We assume that the low part of an auto-inc mode is the same with
- the mode changed and that the caller split the larger mode in the
- correct order. */
- if (GET_CODE (x) == MEM && m68hc11_auto_inc_p (XEXP (x, 0)))
- {
- return gen_rtx_MEM (mode, XEXP (x, 0));
- }
-
- /* Note that a CONST_DOUBLE rtx could represent either an integer or a
- floating-point constant. A CONST_DOUBLE is used whenever the
- constant requires more than one word in order to be adequately
- represented. */
- if (GET_CODE (x) == CONST_DOUBLE)
- {
- long l[2];
-
- if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
- {
- REAL_VALUE_TYPE r;
-
- if (GET_MODE (x) == SFmode)
- {
- REAL_VALUE_FROM_CONST_DOUBLE (r, x);
- REAL_VALUE_TO_TARGET_SINGLE (r, l[0]);
- }
- else
- {
- rtx first, second;
-
- split_double (x, &first, &second);
- return second;
- }
- if (mode == SImode)
- return GEN_INT (l[0]);
-
- return gen_int_mode (l[0], HImode);
- }
- else
- {
- l[0] = CONST_DOUBLE_LOW (x);
- }
- switch (mode)
- {
- case SImode:
- return GEN_INT (l[0]);
- case HImode:
- gcc_assert (GET_MODE (x) == SFmode);
- return gen_int_mode (l[0], HImode);
- default:
- gcc_unreachable ();
- }
- }
-
- if (mode == QImode && D_REG_P (x))
- return gen_rtx_REG (mode, HARD_B_REGNUM);
-
- /* gen_lowpart crashes when it is called with a SUBREG. */
- if (GET_CODE (x) == SUBREG && SUBREG_BYTE (x) != 0)
- {
- switch (mode)
- {
- case SImode:
- return gen_rtx_SUBREG (mode, SUBREG_REG (x), SUBREG_BYTE (x) + 4);
- case HImode:
- return gen_rtx_SUBREG (mode, SUBREG_REG (x), SUBREG_BYTE (x) + 2);
- default:
- gcc_unreachable ();
- }
- }
- x = gen_lowpart (mode, x);
-
- /* Return a different rtx to avoid to share it in several insns
- (when used by a split pattern). Sharing addresses within
- a MEM breaks the Z register replacement (and reloading). */
- if (GET_CODE (x) == MEM)
- x = copy_rtx (x);
- return x;
-}
-
-rtx
-m68hc11_gen_highpart (enum machine_mode mode, rtx x)
-{
- /* We assume that the high part of an auto-inc mode is the same with
- the mode changed and that the caller split the larger mode in the
- correct order. */
- if (GET_CODE (x) == MEM && m68hc11_auto_inc_p (XEXP (x, 0)))
- {
- return gen_rtx_MEM (mode, XEXP (x, 0));
- }
-
- /* Note that a CONST_DOUBLE rtx could represent either an integer or a
- floating-point constant. A CONST_DOUBLE is used whenever the
- constant requires more than one word in order to be adequately
- represented. */
- if (GET_CODE (x) == CONST_DOUBLE)
- {
- long l[2];
-
- if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
- {
- REAL_VALUE_TYPE r;
-
- if (GET_MODE (x) == SFmode)
- {
- REAL_VALUE_FROM_CONST_DOUBLE (r, x);
- REAL_VALUE_TO_TARGET_SINGLE (r, l[1]);
- }
- else
- {
- rtx first, second;
-
- split_double (x, &first, &second);
- return first;
- }
- if (mode == SImode)
- return GEN_INT (l[1]);
-
- return gen_int_mode ((l[1] >> 16), HImode);
- }
- else
- {
- l[1] = CONST_DOUBLE_HIGH (x);
- }
-
- switch (mode)
- {
- case SImode:
- return GEN_INT (l[1]);
- case HImode:
- gcc_assert (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT);
- return gen_int_mode ((l[0] >> 16), HImode);
- default:
- gcc_unreachable ();
- }
- }
- if (GET_CODE (x) == CONST_INT)
- {
- HOST_WIDE_INT val = INTVAL (x);
-
- if (mode == QImode)
- {
- return gen_int_mode (val >> 8, QImode);
- }
- else if (mode == HImode)
- {
- return gen_int_mode (val >> 16, HImode);
- }
- else if (mode == SImode)
- {
- return gen_int_mode ((val >> 16) >> 16, SImode);
- }
- }
- if (mode == QImode && D_REG_P (x))
- return gen_rtx_REG (mode, HARD_A_REGNUM);
-
- /* There is no way in GCC to represent the upper part of a word register.
- To obtain the 8-bit upper part of a soft register, we change the
- reg into a mem rtx. This is possible because they are physically
- located in memory. There is no offset because we are big-endian. */
- if (mode == QImode && S_REG_P (x))
- {
- int pos;
-
- /* Avoid the '*' for direct addressing mode when this
- addressing mode is disabled. */
- pos = TARGET_NO_DIRECT_MODE ? 1 : 0;
- return gen_rtx_MEM (QImode,
- gen_rtx_SYMBOL_REF (Pmode,
- ®_names[REGNO (x)][pos]));
- }
-
- /* gen_highpart crashes when it is called with a SUBREG. */
- switch (GET_CODE (x))
- {
- case SUBREG:
- return gen_rtx_SUBREG (mode, XEXP (x, 0), XINT (x, 1));
- case REG:
- if (REGNO (x) < FIRST_PSEUDO_REGISTER)
- return gen_rtx_REG (mode, REGNO (x));
- else
- return gen_rtx_SUBREG (mode, x, 0);
- case MEM:
- x = change_address (x, mode, 0);
-
- /* Return a different rtx to avoid to share it in several insns
- (when used by a split pattern). Sharing addresses within
- a MEM breaks the Z register replacement (and reloading). */
- if (GET_CODE (x) == MEM)
- x = copy_rtx (x);
- return x;
-
- default:
- gcc_unreachable ();
- }
-}
-\f
-
-/* Obscure register manipulation. */
-
-/* Finds backward in the instructions to see if register 'reg' is
- dead. This is used when generating code to see if we can use 'reg'
- as a scratch register. This allows us to choose a better generation
- of code when we know that some register dies or can be clobbered. */
-
-int
-dead_register_here (rtx x, rtx reg)
-{
- rtx x_reg;
- rtx p;
-
- if (D_REG_P (reg))
- x_reg = gen_rtx_REG (SImode, HARD_X_REGNUM);
- else
- x_reg = 0;
-
- for (p = PREV_INSN (x); p && GET_CODE (p) != CODE_LABEL; p = PREV_INSN (p))
- if (INSN_P (p))
- {
- rtx body;
-
- body = PATTERN (p);
-
- if (GET_CODE (body) == CALL_INSN)
- break;
- if (GET_CODE (body) == JUMP_INSN)
- break;
-
- if (GET_CODE (body) == SET)
- {
- rtx dst = XEXP (body, 0);
-
- if (GET_CODE (dst) == REG && REGNO (dst) == REGNO (reg))
- break;
- if (x_reg && rtx_equal_p (dst, x_reg))
- break;
-
- if (find_regno_note (p, REG_DEAD, REGNO (reg)))
- return 1;
- }
- else if (reg_mentioned_p (reg, p)
- || (x_reg && reg_mentioned_p (x_reg, p)))
- break;
- }
-
- /* Scan forward to see if the register is set in some insns and never
- used since then. */
- for (p = x /*NEXT_INSN (x) */ ; p; p = NEXT_INSN (p))
- {
- rtx body;
-
- if (GET_CODE (p) == CODE_LABEL
- || GET_CODE (p) == JUMP_INSN
- || GET_CODE (p) == CALL_INSN || GET_CODE (p) == BARRIER)
- break;
-
- if (GET_CODE (p) != INSN)
- continue;
-
- body = PATTERN (p);
- if (GET_CODE (body) == SET)
- {
- rtx src = XEXP (body, 1);
- rtx dst = XEXP (body, 0);
-
- if (GET_CODE (dst) == REG
- && REGNO (dst) == REGNO (reg) && !reg_mentioned_p (reg, src))
- return 1;
- }
-
- /* Register is used (may be in source or in dest). */
- if (reg_mentioned_p (reg, p)
- || (x_reg != 0 && GET_MODE (p) == SImode
- && reg_mentioned_p (x_reg, p)))
- break;
- }
- return p == 0 ? 1 : 0;
-}
-\f
-
-/* Code generation operations called from machine description file. */
-
-/* Print the name of register 'regno' in the assembly file. */
-static void
-asm_print_register (FILE *file, int regno)
-{
- const char *name = reg_names[regno];
-
- if (TARGET_NO_DIRECT_MODE && name[0] == '*')
- name++;
-
- fprintf (file, "%s", name);
-}
-
-/* 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.
-
- The M68HC11 specific codes are:
-
- 'b' for the low part of the operand.
- 'h' for the high part of the operand
- The 'b' or 'h' modifiers have no effect if the operand has
- the QImode and is not a S_REG_P (soft register). If the
- operand is a hard register, these two modifiers have no effect.
- 't' generate the temporary scratch register. The operand is
- ignored.
- 'T' generate the low-part temporary scratch register. The operand is
- ignored. */
-
-static void
-m68hc11_print_operand (FILE *file, rtx op, int letter)
-{
- if (letter == 't')
- {
- asm_print_register (file, SOFT_TMP_REGNUM);
- return;
- }
- else if (letter == 'T')
- {
- asm_print_register (file, SOFT_TMP_REGNUM);
- fprintf (file, "+1");
- return;
- }
- else if (letter == '#')
- {
- asm_fprintf (file, "%I");
- }
-
- if (GET_CODE (op) == REG)
- {
- if (letter == 'b' && S_REG_P (op))
- {
- asm_print_register (file, REGNO (op));
- fprintf (file, "+1");
- }
- else if (letter == 'b' && D_REG_P (op))
- {
- asm_print_register (file, HARD_B_REGNUM);
- }
- else
- {
- asm_print_register (file, REGNO (op));
- }
- return;
- }
-
- if (GET_CODE (op) == SYMBOL_REF && (letter == 'b' || letter == 'h'))
- {
- if (letter == 'b')
- asm_fprintf (file, "%I%%lo(");
- else
- asm_fprintf (file, "%I%%hi(");
-
- output_addr_const (file, op);
- fprintf (file, ")");
- return;
- }
-
- /* Get the low or high part of the operand when 'b' or 'h' modifiers
- are specified. If we already have a QImode, there is nothing to do. */
- if (GET_MODE (op) == HImode || GET_MODE (op) == VOIDmode)
- {
- if (letter == 'b')
- {
- op = m68hc11_gen_lowpart (QImode, op);
- }
- else if (letter == 'h')
- {
- op = m68hc11_gen_highpart (QImode, op);
- }
- }
-
- if (GET_CODE (op) == MEM)
- {
- rtx base = XEXP (op, 0);
- switch (GET_CODE (base))
- {
- case PRE_DEC:
- gcc_assert (TARGET_M6812);
- fprintf (file, "%u,-", GET_MODE_SIZE (GET_MODE (op)));
- asm_print_register (file, REGNO (XEXP (base, 0)));
- break;
-
- case POST_DEC:
- gcc_assert (TARGET_M6812);
- fprintf (file, "%u,", GET_MODE_SIZE (GET_MODE (op)));
- asm_print_register (file, REGNO (XEXP (base, 0)));
- fprintf (file, "-");
- break;
-
- case POST_INC:
- gcc_assert (TARGET_M6812);
- fprintf (file, "%u,", GET_MODE_SIZE (GET_MODE (op)));
- asm_print_register (file, REGNO (XEXP (base, 0)));
- fprintf (file, "+");
- break;
-
- case PRE_INC:
- gcc_assert (TARGET_M6812);
- fprintf (file, "%u,+", GET_MODE_SIZE (GET_MODE (op)));
- asm_print_register (file, REGNO (XEXP (base, 0)));
- break;
-
- case MEM:
- gcc_assert (TARGET_M6812);
- fprintf (file, "[");
- m68hc11_print_operand_address (file, XEXP (base, 0));
- fprintf (file, "]");
- break;
-
- default:
- if (m68hc11_page0_symbol_p (base))
- fprintf (file, "*");
-
- output_address (base);
- break;
- }
- }
- else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == SFmode)
- {
- REAL_VALUE_TYPE r;
- long l;
-
- REAL_VALUE_FROM_CONST_DOUBLE (r, op);
- REAL_VALUE_TO_TARGET_SINGLE (r, l);
- asm_fprintf (file, "%I0x%lx", l);
- }
- else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == DFmode)
- {
- char dstr[30];
-
- real_to_decimal (dstr, CONST_DOUBLE_REAL_VALUE (op),
- sizeof (dstr), 0, 1);
- asm_fprintf (file, "%I0r%s", dstr);
- }
- else
- {
- int need_parenthesize = 0;
-
- if (letter != 'i')
- asm_fprintf (file, "%I");
- else
- need_parenthesize = must_parenthesize (op);
-
- if (need_parenthesize)
- fprintf (file, "(");
-
- output_addr_const (file, op);
- if (need_parenthesize)
- fprintf (file, ")");
- }
-}
-
-/* Returns true if the operand 'op' must be printed with parenthesis
- around it. This must be done only if there is a symbol whose name
- is a processor register. */
-static int
-must_parenthesize (rtx op)
-{
- const char *name;
-
- switch (GET_CODE (op))
- {
- case SYMBOL_REF:
- name = XSTR (op, 0);
- /* Avoid a conflict between symbol name and a possible
- register. */
- return (strcasecmp (name, "a") == 0
- || strcasecmp (name, "b") == 0
- || strcasecmp (name, "d") == 0
- || strcasecmp (name, "x") == 0
- || strcasecmp (name, "y") == 0
- || strcasecmp (name, "ix") == 0
- || strcasecmp (name, "iy") == 0
- || strcasecmp (name, "pc") == 0
- || strcasecmp (name, "sp") == 0
- || strcasecmp (name, "ccr") == 0) ? 1 : 0;
-
- case PLUS:
- case MINUS:
- return must_parenthesize (XEXP (op, 0))
- || must_parenthesize (XEXP (op, 1));
-
- case MEM:
- case CONST:
- case ZERO_EXTEND:
- case SIGN_EXTEND:
- return must_parenthesize (XEXP (op, 0));
-
- case CONST_DOUBLE:
- case CONST_INT:
- case LABEL_REF:
- case CODE_LABEL:
- default:
- return 0;
- }
-}
-
-/* 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 ADDR. ADDR is an RTL expression. */
-
-static void
-m68hc11_print_operand_address (FILE *file, rtx addr)
-{
- rtx base;
- rtx offset;
- int need_parenthesis = 0;
-
- switch (GET_CODE (addr))
- {
- case REG:
- gcc_assert (REG_P (addr) && REG_OK_FOR_BASE_STRICT_P (addr));
-
- fprintf (file, "0,");
- asm_print_register (file, REGNO (addr));
- break;
-
- case MEM:
- base = XEXP (addr, 0);
- switch (GET_CODE (base))
- {
- case PRE_DEC:
- gcc_assert (TARGET_M6812);
- fprintf (file, "%u,-", GET_MODE_SIZE (GET_MODE (addr)));
- asm_print_register (file, REGNO (XEXP (base, 0)));
- break;
-
- case POST_DEC:
- gcc_assert (TARGET_M6812);
- fprintf (file, "%u,", GET_MODE_SIZE (GET_MODE (addr)));
- asm_print_register (file, REGNO (XEXP (base, 0)));
- fprintf (file, "-");
- break;
-
- case POST_INC:
- gcc_assert (TARGET_M6812);
- fprintf (file, "%u,", GET_MODE_SIZE (GET_MODE (addr)));
- asm_print_register (file, REGNO (XEXP (base, 0)));
- fprintf (file, "+");
- break;
-
- case PRE_INC:
- gcc_assert (TARGET_M6812);
- fprintf (file, "%u,+", GET_MODE_SIZE (GET_MODE (addr)));
- asm_print_register (file, REGNO (XEXP (base, 0)));
- break;
-
- default:
- need_parenthesis = must_parenthesize (base);
- if (need_parenthesis)
- fprintf (file, "(");
-
- output_addr_const (file, base);
- if (need_parenthesis)
- fprintf (file, ")");
- break;
- }
- break;
-
- case PLUS:
- base = XEXP (addr, 0);
- offset = XEXP (addr, 1);
- if (!G_REG_P (base) && G_REG_P (offset))
- {
- base = XEXP (addr, 1);
- offset = XEXP (addr, 0);
- }
- if (CONSTANT_ADDRESS_P (base))
- {
- need_parenthesis = must_parenthesize (addr);
-
- gcc_assert (CONSTANT_ADDRESS_P (offset));
- if (need_parenthesis)
- fprintf (file, "(");
-
- output_addr_const (file, base);
- fprintf (file, "+");
- output_addr_const (file, offset);
- if (need_parenthesis)
- fprintf (file, ")");
- }
- else
- {
- gcc_assert (REG_P (base) && REG_OK_FOR_BASE_STRICT_P (base));
- if (REG_P (offset))
- {
- gcc_assert (TARGET_M6812);
- asm_print_register (file, REGNO (offset));
- fprintf (file, ",");
- asm_print_register (file, REGNO (base));
- }
- else
- {
- need_parenthesis = must_parenthesize (offset);
- if (need_parenthesis)
- fprintf (file, "(");
-
- output_addr_const (file, offset);
- if (need_parenthesis)
- fprintf (file, ")");
- fprintf (file, ",");
- asm_print_register (file, REGNO (base));
- }
- }
- break;
-
- default:
- if (GET_CODE (addr) == CONST_INT
- && INTVAL (addr) < 0x8000 && INTVAL (addr) >= -0x8000)
- {
- fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (addr));
- }
- else
- {
- need_parenthesis = must_parenthesize (addr);
- if (need_parenthesis)
- fprintf (file, "(");
-
- output_addr_const (file, addr);
- if (need_parenthesis)
- fprintf (file, ")");
- }
- break;
- }
-}
-\f
-
-/* Splitting of some instructions. */
-
-static rtx
-m68hc11_expand_compare (enum rtx_code code, rtx op0, rtx op1)
-{
- rtx ret = 0;
-
- gcc_assert (GET_MODE_CLASS (GET_MODE (op0)) != MODE_FLOAT);
- emit_insn (gen_rtx_SET (VOIDmode, cc0_rtx,
- gen_rtx_COMPARE (VOIDmode, op0, op1)));
- ret = gen_rtx_fmt_ee (code, VOIDmode, cc0_rtx, const0_rtx);
-
- return ret;
-}
-
-rtx
-m68hc11_expand_compare_and_branch (enum rtx_code code, rtx op0, rtx op1,
- rtx label)
-{
- rtx tmp;
-
- switch (GET_MODE (op0))
- {
- case QImode:
- case HImode:
- tmp = m68hc11_expand_compare (code, op0, op1);
- tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
- gen_rtx_LABEL_REF (VOIDmode, label),
- pc_rtx);
- emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp));
- return 0;
-#if 0
-
- /* SCz: from i386.c */
- case SFmode:
- case DFmode:
- /* Don't expand the comparison early, so that we get better code
- when jump or whoever decides to reverse the comparison. */
- {
- rtvec vec;
- int use_fcomi;
-
- code = m68hc11_prepare_fp_compare_args (code, &m68hc11_compare_op0,
- &m68hc11_compare_op1);
-
- tmp = gen_rtx_fmt_ee (code, m68hc11_fp_compare_mode (code),
- m68hc11_compare_op0, m68hc11_compare_op1);
- tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
- gen_rtx_LABEL_REF (VOIDmode, label),
- pc_rtx);
- tmp = gen_rtx_SET (VOIDmode, pc_rtx, tmp);
-
- use_fcomi = ix86_use_fcomi_compare (code);
- vec = rtvec_alloc (3 + !use_fcomi);
- RTVEC_ELT (vec, 0) = tmp;
- RTVEC_ELT (vec, 1)
- = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCFPmode, 18));
- RTVEC_ELT (vec, 2)
- = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCFPmode, 17));
- if (!use_fcomi)
- RTVEC_ELT (vec, 3)
- = gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (HImode));
-
- emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, vec));
- return;
- }
-#endif
-
- case SImode:
- /* Expand SImode branch into multiple compare+branch. */
- {
- rtx lo[2], hi[2], label2;
- enum rtx_code code1, code2, code3;
-
- if (CONSTANT_P (op0) && !CONSTANT_P (op1))
- {
- tmp = op0;
- op0 = op1;
- op1 = tmp;
- code = swap_condition (code);
- }
- lo[0] = m68hc11_gen_lowpart (HImode, op0);
- lo[1] = m68hc11_gen_lowpart (HImode, op1);
- hi[0] = m68hc11_gen_highpart (HImode, op0);
- hi[1] = m68hc11_gen_highpart (HImode, op1);
-
- /* Otherwise, if we are doing less-than, op1 is a constant and the
- low word is zero, then we can just examine the high word. */
-
- if (GET_CODE (hi[1]) == CONST_INT && lo[1] == const0_rtx
- && (code == LT || code == LTU))
- {
- return m68hc11_expand_compare_and_branch (code, hi[0], hi[1],
- label);
- }
-
- /* Otherwise, we need two or three jumps. */
-
- label2 = gen_label_rtx ();
-
- code1 = code;
- code2 = swap_condition (code);
- code3 = unsigned_condition (code);
-
- switch (code)
- {
- case LT:
- case GT:
- case LTU:
- case GTU:
- break;
-
- case LE:
- code1 = LT;
- code2 = GT;
- break;
- case GE:
- code1 = GT;
- code2 = LT;
- break;
- case LEU:
- code1 = LTU;
- code2 = GTU;
- break;
- case GEU:
- code1 = GTU;
- code2 = LTU;
- break;
-
- case EQ:
- code1 = UNKNOWN;
- code2 = NE;
- break;
- case NE:
- code2 = UNKNOWN;
- break;
-
- default:
- gcc_unreachable ();
- }
-
- /*
- * a < b =>
- * if (hi(a) < hi(b)) goto true;
- * if (hi(a) > hi(b)) goto false;
- * if (lo(a) < lo(b)) goto true;
- * false:
- */
- if (code1 != UNKNOWN)
- m68hc11_expand_compare_and_branch (code1, hi[0], hi[1], label);
- if (code2 != UNKNOWN)
- m68hc11_expand_compare_and_branch (code2, hi[0], hi[1], label2);
-
- m68hc11_expand_compare_and_branch (code3, lo[0], lo[1], label);
-
- if (code2 != UNKNOWN)
- emit_label (label2);
- return 0;
- }
-
- default:
- gcc_unreachable ();
- }
- return 0;
-}
-
-/* Return the increment/decrement mode of a MEM if it is such.
- Return CONST if it is anything else. */
-static int
-autoinc_mode (rtx x)
-{
- if (GET_CODE (x) != MEM)
- return CONST;
-
- x = XEXP (x, 0);
- if (GET_CODE (x) == PRE_INC
- || GET_CODE (x) == PRE_DEC
- || GET_CODE (x) == POST_INC
- || GET_CODE (x) == POST_DEC)
- return GET_CODE (x);
-
- return CONST;
-}
-
-static int
-m68hc11_make_autoinc_notes (rtx *x, void *data)
-{
- rtx insn;
-
- switch (GET_CODE (*x))
- {
- case PRE_DEC:
- case PRE_INC:
- case POST_DEC:
- case POST_INC:
- insn = (rtx) data;
- REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC, XEXP (*x, 0),
- REG_NOTES (insn));
- return -1;
-
- default:
- return 0;
- }
-}
-
-/* Split a DI, SI or HI move into several smaller move operations.
- The scratch register 'scratch' is used as a temporary to load
- store intermediate values. It must be a hard register. */
-void
-m68hc11_split_move (rtx to, rtx from, rtx scratch)
-{
- rtx low_to, low_from;
- rtx high_to, high_from;
- rtx insn;
- enum machine_mode mode;
- int offset = 0;
- int autoinc_from = autoinc_mode (from);
- int autoinc_to = autoinc_mode (to);
-
- mode = GET_MODE (to);
-
- /* If the TO and FROM contain autoinc modes that are not compatible
- together (one pop and the other a push), we must change one to
- an offsetable operand and generate an appropriate add at the end. */
- if (TARGET_M6812 && GET_MODE_SIZE (mode) > 2)
- {
- rtx reg;
- int code;
-
- /* The source uses an autoinc mode which is not compatible with
- a split (this would result in a word swap). */
- if (autoinc_from == PRE_INC || autoinc_from == POST_DEC)
- {
- code = GET_CODE (XEXP (from, 0));
- reg = XEXP (XEXP (from, 0), 0);
- offset = GET_MODE_SIZE (GET_MODE (from));
- if (code == POST_DEC)
- offset = -offset;
-
- if (code == PRE_INC)
- emit_insn (gen_addhi3 (reg, reg, GEN_INT (offset)));
-
- m68hc11_split_move (to, gen_rtx_MEM (GET_MODE (from), reg), scratch);
- if (code == POST_DEC)
- emit_insn (gen_addhi3 (reg, reg, GEN_INT (offset)));
- return;
- }
-
- /* Likewise for destination. */
- if (autoinc_to == PRE_INC || autoinc_to == POST_DEC)
- {
- code = GET_CODE (XEXP (to, 0));
- reg = XEXP (XEXP (to, 0), 0);
- offset = GET_MODE_SIZE (GET_MODE (to));
- if (code == POST_DEC)
- offset = -offset;
-
- if (code == PRE_INC)
- emit_insn (gen_addhi3 (reg, reg, GEN_INT (offset)));
-
- m68hc11_split_move (gen_rtx_MEM (GET_MODE (to), reg), from, scratch);
- if (code == POST_DEC)
- emit_insn (gen_addhi3 (reg, reg, GEN_INT (offset)));
- return;
- }
-
- /* The source and destination auto increment modes must be compatible
- with each other: same direction. */
- if ((autoinc_to != autoinc_from
- && autoinc_to != CONST && autoinc_from != CONST)
- /* The destination address register must not be used within
- the source operand because the source address would change
- while doing the copy. */
- || (autoinc_to != CONST
- && reg_mentioned_p (XEXP (XEXP (to, 0), 0), from)
- && !IS_STACK_PUSH (to)))
- {
- /* Must change the destination. */
- code = GET_CODE (XEXP (to, 0));
- reg = XEXP (XEXP (to, 0), 0);
- offset = GET_MODE_SIZE (GET_MODE (to));
- if (code == PRE_DEC || code == POST_DEC)
- offset = -offset;
-
- if (code == PRE_DEC || code == PRE_INC)
- emit_insn (gen_addhi3 (reg, reg, GEN_INT (offset)));
- m68hc11_split_move (gen_rtx_MEM (GET_MODE (to), reg), from, scratch);
- if (code == POST_DEC || code == POST_INC)
- emit_insn (gen_addhi3 (reg, reg, GEN_INT (offset)));
-
- return;
- }
-
- /* Likewise, the source address register must not be used within
- the destination operand. */
- if (autoinc_from != CONST
- && reg_mentioned_p (XEXP (XEXP (from, 0), 0), to)
- && !IS_STACK_PUSH (to))
- {
- /* Must change the source. */
- code = GET_CODE (XEXP (from, 0));
- reg = XEXP (XEXP (from, 0), 0);
- offset = GET_MODE_SIZE (GET_MODE (from));
- if (code == PRE_DEC || code == POST_DEC)
- offset = -offset;
-
- if (code == PRE_DEC || code == PRE_INC)
- emit_insn (gen_addhi3 (reg, reg, GEN_INT (offset)));
- m68hc11_split_move (to, gen_rtx_MEM (GET_MODE (from), reg), scratch);
- if (code == POST_DEC || code == POST_INC)
- emit_insn (gen_addhi3 (reg, reg, GEN_INT (offset)));
-
- return;
- }
- }
-
- if (GET_MODE_SIZE (mode) == 8)
- mode = SImode;
- else if (GET_MODE_SIZE (mode) == 4)
- mode = HImode;
- else
- mode = QImode;
-
- if (TARGET_M6812
- && IS_STACK_PUSH (to)
- && reg_mentioned_p (gen_rtx_REG (HImode, HARD_SP_REGNUM), from))
- {
- if (mode == SImode)
- {
- offset = 4;
- }
- else if (mode == HImode)
- {
- offset = 2;
- }
- else
- offset = 0;
- }
-
- low_to = m68hc11_gen_lowpart (mode, to);
- high_to = m68hc11_gen_highpart (mode, to);
-
- low_from = m68hc11_gen_lowpart (mode, from);
- high_from = m68hc11_gen_highpart (mode, from);
-
- if (offset)
- {
- high_from = adjust_address (high_from, mode, offset);
- low_from = high_from;
- }
-
- /* When copying with a POST_INC mode, we must copy the
- high part and then the low part to guarantee a correct
- 32/64-bit copy. */
- if (TARGET_M6812
- && GET_MODE_SIZE (mode) >= 2
- && autoinc_from != autoinc_to
- && (autoinc_from == POST_INC || autoinc_to == POST_INC))
- {
- rtx swap;
-
- swap = low_to;
- low_to = high_to;
- high_to = swap;
-
- swap = low_from;
- low_from = high_from;
- high_from = swap;
- }
- if (mode == SImode)
- {
- m68hc11_split_move (low_to, low_from, scratch);
- m68hc11_split_move (high_to, high_from, scratch);
- }
- else if (H_REG_P (to) || H_REG_P (from)
- || (low_from == const0_rtx
- && high_from == const0_rtx
- && ! push_operand (to, GET_MODE (to))
- && ! H_REG_P (scratch))
- || (TARGET_M6812
- && (!m68hc11_register_indirect_p (from, GET_MODE (from))
- || m68hc11_small_indexed_indirect_p (from,
- GET_MODE (from)))
- && (!m68hc11_register_indirect_p (to, GET_MODE (to))
- || m68hc11_small_indexed_indirect_p (to, GET_MODE (to)))))
- {
- insn = emit_move_insn (low_to, low_from);
- for_each_rtx (&PATTERN (insn), m68hc11_make_autoinc_notes, insn);
-
- insn = emit_move_insn (high_to, high_from);
- for_each_rtx (&PATTERN (insn), m68hc11_make_autoinc_notes, insn);
- }
- else
- {
- insn = emit_move_insn (scratch, low_from);
- for_each_rtx (&PATTERN (insn), m68hc11_make_autoinc_notes, insn);
- insn = emit_move_insn (low_to, scratch);
- for_each_rtx (&PATTERN (insn), m68hc11_make_autoinc_notes, insn);
-
- insn = emit_move_insn (scratch, high_from);
- for_each_rtx (&PATTERN (insn), m68hc11_make_autoinc_notes, insn);
- insn = emit_move_insn (high_to, scratch);
- for_each_rtx (&PATTERN (insn), m68hc11_make_autoinc_notes, insn);
- }
-}
-
-static rtx
-simplify_logical (enum machine_mode mode, int code, rtx operand, rtx *result)
-{
- int val;
- int mask;
-
- *result = 0;
- if (GET_CODE (operand) != CONST_INT)
- return operand;
-
- if (mode == HImode)
- mask = 0x0ffff;
- else
- mask = 0x0ff;
-
- val = INTVAL (operand);
- switch (code)
- {
- case IOR:
- if ((val & mask) == 0)
- return 0;
- if ((val & mask) == mask)
- *result = constm1_rtx;
- break;
-
- case AND:
- if ((val & mask) == 0)
- *result = const0_rtx;
- if ((val & mask) == mask)
- return 0;
- break;
-
- case XOR:
- if ((val & mask) == 0)
- return 0;
- break;
- }
- return operand;
-}
-
-static void
-m68hc11_emit_logical (enum machine_mode mode, enum rtx_code code, rtx *operands)
-{
- rtx result;
- int need_copy;
-
- need_copy = (rtx_equal_p (operands[0], operands[1])
- || rtx_equal_p (operands[0], operands[2])) ? 0 : 1;
-
- operands[1] = simplify_logical (mode, code, operands[1], &result);
- operands[2] = simplify_logical (mode, code, operands[2], &result);
-
- if (result && GET_CODE (result) == CONST_INT)
- {
- if (!H_REG_P (operands[0]) && operands[3]
- && (INTVAL (result) != 0 || IS_STACK_PUSH (operands[0])))
- {
- emit_move_insn (operands[3], result);
- emit_move_insn (operands[0], operands[3]);
- }
- else
- {
- emit_move_insn (operands[0], result);
- }
- }
- else if (operands[1] != 0 && operands[2] != 0)
- {
- if (!H_REG_P (operands[0]) && operands[3])
- {
- emit_move_insn (operands[3], operands[1]);
- emit_insn (gen_rtx_SET (mode,
- operands[3],
- gen_rtx_fmt_ee (code, mode,
- operands[3], operands[2])));
- emit_move_insn (operands[0], operands[3]);
- }
- else
- {
- emit_insn (gen_rtx_SET (mode, operands[0],
- gen_rtx_fmt_ee (code, mode,
- operands[0], operands[2])));
- }
- }
-
- /* The logical operation is similar to a copy. */
- else if (need_copy)
- {
- rtx src;
-
- if (GET_CODE (operands[1]) == CONST_INT)
- src = operands[2];
- else
- src = operands[1];
-
- if (!H_REG_P (operands[0]) && !H_REG_P (src))
- {
- emit_move_insn (operands[3], src);
- emit_move_insn (operands[0], operands[3]);
- }
- else
- {
- emit_move_insn (operands[0], src);
- }
- }
-}
-
-void
-m68hc11_split_logical (enum machine_mode mode, enum rtx_code code,
- rtx *operands)
-{
- rtx low[4];
- rtx high[4];
-
- low[0] = m68hc11_gen_lowpart (mode, operands[0]);
- low[1] = m68hc11_gen_lowpart (mode, operands[1]);
- low[2] = m68hc11_gen_lowpart (mode, operands[2]);
-
- high[0] = m68hc11_gen_highpart (mode, operands[0]);
- high[1] = m68hc11_gen_highpart (mode, operands[1]);
- high[2] = m68hc11_gen_highpart (mode, operands[2]);
-
- low[3] = operands[3];
- high[3] = operands[3];
- if (mode == SImode)
- {
- m68hc11_split_logical (HImode, code, low);
- m68hc11_split_logical (HImode, code, high);
- return;
- }
-
- m68hc11_emit_logical (mode, code, low);
- m68hc11_emit_logical (mode, code, high);
-}
-\f
-
-/* Code generation. */
-
-void
-m68hc11_output_swap (rtx insn ATTRIBUTE_UNUSED, rtx operands[])
-{
- /* We have to be careful with the cc_status. An address register swap
- is generated for some comparison. The comparison is made with D
- but the branch really uses the address register. See the split
- pattern for compare. The xgdx/xgdy preserve the flags but after
- the exchange, the flags will reflect to the value of X and not D.
- Tell this by setting the cc_status according to the cc_prev_status. */
- if (X_REG_P (operands[1]) || X_REG_P (operands[0]))
- {
- if (cc_prev_status.value1 != 0
- && (D_REG_P (cc_prev_status.value1)
- || X_REG_P (cc_prev_status.value1)))
- {
- cc_status = cc_prev_status;
- if (D_REG_P (cc_status.value1))
- cc_status.value1 = gen_rtx_REG (GET_MODE (cc_status.value1),
- HARD_X_REGNUM);
- else
- cc_status.value1 = gen_rtx_REG (GET_MODE (cc_status.value1),
- HARD_D_REGNUM);
- }
- else
- CC_STATUS_INIT;
-
- output_asm_insn ("xgdx", operands);
- }
- else
- {
- if (cc_prev_status.value1 != 0
- && (D_REG_P (cc_prev_status.value1)
- || Y_REG_P (cc_prev_status.value1)))
- {
- cc_status = cc_prev_status;
- if (D_REG_P (cc_status.value1))
- cc_status.value1 = gen_rtx_REG (GET_MODE (cc_status.value1),
- HARD_Y_REGNUM);
- else
- cc_status.value1 = gen_rtx_REG (GET_MODE (cc_status.value1),
- HARD_D_REGNUM);
- }
- else
- CC_STATUS_INIT;
-
- output_asm_insn ("xgdy", operands);
- }
-}
-
-/* Returns 1 if the next insn after 'insn' is a test of the register 'reg'.
- This is used to decide whether a move that set flags should be used
- instead. */
-int
-next_insn_test_reg (rtx insn, rtx reg)
-{
- rtx body;
-
- insn = next_nonnote_insn (insn);
- if (GET_CODE (insn) != INSN)
- return 0;
-
- body = PATTERN (insn);
- if (sets_cc0_p (body) != 1)
- return 0;
-
- if (rtx_equal_p (XEXP (body, 1), reg) == 0)
- return 0;
-
- return 1;
-}
-
-/* Generate the code to move a 16-bit operand into another one. */
-
-void
-m68hc11_gen_movhi (rtx insn, rtx *operands)
-{
- int reg;
-
- /* Move a register or memory to the same location.
- This is possible because such insn can appear
- in a non-optimizing mode. */
- if (operands[0] == operands[1] || rtx_equal_p (operands[0], operands[1]))
- {
- cc_status = cc_prev_status;
- return;
- }
-
- if (TARGET_M6812)
- {
- rtx from = operands[1];
- rtx to = operands[0];
-
- if (IS_STACK_PUSH (to) && H_REG_P (from))
- {
- cc_status = cc_prev_status;
- switch (REGNO (from))
- {
- case HARD_X_REGNUM:
- case HARD_Y_REGNUM:
- case HARD_D_REGNUM:
- output_asm_insn ("psh%1", operands);
- break;
- case HARD_SP_REGNUM:
- output_asm_insn ("sts\t2,-sp", operands);
- break;
- default:
- gcc_unreachable ();
- }
- return;
- }
- if (IS_STACK_POP (from) && H_REG_P (to))
- {
- cc_status = cc_prev_status;
- switch (REGNO (to))
- {
- case HARD_X_REGNUM:
- case HARD_Y_REGNUM:
- case HARD_D_REGNUM:
- output_asm_insn ("pul%0", operands);
- break;
- default:
- gcc_unreachable ();
- }
- return;
- }
- if (H_REG_P (operands[0]) && H_REG_P (operands[1]))
- {
- m68hc11_notice_keep_cc (operands[0]);
- output_asm_insn ("tfr\t%1,%0", operands);
- }
- else if (H_REG_P (operands[0]))
- {
- if (SP_REG_P (operands[0]))
- output_asm_insn ("lds\t%1", operands);
- else
- output_asm_insn ("ld%0\t%1", operands);
- }
- else if (H_REG_P (operands[1]))
- {
- if (SP_REG_P (operands[1]))
- output_asm_insn ("sts\t%0", operands);
- else
- output_asm_insn ("st%1\t%0", operands);
- }
-
- /* The 68hc12 does not support (MEM:HI (MEM:HI)) with the movw
- instruction. We have to use a scratch register as temporary location.
- Trying to use a specific pattern or constrain failed. */
- else if (GET_CODE (to) == MEM && GET_CODE (XEXP (to, 0)) == MEM)
- {
- rtx ops[4];
-
- ops[0] = to;
- ops[2] = from;
- ops[3] = 0;
- if (dead_register_here (insn, d_reg))
- ops[1] = d_reg;
- else if (dead_register_here (insn, ix_reg))
- ops[1] = ix_reg;
- else if (dead_register_here (insn, iy_reg))
- ops[1] = iy_reg;
- else
- {
- ops[1] = d_reg;
- ops[3] = d_reg;
- output_asm_insn ("psh%3", ops);
- }
-
- ops[0] = to;
- ops[2] = from;
- output_asm_insn ("ld%1\t%2", ops);
- output_asm_insn ("st%1\t%0", ops);
- if (ops[3])
- output_asm_insn ("pul%3", ops);
- }
-
- /* Use movw for non-null constants or when we are clearing
- a volatile memory reference. However, this is possible
- only if the memory reference has a small offset or is an
- absolute address. */
- else if (GET_CODE (from) == CONST_INT
- && INTVAL (from) == 0
- && (MEM_VOLATILE_P (to) == 0
- || m68hc11_small_indexed_indirect_p (to, HImode) == 0))
- {
- output_asm_insn ("clr\t%h0", operands);
- output_asm_insn ("clr\t%b0", operands);
- }
- else
- {
- if ((m68hc11_register_indirect_p (from, GET_MODE (from))
- && !m68hc11_small_indexed_indirect_p (from, GET_MODE (from)))
- || (m68hc11_register_indirect_p (to, GET_MODE (to))
- && !m68hc11_small_indexed_indirect_p (to, GET_MODE (to))))
- {
- rtx ops[3];
-
- if (operands[2])
- {
- ops[0] = operands[2];
- ops[1] = from;
- ops[2] = 0;
- m68hc11_gen_movhi (insn, ops);
- ops[0] = to;
- ops[1] = operands[2];
- m68hc11_gen_movhi (insn, ops);
- return;
- }
- else
- {
- /* !!!! SCz wrong here. */
- fatal_insn ("move insn not handled", insn);
- }
- }
- else
- {
- m68hc11_notice_keep_cc (operands[0]);
- output_asm_insn ("movw\t%1,%0", operands);
- }
- }
- return;
- }
-
- if (IS_STACK_POP (operands[1]) && H_REG_P (operands[0]))
- {
- cc_status = cc_prev_status;
- switch (REGNO (operands[0]))
- {
- case HARD_X_REGNUM:
- case HARD_Y_REGNUM:
- output_asm_insn ("pul%0", operands);
- break;
- case HARD_D_REGNUM:
- output_asm_insn ("pula", operands);
- output_asm_insn ("pulb", operands);
- break;
- default:
- gcc_unreachable ();
- }
- return;
- }
- /* Some moves to a hard register are special. Not all of them
- are really supported and we have to use a temporary
- location to provide them (either the stack of a temp var). */
- if (H_REG_P (operands[0]))
- {
- switch (REGNO (operands[0]))
- {
- case HARD_D_REGNUM:
- if (X_REG_P (operands[1]))
- {
- if (optimize && find_regno_note (insn, REG_DEAD, HARD_X_REGNUM))
- {
- m68hc11_output_swap (insn, operands);
- }
- else if (next_insn_test_reg (insn, operands[0]))
- {
- output_asm_insn ("stx\t%t0\n\tldd\t%t0", operands);
- }
- else
- {
- m68hc11_notice_keep_cc (operands[0]);
- output_asm_insn ("pshx\n\tpula\n\tpulb", operands);
- }
- }
- else if (Y_REG_P (operands[1]))
- {
- if (optimize && find_regno_note (insn, REG_DEAD, HARD_Y_REGNUM))
- {
- m68hc11_output_swap (insn, operands);
- }
- else
- {
- /* %t means *ZTMP scratch register. */
- output_asm_insn ("sty\t%t1", operands);
- output_asm_insn ("ldd\t%t1", operands);
- }
- }
- else if (SP_REG_P (operands[1]))
- {
- CC_STATUS_INIT;
- if (ix_reg == 0)
- create_regs_rtx ();
- if (optimize == 0 || dead_register_here (insn, ix_reg) == 0)
- output_asm_insn ("xgdx", operands);
- output_asm_insn ("tsx", operands);
- output_asm_insn ("xgdx", operands);
- }
- else if (IS_STACK_POP (operands[1]))
- {
- output_asm_insn ("pula\n\tpulb", operands);
- }
- else if (GET_CODE (operands[1]) == CONST_INT
- && INTVAL (operands[1]) == 0)
- {
- output_asm_insn ("clra\n\tclrb", operands);
- }
- else
- {
- output_asm_insn ("ldd\t%1", operands);
- }
- break;
-
- case HARD_X_REGNUM:
- if (D_REG_P (operands[1]))
- {
- if (optimize && find_regno_note (insn, REG_DEAD, HARD_D_REGNUM))
- {
- m68hc11_output_swap (insn, operands);
- }
- else if (next_insn_test_reg (insn, operands[0]))
- {
- output_asm_insn ("std\t%t0\n\tldx\t%t0", operands);
- }
- else
- {
- m68hc11_notice_keep_cc (operands[0]);
- output_asm_insn ("pshb", operands);
- output_asm_insn ("psha", operands);
- output_asm_insn ("pulx", operands);
- }
- }
- else if (Y_REG_P (operands[1]))
- {
- /* When both D and Y are dead, use the sequence xgdy, xgdx
- to move Y into X. The D and Y registers are modified. */
- if (optimize && find_regno_note (insn, REG_DEAD, HARD_Y_REGNUM)
- && dead_register_here (insn, d_reg))
- {
- output_asm_insn ("xgdy", operands);
- output_asm_insn ("xgdx", operands);
- CC_STATUS_INIT;
- }
- else if (!optimize_size)
- {
- output_asm_insn ("sty\t%t1", operands);
- output_asm_insn ("ldx\t%t1", operands);
- }
- else
- {
- CC_STATUS_INIT;
- output_asm_insn ("pshy", operands);
- output_asm_insn ("pulx", operands);
- }
- }
- else if (SP_REG_P (operands[1]))
- {
- /* tsx, tsy preserve the flags */
- cc_status = cc_prev_status;
- output_asm_insn ("tsx", operands);
- }
- else
- {
- output_asm_insn ("ldx\t%1", operands);
- }
- break;
-
- case HARD_Y_REGNUM:
- if (D_REG_P (operands[1]))
- {
- if (optimize && find_regno_note (insn, REG_DEAD, HARD_D_REGNUM))
- {
- m68hc11_output_swap (insn, operands);
- }
- else
- {
- output_asm_insn ("std\t%t1", operands);
- output_asm_insn ("ldy\t%t1", operands);
- }
- }
- else if (X_REG_P (operands[1]))
- {
- /* When both D and X are dead, use the sequence xgdx, xgdy
- to move X into Y. The D and X registers are modified. */
- if (optimize && find_regno_note (insn, REG_DEAD, HARD_X_REGNUM)
- && dead_register_here (insn, d_reg))
- {
- output_asm_insn ("xgdx", operands);
- output_asm_insn ("xgdy", operands);
- CC_STATUS_INIT;
- }
- else if (!optimize_size)
- {
- output_asm_insn ("stx\t%t1", operands);
- output_asm_insn ("ldy\t%t1", operands);
- }
- else
- {
- CC_STATUS_INIT;
- output_asm_insn ("pshx", operands);
- output_asm_insn ("puly", operands);
- }
- }
- else if (SP_REG_P (operands[1]))
- {
- /* tsx, tsy preserve the flags */
- cc_status = cc_prev_status;
- output_asm_insn ("tsy", operands);
- }
- else
- {
- output_asm_insn ("ldy\t%1", operands);
- }
- break;
-
- case HARD_SP_REGNUM:
- if (D_REG_P (operands[1]))
- {
- m68hc11_notice_keep_cc (operands[0]);
- output_asm_insn ("xgdx", operands);
- output_asm_insn ("txs", operands);
- output_asm_insn ("xgdx", operands);
- }
- else if (X_REG_P (operands[1]))
- {
- /* tys, txs preserve the flags */
- cc_status = cc_prev_status;
- output_asm_insn ("txs", operands);
- }
- else if (Y_REG_P (operands[1]))
- {
- /* tys, txs preserve the flags */
- cc_status = cc_prev_status;
- output_asm_insn ("tys", operands);
- }
- else
- {
- /* lds sets the flags but the des does not. */
- CC_STATUS_INIT;
- output_asm_insn ("lds\t%1", operands);
- output_asm_insn ("des", operands);
- }
- break;
-
- default:
- fatal_insn ("invalid register in the move instruction", insn);
- break;
- }
- return;
- }
- if (SP_REG_P (operands[1]) && REG_P (operands[0])
- && REGNO (operands[0]) == HARD_FRAME_POINTER_REGNUM)
- {
- output_asm_insn ("sts\t%0", operands);
- return;
- }
-
- if (IS_STACK_PUSH (operands[0]) && H_REG_P (operands[1]))
- {
- cc_status = cc_prev_status;
- switch (REGNO (operands[1]))
- {
- case HARD_X_REGNUM:
- case HARD_Y_REGNUM:
- output_asm_insn ("psh%1", operands);
- break;
- case HARD_D_REGNUM:
- output_asm_insn ("pshb", operands);
- output_asm_insn ("psha", operands);
- break;
- default:
- gcc_unreachable ();
- }
- return;
- }
-
- /* Operand 1 must be a hard register. */
- if (!H_REG_P (operands[1]))
- {
- fatal_insn ("invalid operand in the instruction", insn);
- }
-
- reg = REGNO (operands[1]);
- switch (reg)
- {
- case HARD_D_REGNUM:
- output_asm_insn ("std\t%0", operands);
- break;
-
- case HARD_X_REGNUM:
- output_asm_insn ("stx\t%0", operands);
- break;
-
- case HARD_Y_REGNUM:
- output_asm_insn ("sty\t%0", operands);
- break;
-
- case HARD_SP_REGNUM:
- if (ix_reg == 0)
- create_regs_rtx ();
-
- if (REG_P (operands[0]) && REGNO (operands[0]) == SOFT_TMP_REGNUM)
- {
- output_asm_insn ("pshx", operands);
- output_asm_insn ("tsx", operands);
- output_asm_insn ("inx", operands);
- output_asm_insn ("inx", operands);
- output_asm_insn ("stx\t%0", operands);
- output_asm_insn ("pulx", operands);
- }
-
- else if (reg_mentioned_p (ix_reg, operands[0]))
- {
- output_asm_insn ("sty\t%t0", operands);
- output_asm_insn ("tsy", operands);
- output_asm_insn ("sty\t%0", operands);
- output_asm_insn ("ldy\t%t0", operands);
- }
- else
- {
- output_asm_insn ("stx\t%t0", operands);
- output_asm_insn ("tsx", operands);
- output_asm_insn ("stx\t%0", operands);
- output_asm_insn ("ldx\t%t0", operands);
- }
- CC_STATUS_INIT;
- break;
-
- default:
- fatal_insn ("invalid register in the move instruction", insn);
- break;
- }
-}
-
-void
-m68hc11_gen_movqi (rtx insn, rtx *operands)
-{
- /* Move a register or memory to the same location.
- This is possible because such insn can appear
- in a non-optimizing mode. */
- if (operands[0] == operands[1] || rtx_equal_p (operands[0], operands[1]))
- {
- cc_status = cc_prev_status;
- return;
- }
-
- if (TARGET_M6812)
- {
-
- if (H_REG_P (operands[0]) && H_REG_P (operands[1]))
- {
- m68hc11_notice_keep_cc (operands[0]);
- output_asm_insn ("tfr\t%1,%0", operands);
- }
- else if (H_REG_P (operands[0]))
- {
- if (IS_STACK_POP (operands[1]))
- output_asm_insn ("pul%b0", operands);
- else if (Q_REG_P (operands[0]))
- output_asm_insn ("lda%0\t%b1", operands);
- else if (D_REG_P (operands[0]))
- output_asm_insn ("ldab\t%b1", operands);
- else
- goto m6811_move;
- }
- else if (H_REG_P (operands[1]))
- {
- if (Q_REG_P (operands[1]))
- output_asm_insn ("sta%1\t%b0", operands);
- else if (D_REG_P (operands[1]))
- output_asm_insn ("stab\t%b0", operands);
- else
- goto m6811_move;
- }
- else
- {
- rtx from = operands[1];
- rtx to = operands[0];
-
- if ((m68hc11_register_indirect_p (from, GET_MODE (from))
- && !m68hc11_small_indexed_indirect_p (from, GET_MODE (from)))
- || (m68hc11_register_indirect_p (to, GET_MODE (to))
- && !m68hc11_small_indexed_indirect_p (to, GET_MODE (to))))
- {
- rtx ops[3];
-
- if (operands[2])
- {
- ops[0] = operands[2];
- ops[1] = from;
- ops[2] = 0;
- m68hc11_gen_movqi (insn, ops);
- ops[0] = to;
- ops[1] = operands[2];
- m68hc11_gen_movqi (insn, ops);
- }
- else
- {
- /* !!!! SCz wrong here. */
- fatal_insn ("move insn not handled", insn);
- }
- }
- else
- {
- if (GET_CODE (from) == CONST_INT && INTVAL (from) == 0)
- {
- output_asm_insn ("clr\t%b0", operands);
- }
- else
- {
- m68hc11_notice_keep_cc (operands[0]);
- output_asm_insn ("movb\t%b1,%b0", operands);
- }
- }
- }
- return;
- }
-
- m6811_move:
- if (H_REG_P (operands[0]))
- {
- switch (REGNO (operands[0]))
- {
- case HARD_B_REGNUM:
- case HARD_D_REGNUM:
- if (X_REG_P (operands[1]))
- {
- if (optimize && find_regno_note (insn, REG_DEAD, HARD_X_REGNUM))
- {
- m68hc11_output_swap (insn, operands);
- }
- else
- {
- output_asm_insn ("stx\t%t1", operands);
- output_asm_insn ("ldab\t%T0", operands);
- }
- }
- else if (Y_REG_P (operands[1]))
- {
- if (optimize && find_regno_note (insn, REG_DEAD, HARD_Y_REGNUM))
- {
- m68hc11_output_swap (insn, operands);
- }
- else
- {
- output_asm_insn ("sty\t%t1", operands);
- output_asm_insn ("ldab\t%T0", operands);
- }
- }
- else if (!DB_REG_P (operands[1]) && !D_REG_P (operands[1])
- && !DA_REG_P (operands[1]))
- {
- output_asm_insn ("ldab\t%b1", operands);
- }
- else if (DA_REG_P (operands[1]))
- {
- output_asm_insn ("tab", operands);
- }
- else
- {
- cc_status = cc_prev_status;
- return;
- }
- break;
-
- case HARD_A_REGNUM:
- if (X_REG_P (operands[1]))
- {
- output_asm_insn ("stx\t%t1", operands);
- output_asm_insn ("ldaa\t%T0", operands);
- }
- else if (Y_REG_P (operands[1]))
- {
- output_asm_insn ("sty\t%t1", operands);
- output_asm_insn ("ldaa\t%T0", operands);
- }
- else if (!DB_REG_P (operands[1]) && !D_REG_P (operands[1])
- && !DA_REG_P (operands[1]))
- {
- output_asm_insn ("ldaa\t%b1", operands);
- }
- else if (!DA_REG_P (operands[1]))
- {
- output_asm_insn ("tba", operands);
- }
- else
- {
- cc_status = cc_prev_status;
- }
- break;
-
- case HARD_X_REGNUM:
- if (D_REG_P (operands[1]))
- {
- if (optimize && find_regno_note (insn, REG_DEAD, HARD_D_REGNUM))
- {
- m68hc11_output_swap (insn, operands);
- }
- else
- {
- output_asm_insn ("stab\t%T1", operands);
- output_asm_insn ("ldx\t%t1", operands);
- }
- CC_STATUS_INIT;
- }
- else if (Y_REG_P (operands[1]))
- {
- output_asm_insn ("sty\t%t0", operands);
- output_asm_insn ("ldx\t%t0", operands);
- }
- else if (GET_CODE (operands[1]) == CONST_INT)
- {
- output_asm_insn ("ldx\t%1", operands);
- }
- else if (dead_register_here (insn, d_reg))
- {
- output_asm_insn ("ldab\t%b1", operands);
- output_asm_insn ("xgdx", operands);
- }
- else if (!reg_mentioned_p (operands[0], operands[1]))
- {
- output_asm_insn ("xgdx", operands);
- output_asm_insn ("ldab\t%b1", operands);
- output_asm_insn ("xgdx", operands);
- }
- else
- {
- output_asm_insn ("pshb", operands);
- output_asm_insn ("ldab\t%b1", operands);
- output_asm_insn ("stab\t%T1", operands);
- output_asm_insn ("ldx\t%t1", operands);
- output_asm_insn ("pulb", operands);
- CC_STATUS_INIT;
- }
- break;
-
- case HARD_Y_REGNUM:
- if (D_REG_P (operands[1]))
- {
- output_asm_insn ("stab\t%T1", operands);
- output_asm_insn ("ldy\t%t1", operands);
- CC_STATUS_INIT;
- }
- else if (X_REG_P (operands[1]))
- {
- output_asm_insn ("stx\t%t1", operands);
- output_asm_insn ("ldy\t%t1", operands);
- CC_STATUS_INIT;
- }
- else if (GET_CODE (operands[1]) == CONST_INT)
- {
- output_asm_insn ("ldy\t%1", operands);
- }
- else if (dead_register_here (insn, d_reg))
- {
- output_asm_insn ("ldab\t%b1", operands);
- output_asm_insn ("xgdy", operands);
- }
- else if (!reg_mentioned_p (operands[0], operands[1]))
- {
- output_asm_insn ("xgdy", operands);
- output_asm_insn ("ldab\t%b1", operands);
- output_asm_insn ("xgdy", operands);
- }
- else
- {
- output_asm_insn ("pshb", operands);
- output_asm_insn ("ldab\t%b1", operands);
- output_asm_insn ("stab\t%T1", operands);
- output_asm_insn ("ldy\t%t1", operands);
- output_asm_insn ("pulb", operands);
- CC_STATUS_INIT;
- }
- break;
-
- default:
- fatal_insn ("invalid register in the instruction", insn);
- break;
- }
- }
- else if (H_REG_P (operands[1]))
- {
- switch (REGNO (operands[1]))
- {
- case HARD_D_REGNUM:
- case HARD_B_REGNUM:
- output_asm_insn ("stab\t%b0", operands);
- break;
-
- case HARD_A_REGNUM:
- output_asm_insn ("staa\t%b0", operands);
- break;
-
- case HARD_X_REGNUM:
- output_asm_insn ("xgdx\n\tstab\t%b0\n\txgdx", operands);
- break;
-
- case HARD_Y_REGNUM:
- output_asm_insn ("xgdy\n\tstab\t%b0\n\txgdy", operands);
- break;
-
- default:
- fatal_insn ("invalid register in the move instruction", insn);
- break;
- }
- return;
- }
- else
- {
- fatal_insn ("operand 1 must be a hard register", insn);
- }
-}
-
-/* Generate the code for a ROTATE or ROTATERT on a QI or HI mode.
- The source and destination must be D or A and the shift must
- be a constant. */
-void
-m68hc11_gen_rotate (enum rtx_code code, rtx insn, rtx operands[])
-{
- int val;
-
- if (GET_CODE (operands[2]) != CONST_INT
- || (!D_REG_P (operands[0]) && !DA_REG_P (operands[0])))
- fatal_insn ("invalid rotate insn", insn);
-
- val = INTVAL (operands[2]);
- if (code == ROTATERT)
- val = GET_MODE_SIZE (GET_MODE (operands[0])) * BITS_PER_UNIT - val;
-
- if (GET_MODE (operands[0]) != QImode)
- CC_STATUS_INIT;
-
- /* Rotate by 8-bits if the shift is within [5..11]. */
- if (val >= 5 && val <= 11)
- {
- if (TARGET_M6812)
- output_asm_insn ("exg\ta,b", operands);
- else
- {
- output_asm_insn ("psha", operands);
- output_asm_insn ("tba", operands);
- output_asm_insn ("pulb", operands);
- }
- val -= 8;
- }
-
- /* If the shift is big, invert the rotation. */
- else if (val >= 12)
- {
- val = val - 16;
- }
-
- if (val > 0)
- {
- while (--val >= 0)
- {
- /* Set the carry to bit-15, but don't change D yet. */
- if (GET_MODE (operands[0]) != QImode)
- {
- output_asm_insn ("asra", operands);
- output_asm_insn ("rola", operands);
- }
-
- /* Rotate B first to move the carry to bit-0. */
- if (D_REG_P (operands[0]))
- output_asm_insn ("rolb", operands);
-
- if (GET_MODE (operands[0]) != QImode || DA_REG_P (operands[0]))
- output_asm_insn ("rola", operands);
- }
- }
- else
- {
- while (++val <= 0)
- {
- /* Set the carry to bit-8 of D. */
- if (GET_MODE (operands[0]) != QImode)
- output_asm_insn ("tap", operands);
-
- /* Rotate B first to move the carry to bit-7. */
- if (D_REG_P (operands[0]))
- output_asm_insn ("rorb", operands);
-
- if (GET_MODE (operands[0]) != QImode || DA_REG_P (operands[0]))
- output_asm_insn ("rora", operands);
- }
- }
-}
-
-\f
-
-/* 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. */
-
-void
-m68hc11_notice_update_cc (rtx exp, rtx insn ATTRIBUTE_UNUSED)
-{
- /* recognize SET insn's. */
- if (GET_CODE (exp) == SET)
- {
- /* Jumps do not alter the cc's. */
- if (SET_DEST (exp) == pc_rtx)
- ;
-
- /* NOTE: most instructions don't affect the carry bit, but the
- bhi/bls/bhs/blo instructions use it. This isn't mentioned in
- the conditions.h header. */
-
- /* Function calls clobber the cc's. */
- else if (GET_CODE (SET_SRC (exp)) == CALL)
- {
- CC_STATUS_INIT;
- }
-
- /* Tests and compares set the cc's in predictable ways. */
- else if (SET_DEST (exp) == cc0_rtx)
- {
- cc_status.flags = 0;
- cc_status.value1 = XEXP (exp, 0);
- if (GET_CODE (XEXP (exp, 1)) == COMPARE
- && XEXP (XEXP (exp, 1), 1) == CONST0_RTX (GET_MODE (XEXP (XEXP (exp, 1), 0))))
- cc_status.value2 = XEXP (XEXP (exp, 1), 0);
- else
- cc_status.value2 = XEXP (exp, 1);
- }
- else
- {
- /* All other instructions affect the condition codes. */
- cc_status.flags = 0;
- cc_status.value1 = XEXP (exp, 0);
- cc_status.value2 = XEXP (exp, 1);
- }
- }
- else
- {
- /* Default action if we haven't recognized something
- and returned earlier. */
- CC_STATUS_INIT;
- }
-
- if (cc_status.value2 != 0)
- switch (GET_CODE (cc_status.value2))
- {
- /* These logical operations can generate several insns.
- The flags are setup according to what is generated. */
- case IOR:
- case XOR:
- case AND:
- break;
-
- /* The (not ...) generates several 'com' instructions for
- non QImode. We have to invalidate the flags. */
- case NOT:
- if (GET_MODE (cc_status.value2) != QImode)
- CC_STATUS_INIT;
- break;
-
- case PLUS:
- case MINUS:
- case MULT:
- case DIV:
- case UDIV:
- case MOD:
- case UMOD:
- case NEG:
- if (GET_MODE (cc_status.value2) != VOIDmode)
- cc_status.flags |= CC_NO_OVERFLOW;
- break;
-
- /* The asl sets the overflow bit in such a way that this
- makes the flags unusable for a next compare insn. */
- case ASHIFT:
- case ROTATE:
- case ROTATERT:
- if (GET_MODE (cc_status.value2) != VOIDmode)
- cc_status.flags |= CC_NO_OVERFLOW;
- break;
-
- /* A load/store instruction does not affect the carry. */
- case MEM:
- case SYMBOL_REF:
- case REG:
- case CONST_INT:
- cc_status.flags |= CC_NO_OVERFLOW;
- break;
-
- default:
- break;
- }
- if (cc_status.value1 && GET_CODE (cc_status.value1) == REG
- && cc_status.value2
- && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2))
- cc_status.value2 = 0;
-
- else if (cc_status.value1 && side_effects_p (cc_status.value1))
- cc_status.value1 = 0;
-
- else if (cc_status.value2 && side_effects_p (cc_status.value2))
- cc_status.value2 = 0;
-}
-
-/* The current instruction does not affect the flags but changes
- the register 'reg'. See if the previous flags can be kept for the
- next instruction to avoid a comparison. */
-void
-m68hc11_notice_keep_cc (rtx reg)
-{
- if (reg == 0
- || cc_prev_status.value1 == 0
- || rtx_equal_p (reg, cc_prev_status.value1)
- || (cc_prev_status.value2
- && reg_mentioned_p (reg, cc_prev_status.value2)))
- CC_STATUS_INIT;
- else
- cc_status = cc_prev_status;
-}
-
-\f
-
-/* Machine Specific Reorg. */
-
-/* Z register replacement:
-
- GCC treats the Z register as an index base address register like
- X or Y. In general, it uses it during reload to compute the address
- of some operand. This helps the reload pass to avoid to fall into the
- register spill failure.
-
- The Z register is in the A_REGS class. In the machine description,
- the 'A' constraint matches it. The 'x' or 'y' constraints do not.
-
- It can appear everywhere an X or Y register can appear, except for
- some templates in the clobber section (when a clobber of X or Y is asked).
- For a given instruction, the template must ensure that no more than
- 2 'A' registers are used. Otherwise, the register replacement is not
- possible.
-
- To replace the Z register, the algorithm is not terrific:
- 1. Insns that do not use the Z register are not changed
- 2. When a Z register is used, we scan forward the insns to see
- a potential register to use: either X or Y and sometimes D.
- We stop when a call, a label or a branch is seen, or when we
- detect that both X and Y are used (probably at different times, but it does
- not matter).
- 3. The register that will be used for the replacement of Z is saved
- in a .page0 register or on the stack. If the first instruction that
- used Z, uses Z as an input, the value is loaded from another .page0
- register. The replacement register is pushed on the stack in the
- rare cases where a compare insn uses Z and we couldn't find if X/Y
- are dead.
- 4. The Z register is replaced in all instructions until we reach
- the end of the Z-block, as detected by step 2.
- 5. If we detect that Z is still alive, its value is saved.
- If the replacement register is alive, its old value is loaded.
-
- The Z register can be disabled with -ffixed-z.
-*/
-
-struct replace_info
-{
- rtx first;
- rtx replace_reg;
- int need_save_z;
- int must_load_z;
- int must_save_reg;
- int must_restore_reg;
- rtx last;
- int regno;
- int x_used;
- int y_used;
- int can_use_d;
- int found_call;
- int z_died;
- int z_set_count;
- rtx z_value;
- int must_push_reg;
- int save_before_last;
- int z_loaded_with_sp;
-};
-
-static int m68hc11_check_z_replacement (rtx, struct replace_info *);
-static void m68hc11_find_z_replacement (rtx, struct replace_info *);
-static void m68hc11_z_replacement (rtx);
-static void m68hc11_reassign_regs (rtx);
-
-int z_replacement_completed = 0;
-
-/* Analyze the insn to find out which replacement register to use and
- the boundaries of the replacement.
- Returns 0 if we reached the last insn to be replaced, 1 if we can
- continue replacement in next insns. */
-
-static int
-m68hc11_check_z_replacement (rtx insn, struct replace_info *info)
-{
- int this_insn_uses_ix;
- int this_insn_uses_iy;
- int this_insn_uses_z;
- int this_insn_uses_z_in_dst;
- int this_insn_uses_d;
- rtx body;
- int z_dies_here;
-
- /* A call is said to clobber the Z register, we don't need
- to save the value of Z. We also don't need to restore
- the replacement register (unless it is used by the call). */
- if (GET_CODE (insn) == CALL_INSN)
- {
- body = PATTERN (insn);
-
- info->can_use_d = 0;
-
- /* If the call is an indirect call with Z, we have to use the
- Y register because X can be used as an input (D+X).
- We also must not save Z nor restore Y. */
- if (reg_mentioned_p (z_reg, body))
- {
- insn = NEXT_INSN (insn);
- info->x_used = 1;
- info->y_used = 0;
- info->found_call = 1;
- info->must_restore_reg = 0;
- info->last = NEXT_INSN (insn);
- }
- info->need_save_z = 0;
- return 0;
- }
- if (GET_CODE (insn) == CODE_LABEL
- || GET_CODE (insn) == BARRIER || GET_CODE (insn) == ASM_INPUT)
- return 0;
-
- if (GET_CODE (insn) == JUMP_INSN)
- {
- if (reg_mentioned_p (z_reg, insn) == 0)
- return 0;
-
- info->can_use_d = 0;
- info->must_save_reg = 0;
- info->must_restore_reg = 0;
- info->need_save_z = 0;
- info->last = NEXT_INSN (insn);
- return 0;
- }
- if (GET_CODE (insn) != INSN && GET_CODE (insn) != JUMP_INSN)
- {
- return 1;
- }
-
- /* Z register dies here. */
- z_dies_here = find_regno_note (insn, REG_DEAD, HARD_Z_REGNUM) != NULL;
-
- body = PATTERN (insn);
- if (GET_CODE (body) == SET)
- {
- rtx src = XEXP (body, 1);
- rtx dst = XEXP (body, 0);
-
- /* Condition code is set here. We have to restore the X/Y and
- save into Z before any test/compare insn because once we save/restore
- we can change the condition codes. When the compare insn uses Z and
- we can't use X/Y, the comparison is made with the *ZREG soft register
- (this is supported by cmphi, cmpqi, tsthi, tstqi patterns). */
- if (dst == cc0_rtx)
- {
- if ((GET_CODE (src) == REG && REGNO (src) == HARD_Z_REGNUM)
- || (GET_CODE (src) == COMPARE &&
- ((rtx_equal_p (XEXP (src, 0), z_reg)
- && H_REG_P (XEXP (src, 1)))
- || (rtx_equal_p (XEXP (src, 1), z_reg)
- && H_REG_P (XEXP (src, 0))))))
- {
- if (insn == info->first)
- {
- info->must_load_z = 0;
- info->must_save_reg = 0;
- info->must_restore_reg = 0;
- info->need_save_z = 0;
- info->found_call = 1;
- info->regno = SOFT_Z_REGNUM;
- info->last = NEXT_INSN (insn);
- }
- return 0;
- }
- if (reg_mentioned_p (z_reg, src) == 0)
- {
- info->can_use_d = 0;
- return 0;
- }
-
- if (insn != info->first)
- return 0;
-
- /* Compare insn which uses Z. We have to save/restore the X/Y
- register without modifying the condition codes. For this
- we have to use a push/pop insn. */
- info->must_push_reg = 1;
- info->last = insn;
- }
-
- /* Z reg is set to something new. We don't need to load it. */
- if (Z_REG_P (dst))
- {
- if (!reg_mentioned_p (z_reg, src))
- {
- /* Z reg is used before being set. Treat this as
- a new sequence of Z register replacement. */
- if (insn != info->first)
- {
- return 0;
- }
- info->must_load_z = 0;
- }
- info->z_set_count++;
- info->z_value = src;
- if (SP_REG_P (src))
- info->z_loaded_with_sp = 1;
- }
- else if (reg_mentioned_p (z_reg, dst))
- info->can_use_d = 0;
-
- this_insn_uses_d = reg_mentioned_p (d_reg, src)
- | reg_mentioned_p (d_reg, dst);
- this_insn_uses_ix = reg_mentioned_p (ix_reg, src)
- | reg_mentioned_p (ix_reg, dst);
- this_insn_uses_iy = reg_mentioned_p (iy_reg, src)
- | reg_mentioned_p (iy_reg, dst);
- this_insn_uses_z = reg_mentioned_p (z_reg, src);
-
- /* If z is used as an address operand (like (MEM (reg z))),
- we can't replace it with d. */
- if (this_insn_uses_z && !Z_REG_P (src)
- && !(m68hc11_arith_operator (src, GET_MODE (src))
- && Z_REG_P (XEXP (src, 0))
- && !reg_mentioned_p (z_reg, XEXP (src, 1))
- && insn == info->first
- && dead_register_here (insn, d_reg)))
- info->can_use_d = 0;
-
- this_insn_uses_z_in_dst = reg_mentioned_p (z_reg, dst);
- if (TARGET_M6812 && !z_dies_here
- && ((this_insn_uses_z && side_effects_p (src))
- || (this_insn_uses_z_in_dst && side_effects_p (dst))))
- {
- info->need_save_z = 1;
- info->z_set_count++;
- }
- this_insn_uses_z |= this_insn_uses_z_in_dst;
-
- if (this_insn_uses_z && this_insn_uses_ix && this_insn_uses_iy)
- {
- fatal_insn ("registers IX, IY and Z used in the same INSN", insn);
- }
-
- if (this_insn_uses_d)
- info->can_use_d = 0;
-
- /* IX and IY are used at the same time, we have to restore
- the value of the scratch register before this insn. */
- if (this_insn_uses_ix && this_insn_uses_iy)
- {
- return 0;
- }
-
- if (this_insn_uses_ix && X_REG_P (dst) && GET_MODE (dst) == SImode)
- info->can_use_d = 0;
-
- if (info->x_used == 0 && this_insn_uses_ix)
- {
- if (info->y_used)
- {
- /* We have a (set (REG:HI X) (REG:HI Z)).
- Since we use Z as the replacement register, this insn
- is no longer necessary. We turn it into a note. We must
- not reload the old value of X. */
- if (X_REG_P (dst) && rtx_equal_p (src, z_reg))
- {
- if (z_dies_here)
- {
- info->need_save_z = 0;
- info->z_died = 1;
- }
- info->must_save_reg = 0;
- info->must_restore_reg = 0;
- info->found_call = 1;
- info->can_use_d = 0;
- SET_INSN_DELETED (insn);
- info->last = NEXT_INSN (insn);
- return 0;
- }
-
- if (X_REG_P (dst)
- && (rtx_equal_p (src, z_reg)
- || (z_dies_here && !reg_mentioned_p (ix_reg, src))))
- {
- if (z_dies_here)
- {
- info->need_save_z = 0;
- info->z_died = 1;
- }
- info->last = NEXT_INSN (insn);
- info->must_save_reg = 0;
- info->must_restore_reg = 0;
- }
- else if (X_REG_P (dst) && reg_mentioned_p (z_reg, src)
- && !reg_mentioned_p (ix_reg, src))
- {
- if (z_dies_here)
- {
- info->z_died = 1;
- info->need_save_z = 0;
- }
- else if (TARGET_M6812 && side_effects_p (src))
- {
- info->last = 0;
- info->must_restore_reg = 0;
- return 0;
- }
- else
- {
- info->save_before_last = 1;
- }
- info->must_restore_reg = 0;
- info->last = NEXT_INSN (insn);
- }
- else if (info->can_use_d)
- {
- info->last = NEXT_INSN (insn);
- info->x_used = 1;
- }
- return 0;
- }
- info->x_used = 1;
- if (z_dies_here && !reg_mentioned_p (ix_reg, src)
- && GET_CODE (dst) == REG && REGNO (dst) == HARD_X_REGNUM)
- {
- info->need_save_z = 0;
- info->z_died = 1;
- info->last = NEXT_INSN (insn);
- info->regno = HARD_X_REGNUM;
- info->must_save_reg = 0;
- info->must_restore_reg = 0;
- return 0;
- }
- if (rtx_equal_p (src, z_reg) && rtx_equal_p (dst, ix_reg))
- {
- info->regno = HARD_X_REGNUM;
- info->must_restore_reg = 0;
- info->must_save_reg = 0;
- return 0;
- }
- }
- if (info->y_used == 0 && this_insn_uses_iy)
- {
- if (info->x_used)
- {
- if (Y_REG_P (dst) && rtx_equal_p (src, z_reg))
- {
- if (z_dies_here)
- {
- info->need_save_z = 0;
- info->z_died = 1;
- }
- info->must_save_reg = 0;
- info->must_restore_reg = 0;
- info->found_call = 1;
- info->can_use_d = 0;
- SET_INSN_DELETED (insn);
- info->last = NEXT_INSN (insn);
- return 0;
- }
-
- if (Y_REG_P (dst)
- && (rtx_equal_p (src, z_reg)
- || (z_dies_here && !reg_mentioned_p (iy_reg, src))))
- {
- if (z_dies_here)
- {
- info->z_died = 1;
- info->need_save_z = 0;
- }
- info->last = NEXT_INSN (insn);
- info->must_save_reg = 0;
- info->must_restore_reg = 0;
- }
- else if (Y_REG_P (dst) && reg_mentioned_p (z_reg, src)
- && !reg_mentioned_p (iy_reg, src))
- {
- if (z_dies_here)
- {
- info->z_died = 1;
- info->need_save_z = 0;
- }
- else if (TARGET_M6812 && side_effects_p (src))
- {
- info->last = 0;
- info->must_restore_reg = 0;
- return 0;
- }
- else
- {
- info->save_before_last = 1;
- }
- info->must_restore_reg = 0;
- info->last = NEXT_INSN (insn);
- }
- else if (info->can_use_d)
- {
- info->last = NEXT_INSN (insn);
- info->y_used = 1;
- }
-
- return 0;
- }
- info->y_used = 1;
- if (z_dies_here && !reg_mentioned_p (iy_reg, src)
- && GET_CODE (dst) == REG && REGNO (dst) == HARD_Y_REGNUM)
- {
- info->need_save_z = 0;
- info->z_died = 1;
- info->last = NEXT_INSN (insn);
- info->regno = HARD_Y_REGNUM;
- info->must_save_reg = 0;
- info->must_restore_reg = 0;
- return 0;
- }
- if (rtx_equal_p (src, z_reg) && rtx_equal_p (dst, iy_reg))
- {
- info->regno = HARD_Y_REGNUM;
- info->must_restore_reg = 0;
- info->must_save_reg = 0;
- return 0;
- }
- }
- if (z_dies_here)
- {
- info->need_save_z = 0;
- info->z_died = 1;
- if (info->last == 0)
- info->last = NEXT_INSN (insn);
- return 0;
- }
- return info->last != NULL_RTX ? 0 : 1;
- }
- if (GET_CODE (body) == PARALLEL)
- {
- int i;
- char ix_clobber = 0;
- char iy_clobber = 0;
- char z_clobber = 0;
- this_insn_uses_iy = 0;
- this_insn_uses_ix = 0;
- this_insn_uses_z = 0;
-
- for (i = XVECLEN (body, 0) - 1; i >= 0; i--)
- {
- rtx x;
- int uses_ix, uses_iy, uses_z;
-
- x = XVECEXP (body, 0, i);
-
- if (info->can_use_d && reg_mentioned_p (d_reg, x))
- info->can_use_d = 0;
-
- uses_ix = reg_mentioned_p (ix_reg, x);
- uses_iy = reg_mentioned_p (iy_reg, x);
- uses_z = reg_mentioned_p (z_reg, x);
- if (GET_CODE (x) == CLOBBER)
- {
- ix_clobber |= uses_ix;
- iy_clobber |= uses_iy;
- z_clobber |= uses_z;
- }
- else
- {
- this_insn_uses_ix |= uses_ix;
- this_insn_uses_iy |= uses_iy;
- this_insn_uses_z |= uses_z;
- }
- if (uses_z && GET_CODE (x) == SET)
- {
- rtx dst = XEXP (x, 0);
-
- if (Z_REG_P (dst))
- info->z_set_count++;
- }
- if (TARGET_M6812 && uses_z && side_effects_p (x))
- info->need_save_z = 1;
-
- if (z_clobber)
- info->need_save_z = 0;
- }
- if (debug_m6811)
- {
- printf ("Uses X:%d Y:%d Z:%d CX:%d CY:%d CZ:%d\n",
- this_insn_uses_ix, this_insn_uses_iy,
- this_insn_uses_z, ix_clobber, iy_clobber, z_clobber);
- debug_rtx (insn);
- }
- if (this_insn_uses_z)
- info->can_use_d = 0;
-
- if (z_clobber && info->first != insn)
- {
- info->need_save_z = 0;
- info->last = insn;
- return 0;
- }
- if (z_clobber && info->x_used == 0 && info->y_used == 0)
- {
- if (this_insn_uses_z == 0 && insn == info->first)
- {
- info->must_load_z = 0;
- }
- if (dead_register_here (insn, d_reg))
- {
- info->regno = HARD_D_REGNUM;
- info->must_save_reg = 0;
- info->must_restore_reg = 0;
- }
- else if (dead_register_here (insn, ix_reg))
- {
- info->regno = HARD_X_REGNUM;
- info->must_save_reg = 0;
- info->must_restore_reg = 0;
- }
- else if (dead_register_here (insn, iy_reg))
- {
- info->regno = HARD_Y_REGNUM;
- info->must_save_reg = 0;
- info->must_restore_reg = 0;
- }
- if (info->regno >= 0)
- {
- info->last = NEXT_INSN (insn);
- return 0;
- }
- if (this_insn_uses_ix == 0)
- {
- info->regno = HARD_X_REGNUM;
- info->must_save_reg = 1;
- info->must_restore_reg = 1;
- }
- else if (this_insn_uses_iy == 0)
- {
- info->regno = HARD_Y_REGNUM;
- info->must_save_reg = 1;
- info->must_restore_reg = 1;
- }
- else
- {
- info->regno = HARD_D_REGNUM;
- info->must_save_reg = 1;
- info->must_restore_reg = 1;
- }
- info->last = NEXT_INSN (insn);
- return 0;
- }
-
- if (((info->x_used || this_insn_uses_ix) && iy_clobber)
- || ((info->y_used || this_insn_uses_iy) && ix_clobber))
- {
- if (this_insn_uses_z)
- {
- if (info->y_used == 0 && iy_clobber)
- {
- info->regno = HARD_Y_REGNUM;
- info->must_save_reg = 0;
- info->must_restore_reg = 0;
- }
- if (info->first != insn
- && ((info->y_used && ix_clobber)
- || (info->x_used && iy_clobber)))
- info->last = insn;
- else
- info->last = NEXT_INSN (insn);
- info->save_before_last = 1;
- }
- return 0;
- }
- if (this_insn_uses_ix && this_insn_uses_iy)
- {
- if (this_insn_uses_z)
- {
- fatal_insn ("cannot do z-register replacement", insn);
- }
- return 0;
- }
- if (info->x_used == 0 && (this_insn_uses_ix || ix_clobber))
- {
- if (info->y_used)
- {
- return 0;
- }
- info->x_used = 1;
- if (iy_clobber || z_clobber)
- {
- info->last = NEXT_INSN (insn);
- info->save_before_last = 1;
- return 0;
- }
- }
-
- if (info->y_used == 0 && (this_insn_uses_iy || iy_clobber))
- {
- if (info->x_used)
- {
- return 0;
- }
- info->y_used = 1;
- if (ix_clobber || z_clobber)
- {
- info->last = NEXT_INSN (insn);
- info->save_before_last = 1;
- return 0;
- }
- }
- if (z_dies_here)
- {
- info->z_died = 1;
- info->need_save_z = 0;
- }
- return 1;
- }
- if (GET_CODE (body) == CLOBBER)
- {
- rtx dst = XEXP (body, 0);
-
- this_insn_uses_ix = reg_mentioned_p (ix_reg, dst);
- this_insn_uses_iy = reg_mentioned_p (iy_reg, dst);
-
- /* IX and IY are used at the same time, we have to restore
- the value of the scratch register before this insn. */
- if (this_insn_uses_ix && this_insn_uses_iy)
- {
- return 0;
- }
- if (info->x_used == 0 && this_insn_uses_ix)
- {
- if (info->y_used)
- {
- return 0;
- }
- info->x_used = 1;
- }
- if (info->y_used == 0 && this_insn_uses_iy)
- {
- if (info->x_used)
- {
- return 0;
- }
- info->y_used = 1;
- }
- return 1;
- }
- return 1;
-}
-
-static void
-m68hc11_find_z_replacement (rtx insn, struct replace_info *info)
-{
- int reg;
-
- info->replace_reg = NULL_RTX;
- info->must_load_z = 1;
- info->need_save_z = 1;
- info->must_save_reg = 1;
- info->must_restore_reg = 1;
- info->first = insn;
- info->x_used = 0;
- info->y_used = 0;
- info->can_use_d = TARGET_M6811 ? 1 : 0;
- info->found_call = 0;
- info->z_died = 0;
- info->last = 0;
- info->regno = -1;
- info->z_set_count = 0;
- info->z_value = NULL_RTX;
- info->must_push_reg = 0;
- info->save_before_last = 0;
- info->z_loaded_with_sp = 0;
-
- /* Scan the insn forward to find an address register that is not used.
- Stop when:
- - the flow of the program changes,
- - when we detect that both X and Y are necessary,
- - when the Z register dies,
- - when the condition codes are set. */
-
- for (; insn && info->z_died == 0; insn = NEXT_INSN (insn))
- {
- if (m68hc11_check_z_replacement (insn, info) == 0)
- break;
- }
-
- /* May be we can use Y or X if they contain the same value as Z.
- This happens very often after the reload. */
- if (info->z_set_count == 1)
- {
- rtx p = info->first;
- rtx v = 0;
-
- if (info->x_used)
- {
- v = find_last_value (iy_reg, &p, insn, 1);
- }
- else if (info->y_used)
- {
- v = find_last_value (ix_reg, &p, insn, 1);
- }
- if (v && (v != iy_reg && v != ix_reg) && rtx_equal_p (v, info->z_value))
- {
- if (info->x_used)
- info->regno = HARD_Y_REGNUM;
- else
- info->regno = HARD_X_REGNUM;
- info->must_load_z = 0;
- info->must_save_reg = 0;
- info->must_restore_reg = 0;
- info->found_call = 1;
- }
- }
- if (info->z_set_count == 0)
- info->need_save_z = 0;
-
- if (insn == 0)
- info->need_save_z = 0;
-
- if (info->last == 0)
- info->last = insn;
-
- if (info->regno >= 0)
- {
- reg = info->regno;
- info->replace_reg = gen_rtx_REG (HImode, reg);
- }
- else if (info->can_use_d)
- {
- reg = HARD_D_REGNUM;
- info->replace_reg = d_reg;
- }
- else if (info->x_used)
- {
- reg = HARD_Y_REGNUM;
- info->replace_reg = iy_reg;
- }
- else
- {
- reg = HARD_X_REGNUM;
- info->replace_reg = ix_reg;
- }
- info->regno = reg;
-
- if (info->must_save_reg && info->must_restore_reg)
- {
- if (insn && dead_register_here (insn, info->replace_reg))
- {
- info->must_save_reg = 0;
- info->must_restore_reg = 0;
- }
- }
-}
-
-/* The insn uses the Z register. Find a replacement register for it
- (either X or Y) and replace it in the insn and the next ones until
- the flow changes or the replacement register is used. Instructions
- are emitted before and after the Z-block to preserve the value of
- Z and of the replacement register. */
-
-static void
-m68hc11_z_replacement (rtx insn)
-{
- rtx replace_reg_qi;
- rtx replace_reg;
- struct replace_info info;
-
- /* Find trivial case where we only need to replace z with the
- equivalent soft register. */
- if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SET)
- {
- rtx body = PATTERN (insn);
- rtx src = XEXP (body, 1);
- rtx dst = XEXP (body, 0);
-
- if (Z_REG_P (dst) && (H_REG_P (src) && !SP_REG_P (src)))
- {
- XEXP (body, 0) = gen_rtx_REG (GET_MODE (dst), SOFT_Z_REGNUM);
- return;
- }
- else if (Z_REG_P (src)
- && ((H_REG_P (dst) && !SP_REG_P (src)) || dst == cc0_rtx))
- {
- XEXP (body, 1) = gen_rtx_REG (GET_MODE (src), SOFT_Z_REGNUM);
- return;
- }
- else if (D_REG_P (dst)
- && m68hc11_arith_operator (src, GET_MODE (src))
- && D_REG_P (XEXP (src, 0)) && Z_REG_P (XEXP (src, 1)))
- {
- XEXP (src, 1) = gen_rtx_REG (GET_MODE (src), SOFT_Z_REGNUM);
- return;
- }
- else if (Z_REG_P (dst) && GET_CODE (src) == CONST_INT
- && INTVAL (src) == 0)
- {
- XEXP (body, 0) = gen_rtx_REG (GET_MODE (dst), SOFT_Z_REGNUM);
- /* Force it to be re-recognized. */
- INSN_CODE (insn) = -1;
- return;
- }
- }
-
- m68hc11_find_z_replacement (insn, &info);
-
- replace_reg = info.replace_reg;
- replace_reg_qi = NULL_RTX;
-
- /* Save the X register in a .page0 location. */
- if (info.must_save_reg && !info.must_push_reg)
- {
- rtx dst;
-
- if (info.must_push_reg && 0)
- dst = gen_rtx_MEM (HImode,
- gen_rtx_PRE_DEC (HImode,
- gen_rtx_REG (HImode, HARD_SP_REGNUM)));
- else
- dst = gen_rtx_REG (HImode, SOFT_SAVED_XY_REGNUM);
-
- emit_insn_before (gen_movhi (dst,
- gen_rtx_REG (HImode, info.regno)), insn);
- }
- if (info.must_load_z && !info.must_push_reg)
- {
- emit_insn_before (gen_movhi (gen_rtx_REG (HImode, info.regno),
- gen_rtx_REG (HImode, SOFT_Z_REGNUM)),
- insn);
- }
-
-
- /* Replace all occurrence of Z by replace_reg.
- Stop when the last instruction to replace is reached.
- Also stop when we detect a change in the flow (but it's not
- necessary; just safeguard). */
-
- for (; insn && insn != info.last; insn = NEXT_INSN (insn))
- {
- rtx body;
-
- if (GET_CODE (insn) == CODE_LABEL || GET_CODE (insn) == BARRIER)
- break;
-
- if (GET_CODE (insn) != INSN
- && GET_CODE (insn) != CALL_INSN && GET_CODE (insn) != JUMP_INSN)
- continue;
-
- body = PATTERN (insn);
- if (GET_CODE (body) == SET || GET_CODE (body) == PARALLEL
- || GET_CODE (body) == ASM_OPERANDS
- || GET_CODE (insn) == CALL_INSN || GET_CODE (insn) == JUMP_INSN)
- {
- rtx note;
-
- if (debug_m6811 && reg_mentioned_p (replace_reg, body))
- {
- printf ("Reg mentioned here...:\n");
- fflush (stdout);
- debug_rtx (insn);
- }
-
- /* Stack pointer was decremented by 2 due to the push.
- Correct that by adding 2 to the destination. */
- if (info.must_push_reg
- && info.z_loaded_with_sp && GET_CODE (body) == SET)
- {
- rtx src, dst;
-
- src = SET_SRC (body);
- dst = SET_DEST (body);
- if (SP_REG_P (src) && Z_REG_P (dst))
- emit_insn_after (gen_addhi3 (dst, dst, const2_rtx), insn);
- }
-
- /* Replace any (REG:HI Z) occurrence by either X or Y. */
- if (!validate_replace_rtx (z_reg, replace_reg, insn))
- {
- INSN_CODE (insn) = -1;
- if (!validate_replace_rtx (z_reg, replace_reg, insn))
- fatal_insn ("cannot do z-register replacement", insn);
- }
-
- /* Likewise for (REG:QI Z). */
- if (reg_mentioned_p (z_reg, insn))
- {
- if (replace_reg_qi == NULL_RTX)
- replace_reg_qi = gen_rtx_REG (QImode, REGNO (replace_reg));
- validate_replace_rtx (z_reg_qi, replace_reg_qi, insn);
- }
-
- /* If there is a REG_INC note on Z, replace it with a
- REG_INC note on the replacement register. This is necessary
- to make sure that the flow pass will identify the change
- and it will not remove a possible insn that saves Z. */
- for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
- {
- if (REG_NOTE_KIND (note) == REG_INC
- && GET_CODE (XEXP (note, 0)) == REG
- && REGNO (XEXP (note, 0)) == REGNO (z_reg))
- {
- XEXP (note, 0) = replace_reg;
- }
- }
- }
- if (GET_CODE (insn) == CALL_INSN || GET_CODE (insn) == JUMP_INSN)
- break;
- }
-
- /* Save Z before restoring the old value. */
- if (insn && info.need_save_z && !info.must_push_reg)
- {
- rtx save_pos_insn = insn;
-
- /* If Z is clobber by the last insn, we have to save its value
- before the last instruction. */
- if (info.save_before_last)
- save_pos_insn = PREV_INSN (save_pos_insn);
-
- emit_insn_before (gen_movhi (gen_rtx_REG (HImode, SOFT_Z_REGNUM),
- gen_rtx_REG (HImode, info.regno)),
- save_pos_insn);
- }
-
- if (info.must_push_reg && info.last)
- {
- rtx new_body, body;
-
- body = PATTERN (info.last);
- new_body = gen_rtx_PARALLEL (VOIDmode,
- gen_rtvec (3, body,
- gen_rtx_USE (VOIDmode,
- replace_reg),
- gen_rtx_USE (VOIDmode,
- gen_rtx_REG (HImode,
- SOFT_Z_REGNUM))));
- PATTERN (info.last) = new_body;
-
- /* Force recognition on insn since we changed it. */
- INSN_CODE (insn) = -1;
-
- if (!validate_replace_rtx (z_reg, replace_reg, info.last))
- {
- fatal_insn ("invalid Z register replacement for insn", insn);
- }
- insn = NEXT_INSN (info.last);
- }
-
- /* Restore replacement register unless it was died. */
- if (insn && info.must_restore_reg && !info.must_push_reg)
- {
- rtx dst;
-
- if (info.must_push_reg && 0)
- dst = gen_rtx_MEM (HImode,
- gen_rtx_POST_INC (HImode,
- gen_rtx_REG (HImode, HARD_SP_REGNUM)));
- else
- dst = gen_rtx_REG (HImode, SOFT_SAVED_XY_REGNUM);
-
- emit_insn_before (gen_movhi (gen_rtx_REG (HImode, info.regno),
- dst), insn);
- }
-
-}
-
-
-/* Scan all the insn and re-affects some registers
- - The Z register (if it was used), is affected to X or Y depending
- on the instruction. */
-
-static void
-m68hc11_reassign_regs (rtx first)
-{
- rtx insn;
-
- ix_reg = gen_rtx_REG (HImode, HARD_X_REGNUM);
- iy_reg = gen_rtx_REG (HImode, HARD_Y_REGNUM);
- z_reg = gen_rtx_REG (HImode, HARD_Z_REGNUM);
- z_reg_qi = gen_rtx_REG (QImode, HARD_Z_REGNUM);
-
- /* Scan all insns to replace Z by X or Y preserving the old value
- of X/Y and restoring it afterward. */
-
- for (insn = first; insn; insn = NEXT_INSN (insn))
- {
- rtx body;
-
- if (GET_CODE (insn) == CODE_LABEL
- || GET_CODE (insn) == NOTE || GET_CODE (insn) == BARRIER)
- continue;
-
- if (!INSN_P (insn))
- continue;
-
- body = PATTERN (insn);
- if (GET_CODE (body) == CLOBBER || GET_CODE (body) == USE)
- continue;
-
- if (GET_CODE (body) == CONST_INT || GET_CODE (body) == ASM_INPUT
- || GET_CODE (body) == ASM_OPERANDS
- || GET_CODE (body) == UNSPEC || GET_CODE (body) == UNSPEC_VOLATILE)
- continue;
-
- if (GET_CODE (body) == SET || GET_CODE (body) == PARALLEL
- || GET_CODE (insn) == CALL_INSN || GET_CODE (insn) == JUMP_INSN)
- {
-
- /* If Z appears in this insn, replace it in the current insn
- and the next ones until the flow changes or we have to
- restore back the replacement register. */
-
- if (reg_mentioned_p (z_reg, body))
- {
- m68hc11_z_replacement (insn);
- }
- }
- else
- {
- printf ("insn not handled by Z replacement:\n");
- fflush (stdout);
- debug_rtx (insn);
- }
- }
-}
-
-
-/* Machine-dependent reorg pass.
- Specific optimizations are defined here:
- - this pass changes the Z register into either X or Y
- (it preserves X/Y previous values in a memory slot in page0).
-
- When this pass is finished, the global variable
- 'z_replacement_completed' is set to 2. */
-
-static void
-m68hc11_reorg (void)
-{
- int split_done = 0;
- rtx first;
-
- z_replacement_completed = 0;
- z_reg = gen_rtx_REG (HImode, HARD_Z_REGNUM);
- first = get_insns ();
-
- /* Some RTX are shared at this point. This breaks the Z register
- replacement, unshare everything. */
- unshare_all_rtl_again (first);
-
- /* Force a split of all splittable insn. This is necessary for the
- Z register replacement mechanism because we end up with basic insns. */
- split_all_insns_noflow ();
- split_done = 1;
-
- z_replacement_completed = 1;
- m68hc11_reassign_regs (first);
-
- if (optimize)
- compute_bb_for_insn ();
-
- /* After some splitting, there are some opportunities for CSE pass.
- This happens quite often when 32-bit or above patterns are split. */
- if (optimize > 0 && split_done)
- {
- reload_cse_regs (first);
- }
-
- /* Re-create the REG_DEAD notes. These notes are used in the machine
- description to use the best assembly directives. */
- if (optimize)
- {
- df_note_add_problem ();
- df_analyze ();
- df_remove_problem (df_note);
- }
-
- z_replacement_completed = 2;
-
- /* If optimizing, then go ahead and split insns that must be
- split after Z register replacement. This gives more opportunities
- for peephole (in particular for consecutives xgdx/xgdy). */
- if (optimize > 0)
- split_all_insns_noflow ();
-
- /* Once insns are split after the z_replacement_completed == 2,
- we must not re-run the life_analysis. The xgdx/xgdy patterns
- are not recognized and the life_analysis pass removes some
- insns because it thinks some (SETs) are noops or made to dead
- stores (which is false due to the swap).
-
- Do a simple pass to eliminate the noop set that the final
- split could generate (because it was easier for split definition). */
- {
- rtx insn;
-
- for (insn = first; insn; insn = NEXT_INSN (insn))
- {
- rtx body;
-
- if (INSN_DELETED_P (insn))
- continue;
- if (!INSN_P (insn))
- continue;
-
- /* Remove the (set (R) (R)) insns generated by some splits. */
- body = PATTERN (insn);
- if (GET_CODE (body) == SET
- && rtx_equal_p (SET_SRC (body), SET_DEST (body)))
- {
- SET_INSN_DELETED (insn);
- continue;
- }
- }
- }
-}
-\f
-/* Override memcpy */
-
-static void
-m68hc11_init_libfuncs (void)
-{
- memcpy_libfunc = init_one_libfunc ("__memcpy");
- memcmp_libfunc = init_one_libfunc ("__memcmp");
- memset_libfunc = init_one_libfunc ("__memset");
-}
-
-\f
-
-/* Cost functions. */
-
-/* Cost of moving memory. */
-int
-m68hc11_memory_move_cost (enum machine_mode mode, enum reg_class rclass,
- int in ATTRIBUTE_UNUSED)
-{
- if (rclass <= H_REGS && rclass > NO_REGS)
- {
- if (GET_MODE_SIZE (mode) <= 2)
- return COSTS_N_INSNS (1) + (reload_completed | reload_in_progress);
- else
- return COSTS_N_INSNS (2) + (reload_completed | reload_in_progress);
- }
- else
- {
- if (GET_MODE_SIZE (mode) <= 2)
- return COSTS_N_INSNS (3);
- else
- return COSTS_N_INSNS (4);
- }
-}
-
-
-/* Cost of moving data from a register of class 'from' to on in class 'to'.
- Reload does not check the constraint of set insns when the two registers
- have a move cost of 2. Setting a higher cost will force reload to check
- the constraints. */
-int
-m68hc11_register_move_cost (enum machine_mode mode, enum reg_class from,
- enum reg_class to)
-{
- /* All costs are symmetric, so reduce cases by putting the
- lower number class as the destination. */
- if (from < to)
- {
- enum reg_class tmp = to;
- to = from, from = tmp;
- }
- if (to >= S_REGS)
- return m68hc11_memory_move_cost (mode, S_REGS, 0);
- else if (from <= S_REGS)
- return COSTS_N_INSNS (1) + (reload_completed | reload_in_progress);
- else
- return COSTS_N_INSNS (2);
-}
-
-
-/* Provide the costs of an addressing mode that contains ADDR.
- If ADDR is not a valid address, its cost is irrelevant. */
-
-static int
-m68hc11_address_cost (rtx addr, bool speed ATTRIBUTE_UNUSED)
-{
- int cost = 4;
-
- switch (GET_CODE (addr))
- {
- case REG:
- /* Make the cost of hard registers and specially SP, FP small. */
- if (REGNO (addr) < FIRST_PSEUDO_REGISTER)
- cost = 0;
- else
- cost = 1;
- break;
-
- case SYMBOL_REF:
- cost = 8;
- break;
-
- case LABEL_REF:
- case CONST:
- cost = 0;
- break;
-
- case PLUS:
- {
- register rtx plus0 = XEXP (addr, 0);
- register rtx plus1 = XEXP (addr, 1);
-
- if (GET_CODE (plus0) != REG)
- break;
-
- switch (GET_CODE (plus1))
- {
- case CONST_INT:
- if (INTVAL (plus1) >= 2 * m68hc11_max_offset
- || INTVAL (plus1) < m68hc11_min_offset)
- cost = 3;
- else if (INTVAL (plus1) >= m68hc11_max_offset)
- cost = 2;
- else
- cost = 1;
- if (REGNO (plus0) < FIRST_PSEUDO_REGISTER)
- cost += 0;
- else
- cost += 1;
- break;
-
- case SYMBOL_REF:
- cost = 8;
- break;
-
- case CONST:
- case LABEL_REF:
- cost = 0;
- break;
-
- default:
- break;
- }
- break;
- }
- case PRE_DEC:
- case PRE_INC:
- if (SP_REG_P (XEXP (addr, 0)))
- cost = 1;
- break;
-
- default:
- break;
- }
- if (debug_m6811)
- {
- printf ("Address cost: %d for :", cost);
- fflush (stdout);
- debug_rtx (addr);
- }
-
- return cost;
-}
-
-static int
-m68hc11_shift_cost (enum machine_mode mode, rtx x, int shift)
-{
- int total;
-
- total = rtx_cost (x, SET, !optimize_size);
- if (mode == QImode)
- total += m68hc11_cost->shiftQI_const[shift % 8];
- else if (mode == HImode)
- total += m68hc11_cost->shiftHI_const[shift % 16];
- else if (shift == 8 || shift == 16 || shift == 32)
- total += m68hc11_cost->shiftHI_const[8];
- else if (shift != 0 && shift != 16 && shift != 32)
- {
- total += m68hc11_cost->shiftHI_const[1] * shift;
- }
-
- /* For SI and others, the cost is higher. */
- if (GET_MODE_SIZE (mode) > 2 && (shift % 16) != 0)
- total *= GET_MODE_SIZE (mode) / 2;
-
- /* When optimizing for size, make shift more costly so that
- multiplications are preferred. */
- if (optimize_size && (shift % 8) != 0)
- total *= 2;
-
- return total;
-}
-
-static int
-m68hc11_rtx_costs_1 (rtx x, enum rtx_code code,
- enum rtx_code outer_code ATTRIBUTE_UNUSED)
-{
- enum machine_mode mode = GET_MODE (x);
- int extra_cost = 0;
- int total;
-
- switch (code)
- {
- case ROTATE:
- case ROTATERT:
- case ASHIFT:
- case LSHIFTRT:
- case ASHIFTRT:
- if (GET_CODE (XEXP (x, 1)) == CONST_INT)
- {
- return m68hc11_shift_cost (mode, XEXP (x, 0), INTVAL (XEXP (x, 1)));
- }
-
- total = rtx_cost (XEXP (x, 0), code, !optimize_size) + rtx_cost (XEXP (x, 1), code, !optimize_size);
- total += m68hc11_cost->shift_var;
- return total;
-
- case AND:
- case XOR:
- case IOR:
- total = rtx_cost (XEXP (x, 0), code, !optimize_size) + rtx_cost (XEXP (x, 1), code, !optimize_size);
- total += m68hc11_cost->logical;
-
- /* Logical instructions are byte instructions only. */
- total *= GET_MODE_SIZE (mode);
- return total;
-
- case MINUS:
- case PLUS:
- total = rtx_cost (XEXP (x, 0), code, !optimize_size) + rtx_cost (XEXP (x, 1), code, !optimize_size);
- total += m68hc11_cost->add;
- if (GET_MODE_SIZE (mode) > 2)
- {
- total *= GET_MODE_SIZE (mode) / 2;
- }
- return total;
-
- case UDIV:
- case DIV:
- case MOD:
- total = rtx_cost (XEXP (x, 0), code, !optimize_size) + rtx_cost (XEXP (x, 1), code, !optimize_size);
- switch (mode)
- {
- case QImode:
- total += m68hc11_cost->divQI;
- break;
-
- case HImode:
- total += m68hc11_cost->divHI;
- break;
-
- case SImode:
- default:
- total += m68hc11_cost->divSI;
- break;
- }
- return total;
-
- case MULT:
- /* mul instruction produces 16-bit result. */
- if (mode == HImode && GET_CODE (XEXP (x, 0)) == ZERO_EXTEND
- && GET_CODE (XEXP (x, 1)) == ZERO_EXTEND)
- return m68hc11_cost->multQI
- + rtx_cost (XEXP (XEXP (x, 0), 0), code, !optimize_size)
- + rtx_cost (XEXP (XEXP (x, 1), 0), code, !optimize_size);
-
- /* emul instruction produces 32-bit result for 68HC12. */
- if (TARGET_M6812 && mode == SImode
- && GET_CODE (XEXP (x, 0)) == ZERO_EXTEND
- && GET_CODE (XEXP (x, 1)) == ZERO_EXTEND)
- return m68hc11_cost->multHI
- + rtx_cost (XEXP (XEXP (x, 0), 0), code, !optimize_size)
- + rtx_cost (XEXP (XEXP (x, 1), 0), code, !optimize_size);
-
- total = rtx_cost (XEXP (x, 0), code, !optimize_size)
- + rtx_cost (XEXP (x, 1), code, !optimize_size);
- switch (mode)
- {
- case QImode:
- total += m68hc11_cost->multQI;
- break;
-
- case HImode:
- total += m68hc11_cost->multHI;
- break;
-
- case SImode:
- default:
- total += m68hc11_cost->multSI;
- break;
- }
- return total;
-
- case NEG:
- case SIGN_EXTEND:
- extra_cost = COSTS_N_INSNS (2);
-
- /* Fall through */
- case NOT:
- case COMPARE:
- case ABS:
- case ZERO_EXTEND:
- case ZERO_EXTRACT:
- total = extra_cost + rtx_cost (XEXP (x, 0), code, !optimize_size);
- if (mode == QImode)
- {
- return total + COSTS_N_INSNS (1);
- }
- if (mode == HImode)
- {
- return total + COSTS_N_INSNS (2);
- }
- if (mode == SImode)
- {
- return total + COSTS_N_INSNS (4);
- }
- return total + COSTS_N_INSNS (8);
-
- case IF_THEN_ELSE:
- if (GET_CODE (XEXP (x, 1)) == PC || GET_CODE (XEXP (x, 2)) == PC)
- return COSTS_N_INSNS (1);
-
- return COSTS_N_INSNS (1);
-
- default:
- return COSTS_N_INSNS (4);
- }
-}
-
-static bool
-m68hc11_rtx_costs (rtx x, int codearg, int outer_code_arg, int *total,
- bool speed ATTRIBUTE_UNUSED)
-{
- enum rtx_code code = (enum rtx_code) codearg;
- enum rtx_code outer_code = (enum rtx_code) outer_code_arg;
-
- switch (code)
- {
- /* Constants are cheap. Moving them in registers must be avoided
- because most instructions do not handle two register operands. */
- case CONST_INT:
- case CONST:
- case LABEL_REF:
- case SYMBOL_REF:
- case CONST_DOUBLE:
- /* Logical and arithmetic operations with a constant operand are
- better because they are not supported with two registers. */
- /* 'clr' is slow */
- if (outer_code == SET && x == const0_rtx)
- /* After reload, the reload_cse pass checks the cost to change
- a SET into a PLUS. Make const0 cheap then. */
- *total = 1 - reload_completed;
- else
- *total = 0;
- return true;
-
- case ZERO_EXTRACT:
- if (outer_code != COMPARE)
- return false;
-
- case ROTATE:
- case ROTATERT:
- case ASHIFT:
- case LSHIFTRT:
- case ASHIFTRT:
- case MINUS:
- case PLUS:
- case AND:
- case XOR:
- case IOR:
- case UDIV:
- case DIV:
- case MOD:
- case MULT:
- case NEG:
- case SIGN_EXTEND:
- case NOT:
- case COMPARE:
- case ZERO_EXTEND:
- case IF_THEN_ELSE:
- *total = m68hc11_rtx_costs_1 (x, code, outer_code);
- return true;
-
- default:
- return false;
- }
-}
-\f
-
-/* Worker function for TARGET_ASM_FILE_START. */
-
-static void
-m68hc11_file_start (void)
-{
- default_file_start ();
-
- fprintf (asm_out_file, "\t.mode %s\n", TARGET_SHORT ? "mshort" : "mlong");
-}
-
-
-/* Worker function for TARGET_ASM_CONSTRUCTOR. */
-
-static void
-m68hc11_asm_out_constructor (rtx symbol, int priority)
-{
- default_ctor_section_asm_out_constructor (symbol, priority);
- fprintf (asm_out_file, "\t.globl\t__do_global_ctors\n");
-}
-
-/* Worker function for TARGET_ASM_DESTRUCTOR. */
-
-static void
-m68hc11_asm_out_destructor (rtx symbol, int priority)
-{
- default_dtor_section_asm_out_destructor (symbol, priority);
- fprintf (asm_out_file, "\t.globl\t__do_global_dtors\n");
-}
-
-/* Worker function for TARGET_STRUCT_VALUE_RTX. */
-
-static rtx
-m68hc11_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
- int incoming ATTRIBUTE_UNUSED)
-{
- return gen_rtx_REG (Pmode, HARD_D_REGNUM);
-}
-
-/* Return true if type TYPE should be returned in memory.
- Blocks and data types largers than 4 bytes cannot be returned
- in the register (D + X = 4). */
-
-static bool
-m68hc11_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
-{
- if (TYPE_MODE (type) == BLKmode)
- {
- HOST_WIDE_INT size = int_size_in_bytes (type);
- return (size == -1 || size > 4);
- }
- else
- return GET_MODE_SIZE (TYPE_MODE (type)) > 4;
-}
-
-#include "gt-m68hc11.h"
+++ /dev/null
-/* Definitions of target machine for GNU compiler.
- Motorola 68HC11 and 68HC12.
- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
- Free Software Foundation, Inc.
- Contributed by Stephane Carrez (stcarrez@nerim.fr)
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>.
-
-Note:
- A first 68HC11 port was made by Otto Lind (otto@coactive.com)
- on gcc 2.6.3. I have used it as a starting point for this port.
- However, this new port is a complete re-write. Its internal
- design is completely different. The generated code is not
- compatible with the gcc 2.6.3 port.
-
- The gcc 2.6.3 port is available at:
-
- ftp.unina.it/pub/electronics/motorola/68hc11/gcc/gcc-6811-fsf.tar.gz
-
-*/
-
-/*****************************************************************************
-**
-** Controlling the Compilation Driver, `gcc'
-**
-*****************************************************************************/
-
-#undef ENDFILE_SPEC
-
-/* Compile and assemble for a 68hc11 unless there is a -m68hc12 option. */
-#ifndef ASM_SPEC
-#define ASM_SPEC \
-"%{m68hc12:-m68hc12}" \
-"%{m68hcs12:-m68hcs12}" \
-"%{!m68hc12:%{!m68hcs12:-m68hc11}} " \
-"%{mshort:-mshort}%{!mshort:-mlong} " \
-"%{fshort-double:-mshort-double}%{!fshort-double:-mlong-double}"
-#endif
-
-/* We need to tell the linker the target elf format. Just pass an
- emulation option. This can be overridden by -Wl option of gcc. */
-#ifndef LINK_SPEC
-#define LINK_SPEC \
-"%{m68hc12:-m m68hc12elf}" \
-"%{m68hcs12:-m m68hc12elf}" \
-"%{!m68hc12:%{!m68hcs12:-m m68hc11elf}} " \
-"%{!mnorelax:%{!m68hc12:%{!m68hcs12:-relax}}}"
-#endif
-
-#ifndef LIB_SPEC
-#define LIB_SPEC ""
-#endif
-
-#ifndef CC1_SPEC
-#define CC1_SPEC ""
-#endif
-
-#ifndef CPP_SPEC
-#define CPP_SPEC \
-"%{mshort:-D__HAVE_SHORT_INT__ -D__INT__=16}\
- %{!mshort:-D__INT__=32}\
- %{m68hc12:-Dmc6812 -DMC6812 -Dmc68hc12}\
- %{m68hcs12:-Dmc6812 -DMC6812 -Dmc68hcs12}\
- %{!m68hc12:%{!m68hcs12:-Dmc6811 -DMC6811 -Dmc68hc11}}\
- %{fshort-double:-D__HAVE_SHORT_DOUBLE__}\
- %{mlong-calls:-D__USE_RTC__}"
-#endif
-
-#undef STARTFILE_SPEC
-#define STARTFILE_SPEC "crt1%O%s"
-
-/* Names to predefine in the preprocessor for this target machine. */
-#define TARGET_CPU_CPP_BUILTINS() \
- do \
- { \
- builtin_define_std ("mc68hc1x"); \
- } \
- while (0)
-
-/* As an embedded target, we have no libc. */
-#ifndef inhibit_libc
-# define inhibit_libc
-#endif
-
-/* Forward type declaration for prototypes definitions.
- rtx_ptr is equivalent to rtx. Can't use the same name. */
-struct rtx_def;
-typedef struct rtx_def *rtx_ptr;
-
-union tree_node;
-typedef union tree_node *tree_ptr;
-
-/* We can't declare enum machine_mode forward nor include 'machmode.h' here.
- Prototypes defined here will use an int instead. It's better than no
- prototype at all. */
-typedef int enum_machine_mode;
-
-/*****************************************************************************
-**
-** Run-time Target Specification
-**
-*****************************************************************************/
-
-/* Run-time compilation parameters selecting different hardware subsets. */
-
-extern short *reg_renumber; /* def in local_alloc.c */
-
-#define TARGET_OP_TIME (optimize && optimize_size == 0)
-#define TARGET_RELAX (TARGET_NO_DIRECT_MODE)
-
-/* Default target_flags if no switches specified. */
-#ifndef TARGET_DEFAULT
-# define TARGET_DEFAULT 0
-#endif
-
-/* Define this macro as a C expression for the initializer of an
- array of string to tell the driver program which options are
- defaults for this target and thus do not need to be handled
- specially when using `MULTILIB_OPTIONS'. */
-#ifndef MULTILIB_DEFAULTS
-# if TARGET_DEFAULT & MASK_M6811
-# define MULTILIB_DEFAULTS { "m68hc11" }
-# else
-# define MULTILIB_DEFAULTS { "m68hc12" }
-# endif
-#endif
-
-/* Print subsidiary information on the compiler version in use. */
-#define TARGET_VERSION fprintf (stderr, " (MC68HC11/MC68HC12/MC68HCS12)")
-
-\f
-/* Define cost parameters for a given processor variant. */
-struct processor_costs {
- const int add; /* cost of an add instruction */
- const int logical; /* cost of a logical instruction */
- const int shift_var;
- const int shiftQI_const[8];
- const int shiftHI_const[16];
- const int multQI;
- const int multHI;
- const int multSI;
- const int divQI;
- const int divHI;
- const int divSI;
-};
-
-/* Costs for the current processor. */
-extern const struct processor_costs *m68hc11_cost;
-\f
-
-/* target machine storage layout */
-
-/* Define this if most significant byte of a word is the lowest numbered. */
-#define BYTES_BIG_ENDIAN 1
-
-/* 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 word of a multiword number is numbered. */
-#define WORDS_BIG_ENDIAN 1
-
-/* Width of a word, in units (bytes). */
-#define UNITS_PER_WORD 2
-
-/* Definition of size_t. This is really an unsigned short as the
- 68hc11 only handles a 64K address space. */
-#define SIZE_TYPE "short unsigned int"
-
-/* A C expression for a string describing the name of the data type
- to use for the result of subtracting two pointers. The typedef
- name `ptrdiff_t' is defined using the contents of the string.
- The 68hc11 only has a 64K address space. */
-#define PTRDIFF_TYPE "short int"
-
-/* Allocation boundary (bits) for storing pointers in memory. */
-#define POINTER_BOUNDARY 8
-
-/* Normal alignment required for function parameters on the stack, in bits.
- This can't be less than BITS_PER_WORD */
-#define PARM_BOUNDARY (BITS_PER_WORD)
-
-/* Boundary (bits) on which stack pointer should be aligned. */
-#define STACK_BOUNDARY 8
-
-/* Allocation boundary (bits) for the code of a function. */
-#define FUNCTION_BOUNDARY 8
-
-#define BIGGEST_ALIGNMENT 8
-
-/* Alignment of field after `int : 0' in a structure. */
-#define EMPTY_FIELD_BOUNDARY 8
-
-/* Every structure's size must be a multiple of this. */
-#define STRUCTURE_SIZE_BOUNDARY 8
-
-/* Define this if instructions will fail to work if given data not
- on the nominal alignment. If instructions will merely go slower
- in that case, do not define this macro. */
-#define STRICT_ALIGNMENT 0
-
-/* 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 64
-\f
-/* target machine storage layout */
-
-/* Size (bits) of the type "int" on target machine
- (If undefined, default is BITS_PER_WORD). */
-#define INT_TYPE_SIZE (TARGET_SHORT ? 16 : 32)
-
-/* Size (bits) of the type "short" on target machine */
-#define SHORT_TYPE_SIZE 16
-
-/* Size (bits) of the type "long" on target machine */
-#define LONG_TYPE_SIZE 32
-
-/* Size (bits) of the type "long long" on target machine */
-#define LONG_LONG_TYPE_SIZE 64
-
-/* A C expression for the size in bits of the type `float' on the
- target machine. If you don't define this, the default is one word.
- Don't use default: a word is only 16. */
-#define FLOAT_TYPE_SIZE 32
-
-/* A C expression for the size in bits of the type double on the target
- machine. If you don't define this, the default is two words.
- Be IEEE compliant. */
-#define DOUBLE_TYPE_SIZE 64
-
-#define LONG_DOUBLE_TYPE_SIZE 64
-
-/* Define this as 1 if `char' should by default be signed; else as 0. */
-#define DEFAULT_SIGNED_CHAR 0
-
-/* Define these to avoid dependence on meaning of `int'.
- Note that WCHAR_TYPE_SIZE is used in cexp.y,
- where TARGET_SHORT is not available. */
-#define WCHAR_TYPE "short int"
-#define WCHAR_TYPE_SIZE 16
-\f
-
-/* Standard register usage. */
-
-#define HARD_REG_SIZE (UNITS_PER_WORD)
-
-/* Assign names to real MC68HC11 registers.
- A and B registers are not really used (A+B = D)
- X register is first so that GCC allocates X+D for 32-bit integers and
- the lowpart of that integer will be D. Having the lower part in D is
- better for 32<->16bit conversions and for many arithmetic operations. */
-#define HARD_X_REGNUM 0
-#define HARD_D_REGNUM 1
-#define HARD_Y_REGNUM 2
-#define HARD_SP_REGNUM 3
-#define HARD_PC_REGNUM 4
-#define HARD_A_REGNUM 5
-#define HARD_B_REGNUM 6
-#define HARD_CCR_REGNUM 7
-
-/* The Z register does not really exist in the 68HC11. This a fake register
- for GCC. It is treated exactly as an index register (X or Y). It is only
- in the A_REGS class, which is the BASE_REG_CLASS for GCC. Defining this
- register helps the reload pass of GCC. Otherwise, the reload often dies
- with register spill failures.
-
- The Z register is replaced by either X or Y during the machine specific
- reorg (m68hc11_reorg). It is saved in the SOFT_Z_REGNUM soft-register
- when this is necessary.
-
- It's possible to tell GCC not to use this register with -ffixed-z. */
-#define HARD_Z_REGNUM 8
-
-/* The frame pointer is a soft-register. It's treated as such by GCC:
- it is not and must not be part of the BASE_REG_CLASS. */
-#define DEFAULT_HARD_FP_REGNUM (9)
-#define HARD_FP_REGNUM (9)
-#define HARD_AP_REGNUM (HARD_FP_REGNUM)
-
-/* Temporary soft-register used in some cases when an operand came
- up into a bad register class (D, X, Y, SP) and gcc failed to
- recognize this. This register is never allocated by GCC. */
-#define SOFT_TMP_REGNUM 10
-
-/* The soft-register which is used to save the Z register
- (see Z register replacement notes in m68hc11.c). */
-#define SOFT_Z_REGNUM 11
-
-/* The soft-register which is used to save either X or Y. */
-#define SOFT_SAVED_XY_REGNUM 12
-
-/* A fake clobber register for 68HC12 patterns. */
-#define FAKE_CLOBBER_REGNUM (13)
-
-/* Define 32 soft-registers of 16-bit each. By default,
- only 12 of them are enabled and can be used by GCC. The
- -msoft-reg-count=<n> option allows to control the number of valid
- soft-registers. GCC can put 32-bit values in them
- by allocating consecutive registers. The first 3 soft-registers
- are never allocated by GCC. They are used in case the insn template needs
- a temporary register, or for the Z register replacement. */
-
-#define MAX_SOFT_REG_COUNT (32)
-#define SOFT_REG_FIXED 0, 0, 0, 0, 0, 0, 0, 0, \
- 0, 0, 0, 0, 1, 1, 1, 1, \
- 1, 1, 1, 1, 1, 1, 1, 1, \
- 1, 1, 1, 1, 1, 1, 1, 1
-#define SOFT_REG_USED 0, 0, 0, 0, 0, 0, 0, 0, \
- 0, 0, 0, 0, 1, 1, 1, 1, \
- 1, 1, 1, 1, 1, 1, 1, 1, \
- 1, 1, 1, 1, 1, 1, 1, 1
-#define SOFT_REG_ORDER \
-SOFT_REG_FIRST, SOFT_REG_FIRST+1,SOFT_REG_FIRST+2,SOFT_REG_FIRST+3,\
-SOFT_REG_FIRST+4, SOFT_REG_FIRST+5,SOFT_REG_FIRST+6,SOFT_REG_FIRST+7,\
-SOFT_REG_FIRST+8, SOFT_REG_FIRST+9,SOFT_REG_FIRST+10,SOFT_REG_FIRST+11,\
-SOFT_REG_FIRST+12, SOFT_REG_FIRST+13,SOFT_REG_FIRST+14,SOFT_REG_FIRST+15,\
-SOFT_REG_FIRST+16, SOFT_REG_FIRST+17,SOFT_REG_FIRST+18,SOFT_REG_FIRST+19,\
-SOFT_REG_FIRST+20, SOFT_REG_FIRST+21,SOFT_REG_FIRST+22,SOFT_REG_FIRST+23,\
-SOFT_REG_FIRST+24, SOFT_REG_FIRST+25,SOFT_REG_FIRST+26,SOFT_REG_FIRST+27,\
-SOFT_REG_FIRST+28, SOFT_REG_FIRST+29,SOFT_REG_FIRST+30,SOFT_REG_FIRST+31
-
-#define SOFT_REG_NAMES \
-"*_.d1", "*_.d2", "*_.d3", "*_.d4", \
-"*_.d5", "*_.d6", "*_.d7", "*_.d8", \
-"*_.d9", "*_.d10", "*_.d11", "*_.d12", \
-"*_.d13", "*_.d14", "*_.d15", "*_.d16", \
-"*_.d17", "*_.d18", "*_.d19", "*_.d20", \
-"*_.d21", "*_.d22", "*_.d23", "*_.d24", \
-"*_.d25", "*_.d26", "*_.d27", "*_.d28", \
-"*_.d29", "*_.d30", "*_.d31", "*_.d32"
-
-/* First available soft-register for GCC. */
-#define SOFT_REG_FIRST (SOFT_SAVED_XY_REGNUM+2)
-
-/* Last available soft-register for GCC. */
-#define SOFT_REG_LAST (SOFT_REG_FIRST+MAX_SOFT_REG_COUNT)
-#define SOFT_FP_REGNUM (SOFT_REG_LAST)
-#define SOFT_AP_REGNUM (SOFT_FP_REGNUM+1)
-
-/* Number of actual hardware registers. The hardware registers are assigned
- numbers for the compiler from 0 to just below FIRST_PSEUDO_REGISTER.
- All registers that the compiler knows about must be given numbers, even
- those that are not normally considered general registers. */
-#define FIRST_PSEUDO_REGISTER (SOFT_REG_LAST+2)
-
-/* 1 for registers that have pervasive standard uses and are not available
- for the register allocator. */
-#define FIXED_REGISTERS \
- {0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1,1, 1, SOFT_REG_FIXED, 1, 1}
-/* X, D, Y, SP,PC,A, B, CCR, Z, FP,ZTMP,ZR,XYR, FK, D1 - D32, SOFT-FP, AP */
-
-/* 1 for registers not available across function calls. For our pseudo
- registers, all are available. */
-#define CALL_USED_REGISTERS \
- {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1, 1, SOFT_REG_USED, 1, 1}
-/* X, D, Y, SP,PC,A, B, CCR, Z, FP, ZTMP,ZR,XYR, D1 - 32, SOFT-FP, AP */
-
-
-/* List the order in which to allocate registers. Each register must be
- listed once, even those in FIXED_REGISTERS. */
-#define REG_ALLOC_ORDER \
-{ HARD_D_REGNUM, HARD_X_REGNUM, HARD_Y_REGNUM, \
- SOFT_REG_ORDER, HARD_Z_REGNUM, HARD_PC_REGNUM, HARD_A_REGNUM, \
- HARD_B_REGNUM, HARD_CCR_REGNUM, HARD_FP_REGNUM, SOFT_FP_REGNUM, \
- HARD_SP_REGNUM, SOFT_TMP_REGNUM, SOFT_Z_REGNUM, SOFT_SAVED_XY_REGNUM, \
- SOFT_AP_REGNUM, FAKE_CLOBBER_REGNUM }
-
-/* A C expression for the number of consecutive hard registers,
- starting at register number REGNO, required to hold a value of
- mode MODE. */
-#define HARD_REGNO_NREGS(REGNO, MODE) \
-((Q_REGNO_P (REGNO)) ? (GET_MODE_SIZE (MODE)) : \
- ((GET_MODE_SIZE (MODE) + HARD_REG_SIZE - 1) / HARD_REG_SIZE))
-
-/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
- - 8-bit values are stored anywhere (except the SP register).
- - 16-bit values can be stored in any register whose mode is 16
- - 32-bit values can be stored in D, X registers or in a soft register
- (except the last one because we need 2 soft registers)
- - Values whose size is > 32 bit are not stored in real hard
- registers. They may be stored in soft registers if there are
- enough of them. */
-#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.
-
- All modes are tieable except QImode. */
-#define MODES_TIEABLE_P(MODE1, MODE2) \
- (((MODE1) == (MODE2)) \
- || ((MODE1) != QImode && (MODE2) != QImode))
-\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 M68hc11 has so few registers that it's not possible for GCC to
- do any register allocation without breaking. We extend the processor
- registers by having soft registers. These registers are treated as
- hard registers by GCC but they are located in memory and accessed by page0
- accesses (IND mode). */
-enum reg_class
-{
- NO_REGS,
- D_REGS, /* 16-bit data register */
- X_REGS, /* 16-bit X register */
- Y_REGS, /* 16-bit Y register */
- SP_REGS, /* 16-bit stack pointer */
- DA_REGS, /* 8-bit A reg. */
- DB_REGS, /* 8-bit B reg. */
- Z_REGS, /* 16-bit fake Z register */
- D8_REGS, /* 8-bit A or B reg. */
- Q_REGS, /* 8-bit (byte (QI)) data (A, B or D) */
- D_OR_X_REGS, /* D or X register */
- D_OR_Y_REGS, /* D or Y register */
- D_OR_SP_REGS, /* D or SP register */
- X_OR_Y_REGS, /* IX or Y register */
- A_REGS, /* 16-bit address register (X, Y, Z) */
- X_OR_SP_REGS, /* X or SP register */
- Y_OR_SP_REGS, /* Y or SP register */
- X_OR_Y_OR_D_REGS, /* X, Y or D */
- A_OR_D_REGS, /* X, Y, Z or D */
- A_OR_SP_REGS, /* X, Y, Z or SP */
- H_REGS, /* 16-bit hard register (D, X, Y, Z, SP) */
- S_REGS, /* 16-bit soft register */
- D_OR_S_REGS, /* 16-bit soft register or D register */
- X_OR_S_REGS, /* 16-bit soft register or X register */
- Y_OR_S_REGS, /* 16-bit soft register or Y register */
- Z_OR_S_REGS, /* 16-bit soft register or Z register */
- SP_OR_S_REGS, /* 16-bit soft register or SP register */
- D_OR_X_OR_S_REGS, /* 16-bit soft register or D or X register */
- D_OR_Y_OR_S_REGS, /* 16-bit soft register or D or Y register */
- D_OR_SP_OR_S_REGS, /* 16-bit soft register or D or SP register */
- A_OR_S_REGS, /* 16-bit soft register or X, Y registers */
- D_OR_A_OR_S_REGS, /* 16-bit soft register or D, X, Y registers */
- TMP_REGS, /* 16-bit fake scratch register */
- D_OR_A_OR_TMP_REGS, /* General scratch register */
- G_REGS, /* 16-bit general register
- (H_REGS + soft registers) */
- ALL_REGS,
- LIM_REG_CLASSES
-};
-
-/* alias GENERAL_REGS to G_REGS. */
-#define GENERAL_REGS G_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", \
- "D_REGS", \
- "X_REGS", \
- "Y_REGS", \
- "SP_REGS", \
- "DA_REGS", \
- "DB_REGS", \
- "D8_REGS", \
- "Z_REGS", \
- "Q_REGS", \
- "D_OR_X_REGS", \
- "D_OR_Y_REGS", \
- "D_OR_SP_REGS", \
- "X_OR_Y_REGS", \
- "A_REGS", \
- "X_OR_SP_REGS", \
- "Y_OR_SP_REGS", \
- "X_OR_Y_OR_D_REGS", \
- "A_OR_D_REGS", \
- "A_OR_SP_REGS", \
- "H_REGS", \
- "S_REGS", \
- "D_OR_S_REGS", \
- "X_OR_S_REGS", \
- "Y_OR_S_REGS", \
- "Z_OR_S_REGS", \
- "SP_OR_S_REGS", \
- "D_OR_X_OR_S_REGS", \
- "D_OR_Y_OR_S_REGS", \
- "D_OR_SP_OR_S_REGS", \
- "A_OR_S_REGS", \
- "D_OR_A_OR_S_REGS", \
- "TMP_REGS", \
- "D_OR_A_OR_TMP_REGS", \
- "G_REGS", \
- "ALL_REGS" }
-
-/* 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. */
-
-/*--------------------------------------------------------------
- X 0x00000001
- D 0x00000002
- Y 0x00000004
- SP 0x00000008
- PC 0x00000010
- A 0x00000020
- B 0x00000040
- CCR 0x00000080
- Z 0x00000100
- FRAME 0x00000200
- ZTMP 0x00000400
- ZREG 0x00000800
- XYREG 0x00001000
- FAKE 0x00002000
- Di 0xFFFFc000, 0x03FFF
- SFRAME 0x00000000, 0x04000
- AP 0x00000000, 0x08000
-
- D_OR_X_REGS represents D+X. It is used for 32-bits numbers.
- A_REGS represents a valid base register for indexing. It represents
- X,Y and the Z register.
- S_REGS represents the soft-registers. This includes the hard frame
- and soft frame registers.
---------------------------------------------------------------*/
-
-#define REG_CLASS_CONTENTS \
-/* NO_REGS */ {{ 0x00000000, 0x00000000 }, \
-/* D_REGS */ { 0x00000002, 0x00000000 }, /* D */ \
-/* X_REGS */ { 0x00000001, 0x00000000 }, /* X */ \
-/* Y_REGS */ { 0x00000004, 0x00000000 }, /* Y */ \
-/* SP_REGS */ { 0x00000008, 0x00000000 }, /* SP */ \
-/* DA_REGS */ { 0x00000020, 0x00000000 }, /* A */ \
-/* DB_REGS */ { 0x00000040, 0x00000000 }, /* B */ \
-/* Z_REGS */ { 0x00000100, 0x00000000 }, /* Z */ \
-/* D8_REGS */ { 0x00000060, 0x00000000 }, /* A B */ \
-/* Q_REGS */ { 0x00000062, 0x00000000 }, /* A B D */ \
-/* D_OR_X_REGS */ { 0x00000003, 0x00000000 }, /* D X */ \
-/* D_OR_Y_REGS */ { 0x00000006, 0x00000000 }, /* D Y */ \
-/* D_OR_SP_REGS */ { 0x0000000A, 0x00000000 }, /* D SP */ \
-/* X_OR_Y_REGS */ { 0x00000005, 0x00000000 }, /* X Y */ \
-/* A_REGS */ { 0x00000105, 0x00000000 }, /* X Y Z */ \
-/* X_OR_SP_REGS */ { 0x00000009, 0x00000000 }, /* X SP */ \
-/* Y_OR_SP_REGS */ { 0x0000000C, 0x00000000 }, /* Y SP */ \
-/* X_OR_Y_OR_D_REGS */ { 0x00000007, 0x00000000 }, /* D X Y */ \
-/* A_OR_D_REGS */ { 0x00000107, 0x00000000 }, /* D X Y Z */ \
-/* A_OR_SP_REGS */ { 0x0000010D, 0x00000000 }, /* X Y SP */ \
-/* H_REGS */ { 0x0000010F, 0x00000000 }, /* D X Y SP */ \
-/* S_REGS */ { 0xFFFFDE00, 0x00007FFF }, /* _.D,..,FP,Z* */ \
-/* D_OR_S_REGS */ { 0xFFFFDE02, 0x00007FFF }, /* D _.D */ \
-/* X_OR_S_REGS */ { 0xFFFFDE01, 0x00007FFF }, /* X _.D */ \
-/* Y_OR_S_REGS */ { 0xFFFFDE04, 0x00007FFF }, /* Y _.D */ \
-/* Z_OR_S_REGS */ { 0xFFFFDF00, 0x00007FFF }, /* Z _.D */ \
-/* SP_OR_S_REGS */ { 0xFFFFDE08, 0x00007FFF }, /* SP _.D */ \
-/* D_OR_X_OR_S_REGS */ { 0xFFFFDE03, 0x00007FFF }, /* D X _.D */ \
-/* D_OR_Y_OR_S_REGS */ { 0xFFFFDE06, 0x00007FFF }, /* D Y _.D */ \
-/* D_OR_SP_OR_S_REGS */ { 0xFFFFDE0A, 0x00007FFF }, /* D SP _.D */ \
-/* A_OR_S_REGS */ { 0xFFFFDF05, 0x00007FFF }, /* X Y _.D */ \
-/* D_OR_A_OR_S_REGS */ { 0xFFFFDF07, 0x00007FFF }, /* D X Y _.D */ \
-/* TMP_REGS */ { 0x00002000, 0x00000000 }, /* FAKE */ \
-/* D_OR_A_OR_TMP_REGS*/ { 0x00002107, 0x00000000 }, /* D X Y Z Fake */ \
-/* G_REGS */ { 0xFFFFFF1F, 0x00007FFF }, /* ? _.D D X Y */ \
-/* ALL_REGS*/ { 0xFFFFFFFF, 0x00007FFF }}
-
-
-/* set up a C expression whose value is a register class containing hard
- register REGNO */
-#define Q_REGNO_P(REGNO) ((REGNO) == HARD_A_REGNUM \
- || (REGNO) == HARD_B_REGNUM)
-#define Q_REG_P(X) (REG_P (X) && Q_REGNO_P (REGNO (X)))
-
-#define D_REGNO_P(REGNO) ((REGNO) == HARD_D_REGNUM)
-#define D_REG_P(X) (REG_P (X) && D_REGNO_P (REGNO (X)))
-
-#define DB_REGNO_P(REGNO) ((REGNO) == HARD_B_REGNUM)
-#define DB_REG_P(X) (REG_P (X) && DB_REGNO_P (REGNO (X)))
-#define DA_REGNO_P(REGNO) ((REGNO) == HARD_A_REGNUM)
-#define DA_REG_P(X) (REG_P (X) && DA_REGNO_P (REGNO (X)))
-
-#define X_REGNO_P(REGNO) ((REGNO) == HARD_X_REGNUM)
-#define X_REG_P(X) (REG_P (X) && X_REGNO_P (REGNO (X)))
-
-#define Y_REGNO_P(REGNO) ((REGNO) == HARD_Y_REGNUM)
-#define Y_REG_P(X) (REG_P (X) && Y_REGNO_P (REGNO (X)))
-
-#define Z_REGNO_P(REGNO) ((REGNO) == HARD_Z_REGNUM)
-#define Z_REG_P(X) (REG_P (X) && Z_REGNO_P (REGNO (X)))
-
-#define SP_REGNO_P(REGNO) ((REGNO) == HARD_SP_REGNUM)
-#define SP_REG_P(X) (REG_P (X) && SP_REGNO_P (REGNO (X)))
-
-/* Address register. */
-#define A_REGNO_P(REGNO) ((REGNO) == HARD_X_REGNUM \
- || (REGNO) == HARD_Y_REGNUM \
- || (REGNO) == HARD_Z_REGNUM)
-#define A_REG_P(X) (REG_P (X) && A_REGNO_P (REGNO (X)))
-
-/* M68hc11 hard registers. */
-#define H_REGNO_P(REGNO) (D_REGNO_P (REGNO) || A_REGNO_P (REGNO) \
- || SP_REGNO_P (REGNO) || Q_REGNO_P (REGNO))
-#define H_REG_P(X) (REG_P (X) && H_REGNO_P (REGNO (X)))
-
-#define FAKE_REGNO_P(REGNO) ((REGNO) == FAKE_CLOBBER_REGNUM)
-#define FAKE_REG_P(X) (REG_P (X) && FAKE_REGNO_P (REGNO (X)))
-
-/* Soft registers (or register emulation for gcc). The temporary register
- used by insn template must be part of the S_REGS class so that it
- matches the 'u' constraint. */
-#define S_REGNO_P(REGNO) ((REGNO) >= SOFT_TMP_REGNUM \
- && (REGNO) <= SOFT_REG_LAST \
- && (REGNO) != FAKE_CLOBBER_REGNUM)
-#define S_REG_P(X) (REG_P (X) && S_REGNO_P (REGNO (X)))
-
-#define Z_REGNO_P(REGNO) ((REGNO) == HARD_Z_REGNUM)
-#define Z_REG_P(X) (REG_P (X) && Z_REGNO_P (REGNO (X)))
-
-/* General register. */
-#define G_REGNO_P(REGNO) (H_REGNO_P (REGNO) || S_REGNO_P (REGNO) \
- || ((REGNO) == HARD_PC_REGNUM) \
- || ((REGNO) == HARD_FP_REGNUM) \
- || ((REGNO) == SOFT_FP_REGNUM) \
- || ((REGNO) == FAKE_CLOBBER_REGNUM) \
- || ((REGNO) == SOFT_AP_REGNUM))
-
-#define G_REG_P(X) (REG_P (X) && G_REGNO_P (REGNO (X)))
-
-#define REGNO_REG_CLASS(REGNO) \
- (D_REGNO_P (REGNO) ? D_REGS : \
- (X_REGNO_P (REGNO) ? X_REGS : \
- (Y_REGNO_P (REGNO) ? Y_REGS : \
- (SP_REGNO_P (REGNO) ? SP_REGS : \
- (Z_REGNO_P (REGNO) ? Z_REGS : \
- (H_REGNO_P (REGNO) ? H_REGS : \
- (FAKE_REGNO_P (REGNO) ? TMP_REGS : \
- (S_REGNO_P (REGNO) ? S_REGS : \
- (DA_REGNO_P (REGNO) ? DA_REGS: \
- (DB_REGNO_P (REGNO) ? DB_REGS: \
- (G_REGNO_P (REGNO) ? G_REGS : ALL_REGS)))))))))))
-
-
-/* Get reg_class from a letter in the machine description. */
-
-extern enum reg_class m68hc11_tmp_regs_class;
-#define REG_CLASS_FROM_LETTER(C) \
- ((C) == 'a' ? DA_REGS : \
- (C) == 'A' ? A_REGS : \
- (C) == 'b' ? DB_REGS : \
- (C) == 'B' ? X_OR_Y_REGS : \
- (C) == 'd' ? D_REGS : \
- (C) == 'D' ? D_OR_X_REGS : \
- (C) == 'q' ? Q_REGS : \
- (C) == 'h' ? H_REGS : \
- (C) == 't' ? TMP_REGS : \
- (C) == 'u' ? S_REGS : \
- (C) == 'v' ? m68hc11_tmp_regs_class : \
- (C) == 'w' ? SP_REGS : \
- (C) == 'x' ? X_REGS : \
- (C) == 'y' ? Y_REGS : \
- (C) == 'z' ? Z_REGS : NO_REGS)
-
-#define PREFERRED_RELOAD_CLASS(X,CLASS) preferred_reload_class(X,CLASS)
-
-#define TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P hook_bool_mode_true
-
-/* A C expression that is nonzero if hard register number REGNO2 can be
- considered for use as a rename register for REGNO1 */
-
-#define HARD_REGNO_RENAME_OK(REGNO1,REGNO2) \
- m68hc11_hard_regno_rename_ok ((REGNO1), (REGNO2))
-
-/* Return the maximum number of consecutive registers needed to represent
- mode MODE in a register of class CLASS. */
-#define CLASS_MAX_NREGS(CLASS, MODE) \
-(((CLASS) == DA_REGS || (CLASS) == DB_REGS \
- || (CLASS) == D8_REGS || (CLASS) == Q_REGS) ? GET_MODE_SIZE (MODE) \
- : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
-
-/* 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.
-
- `K' is for 0.
- `L' is for range -65536 to 65536
- `M' is for values whose 16-bit low part is 0
- 'N' is for +1 or -1.
- 'O' is for 16 (for rotate using swap).
- 'P' is for range -8 to 2 (used by addhi_sp)
-
- 'I', 'J' are not used. */
-
-#define CONST_OK_FOR_LETTER_P(VALUE, C) \
- ((C) == 'K' ? (VALUE) == 0 : \
- (C) == 'L' ? ((VALUE) >= -65536 && (VALUE) <= 65535) : \
- (C) == 'M' ? ((VALUE) & 0x0ffffL) == 0 : \
- (C) == 'N' ? ((VALUE) == 1 || (VALUE) == -1) : \
- (C) == 'I' ? ((VALUE) >= -2 && (VALUE) <= 2) : \
- (C) == 'O' ? (VALUE) == 16 : \
- (C) == 'P' ? ((VALUE) <= 2 && (VALUE) >= -8) : 0)
-
-/* Similar, but for floating constants, and defining letters G and H.
-
- `G' is for 0.0. */
-#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \
- ((C) == 'G' ? (GET_MODE_CLASS (GET_MODE (VALUE)) == MODE_FLOAT \
- && VALUE == CONST0_RTX (GET_MODE (VALUE))) : 0)
-
-/* 'U' represents certain kind of memory indexed operand for 68HC12.
- and any memory operand for 68HC11.
- 'R' represents indexed addressing mode or access to page0 for 68HC11.
- For 68HC12, it represents any memory operand. */
-#define EXTRA_CONSTRAINT(OP, C) \
-((C) == 'U' ? m68hc11_small_indexed_indirect_p (OP, GET_MODE (OP)) \
- : (C) == 'Q' ? m68hc11_symbolic_p (OP, GET_MODE (OP)) \
- : (C) == 'R' ? m68hc11_indirect_p (OP, GET_MODE (OP)) \
- : (C) == 'S' ? (memory_operand (OP, GET_MODE (OP)) \
- && non_push_operand (OP, GET_MODE (OP))) : 0)
-
-\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 to nonzero 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 to 0 for 68HC11, the frame pointer is the bottom
- of local variables. */
-#define FRAME_GROWS_DOWNWARD 0
-
-/* Define this if successive arguments to a function occupy decreasing
- addresses in the stack. */
-/* #define ARGS_GROW_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 0
-
-/* Offset of first parameter from the argument pointer register value. */
-
-#define FIRST_PARM_OFFSET(FNDECL) 2
-
-/* After the prologue, RA is at 0(AP) in the current frame. */
-#define RETURN_ADDR_RTX(COUNT, FRAME) \
- ((COUNT) == 0 \
- ? gen_rtx_MEM (Pmode, arg_pointer_rtx) \
- : 0)
-
-/* Before the prologue, the top of the frame is at 2(sp). */
-#define INCOMING_FRAME_SP_OFFSET 2
-
-/* Define this if functions should assume that stack space has been
- allocated for arguments even when their values are passed in
- registers.
-
- The value of this macro is the size, in bytes, of the area reserved for
- arguments passed in registers.
-
- This space can either be allocated by the caller or be a part of the
- machine-dependent stack frame: `OUTGOING_REG_PARM_STACK_SPACE'
- says which. */
-/* #define REG_PARM_STACK_SPACE(FNDECL) 2 */
-
-/* Define this macro if REG_PARM_STACK_SPACE is defined but stack
- parameters don't skip the area specified by REG_PARM_STACK_SPACE.
- Normally, when a parameter is not passed in registers, it is placed on
- the stack beyond the REG_PARM_STACK_SPACE area. Defining this macro
- suppresses this behavior and causes the parameter to be passed on the
- stack in its natural location. */
-/* #define STACK_PARMS_IN_REG_PARM_AREA */
-
-/* Register to use for pushing function arguments. */
-#define STACK_POINTER_REGNUM HARD_SP_REGNUM
-
-/* Base register for access to local variables of the function. */
-#define FRAME_POINTER_REGNUM SOFT_FP_REGNUM
-
-#define HARD_FRAME_POINTER_REGNUM HARD_FP_REGNUM
-
-/* Base register for access to arguments of the function. */
-#define ARG_POINTER_REGNUM SOFT_AP_REGNUM
-
-/* Register in which static-chain is passed to a function. */
-#define STATIC_CHAIN_REGNUM SOFT_Z_REGNUM
-
-\f
-/* 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.
-
- We have two registers that are eliminated on the 6811. The pseudo arg
- pointer and pseudo frame pointer registers can always be eliminated;
- they are replaced with either the stack or the real frame pointer. */
-
-#define ELIMINABLE_REGS \
-{{ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
- {ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \
- {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
- {FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}}
-
-/* Define the offset between two registers, one to be eliminated, and the other
- its replacement, at the start of a routine. */
-
-#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
- { OFFSET = m68hc11_initial_elimination_offset (FROM, TO); }
-
-\f
-/* Passing Function Arguments on the Stack. */
-
-/* If we generate an insn to push BYTES bytes, this says how many the
- stack pointer really advances by. No rounding or alignment needed
- for MC6811. */
-#define PUSH_ROUNDING(BYTES) (BYTES)
-\f
-/* Passing Arguments in Registers. */
-
-/* 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. */
-
-typedef struct m68hc11_args
-{
- int words;
- int nregs;
-} CUMULATIVE_ARGS;
-
-/* If defined, a C expression which determines whether, and in which direction,
- to pad out an argument with extra space. The value should be of type
- `enum direction': either `upward' to pad above the argument,
- `downward' to pad below, or `none' to inhibit padding.
-
- Structures are stored left shifted in their argument slot. */
-#define FUNCTION_ARG_PADDING(MODE, TYPE) \
- m68hc11_function_arg_padding ((MODE), (TYPE))
-
-#undef PAD_VARARGS_DOWN
-#define PAD_VARARGS_DOWN \
- (m68hc11_function_arg_padding (TYPE_MODE (type), type) == downward)
-
-/* 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, N_NAMED_ARGS) \
- (m68hc11_init_cumulative_args (&CUM, FNTYPE, LIBNAME))
-
-/* Define the profitability of saving registers around calls.
-
- Disable this because the saving instructions generated by
- caller-save need a reload and the way it is implemented,
- it forbids all spill registers at that point. Enabling
- caller saving results in spill failure. */
-#define CALLER_SAVE_PROFITABLE(REFS,CALLS) 0
-
-/* 1 if N is a possible register number for function argument passing.
- D is for 16-bit values, X is for 32-bit (X+D). */
-#define FUNCTION_ARG_REGNO_P(N) \
- (((N) == HARD_D_REGNUM) || ((N) == HARD_X_REGNUM))
-
-/* All return values are in the D or X+D registers:
- - 8 and 16-bit values are returned in D.
- BLKmode are passed in D as pointer.
- - 32-bit values are returned in X + D.
- The high part is passed in X and the low part in D.
- For GCC, the register number must be HARD_X_REGNUM. */
-#define FUNCTION_VALUE(VALTYPE, FUNC) \
- gen_rtx_REG (TYPE_MODE (VALTYPE), \
- ((TYPE_MODE (VALTYPE) == BLKmode \
- || GET_MODE_SIZE (TYPE_MODE (VALTYPE)) <= 2) \
- ? HARD_D_REGNUM : HARD_X_REGNUM))
-
-#define LIBCALL_VALUE(MODE) \
- gen_rtx_REG (MODE, \
- (((MODE) == BLKmode || GET_MODE_SIZE (MODE) <= 2) \
- ? HARD_D_REGNUM : HARD_X_REGNUM))
-
-/* 1 if N is a possible register number for a function value. */
-#define FUNCTION_VALUE_REGNO_P(N) \
- ((N) == HARD_D_REGNUM || (N) == HARD_X_REGNUM)
-
-/* 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
-
-\f
-/* Generating Code for Profiling. */
-
-/* Output assembler code to FILE to increment profiler label # LABELNO
- for profiling a function entry. */
-#define FUNCTION_PROFILER(FILE, LABELNO) \
- fprintf (FILE, "\tldy\t.LP%d\n\tjsr mcount\n", (LABELNO))
-
-/* Length in units of the trampoline for entering a nested function. */
-#define TRAMPOLINE_SIZE (TARGET_M6811 ? 11 : 9)
-
-\f
-/* Addressing modes, and classification of registers for them. */
-
-#define ADDR_STRICT 0x01 /* Accept only registers in class A_REGS */
-#define ADDR_INCDEC 0x02 /* Post/Pre inc/dec */
-#define ADDR_INDEXED 0x04 /* D-reg index */
-#define ADDR_OFFSET 0x08
-#define ADDR_INDIRECT 0x10 /* Accept (mem (mem ...)) for [n,X] */
-#define ADDR_CONST 0x20 /* Accept const and symbol_ref */
-
-/* The 68HC12 has all the post/pre increment/decrement modes. */
-#define HAVE_POST_INCREMENT (TARGET_M6812 && TARGET_AUTO_INC_DEC)
-#define HAVE_PRE_INCREMENT (TARGET_M6812 && TARGET_AUTO_INC_DEC)
-#define HAVE_POST_DECREMENT (TARGET_M6812 && TARGET_AUTO_INC_DEC)
-#define HAVE_PRE_DECREMENT (TARGET_M6812 && TARGET_AUTO_INC_DEC)
-
-/* The class value for base registers. This depends on the target:
- A_REGS for 68HC11 and A_OR_SP_REGS for 68HC12. The class value
- is stored at init time. */
-extern enum reg_class m68hc11_base_reg_class;
-#define BASE_REG_CLASS m68hc11_base_reg_class
-
-/* The class value for index registers. This is NO_REGS for 68HC11. */
-
-extern enum reg_class m68hc11_index_reg_class;
-#define INDEX_REG_CLASS m68hc11_index_reg_class
-
-/* 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. */
-
-
-extern unsigned char m68hc11_reg_valid_for_base[FIRST_PSEUDO_REGISTER];
-#define REG_VALID_FOR_BASE_P(REGNO) \
- ((REGNO) < FIRST_PSEUDO_REGISTER \
- && m68hc11_reg_valid_for_base[REGNO])
-
-/* Internal macro, return 1 if REGNO is a valid index register. */
-extern unsigned char m68hc11_reg_valid_for_index[FIRST_PSEUDO_REGISTER];
-#define REG_VALID_FOR_INDEX_P(REGNO) \
- ((REGNO) < FIRST_PSEUDO_REGISTER \
- && m68hc11_reg_valid_for_index[REGNO])
-
-/* Internal macro, the nonstrict definition for REGNO_OK_FOR_BASE_P. */
-#define REGNO_OK_FOR_BASE_NONSTRICT_P(REGNO) \
- ((REGNO) >= FIRST_PSEUDO_REGISTER \
- || REG_VALID_FOR_BASE_P (REGNO) \
- || (REGNO) == FRAME_POINTER_REGNUM \
- || (REGNO) == HARD_FRAME_POINTER_REGNUM \
- || (REGNO) == ARG_POINTER_REGNUM \
- || (reg_renumber && REG_VALID_FOR_BASE_P (reg_renumber[REGNO])))
-
-/* Internal macro, the nonstrict definition for REGNO_OK_FOR_INDEX_P. */
-#define REGNO_OK_FOR_INDEX_NONSTRICT_P(REGNO) \
- (TARGET_M6812 \
- && ((REGNO) >= FIRST_PSEUDO_REGISTER \
- || REG_VALID_FOR_INDEX_P (REGNO) \
- || (reg_renumber && REG_VALID_FOR_INDEX_P (reg_renumber[REGNO]))))
-
-/* Internal macro, the strict definition for REGNO_OK_FOR_BASE_P. */
-#define REGNO_OK_FOR_BASE_STRICT_P(REGNO) \
- ((REGNO) < FIRST_PSEUDO_REGISTER ? REG_VALID_FOR_BASE_P (REGNO) \
- : (reg_renumber && REG_VALID_FOR_BASE_P (reg_renumber[REGNO])))
-
-/* Internal macro, the strict definition for REGNO_OK_FOR_INDEX_P. */
-#define REGNO_OK_FOR_INDEX_STRICT_P(REGNO) \
- (TARGET_M6812 \
- && ((REGNO) < FIRST_PSEUDO_REGISTER ? REG_VALID_FOR_INDEX_P (REGNO) \
- : (reg_renumber && REG_VALID_FOR_INDEX_P (reg_renumber[REGNO]))))
-
-#define REGNO_OK_FOR_BASE_P2(REGNO,STRICT) \
- ((STRICT) ? (REGNO_OK_FOR_BASE_STRICT_P (REGNO)) \
- : (REGNO_OK_FOR_BASE_NONSTRICT_P (REGNO)))
-
-#define REGNO_OK_FOR_INDEX_P2(REGNO,STRICT) \
- ((STRICT) ? (REGNO_OK_FOR_INDEX_STRICT_P (REGNO)) \
- : (REGNO_OK_FOR_INDEX_NONSTRICT_P (REGNO)))
-
-#define REGNO_OK_FOR_BASE_P(REGNO) REGNO_OK_FOR_BASE_STRICT_P (REGNO)
-#define REGNO_OK_FOR_INDEX_P(REGNO) REGNO_OK_FOR_INDEX_STRICT_P (REGNO)
-
-#define REG_OK_FOR_BASE_STRICT_P(X) REGNO_OK_FOR_BASE_STRICT_P (REGNO (X))
-#define REG_OK_FOR_BASE_NONSTRICT_P(X) REGNO_OK_FOR_BASE_NONSTRICT_P (REGNO (X))
-#define REG_OK_FOR_INDEX_STRICT_P(X) REGNO_OK_FOR_INDEX_STRICT_P (REGNO (X))
-#define REG_OK_FOR_INDEX_NONSTRICT_P(X) REGNO_OK_FOR_INDEX_NONSTRICT_P (REGNO (X))
-
-/* see PUSH_POP_ADDRESS_P() below for an explanation of this. */
-#define IS_STACK_PUSH(operand) \
- ((GET_CODE (operand) == MEM) \
- && (GET_CODE (XEXP (operand, 0)) == PRE_DEC) \
- && (SP_REG_P (XEXP (XEXP (operand, 0), 0))))
-
-#define IS_STACK_POP(operand) \
- ((GET_CODE (operand) == MEM) \
- && (GET_CODE (XEXP (operand, 0)) == POST_INC) \
- && (SP_REG_P (XEXP (XEXP (operand, 0), 0))))
-
-/* Maximum number of registers that can appear in a valid memory address */
-#define MAX_REGS_PER_ADDRESS 2
-
-/* TARGET_LEGITIMATE_ADDRESS_P 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. */
-
-/*--------------------------------------------------------------
- Valid addresses are either direct or indirect (MEM) versions
- of the following forms:
- constant N
- register ,X
- indexed N,X
---------------------------------------------------------------*/
-
-/* The range of index that is allowed by indirect addressing. */
-
-#define VALID_MIN_OFFSET m68hc11_min_offset
-#define VALID_MAX_OFFSET m68hc11_max_offset
-
-/* The offset values which are allowed by the n,x and n,y addressing modes.
- Take into account the size of the mode because we may have to add
- a mode offset to access the lowest part of the data.
- (For example, for an SImode, the last valid offset is 252.) */
-#define VALID_CONSTANT_OFFSET_P(X,MODE) \
-(((GET_CODE (X) == CONST_INT) && \
- ((INTVAL (X) >= VALID_MIN_OFFSET) \
- && ((INTVAL (X) <= VALID_MAX_OFFSET \
- - (HOST_WIDE_INT) (GET_MODE_SIZE (MODE) + 1))))) \
-|| (TARGET_M6812 \
- && ((GET_CODE (X) == SYMBOL_REF) \
- || GET_CODE (X) == LABEL_REF \
- || GET_CODE (X) == CONST)))
-
-/* This is included to allow stack push/pop operations. Special hacks in the
- md and m6811.c files exist to support this. */
-#define PUSH_POP_ADDRESS_P(X) \
- (((GET_CODE (X) == PRE_DEC) || (GET_CODE (X) == POST_INC)) \
- && SP_REG_P (XEXP (X, 0)))
-
-/* 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 a base reg. */
-#define REG_OK_FOR_BASE_P(X) REG_OK_FOR_BASE_NONSTRICT_P(X)
-
-/* Nonzero if X is a hard reg that can be used as an index. */
-#define REG_OK_FOR_INDEX_P(X) REG_OK_FOR_INDEX_NONSTRICT_P(X)
-#else
-#define REG_OK_FOR_BASE_P(X) REG_OK_FOR_BASE_STRICT_P(X)
-#define REG_OK_FOR_INDEX_P(X) REG_OK_FOR_INDEX_STRICT_P(X)
-#endif
-
-
-/* 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
-/* Tell final.c how to eliminate redundant test instructions. */
-
-#define NOTICE_UPDATE_CC(EXP, INSN) \
- m68hc11_notice_update_cc ((EXP), (INSN))
-
-/* Move costs between classes of registers */
-#define REGISTER_MOVE_COST(MODE, CLASS1, CLASS2) \
- (m68hc11_register_move_cost (MODE, CLASS1, CLASS2))
-
-/* Move cost between register and memory.
- - Move to a 16-bit register is reasonable,
- - Move to a soft register can be expensive. */
-#define MEMORY_MOVE_COST(MODE,CLASS,IN) \
- m68hc11_memory_move_cost ((MODE),(CLASS),(IN))
-
-/* A C expression for the cost of a branch instruction. A value of 1
- is the default; other values are interpreted relative to that.
-
- Pretend branches are cheap because GCC generates sub-optimal code
- for the default value. */
-#define BRANCH_COST(speed_p, predictable_p) 0
-
-/* Nonzero if access to memory by bytes is slow and undesirable. */
-#define SLOW_BYTE_ACCESS 0
-
-/* It is as good to call a constant function address as to call an address
- kept in a register. */
-#define NO_FUNCTION_CSE
-
-/* Try a machine-dependent way of reloading an illegitimate address
- operand. If we find one, push the reload and jump to WIN. This
- macro is used in only one place: `find_reloads_address' in reload.c.
-
- For M68HC11, we handle large displacements of a base register
- by splitting the addend across an addhi3 insn.
-
- For M68HC12, the 64K offset range is available.
- */
-
-#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_LEVELS,WIN) \
-do { \
- /* We must recognize output that we have already generated ourselves. */ \
- if (GET_CODE (X) == PLUS \
- && GET_CODE (XEXP (X, 0)) == PLUS \
- && GET_CODE (XEXP (XEXP (X, 0), 0)) == REG \
- && GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT \
- && GET_CODE (XEXP (X, 1)) == CONST_INT) \
- { \
- push_reload (XEXP (X, 0), NULL_RTX, &XEXP (X, 0), NULL, \
- BASE_REG_CLASS, GET_MODE (X), VOIDmode, 0, 0, \
- OPNUM, TYPE); \
- goto WIN; \
- } \
- if (GET_CODE (X) == PLUS \
- && GET_CODE (XEXP (X, 0)) == REG \
- && GET_CODE (XEXP (X, 1)) == CONST_INT \
- && !VALID_CONSTANT_OFFSET_P (XEXP (X, 1), MODE)) \
- { \
- HOST_WIDE_INT val = INTVAL (XEXP (X, 1)); \
- HOST_WIDE_INT low, high; \
- high = val & (~0x0FF); \
- low = val & 0x00FF; \
- if (low >= 256-15) { high += 16; low -= 16; } \
- /* Reload the high part into a base reg; leave the low part \
- in the mem directly. */ \
- \
- X = gen_rtx_PLUS (Pmode, \
- gen_rtx_PLUS (Pmode, XEXP (X, 0), \
- GEN_INT (high)), \
- GEN_INT (low)); \
- \
- push_reload (XEXP (X, 0), NULL_RTX, &XEXP (X, 0), NULL, \
- BASE_REG_CLASS, GET_MODE (X), VOIDmode, 0, 0, \
- OPNUM, TYPE); \
- goto WIN; \
- } \
-} while (0)
-
-\f
-/* Defining the Output Assembler Language. */
-
-/* A default list of other sections which we might be "in" at any given
- time. For targets that use additional sections (e.g. .tdesc) you
- should override this definition in the target-specific file which
- includes this file. */
-
-/* Output before read-only data. */
-#define TEXT_SECTION_ASM_OP ("\t.sect\t.text")
-
-/* Output before writable data. */
-#define DATA_SECTION_ASM_OP ("\t.sect\t.data")
-
-/* Output before uninitialized data. */
-#define BSS_SECTION_ASM_OP ("\t.sect\t.bss")
-
-/* Define the pseudo-ops used to switch to the .ctors and .dtors sections.
-
- Same as config/elfos.h but don't mark these section SHF_WRITE since
- there is no shared library problem. */
-#undef CTORS_SECTION_ASM_OP
-#define CTORS_SECTION_ASM_OP "\t.section\t.ctors,\"a\""
-
-#undef DTORS_SECTION_ASM_OP
-#define DTORS_SECTION_ASM_OP "\t.section\t.dtors,\"a\""
-
-#define TARGET_ASM_CONSTRUCTOR m68hc11_asm_out_constructor
-#define TARGET_ASM_DESTRUCTOR m68hc11_asm_out_destructor
-
-/* Comment character */
-#define ASM_COMMENT_START ";"
-
-/* Output to assembler file text saying following lines
- may contain character constants, extra white space, comments, etc. */
-#define ASM_APP_ON "; Begin inline assembler code\n#APP\n"
-
-/* Output to assembler file text saying following lines
- no longer contain unusual constructs. */
-#define ASM_APP_OFF "; End of inline assembler code\n#NO_APP\n"
-
-/* 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.
-
- For 68HC12 we mark functions that return with 'rtc'. The linker
- will ensure that a 'call' is really made (instead of 'jsr').
- The debugger needs this information to correctly compute the stack frame.
-
- For 68HC11/68HC12 we also mark interrupt handlers for gdb to
- compute the correct stack frame. */
-
-#undef ASM_DECLARE_FUNCTION_NAME
-#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
- do \
- { \
- fprintf (FILE, "%s", TYPE_ASM_OP); \
- assemble_name (FILE, NAME); \
- putc (',', FILE); \
- fprintf (FILE, TYPE_OPERAND_FMT, "function"); \
- putc ('\n', FILE); \
- \
- if (current_function_far) \
- { \
- fprintf (FILE, "\t.far\t"); \
- assemble_name (FILE, NAME); \
- putc ('\n', FILE); \
- } \
- else if (current_function_interrupt \
- || current_function_trap) \
- { \
- fprintf (FILE, "\t.interrupt\t"); \
- assemble_name (FILE, NAME); \
- putc ('\n', FILE); \
- } \
- ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL)); \
- ASM_OUTPUT_LABEL(FILE, NAME); \
- } \
- while (0)
-
-/* Output #ident as a .ident. */
-
-/* output external reference */
-#undef ASM_OUTPUT_EXTERNAL
-#define ASM_OUTPUT_EXTERNAL(FILE,DECL,NAME) \
- {fputs ("\t; extern\t", FILE); \
- assemble_name (FILE, NAME); \
- fputs ("\n", FILE);}
-
-/* How to refer to registers in assembler output. This sequence is indexed
- by compiler's hard-register-number (see above). */
-#define REGISTER_NAMES \
-{ "x", "d", "y", "sp", "pc", "a", "b", "ccr", "z", \
- "*_.frame", "*_.tmp", "*_.z", "*_.xy", "*fake clobber", \
- SOFT_REG_NAMES, "*sframe", "*ap"}
-
-/* This is how to output an insn to push/pop a register on the stack.
- It need not be very fast code.
-
- Don't define because we don't know how to handle that with
- the STATIC_CHAIN_REGNUM (soft register). Saving the static
- chain must be made inside FUNCTION_PROFILER. */
-
-#undef ASM_OUTPUT_REG_PUSH
-#undef ASM_OUTPUT_REG_POP
-
-/* 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%s\tL%d-L%d\n", integer_asm_op (2, TRUE), VALUE, REL)
-
-/* 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%s\t.L%d\n", integer_asm_op (2, TRUE), VALUE)
-
-/* 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) \
- do { \
- if ((LOG) > 1) \
- fprintf ((FILE), "%s\n", ALIGN_ASM_OP); \
- } while (0)
-
-\f
-/* Assembler Commands for Exception Regions. */
-
-/* Default values provided by GCC should be ok. Assuming that DWARF-2
- frame unwind info is ok for this platform. */
-
-#undef PREFERRED_DEBUGGING_TYPE
-#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
-
-/* For the support of memory banks we need addresses that indicate
- the page number. */
-#define DWARF2_ADDR_SIZE 4
-
-/* SCz 2003-07-08: Don't use as dwarf2 .file/.loc directives because
- the linker is doing relaxation and it does not adjust the debug_line
- sections when it shrinks the code. This results in invalid addresses
- when debugging. This does not bless too much the HC11/HC12 as most
- applications are embedded and small, hence a reasonable debug info.
- This problem is known for binutils 2.13, 2.14 and mainline. */
-#undef HAVE_AS_DWARF2_DEBUG_LINE
-
-/* The prefix for local labels. You should be able to define this as
- an empty string, or any arbitrary string (such as ".", ".L%", etc)
- without having to make any other changes to account for the specific
- definition. Note it is a string literal, not interpreted by printf
- and friends. */
-#define LOCAL_LABEL_PREFIX "."
-
-/* The prefix for immediate operands. */
-#define IMMEDIATE_PREFIX "#"
-#define GLOBAL_ASM_OP "\t.globl\t"
-
-\f
-/* Miscellaneous Parameters. */
-
-/* Specify the machine mode that this machine uses
- for the index in the tablejump instruction. */
-#define CASE_VECTOR_MODE Pmode
-
-/* This flag, if defined, says the same insns that convert to a signed fixnum
- also convert validly to an unsigned one. */
-#define FIXUNS_TRUNC_LIKE_FIX_TRUNC
-
-/* Max number of bytes we can move from memory to memory in one
- reasonably fast instruction. */
-#define MOVE_MAX 2
-
-/* MOVE_RATIO is the number of move instructions that is better than a
- block move. Make this small on 6811, since the code size grows very
- large with each move. */
-#define MOVE_RATIO(speed) 3
-
-/* 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 1
-
-/* 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 HImode
-
-/* 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
-
-extern int debug_m6811;
-extern int z_replacement_completed;
-extern int current_function_interrupt;
-extern int current_function_trap;
-extern int current_function_far;
-
-extern GTY(()) rtx m68hc11_soft_tmp_reg;
-extern GTY(()) rtx ix_reg;
-extern GTY(()) rtx iy_reg;
-extern GTY(()) rtx d_reg;
+++ /dev/null
-;;- Machine description file for Motorola 68HC11 and 68HC12.
-;;- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008
-;;- Free Software Foundation, Inc.
-;;- Contributed by Stephane Carrez (stcarrez@nerim.fr)
-
-;; This file is part of GCC.
-
-;; GCC is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 3, or (at your option)
-;; any later version.
-
-;; GCC is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GCC; see the file COPYING3. If not see
-;; <http://www.gnu.org/licenses/>.
-
-;; Note:
-;; A first 68HC11 port was made by Otto Lind (otto@coactive.com)
-;; on gcc 2.6.3. I have used it as a starting point for this port.
-;; However, this new port is a complete re-write. Its internal
-;; design is completely different. The generated code is not
-;; compatible with the gcc 2.6.3 port.
-;;
-;; The gcc 2.6.3 port is available at:
-;;
-;; ftp.unina.it/pub/electronics/motorola/68hc11/gcc/gcc-6811-fsf.tar.gz
-;;
-
-;;- Instruction patterns. When multiple patterns apply,
-;;- the first one in the file is chosen.
-;;-
-;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
-;;-
-;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
-;;- updates for most instructions.
-
-;;
-;; The following constraints are used:
-;;
-;; Single pair registers:
-;; a register 'a' 8-bit
-;; b register 'b' 8-bit
-;; d register 'd' 16-bit
-;; t pseudo soft register 'TMP' 16-bit
-;; v register 'd' for 68hc11, 16-bit
-;; NO_REG for 68hc12
-;; (used for scratch register)
-;; w register 'sp' 16-bit
-;; x register 'x' 16-bit
-;; y register 'y' 16-bit
-;; z register 'z' 16-bit (fake r for 68HC11 and 68HC12)
-;; D register 'd+x' 32-bit
-;;
-;; Group of registers:
-;; q register 'a' or 'b' or 'd' 8-bit
-;; u pseudo soft register 16-bit
-;; A register 'x', 'y', 'z' 16-bit
-;; B register 'x', 'y' 16-bit
-;; h register 'd', 'x', 'y', 'z' 16-bit
-;;
-;; Other constraints:
-;;
-;; Q an operand which is in memory but whose address is constant
-;; (i.e., a (MEM (SYMBOL_REF x))). This constraint is used by
-;; bset/bclr instructions together with linker relaxation. The
-;; operand can be translated to a page0 addressing mode if the
-;; symbol address is in page0 (0..255).
-;;
-;; R an operand which is in memory and whose address is expressed
-;; with 68HC11/68HC12 indexed addressing mode. In general this
-;; is any valid (MEM) except a (MEM (SYMBOL_REF x)).
-;;
-;; U an operand which is in memory and if it uses the 68HC12 indexed
-;; addressing mode, the offset is in the range -16..+15. This is
-;; used by 68HC12 movb/movw instructions since they do not accept
-;; the full 16-bit offset range (as other insn do).
-;;
-;;
-;; Immediate integer operand constraints:
-;; `L' is for range -65536 to 65536
-;; `M' is for values whose 16-bit low part is 0
-;; 'N' is for +1 or -1.
-;; 'O' is for 16 (for rotate using swap).
-;; 'P' is for range -8 to 2 (used by addhi_sp)
-;;
-;; In many cases, it's not possible to use the 'g' or 'r' constraints.
-;;
-;; Operands modifiers:
-;;
-;; %b Get the low part of the operand (to obtain a QImode)
-;; This modifier must always be used for QImode operations
-;; because a correction must be applied when the operand
-;; is a soft register (ex: *ZD1). Otherwise, we generate
-;; *ZD1 and this is the high part of the register. For other
-;; kinds of operands, if the operand is already QImode, no
-;; additional correction is made.
-;; %h Get the high part of the operand (to obtain a QImode)
-;; %t Represents the temporary/scratch register *_.tmp
-;; The scratch register is used in some cases when GCC puts
-;; some values in bad registers.
-;;
-;; 32/64-bit Patterns:
-;; The 68HC11 does not support 32/64-bit operations. Most of the
-;; 32/64-bit patterns are defined to split the instruction in
-;; 16-bits patterns. Providing split patterns generates better code
-;; than letting GCC implement the 32/64-bit operation itself.
-;;
-;;
-;; Notes:
-;;
-;; o For iorqi3, andqi3, xorqi3 patterns, we must accept the 'A' constraint
-;; otherwise some insn are not satisfied.
-;;
-;; o Split patterns that create a swap_areg pattern (xgdx or xgdy) must
-;; be valid only when z_replacement_completed == 2 because once these
-;; swap instructions are generated, a flow/cse pass fails to handle
-;; them correctly (it would treat the X, Y or D register as dead sometimes).
-;;
-;; o Some split pattern generate instructions that operate on 'a' or 'b'
-;; register directly (high part and low part of D respectively).
-;; Such split pattern must also be valid when z_replacement_completed == 2
-;; because flow/cse is not aware that D is composed of {a, b}.
-;;
-;; o Split patterns that generate a (mem:QI (symbol_reg _.dx)) to access
-;; the high part of a soft register must be expanded after z_replacement
-;; pass.
-;;
-;;---------------------------------------------------------------------------
-;; Constants
-
-(define_constants [
- ;; Register numbers
- (X_REGNUM 0) ; Index X register
- (D_REGNUM 1) ; Data register
- (Y_REGNUM 2) ; Index Y register
- (SP_REGNUM 3) ; Stack pointer
- (PC_REGNUM 4) ; Program counter
- (A_REGNUM 5) ; A (high part of D)
- (B_REGNUM 6) ; B (low part of D)
- (CC_REGNUM 7) ; Condition code register
- (SOFT_TMP_REGNUM 10) ; TMP soft register
- (SOFT_Z_REGNUM 11) ; Z soft register
- (SOFT_XY_REGNUM 12) ; XY soft register
-])
-
-(include "predicates.md")
-
-;;--------------------------------------------------------------------
-;;- Test
-;;--------------------------------------------------------------------
-;;
-;; The test and compare insn must not accept a memory operand with
-;; an auto-inc mode. If we do this, the reload can emit move insns
-;; after the test or compare. Such move will set the flags and therefore
-;; break the comparison. This can happen if the auto-inc register
-;; does not happen to be a hard register (i.e., reloading occurs).
-;; An offsetable memory operand should be ok. The 'tst_operand' and
-;; 'cmp_operand' predicates take care of this rule.
-;;
-
-(define_insn "tsthi_1"
- [(set (cc0)
- (compare (match_operand:HI 0 "tst_operand" "dx,*y")
- (const_int 0)))]
- ""
- "*
-{
- if (D_REG_P (operands[0]) && !TARGET_M6812)
- return \"std\\t%t0\";
- else
- return \"cp%0\\t#0\";
-}")
-
-;;
-;; Split pattern for (tst:QI) on an address register.
-;;
-(define_split
- [(set (cc0)
- (compare (match_operand:QI 0 "hard_addr_reg_operand" "")
- (const_int 0)))]
- "z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode"
- [(parallel [(set (reg:HI D_REGNUM) (match_dup 1))
- (set (match_dup 1) (reg:HI D_REGNUM))])
- (set (cc0) (compare (reg:QI D_REGNUM)
- (const_int 0)))
- (parallel [(set (reg:HI D_REGNUM) (match_dup 1))
- (set (match_dup 1) (reg:HI D_REGNUM))])]
- "operands[1] = gen_rtx_REG (HImode, REGNO (operands[0]));")
-
-(define_insn "tstqi_1"
- [(set (cc0)
- (compare (match_operand:QI 0 "tst_operand" "m,d,*A,!u")
- (const_int 0)))]
- ""
- "*
-{
- if (A_REG_P (operands[0]))
- return \"#\";
-
- else if (D_REG_P (operands[0]))
- return \"tstb\";
-
- else if (dead_register_here (insn, d_reg))
- return \"ldab\\t%b0\";
-
- else
- return \"tst\\t%b0\";
-}")
-
-;;
-;; tstqi_z_used, cmpqi_z_used and cmphi_z_used are patterns generated
-;; during the Z register replacement. They are used when an operand
-;; uses the Z register as an index register (i.e., (MEM:QI (REG:HI Z))).
-;; In that case, we have to preserve the values of the replacement
-;; register (as well as the CC0 since the insns are compare insns).
-;; To do this, the replacement register is pushed on the stack and
-;; restored after the real compare. A pattern+split is defined to
-;; avoid problems with the flow+cse register pass which are made
-;; after Z register replacement.
-;;
-(define_insn_and_split "tstqi_z_used"
- [(set (cc0) (compare (match_operand:QI 0 "tst_operand" "m")
- (const_int 0)))
- (use (match_operand:HI 1 "hard_reg_operand" "dxy"))
- (use (reg:HI SOFT_Z_REGNUM))]
- ""
- "#"
- "z_replacement_completed == 2"
- [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 1))
- (set (match_dup 1) (match_dup 2))
- (set (cc0) (compare (match_dup 0)
- (const_int 0)))
- (set (match_dup 1) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
- "operands[2] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
-
-
-;;--------------------------------------------------------------------
-;;- Compare
-;;--------------------------------------------------------------------
-
-;;
-;; Comparison of a hard register with another one is provided because
-;; it helps GCC to avoid to spill a pseudo hard register.
-;; We use a temporary in page 0, this is equivalent to a pseudo hard reg.
-;; (except that we loose the information that the value is saved in it).
-;;
-;; The split pattern transforms the comparison into a save of one hard
-;; register and a comparison with the temporary.
-;;
-(define_split
- [(set (cc0)
- (compare (match_operand:HI 0 "hard_reg_operand" "")
- (match_operand:HI 1 "hard_reg_operand" "")))]
- "TARGET_M6811
- && reload_completed && !(Z_REG_P (operands[0]) || Z_REG_P (operands[1]))"
- [(set (match_dup 2) (match_dup 1))
- (set (cc0)
- (compare (match_dup 0) (match_dup 2)))]
- "operands[2] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);")
-
-(define_split
- [(set (cc0)
- (compare (match_operand:HI 0 "hard_reg_operand" "")
- (match_operand:HI 1 "hard_reg_operand" "")))]
- "0 && TARGET_M6812
- && reload_completed && !(Z_REG_P (operands[0]) || Z_REG_P (operands[1]))"
- [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 1))
- (set (cc0)
- (compare (match_dup 0) (mem:HI (post_inc:HI (reg:HI SP_REGNUM)))))]
- "")
-
-(define_insn "cmphi_1_hc12"
- [(set (cc0)
- (compare (match_operand:HI 0 "tst_operand"
- "d,?xy,xyd,?xy,d,m,!u,dxy,dxy")
- (match_operand:HI 1 "general_operand"
- "i,i,!u,m,m,dxy,dxy,?*d*A,!*w")))]
- "TARGET_M6812"
- "*
-{
- if (H_REG_P (operands[1]) && !H_REG_P (operands[0]))
- {
- cc_status.flags |= CC_REVERSED;
- return \"cp%1\\t%0\";
- }
- else if (SP_REG_P (operands[1]))
- return \"sts\\t2,-sp\n\\tcp%0\\t2,sp+\";
- else if (H_REG_P (operands[1]))
- return \"psh%1\n\\tcp%0\\t2,sp+\";
- else
- return \"cp%0\\t%1\";
-}")
-
-(define_insn "cmphi_1_hc11"
- [(set (cc0)
- (compare (match_operand:HI 0 "tst_operand"
- "dx,y,xyd,?xy,d,m,m,dxy,dxy,?u*z,dxy,*z")
- (match_operand:HI 1 "cmp_operand"
- "i,i,!u,m,m,?xy,d,?*d*A,?u,dxy,!*w,i")))]
- "TARGET_M6811"
- "*
-{
- if (H_REG_P (operands[1]) && !H_REG_P (operands[0]))
- {
- cc_status.flags |= CC_REVERSED;
- return \"cp%1\\t%0\";
- }
- else if (H_REG_P (operands[1]))
- return \"#\";
- else
- return \"cp%0\\t%1\";
-}")
-
-(define_insn_and_split "cmphi_z_used"
- [(set (cc0)
- (compare (match_operand:HI 0 "tst_operand" "dxy,m")
- (match_operand:HI 1 "cmp_operand" "mi,dxy")))
- (use (match_operand:HI 2 "hard_reg_operand" "dxy,dxy"))
- (use (reg:HI SOFT_Z_REGNUM))]
- ""
- "#"
- "z_replacement_completed == 2"
- [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))
- (set (match_dup 2) (match_dup 3))
- (set (cc0) (compare (match_dup 0) (match_dup 1)))
- (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
- "operands[3] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
-
-;;
-;; 8-bit comparison with address register.
-;; There is no such comparison instruction, we have to temporarily switch
-;; the address register and the D register and do the comparison with D.
-;; The xgdx and xgdy instructions preserve the flags.
-;;
-(define_split
- [(set (cc0)
- (compare (match_operand:QI 0 "hard_addr_reg_operand" "")
- (match_operand:QI 1 "cmp_operand" "")))]
- "z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode"
- [(parallel [(set (reg:HI D_REGNUM) (match_dup 3))
- (set (match_dup 3) (reg:HI D_REGNUM))])
- (set (cc0)
- (compare (reg:QI D_REGNUM) (match_dup 1)))
- (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
- (set (match_dup 3) (reg:HI D_REGNUM))])]
- "operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));")
-
-(define_split
- [(set (cc0)
- (compare (match_operand:QI 0 "hard_reg_operand" "")
- (match_operand:QI 1 "hard_reg_operand" "")))]
- "reload_completed"
- [(set (match_dup 3) (match_dup 4))
- (set (cc0)
- (compare (match_dup 0) (match_dup 2)))]
- "operands[2] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
- operands[3] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
- operands[4] = gen_rtx_REG (HImode, REGNO (operands[1]));")
-
-(define_insn "bitcmpqi"
- [(set (cc0)
- (compare (and:QI (match_operand:QI 0 "tst_operand" "d,d,d,m,!u")
- (match_operand:QI 1 "cmp_operand" "im,*B,u,d,d"))
- (const_int 0)))]
- ""
- "@
- bitb\\t%b1
- #
- bitb\\t%b1
- bitb\\t%b0
- bitb\\t%b0")
-
-(define_split /* "bitcmpqi" */
- [(set (cc0)
- (compare (and:QI (match_operand:QI 0 "tst_operand" "")
- (match_operand:QI 1 "hard_addr_reg_operand" ""))
- (const_int 0)))]
- "z_replacement_completed == 2"
- [(set (match_dup 3) (match_dup 2))
- (set (cc0) (and:QI (match_dup 0) (match_dup 4)))]
- "operands[2] = gen_rtx_REG (HImode, REGNO (operands[1]));
- operands[3] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
- operands[4] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);")
-
-(define_insn_and_split "bitcmpqi_z_used"
- [(set (cc0)
- (compare (and:QI (match_operand:QI 0 "tst_operand" "d,m")
- (match_operand:QI 1 "cmp_operand" "m,d"))
- (const_int 0)))
- (use (match_operand:HI 2 "hard_reg_operand" "xy,xy"))
- (use (reg:HI SOFT_Z_REGNUM))]
- ""
- "#"
- "z_replacement_completed == 2"
- [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))
- (set (match_dup 2) (match_dup 3))
- (set (cc0) (and:QI (match_dup 0) (match_dup 1)))
- (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
- "operands[3] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
-
-(define_insn "bitcmphi"
- [(set (cc0)
- (compare (and:HI (match_operand:HI 0 "tst_operand" "d")
- (match_operand:HI 1 "const_int_operand" "i"))
- (const_int 0)))]
- "(INTVAL (operands[1]) & 0x0ff) == 0
- || (INTVAL (operands[1]) & 0x0ff00) == 0"
- "*
-{
- if ((INTVAL (operands[1]) & 0x0ff) == 0)
- return \"bita\\t%h1\";
- else
- return \"bitb\\t%1\";
-}")
-
-(define_insn "bitcmpqi_12"
- [(set (cc0)
- (compare (zero_extract:HI (match_operand:HI 0 "tst_operand" "d")
- (match_operand:HI 1 "const_int_operand" "i")
- (match_operand:HI 2 "const_int_operand" "i"))
- (const_int 0)))]
- "(unsigned) (INTVAL (operands[2]) + INTVAL (operands[1])) <= 8
- || (((unsigned) (INTVAL (operands[2]) + INTVAL (operands[1])) <= 16)
- && (unsigned) INTVAL (operands[2]) >= 8)"
- "*
-{
- rtx ops[1];
- int mask;
- int startpos = INTVAL (operands[2]);
- int bitsize = INTVAL (operands[1]);
-
- if (startpos >= 8)
- {
- startpos -= 8;
- mask = (1 << (startpos + bitsize)) - 1;
- mask &= ~((1 << startpos) - 1);
-
- ops[0] = GEN_INT (mask);
- output_asm_insn (\"bita\\t%0\", ops);
- }
- else
- {
- mask = (1 << (startpos + bitsize)) - 1;
- mask &= ~((1 << startpos) - 1);
-
- ops[0] = GEN_INT (mask);
- output_asm_insn (\"bitb\\t%0\", ops);
- }
- return \"\";
-}")
-
-(define_insn "cmpqi_1"
- [(set (cc0)
- (compare (match_operand:QI 0 "tst_operand" "d,m,d,!u,*B,d*B")
- (match_operand:QI 1 "cmp_operand" "im,d,!u,d,dim*A,*u")))]
- ""
- "*
-{
- if (A_REG_P (operands[0]) || A_REG_P (operands[1]))
- {
- return \"#\";
- }
- else if (D_REG_P (operands[0]))
- {
- return \"cmpb\\t%b1\";
- }
- cc_status.flags |= CC_REVERSED;
- return \"cmpb\\t%b0\";
-}")
-
-(define_insn_and_split "cmpqi_z_used"
- [(set (cc0)
- (compare (match_operand:QI 0 "tst_operand" "dxy,m")
- (match_operand:QI 1 "cmp_operand" "m,dxy")))
- (use (match_operand:HI 2 "hard_reg_operand" "dxy,dxy"))
- (use (reg:HI SOFT_Z_REGNUM))]
- ""
- "#"
- "z_replacement_completed == 2"
- [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))
- (set (match_dup 2) (match_dup 3))
- (set (cc0) (compare (match_dup 0) (match_dup 1)))
- (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
- "operands[3] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
-
-;;--------------------------------------------------------------------
-;;- Move strict_low_part
-;;--------------------------------------------------------------------
-;;
-;; The (strict_low_part ...) patterns are replaced by normal (set) patterns.
-;; The replacement must be made at the very end because we loose the
-;; (strict_low_part ...) information. This is correct for our machine
-;; description but not for GCC optimization passes.
-;;
-(define_insn_and_split "movstrictsi"
- [(set (strict_low_part (match_operand:SI 0 "non_push_operand" "+um,D,D"))
- (match_operand:SI 1 "general_operand" "D,Dim,uD"))]
- ""
- "#"
- "z_replacement_completed == 2"
- [(set (match_dup 0) (match_dup 1))]
- "")
-
-(define_insn_and_split "movstricthi"
- [(set (strict_low_part (match_operand:HI 0 "non_push_operand" "+um,dA,dA"))
- (match_operand:HI 1 "general_operand" "dA,dAim,u"))]
- ""
- "#"
- "z_replacement_completed == 2"
- [(set (match_dup 0) (match_dup 1))]
- "")
-
-(define_insn_and_split "movstrictqi"
- [(set (strict_low_part (match_operand:QI 0 "non_push_operand" "+mu,!dA"))
- (match_operand:QI 1 "general_operand" "d,imudA"))]
- ""
- "#"
- "z_replacement_completed == 2"
- [(set (match_dup 0) (match_dup 1))]
- "")
-
-;;--------------------------------------------------------------------
-;;- 64-bit Move Operations.
-;; The movdi and movdf patterns are identical except for the mode.
-;; They are also very similar to those for movsi and movsf.
-;;
-;; For 68HC11, we need a scratch register (either D, X, Y)
-;; because there is no memory->memory moves. It must be defined with
-;; earlyclobber (&) so that it does not appear in the source or destination
-;; address. Providing patterns for movdi/movdf allows GCC to generate
-;; better code. [Until now, the scratch register is limited to D because
-;; otherwise we can run out of registers in the A_REGS class for reload].
-;;
-;; For 68HC12, the scratch register is not necessary. To use the same
-;; pattern and same split, we use the 'v' constraint. This tells the
-;; reload to use the _.tmp register (which is not used at all).
-;; The insn will be split in one or several memory moves (movw).
-;; [SCz: this does not work ?? So, I switched temporary to 'd' reg]
-;;--------------------------------------------------------------------
-(define_expand "movdi"
- [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
- (match_operand:DI 1 "general_operand" ""))
- (clobber (match_scratch:HI 2 ""))])]
- ""
- "
- /* For push/pop, emit a REG_INC note to make sure the reload
- inheritance and reload CSE pass notice the change of the stack
- pointer. */
- if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
- {
- rtx insn;
-
- insn = emit_insn (gen_movdi_internal (operands[0], operands[1]));
- REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
- stack_pointer_rtx,
- REG_NOTES (insn));
- DONE;
- }
-")
-
-;; Separate push from normal moves to avoid reloading problems
-;; The 'clr' is not able to push on 68HC11 so we really need a scratch.
-;; We can also accept more scratch registers.
-(define_insn_and_split "*pushdi_internal"
- [(set (match_operand:DI 0 "push_operand" "=<,<,<,<")
- (match_operand:DI 1 "general_operand" "i,U,m,!u"))
- (clobber (match_scratch:HI 2 "=&dA,&d,&d,&dA"))]
- ""
- "#"
- "reload_completed"
- [(const_int 0)]
- "m68hc11_split_move (operands[0], operands[1], operands[2]);
- DONE;")
-
-(define_insn_and_split "movdi_internal"
- [(set (match_operand:DI 0 "non_push_operand" "=m!u,U,!u,U,m,m,!u")
- (match_operand:DI 1 "general_operand" "K,iU,iU,!u,mi,!u,!mu"))
- (clobber (match_scratch:HI 2 "=X,&d,&d,&d,&d,&d,&d"))]
- ""
- "#"
- "reload_completed"
- [(const_int 0)]
- "m68hc11_split_move (operands[0], operands[1], operands[2]);
- DONE;")
-
-(define_expand "movdf"
- [(parallel [(set (match_operand:DF 0 "nonimmediate_operand" "")
- (match_operand:DF 1 "general_operand" ""))
- (clobber (match_scratch:HI 2 ""))])]
- ""
- "/* For push/pop, emit a REG_INC note to make sure the reload
- inheritance and reload CSE pass notice the change of the stack
- pointer. */
- if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
- {
- rtx insn;
-
- insn = emit_insn (gen_movdf_internal (operands[0], operands[1]));
- REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
- stack_pointer_rtx,
- REG_NOTES (insn));
- DONE;
- }
-")
-
-;; See pushdi_internal
-(define_insn_and_split "*pushdf_internal"
- [(set (match_operand:DF 0 "push_operand" "=<,<,<,<")
- (match_operand:DF 1 "general_operand" "i,U,m,!u"))
- (clobber (match_scratch:HI 2 "=&dA,&d,&d,&dA"))]
- ""
- "#"
- "reload_completed"
- [(const_int 0)]
- "m68hc11_split_move (operands[0], operands[1], operands[2]);
- DONE;")
-
-(define_insn_and_split "movdf_internal"
- [(set (match_operand:DF 0 "non_push_operand" "=mu,U,m,!u,U,m,!u")
- (match_operand:DF 1 "general_operand" "G,iU,mi,iU,!u,!u,!mu"))
- (clobber (match_scratch:HI 2 "=X,&d,&d,&d,&d,&d,&d"))]
- ""
- "#"
- "reload_completed"
- [(const_int 0)]
- "m68hc11_split_move (operands[0], operands[1], operands[2]);
- DONE;")
-
-;;--------------------------------------------------------------------
-;;- 32-bit Move Operations.
-;; The movsi and movsf patterns are identical except for the mode.
-;; When we move to/from a hard register (d+x), we don't need a scratch.
-;; Otherwise, a scratch register is used as intermediate register for
-;; the move. The '&' constraint is necessary to make sure the reload
-;; pass does not give us a register that dies in the insn and is used
-;; for input/output operands.
-;;--------------------------------------------------------------------
-(define_expand "movsi"
- [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
- (match_operand:SI 1 "general_operand" ""))
- (clobber (match_scratch:HI 2 ""))])]
- ""
- "/* For push/pop, emit a REG_INC note to make sure the reload
- inheritance and reload CSE pass notice the change of the stack
- pointer. */
- if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
- {
- rtx insn;
-
- insn = emit_insn (gen_movsi_internal (operands[0], operands[1]));
- REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
- stack_pointer_rtx,
- REG_NOTES (insn));
- DONE;
- }
-")
-
-(define_insn_and_split "*pushsi_internal"
- [(set (match_operand:SI 0 "push_operand" "=<,<,<,<,<")
- (match_operand:SI 1 "general_operand" "!D,i,U,m,!u"))
- (clobber (match_scratch:HI 2 "=X,&dA,&d,&d,&dA"))]
- ""
- "#"
- "reload_completed"
- [(const_int 0)]
- "m68hc11_split_move (operands[0], operands[1], operands[2]);
- DONE;")
-
-(define_insn_and_split "movsi_internal"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=mu,mu,?D,m,?D,?u,?u,!u,D")
- (match_operand:SI 1 "general_operand" "K,imu,im,?D,!u,?D,mi,!u,!D"))
- (clobber (match_scratch:HI 2 "=X,&d,X,X,X,X,&d,&d,X"))]
- ""
- "#"
- "reload_completed"
- [(const_int 0)]
- "m68hc11_split_move (operands[0], operands[1], operands[2]);
- DONE;")
-
-(define_expand "movsf"
- [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "")
- (match_operand:SF 1 "general_operand" ""))
- (clobber (match_scratch:HI 2 ""))])]
- ""
- "/* For push/pop, emit a REG_INC note to make sure the reload
- inheritance and reload CSE pass notice the change of the stack
- pointer. */
- if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
- {
- rtx insn;
-
- insn = emit_insn (gen_movsf_internal (operands[0], operands[1]));
- REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
- stack_pointer_rtx,
- REG_NOTES (insn));
- DONE;
- }
-")
-
-(define_insn_and_split "*pushsf_internal"
- [(set (match_operand:SF 0 "push_operand" "=<,<,<,<,<")
- (match_operand:SF 1 "general_operand" "!D,i,U,m,!u"))
- (clobber (match_scratch:HI 2 "=X,&dA,&d,&d,&dA"))]
- ""
- "#"
- "reload_completed"
- [(const_int 0)]
- "m68hc11_split_move (operands[0], operands[1], operands[2]);
- DONE;")
-
-(define_insn_and_split "movsf_internal"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=m!u,m,D,m,D,!u,!u,!u,D")
- (match_operand:SF 1 "general_operand" "G,im,im,D,!u,D,mi,!u,!D"))
- (clobber (match_scratch:HI 2 "=X,&d,X,X,X,X,&d,&d,X"))]
- ""
- "#"
- "reload_completed"
- [(const_int 0)]
- "m68hc11_split_move (operands[0], operands[1], operands[2]);
- DONE;")
-
-
-;;--------------------------------------------------------------------
-;;- 16-bit Move Operations.
-;; We don't need a scratch register.
-;;--------------------------------------------------------------------
-
-(define_insn "*movhi2_push"
- [(set (match_operand:HI 0 "push_operand" "=<,<,<")
- (match_operand:HI 1 "general_operand" "xy,?d,!z"))]
- "TARGET_M6811 && !TARGET_M6812"
- "*
-{
- cc_status = cc_prev_status;
- if (D_REG_P (operands[1]))
- {
- output_asm_insn (\"pshb\", operands);
- return \"psha\";
- }
- else if (X_REG_P (operands[1]))
- {
- return \"pshx\";
- }
- else if (Y_REG_P (operands[1]))
- {
- return \"pshy\";
- }
- fatal_insn (\"Invalid register in the instruction\", insn);
-}")
-
-(define_insn "*movhi2_pop"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=xy,d")
- (match_operand:HI 1 "pop_operand" ">,>"))]
- "TARGET_M6811"
- "*
-{
- cc_status = cc_prev_status;
- if (D_REG_P (operands[0]))
- {
- output_asm_insn (\"pula\", operands);
- return \"pulb\";
- }
- else if (X_REG_P (operands[0]))
- {
- return \"pulx\";
- }
- else if (Y_REG_P (operands[0]))
- {
- return \"puly\";
- }
- fatal_insn (\"Invalid register in the instruction\", insn);
-}")
-
-(define_expand "movhi"
- [(set (match_operand:HI 0 "nonimmediate_operand" "")
- (match_operand:HI 1 "general_operand" ""))]
- ""
- "
-{
- if (reload_in_progress)
- {
- if (m68hc11_reload_operands (operands))
- {
- DONE;
- }
- }
- if (TARGET_M6811 && (reload_in_progress | reload_completed) == 0)
- {
- if (GET_CODE (operands[0]) == MEM &&
- (GET_CODE (operands[1]) == MEM
- || GET_CODE (operands[1]) == CONST_INT))
- {
- operands[1] = force_reg (HImode, operands[1]);
- }
- else if (IS_STACK_PUSH (operands[0])
- && GET_CODE (operands[1]) != REG)
- {
- operands[1] = force_reg (HImode, operands[1]);
- }
- }
- /* For push/pop, emit a REG_INC note to make sure the reload
- inheritance and reload CSE pass notice the change of the stack
- pointer. */
- if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
- {
- rtx insn;
-
- insn = emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
- REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
- stack_pointer_rtx,
- REG_NOTES (insn));
- DONE;
- }
-}")
-
-(define_insn "*movhi_68hc12"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=U,dAw,dAw,m,U,U,m,!u")
- (match_operand:HI 1 "general_operand" "U,dAwim,!u,K,dAwi,!u,dAw,riU"))]
- "TARGET_M6812"
- "*
-{
- m68hc11_gen_movhi (insn, operands);
- return \"\";
-}")
-
-(define_insn "movhi_const0"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=d,A,um")
- (const_int 0))]
- "TARGET_M6811"
- "@
- clra\\n\\tclrb
- ld%0\\t#0
- clr\\t%b0\\n\\tclr\\t%h0")
-
-(define_insn "*movhi_m68hc11"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=dAw,!u,m,m,dAw,!*u")
- (match_operand:HI 1 "general_operand" "dAwim,dAw,dA,?Aw,!*u,dAw"))]
- "TARGET_M6811"
- "*
-{
- m68hc11_gen_movhi (insn, operands);
- return \"\";
-}")
-
-;;--------------------------------------------------------------------
-;;- 8-bit Move Operations.
-;; We don't need a scratch register.
-;;--------------------------------------------------------------------
-;;
-;; The *a alternative also clears the high part of the register.
-;; This should be ok since this is not the (strict_low_part) set.
-;;
-(define_insn "movqi_const0"
- [(set (match_operand:QI 0 "non_push_operand" "=d,m,!u,*A,!*q")
- (const_int 0))]
- ""
- "@
- clrb
- clr\\t%b0
- clr\\t%b0
- ld%0\\t#0
- clr%0")
-
-;;
-;; 8-bit operations on address registers.
-;;
-;; Switch temporary to the D register and load the value in B.
-;; This is possible as long as the address register does not
-;; appear in the source operand.
-;;
-(define_split
- [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
- (match_operand:QI 1 "general_operand" ""))]
- "z_replacement_completed == 2
- && !reg_mentioned_p (operands[0], operands[1])
- && !(D_REG_P (operands[1]) || Q_REG_P (operands[1]))"
- [(parallel [(set (reg:HI D_REGNUM) (match_dup 2))
- (set (match_dup 2) (reg:HI D_REGNUM))])
- (set (reg:QI D_REGNUM) (match_dup 1))
- (parallel [(set (reg:HI D_REGNUM) (match_dup 2))
- (set (match_dup 2) (reg:HI D_REGNUM))])]
- "operands[2] = gen_rtx_REG (HImode, REGNO (operands[0]));")
-
-;;
-;; 8-bit operations on address registers.
-;;
-(define_split
- [(set (match_operand:QI 0 "nonimmediate_operand" "")
- (match_operand:QI 1 "hard_addr_reg_operand" ""))]
- "z_replacement_completed == 2
- && !reg_mentioned_p (operands[1], operands[0])
- && !(D_REG_P (operands[0]) || Q_REG_P (operands[0]))"
- [(parallel [(set (reg:HI D_REGNUM) (match_dup 2))
- (set (match_dup 2) (reg:HI D_REGNUM))])
- (set (match_dup 0) (reg:QI D_REGNUM))
- (parallel [(set (reg:HI D_REGNUM) (match_dup 2))
- (set (match_dup 2) (reg:HI D_REGNUM))])]
- "operands[2] = gen_rtx_REG (HImode, REGNO (operands[1]));")
-
-(define_insn "*movqi2_push"
- [(set (match_operand:QI 0 "push_operand" "=<,<")
- (match_operand:QI 1 "general_operand" "d,!*A"))]
- ""
- "*
-{
- if (A_REG_P (operands[1]))
- return \"#\";
-
- cc_status = cc_prev_status;
- return \"pshb\";
-}")
-
-
-(define_expand "movqi"
- [(set (match_operand:QI 0 "nonimmediate_operand" "")
- (match_operand:QI 1 "general_operand" ""))]
- ""
- "
-{
- if (reload_in_progress)
- {
- if (m68hc11_reload_operands (operands))
- {
- DONE;
- }
- }
- if (TARGET_M6811 && (reload_in_progress | reload_completed) == 0)
- {
- if (GET_CODE (operands[0]) == MEM
- && (GET_CODE (operands[1]) == MEM
- || GET_CODE (operands[1]) == CONST_INT))
- {
- operands[1] = force_reg (QImode, operands[1]);
- }
- else if (IS_STACK_PUSH (operands[0])
- && GET_CODE (operands[1]) != REG)
- {
- operands[1] = force_reg (QImode, operands[1]);
- }
- }
- /* For push/pop, emit a REG_INC note to make sure the reload
- inheritance and reload CSE pass notice the change of the stack
- pointer. */
- if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
- {
- rtx insn;
-
- insn = emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
- REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
- stack_pointer_rtx,
- REG_NOTES (insn));
- DONE;
- }
-}")
-
-(define_insn "*movqi_68hc12"
- [(set (match_operand:QI 0 "nonimmediate_operand"
- "=U,d*AU*q,d*A*qU,d*A*q,m,?*u,m")
- (match_operand:QI 1 "general_operand"
- "U,*ri*q,U,m,d*q,*ri*qU,!*A"))]
- "TARGET_M6812"
- "*
-{
- m68hc11_gen_movqi (insn, operands);
- return \"\";
-}")
-
-(define_insn "*movqi_m68hc11"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=d*A*q,m,m,d*A*q,*u")
- (match_operand:QI 1 "general_operand" "d*Aim*q,d*q,!*A,*u,d*A*q"))]
- "TARGET_M6811"
- "*
-{
- m68hc11_gen_movqi (insn, operands);
- return \"\";
-}")
-
-;;--------------------------------------------------------------------
-;;- Swap registers
-;;--------------------------------------------------------------------
-;; Swapping registers is used for split patterns.
-(define_insn "swap_areg"
- [(set (match_operand:HI 0 "hard_reg_operand" "=d,A")
- (match_operand:HI 1 "hard_reg_operand" "=A,d"))
- (set (match_dup 1) (match_dup 0))]
- ""
- "*
-{
- m68hc11_output_swap (insn, operands);
- return \"\";
-}")
-
-;;--------------------------------------------------------------------
-;;- Truncation insns.
-;;--------------------------------------------------------------------
-;;
-;; Truncation are not necessary because GCC knows how to truncate,
-;; specially when values lie in consecutive registers.
-;;
-
-(define_expand "floatunssisf2"
- [(set (match_operand:SF 0 "nonimmediate_operand" "")
- (unsigned_float:SF (match_operand:SI 1 "general_operand" "")))]
- ""
- "m68hc11_emit_libcall (\"__floatunsisf\", UNSIGNED_FLOAT,
- SFmode, SImode, 2, operands);
- DONE;")
-
-(define_expand "floatunssidf2"
- [(set (match_operand:DF 0 "nonimmediate_operand" "")
- (unsigned_float:DF (match_operand:SI 1 "general_operand" "")))]
- ""
- "m68hc11_emit_libcall (\"__floatunsidf\", UNSIGNED_FLOAT,
- DFmode, SImode, 2, operands);
- DONE;")
-
-;;--------------------------------------------------------------------
-;;- Zero extension insns.
-;;--------------------------------------------------------------------
-
-;;
-;; 64-bit extend. The insn will be split into 16-bit instructions just
-;; before the final pass. We need a scratch register for the split.
-;; The final value can be generated on the stack directly. This is more
-;; efficient and useful for conversions made during parameter passing rules.
-;;
-(define_insn "zero_extendqidi2"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=m,!u,m,!u")
- (zero_extend:DI
- (match_operand:QI 1 "nonimmediate_operand" "m,dmu,*B,*B")))
- (clobber (match_scratch:HI 2 "=&d,&dB,&d,&dB"))]
- ""
- "#")
-
-(define_split
- [(set (match_operand:DI 0 "push_operand" "")
- (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))
- (clobber (match_scratch:HI 2 "=&dB"))]
- "z_replacement_completed == 2"
- [(const_int 0)]
- "
-{
- rtx low = m68hc11_gen_lowpart (SImode, operands[0]);
- rtx push = m68hc11_gen_lowpart (HImode, low);
- rtx src = operands[1];
-
- /* Source operand must be in a hard register. */
- if (!H_REG_P (src))
- {
- src = gen_rtx_REG (QImode, REGNO (operands[2]));
- emit_move_insn (src, operands[1]);
- }
-
- /* Source is in D, we can push B then one word of 0 and we do
- a correction on the stack pointer. */
- if (D_REG_P (src))
- {
- emit_move_insn (m68hc11_gen_lowpart (QImode, push), src);
- emit_move_insn (operands[2], const0_rtx);
- if (D_REG_P (operands[2]))
- {
- emit_move_insn (m68hc11_gen_lowpart (QImode, push), src);
- }
- else
- {
- emit_move_insn (push, operands[2]);
- emit_insn (gen_addhi3 (gen_rtx_REG (HImode, HARD_SP_REGNUM),
- gen_rtx_REG (HImode, HARD_SP_REGNUM),
- const1_rtx));
- }
- }
- else
- {
- /* Source is in X or Y. It's better to push the 16-bit register
- and then to some stack adjustment. */
- src = gen_rtx_REG (HImode, REGNO (src));
- emit_move_insn (push, src);
- emit_move_insn (operands[2], const0_rtx);
- emit_insn (gen_addhi3 (gen_rtx_REG (HImode, HARD_SP_REGNUM),
- gen_rtx_REG (HImode, HARD_SP_REGNUM),
- const1_rtx));
- emit_move_insn (push, operands[2]);
- emit_insn (gen_addhi3 (gen_rtx_REG (HImode, HARD_SP_REGNUM),
- gen_rtx_REG (HImode, HARD_SP_REGNUM),
- const1_rtx));
- }
- emit_move_insn (push, operands[2]);
- emit_move_insn (push, operands[2]);
- emit_move_insn (push, operands[2]);
- DONE;
-}")
-
-(define_split
- [(set (match_operand:DI 0 "nonimmediate_operand" "")
- (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))
- (clobber (match_scratch:HI 2 "=&dB"))]
- "z_replacement_completed == 2"
- [(const_int 0)]
- "
-{
- rtx low = m68hc11_gen_lowpart (SImode, operands[0]);
- rtx low2 = m68hc11_gen_lowpart (HImode, low);
- rtx src = operands[1];
-
- /* Source operand must be in a hard register. */
- if (!H_REG_P (src))
- {
- src = gen_rtx_REG (QImode, REGNO (operands[2]));
- emit_move_insn (src, operands[1]);
- }
-
- emit_move_insn (m68hc11_gen_lowpart (QImode, low2), src);
- emit_move_insn (operands[2], const0_rtx);
- src = gen_rtx_REG (QImode, REGNO (operands[2]));
- emit_move_insn (m68hc11_gen_highpart (QImode, low2), src);
-
- emit_move_insn (m68hc11_gen_highpart (HImode, low), operands[2]);
- low = m68hc11_gen_highpart (SImode, operands[0]);
- emit_move_insn (m68hc11_gen_lowpart (HImode, low), operands[2]);
- emit_move_insn (m68hc11_gen_highpart (HImode, low), operands[2]);
- DONE;
-}")
-
-(define_insn "zero_extendhidi2"
- [(set (match_operand:DI 0 "non_push_operand" "=m,m,m,m,!u,!u")
- (zero_extend:DI
- (match_operand:HI 1 "nonimmediate_operand" "m,d,A,!u,dmA,!u")))
- (clobber (match_scratch:HI 2 "=&d,&B,&d,&dB,&dB,&dB"))]
- ""
- "#")
-
-(define_split
- [(set (match_operand:DI 0 "non_push_operand" "")
- (zero_extend:DI
- (match_operand:HI 1 "nonimmediate_operand" "")))
- (clobber (match_scratch:HI 2 ""))]
- "z_replacement_completed == 2"
- [(const_int 0)]
- "
-{
- rtx low = m68hc11_gen_lowpart (SImode, operands[0]);
- rtx high = m68hc11_gen_highpart (SImode, operands[0]);
- rtx src = operands[1];
-
- /* Make sure the source is in a hard register. */
- if (!H_REG_P (src))
- {
- src = operands[2];
- emit_move_insn (src, operands[1]);
- }
-
- /* Move the low part first for the push. */
- emit_move_insn (m68hc11_gen_lowpart (HImode, low), src);
-
- /* Now, use the scratch register to fill in the zeros. */
- emit_move_insn (operands[2], const0_rtx);
- emit_move_insn (m68hc11_gen_highpart (HImode, low), operands[2]);
- emit_move_insn (m68hc11_gen_lowpart (HImode, high), operands[2]);
- emit_move_insn (m68hc11_gen_highpart (HImode, high), operands[2]);
- DONE;
-}")
-
-(define_insn "zero_extendsidi2"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=m,m,!u,!u")
- (zero_extend:DI
- (match_operand:SI 1 "nonimmediate_operand" "m,Du,m,Du")))
- (clobber (match_scratch:HI 2 "=d,d,d,d"))]
- ""
- "#")
-
-(define_split
- [(set (match_operand:DI 0 "nonimmediate_operand" "")
- (zero_extend:DI
- (match_operand:SI 1 "nonimmediate_operand" "")))
- (clobber (match_scratch:HI 2 ""))]
- "z_replacement_completed == 2"
- [(const_int 0)]
- "
-{
- rtx low = m68hc11_gen_lowpart (SImode, operands[0]);
- rtx high = m68hc11_gen_highpart (SImode, operands[0]);
-
- /* Move the low part first so that this is ok for a push. */
- m68hc11_split_move (low, operands[1], operands[2]);
-
- /* Use the scratch register to clear the high part of the destination. */
- emit_move_insn (operands[2], const0_rtx);
- emit_move_insn (m68hc11_gen_lowpart (HImode, high), operands[2]);
- emit_move_insn (m68hc11_gen_highpart (HImode, high), operands[2]);
- DONE;
-}")
-
-;;
-;; For 16->32bit unsigned extension, we don't allow generation on the stack
-;; because it's less efficient.
-;;
-(define_insn "zero_extendhisi2"
- [(set (match_operand:SI 0 "non_push_operand" "=D,m,u,m,m,!u,!u")
- (zero_extend:SI
- (match_operand:HI 1 "nonimmediate_operand" "dAmu,dA,dA,m,!u,m,!u")))
- (clobber (match_scratch:HI 2 "=X,X,X,&d,&dB,&dB,&dB"))]
- ""
- "#")
-
-(define_split
- [(set (match_operand:SI 0 "non_push_operand" "")
- (zero_extend:SI
- (match_operand:HI 1 "nonimmediate_operand" "")))
- (clobber (match_scratch:HI 2 ""))]
- "reload_completed"
- [(const_int 0)]
- "
-{
- rtx src = operands[1];
-
- if (!H_REG_P (src) && !H_REG_P (operands[0]))
- {
- src = operands[2];
- emit_move_insn (src, operands[1]);
- }
- emit_move_insn (m68hc11_gen_lowpart (HImode, operands[0]), src);
- emit_move_insn (m68hc11_gen_highpart (HImode, operands[0]), const0_rtx);
- DONE;
-}")
-
-(define_insn "zero_extendqisi2"
- [(set (match_operand:SI 0 "non_push_operand" "=D,D,m,m,u")
- (zero_extend:SI
- (match_operand:QI 1 "nonimmediate_operand" "dmu,xy,d,xy,dxy")))]
- ""
- "#")
-
-(define_split
- [(set (match_operand:SI 0 "non_push_operand" "")
- (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
- "reload_completed && !X_REG_P (operands[0])"
- [(set (match_dup 2) (zero_extend:HI (match_dup 1)))
- (set (match_dup 3) (const_int 0))]
- "
- operands[2] = m68hc11_gen_lowpart (HImode, operands[0]);
- operands[3] = m68hc11_gen_highpart (HImode, operands[0]);")
-
-(define_split
- [(set (match_operand:SI 0 "hard_reg_operand" "")
- (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
- "z_replacement_completed == 2 && X_REG_P (operands[0])"
- [(set (match_dup 2) (match_dup 3))
- (set (match_dup 4) (const_int 0))
- (set (match_dup 5) (zero_extend:HI (match_dup 6)))]
- "
- if (X_REG_P (operands[1]))
- {
- emit_insn (gen_swap_areg (gen_rtx_REG (HImode, HARD_D_REGNUM),
- gen_rtx_REG (HImode, HARD_X_REGNUM)));
- emit_insn (gen_zero_extendqihi2 (gen_rtx_REG (HImode, HARD_D_REGNUM),
- gen_rtx_REG (QImode, HARD_D_REGNUM)));
- emit_move_insn (gen_rtx_REG (HImode, HARD_X_REGNUM),
- const0_rtx);
- DONE;
- }
-
- if (reg_mentioned_p (gen_rtx_REG (HImode, HARD_X_REGNUM), operands[1]))
- {
- emit_insn (gen_zero_extendqihi2 (m68hc11_gen_lowpart (HImode,
- operands[0]),
- operands[1]));
- emit_move_insn (gen_rtx_REG (HImode, HARD_X_REGNUM), const0_rtx);
- DONE;
- }
- operands[4] = m68hc11_gen_highpart (HImode, operands[0]);
- operands[5] = m68hc11_gen_lowpart (HImode, operands[0]);
- if (A_REG_P (operands[1]))
- {
- operands[2] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
- operands[3] = gen_rtx_REG (HImode, REGNO (operands[1]));
- operands[6] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
- }
- else
- {
- operands[5] = operands[2] =
- operands[3] = gen_rtx_REG (HImode, HARD_D_REGNUM);
- operands[6] = operands[1];
- }
-")
-
-(define_insn "zero_extendqihi2"
- [(set (match_operand:HI 0 "non_push_operand" "=dm,d,*A,!*u,d,m,!*u")
- (zero_extend:HI
- (match_operand:QI 1 "nonimmediate_operand" "d,*A,d*Am,d,!um,*A,*A")))]
- ""
- "*
-{
- if (A_REG_P (operands[0]))
- return \"#\";
-
- if (H_REG_P (operands[0]))
- {
- output_asm_insn (\"clra\", operands);
- if (operands[0] != operands[1]
- && !(D_REG_P (operands[0]) && D_REG_P (operands[1])))
- {
- if (X_REG_P (operands[1])
- || (D_REG_P (operands[1]) && X_REG_P (operands[0])))
- {
- output_asm_insn (\"stx\\t%t1\", operands);
- output_asm_insn (\"ldab\\t%T0\", operands);
- }
- else if (Y_REG_P (operands[1])
- || (D_REG_P (operands[1]) && Y_REG_P (operands[0])))
- {
- output_asm_insn (\"sty\\t%t1\", operands);
- output_asm_insn (\"ldab\\t%T0\", operands);
- }
- else
- {
- output_asm_insn (\"ldab\\t%b1\", operands);
- }
- cc_status.flags |= CC_NOT_NEGATIVE;
- }
- else
- {
- /* Status refers to the clra insn. Status is ok for others
- * since we have loaded the value in B.
- */
- CC_STATUS_INIT;
- }
- return \"\";
- }
-
- if (A_REG_P (operands[1]))
- {
- output_asm_insn (\"st%1\\t%0\", operands);
- output_asm_insn (\"clr\\t%h0\", operands);
- CC_STATUS_INIT;
- }
- else
- {
- output_asm_insn (\"clr\\t%h0\", operands);
- output_asm_insn (\"stab\\t%b0\", operands);
- cc_status.flags |= CC_NOT_NEGATIVE;
- }
-
- return \"\";
-}")
-
-
-;;--------------------------------------------------------------------
-;;- Sign extension insns.
-;;--------------------------------------------------------------------
-
-(define_insn "extendqisi2"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=D,m,u")
- (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "dmux,d,d")))]
- ""
- "*
-{
- rtx ops[3];
- int need_tst = 0;
-
- /* The 68HC12 has a sign-extension instruction. Use it when the
- destination is the register (X,D). First sign-extend the low
- part and fill X with the sign-extension of the high part. */
- if (TARGET_M6812 && X_REG_P (operands[0]))
- {
- if (!D_REG_P (operands[1]))
- {
- ops[0] = gen_rtx_REG (QImode, HARD_D_REGNUM);
- ops[1] = operands[1];
- m68hc11_gen_movqi (insn, ops);
- }
- return \"sex\\tb,d\\n\\tsex\\ta,x\";
- }
-
- ops[2] = gen_label_rtx ();
-
- if (X_REG_P (operands[1]))
- {
- output_asm_insn (\"xgdx\", operands);
- need_tst = 1;
- }
- else if (X_REG_P (operands[0]))
- {
- /* X can be used as an indexed addressing in the source.
- Get the value before clearing it. */
- if (reg_mentioned_p (ix_reg, operands[1]))
- {
- output_asm_insn (\"ldab\\t%b1\", operands);
- need_tst = 1;
- }
- output_asm_insn (\"ldx\\t#0\", operands);
- }
-
- output_asm_insn (\"clra\", operands);
- if (!X_REG_P (operands[0]))
- {
- ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
- ops[1] = m68hc11_gen_lowpart (QImode, ops[0]);
-
- if (IS_STACK_PUSH (operands[0]))
- {
- output_asm_insn (\"pshb\", ops);
- output_asm_insn (\"tstb\", ops);
- }
- else
- {
- output_asm_insn (\"stab\\t%b1\", ops);
- }
- }
- else if (D_REG_P (operands[1]) || need_tst)
- {
- output_asm_insn (\"tstb\", operands);
- }
- else
- {
- output_asm_insn (\"ldab\\t%b1\", operands);
- }
- output_asm_insn (\"bpl\\t%l2\", ops);
- output_asm_insn (\"deca\", operands);
- if (X_REG_P (operands[0]))
- output_asm_insn (\"dex\", operands);
-
- (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2]));
-
- if (!X_REG_P (operands[0]))
- {
- if (IS_STACK_PUSH (operands[0]))
- {
- output_asm_insn (\"psha\", ops);
- output_asm_insn (\"psha\", ops);
- output_asm_insn (\"psha\", ops);
- }
- else
- {
- output_asm_insn (\"staa\\t%h0\", ops);
-
- ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
- if (dead_register_here (insn, d_reg))
- {
- output_asm_insn (\"tab\", ops);
- output_asm_insn (\"std\\t%0\", ops);
- }
- else
- {
- output_asm_insn (\"staa\\t%b0\", ops);
- output_asm_insn (\"staa\\t%h0\", ops);
- }
- }
- }
-
- CC_STATUS_INIT;
- return \"\";
-}")
-
-
-(define_insn "extendqihi2"
- [(set (match_operand:HI 0 "non_push_operand" "=d,*x*ym,u")
- (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "dum,0,0")))]
- ""
- "*
-{
- rtx ops[2];
-
- if (A_REG_P (operands[0]))
- return \"#\";
-
- ops[0] = gen_label_rtx ();
- if (D_REG_P (operands[0]))
- {
- if (TARGET_M6812)
- {
- if (!D_REG_P (operands[1]))
- {
- ops[0] = gen_rtx_REG (QImode, HARD_D_REGNUM);
- ops[1] = operands[1];
- m68hc11_gen_movqi (insn, ops);
- }
- return \"sex\\tb,d\";
- }
- output_asm_insn (\"clra\", operands);
- if (H_REG_P (operands[1]))
- {
- output_asm_insn (\"tstb\", operands);
- }
- else
- {
- output_asm_insn (\"ldab\\t%b1\", operands);
- }
- output_asm_insn (\"bpl\\t%l0\", ops);
- output_asm_insn (\"deca\", operands);
-
- (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
- CODE_LABEL_NUMBER (ops[0]));
- }
- else
- {
- output_asm_insn (\"clr\\t%h0\", operands);
- if (m68hc11_register_indirect_p (operands[1], HImode))
- {
- ops[1] = operands[1];
- output_asm_insn (\"brclr\\t%b1 #0x80 %l0\", ops);
- CC_STATUS_INIT;
- }
- else
- {
- output_asm_insn (\"tst\\t%b1\", operands);
- output_asm_insn (\"bpl\\t%l0\", ops);
- }
- output_asm_insn (\"dec\\t%h0\", operands);
- (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
- CODE_LABEL_NUMBER (ops[0]));
- }
-
- return \"\";
-}")
-
-;;
-;; Split the special case where the source of the sign extend is
-;; either Y or Z. In that case, we can't move the source in the D
-;; register directly. The movhi pattern handles this move by using
-;; a temporary scratch memory location.
-;;
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
- "reload_completed && (Y_REG_P (operands[1]) || Z_REG_P (operands[1]))"
- [(set (reg:HI D_REGNUM) (match_dup 1))
- (set (match_dup 0) (sign_extend:SI (reg:HI D_REGNUM)))]
- "")
-
-(define_insn "extendhisi2"
- [(set (match_operand:SI 0 "register_operand" "=D,D,D")
- (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "m,!r,dA")))]
- ""
- "*
-{
- rtx ops[2];
- int x_reg_used;
-
- if (Y_REG_P (operands[1]))
- return \"#\";
-
- if (X_REG_P (operands[1]))
- {
- output_asm_insn (\"xgdx\", operands);
- x_reg_used = 1;
- }
- else
- {
- /* X can be used as an indexed addressing in the source.
- Get the value before clearing it. */
- x_reg_used = reg_mentioned_p (ix_reg, operands[1]);
- if (x_reg_used)
- {
- ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
- ops[1] = operands[1];
- m68hc11_gen_movhi (insn, ops);
- }
- }
-
- CC_STATUS_INIT;
- if (TARGET_M6812 && 0)
- {
- /* This sequence of code is larger than the one for 68HC11.
- Don't use it; keep it for documentation. */
- if (!D_REG_P (operands[1]) && !x_reg_used)
- {
- ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
- ops[1] = operands[1];
- m68hc11_gen_movhi (insn, ops);
- }
- output_asm_insn (\"sex\\ta,x\", operands);
- output_asm_insn (\"xgdx\", operands);
- output_asm_insn (\"sex\\ta,d\", operands);
- return \"xgdx\";
- }
-
- output_asm_insn (\"ldx\\t#0\", operands);
- if (D_REG_P (operands[1]) || x_reg_used)
- {
- output_asm_insn (\"tsta\", operands);
- }
- else
- {
- ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
- ops[1] = operands[1];
- m68hc11_gen_movhi (insn, ops);
- }
-
- ops[0] = gen_label_rtx ();
- output_asm_insn (\"bpl\\t%l0\", ops);
- output_asm_insn (\"dex\", operands);
- (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
-
- return \"\";
-}")
-
-
-;;--------------------------------------------------------------------
-;;- Min and Max instructions (68HC12).
-;;--------------------------------------------------------------------
-(define_insn "uminqi3"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m")
- (umin:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
- (match_operand:QI 2 "general_operand" "m,d")))]
- "TARGET_M6812 && TARGET_MIN_MAX"
- "*
-{
- /* Flags are set according to (sub:QI (operand 1) (operand2)).
- The mina/minm use A as the source or destination. This is the
- high part of D. There is no way to express that in the pattern
- so we must use 'exg a,b' to put the operand in the good register. */
- CC_STATUS_INIT;
- if (D_REG_P (operands[0]))
- {
- return \"exg\\ta,b\\n\\tmina\\t%2\\n\\texg\\ta,b\";
- }
- else
- {
- return \"exg\\ta,b\\n\\tminm\\t%0\\n\\texg\\ta,b\";
- }
-}")
-
-(define_insn "umaxqi3"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m")
- (umax:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
- (match_operand:QI 2 "general_operand" "m,d")))]
- "TARGET_M6812 && TARGET_MIN_MAX"
- "*
-{
- /* Flags are set according to (sub:QI (operand 1) (operand2)).
- The maxa/maxm use A as the source or destination. This is the
- high part of D. There is no way to express that in the pattern
- so we must use 'exg a,b' to put the operand in the good register. */
- CC_STATUS_INIT;
- if (D_REG_P (operands[0]))
- {
- return \"exg\\ta,b\\n\\tmaxa\\t%2\\n\\texg\\ta,b\";
- }
- else
- {
- return \"exg\\ta,b\\n\\tmaxm\\t%0\\n\\texg\\ta,b\";
- }
-}")
-
-(define_insn "uminhi3"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=d,m")
- (umin:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
- (match_operand:HI 2 "general_operand" "m,d")))]
- "TARGET_M6812 && TARGET_MIN_MAX"
- "*
-{
- /* Flags are set according to (sub:HI (operand 1) (operand2)). */
- CC_STATUS_INIT;
- if (D_REG_P (operands[0]))
- {
- return \"emind\\t%2\";
- }
- else
- {
- return \"eminm\\t%0\";
- }
-}")
-
-(define_insn "umaxhi3"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=d,m")
- (umax:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
- (match_operand:HI 2 "general_operand" "m,d")))]
- "TARGET_M6812 && TARGET_MIN_MAX"
- "*
-{
- /* Flags are set according to (sub:HI (operand 1) (operand2)). */
- CC_STATUS_INIT;
- if (D_REG_P (operands[0]))
- {
- return \"emaxd\\t%2\";
- }
- else
- {
- return \"emaxm\\t%0\";
- }
-}")
-
-
-;;--------------------------------------------------------------------
-;;- Add instructions.
-;;--------------------------------------------------------------------
-;; 64-bit: Use a library call because what GCC generates is huge.
-;;
-(define_expand "adddi3"
- [(set (match_operand:DI 0 "nonimmediate_operand" "")
- (plus:DI (match_operand:DI 1 "general_operand" "")
- (match_operand:DI 2 "general_operand" "")))]
- ""
- "m68hc11_emit_libcall (\"___adddi3\", PLUS, DImode, DImode, 3, operands);
- DONE;")
-
-;;
-;; - 32-bit Add.
-;;
-(define_expand "addsi3"
- [(parallel [(set (match_operand:SI 0 "register_operand" "")
- (plus:SI (match_operand:SI 1 "general_operand" "")
- (match_operand:SI 2 "general_operand" "")))
- (clobber (match_scratch:HI 3 ""))])]
- ""
- "")
-
-(define_insn "*addsi3_zero_extendhi"
- [(set (match_operand:SI 0 "register_operand" "=D,D,D,D")
- (plus:SI (zero_extend:SI
- (match_operand:HI 1 "general_operand" "dxi,!u,mdxi,!u"))
- (match_operand:SI 2 "general_operand" "mi,mi,D?u,!Du")))
- (clobber (match_scratch:HI 3 "=X,X,X,X"))]
- ""
- "*
-{
- rtx ops[3];
-
- if (X_REG_P (operands[2]))
- {
- ops[0] = operands[1];
- }
- else
- {
- if (X_REG_P (operands[1]))
- {
- output_asm_insn (\"xgdx\", ops);
- }
- else if (!D_REG_P (operands[1]))
- {
- ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
- ops[1] = operands[1];
- m68hc11_gen_movhi (insn, ops);
- }
- ops[0] = m68hc11_gen_lowpart (HImode, operands[2]);
- ops[1] = m68hc11_gen_highpart (HImode, operands[2]);
- }
- ops[2] = gen_label_rtx ();
-
- /* ldx preserves the carry, propagate it by incrementing X directly. */
- output_asm_insn (\"addd\\t%0\", ops);
- if (!X_REG_P (operands[2]))
- output_asm_insn (\"ldx\\t%1\", ops);
-
- output_asm_insn (\"bcc\\t%l2\", ops);
- output_asm_insn (\"inx\", ops);
-
- CC_STATUS_INIT;
- (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2]));
- return \"\";
-}")
-
-
-(define_split /* "*addsi3_zero_extendqi" */
- [(set (match_operand:SI 0 "register_operand" "")
- (plus:SI (zero_extend:SI
- (match_operand:QI 1 "general_operand" ""))
- (match_operand:SI 2 "memory_operand" "")))
- (clobber (match_scratch:HI 3 "=X,X"))]
- "reload_completed"
- [(set (reg:HI D_REGNUM) (zero_extend:HI (match_dup 1)))
- (parallel [(set (match_dup 0)
- (plus:SI (zero_extend:SI (reg:HI D_REGNUM)) (match_dup 2)))
- (clobber (match_dup 3))])]
- "")
-
-(define_insn "*addsi3_zero_extendqi"
- [(set (match_operand:SI 0 "register_operand" "=D,D")
- (plus:SI (zero_extend:SI
- (match_operand:QI 1 "general_operand" "dAmi,!dAmiu"))
- (match_operand:SI 2 "general_operand" "miD,!muiD")))
- (clobber (match_scratch:HI 3 "=X,X"))]
- ""
- "*
-{
- rtx ops[4];
-
- if (GET_CODE (operands[2]) == MEM)
- return \"#\";
-
- if (X_REG_P (operands[2]))
- {
- if (H_REG_P (operands[1]))
- {
- ops[0] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
- ops[1] = gen_rtx_REG (HImode, REGNO (operands[1]));
- m68hc11_gen_movhi (insn, ops);
- }
- else
- {
- ops[0] = operands[1];
- }
- ops[1] = const0_rtx;
- }
- else
- {
- if (X_REG_P (operands[1]))
- {
- output_asm_insn (\"xgdx\", ops);
- }
- else if (!D_REG_P (operands[1]))
- {
- ops[0] = gen_rtx_REG (QImode, HARD_D_REGNUM);
- ops[1] = operands[1];
- m68hc11_gen_movqi (insn, ops);
- }
-
- ops[0] = m68hc11_gen_lowpart (HImode, operands[2]);
- ops[1] = ops[0];
- ops[2] = m68hc11_gen_highpart (HImode, operands[2]);
- output_asm_insn (\"clra\", ops);
- }
-
- /* ldx preserves the carry, propagate it by incrementing X directly. */
- output_asm_insn (\"addb\\t%b0\", ops);
- output_asm_insn (\"adca\\t%h1\", ops);
- if (!X_REG_P (operands[2]))
- output_asm_insn (\"ldx\\t%2\", ops);
-
- /* If the above adca was adding some constant, we don't need to propagate
- the carry unless the constant was 0xff. */
- if (X_REG_P (operands[2])
- || GET_CODE (ops[1]) != CONST_INT
- || ((INTVAL (ops[1]) & 0x0ff00) == 0x0ff00))
- {
- ops[3] = gen_label_rtx ();
-
- output_asm_insn (\"bcc\\t%l3\", ops);
- output_asm_insn (\"inx\", ops);
-
- (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
- CODE_LABEL_NUMBER (ops[3]));
- }
- CC_STATUS_INIT;
- return \"\";
-}")
-
-(define_insn "*addsi3"
- [(set (match_operand:SI 0 "non_push_operand" "=o,D,!u,?D,D")
- (plus:SI (match_operand:SI 1 "non_push_operand" "%0,0,0,0,0")
- (match_operand:SI 2 "general_operand" "ML,i,ML,?D,?oiu")))
- (clobber (match_scratch:HI 3 "=d,X,d,X,X"))]
- ""
- "*
-{
- rtx ops[3];
- const char* add_insn;
- const char* inc_insn;
- const char* incb_mem;
- const char* inch_mem;
- HOST_WIDE_INT val;
-
- if (which_alternative > 2)
- {
- return \"#\";
- }
-
- val = INTVAL (operands[2]);
- if ((val & 0x0ffffL) == 0)
- {
- if (!H_REG_P (operands[0]))
- {
- ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
- ops[1] = m68hc11_gen_highpart (HImode, operands[2]);
- output_asm_insn (\"ldd\\t%0\", ops);
- output_asm_insn (\"addd\\t%1\", ops);
- output_asm_insn (\"std\\t%0\", ops);
- return \"\";
- }
- else if (val == 1)
- {
- return \"inx\";
- }
- else
- {
- return \"#\";
- }
- }
- if ((val & 0xffff0000L) != 0 && (val & 0xffff0000L) != 0xffff0000L)
- {
- return \"#\";
- }
-
- if (val >= 0)
- {
- ops[1] = operands[2];
- add_insn = \"addd\\t%1\";
- inc_insn = \"inx\\t\";
- incb_mem = \"inc\\t%b1\";
- inch_mem = \"inc\\t%h1\";
- }
- else
- {
- ops[1] = GEN_INT (- val);
- add_insn = \"subd\\t%1\";
- inc_insn = \"dex\";
- incb_mem = \"dec\\t%b1\";
- inch_mem = \"dec\\t%h1\";
- }
-
- ops[2] = gen_label_rtx ();
- if (!H_REG_P (operands[0]))
- {
- ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
- output_asm_insn (\"ldd\\t%0\", ops);
- }
- output_asm_insn (add_insn, ops);
- if (!H_REG_P (operands[0]))
- {
- output_asm_insn (\"std\\t%0\", ops);
- }
- output_asm_insn (\"bcc\\t%l2\", ops);
- if (H_REG_P (operands[0]))
- {
- output_asm_insn (inc_insn, ops);
- }
- else
- {
- ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
- ops[1] = ops[0];
- if (INTVAL (operands[2]) < 0)
- {
- output_asm_insn (\"ldd\\t%1\", ops);
- output_asm_insn (\"addd\\t#-1\", ops);
- output_asm_insn (\"std\\t%1\", ops);
- }
- else
- {
- output_asm_insn (incb_mem, ops);
- output_asm_insn (\"bne\\t%l2\", ops);
- output_asm_insn (inch_mem, ops);
- }
- }
- (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2]));
-
- CC_STATUS_INIT;
- return \"\";
-}")
-
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (plus:SI (match_operand:SI 1 "register_operand" "")
- (match_operand:SI 2 "const_int_operand" "")))
- (clobber (match_scratch:HI 3 ""))]
- "reload_completed && z_replacement_completed == 2
- && ((INTVAL (operands[2]) & 0x0FFFF) == 0)"
- [(set (match_dup 5) (match_dup 6))
- (set (reg:HI 0) (plus:HI (reg:HI 0) (match_dup 4)))
- (set (match_dup 6) (match_dup 5))]
- "operands[4] = m68hc11_gen_highpart (HImode, operands[2]);
- if (X_REG_P (operands[0]))
- {
- operands[5] = operands[6] = gen_rtx_REG (HImode, HARD_D_REGNUM);
- }
- else
- {
- operands[6] = m68hc11_gen_highpart (HImode, operands[1]);
- operands[5] = operands[3];
- }
- ")
-
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (plus:SI (match_operand:SI 1 "register_operand" "")
- (match_operand:SI 2 "general_operand" "")))
- (clobber (match_scratch:HI 3 "=X"))]
- "reload_completed && z_replacement_completed == 2
- && (GET_CODE (operands[2]) != CONST_INT ||
- (!(INTVAL (operands[2]) >= -65536 && INTVAL (operands[2]) <= 65535)))"
- [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3)))
- (parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
- (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])
- (set (reg:QI B_REGNUM) (plus:QI (plus:QI (reg:QI CC_REGNUM) (reg:QI B_REGNUM)) (match_dup 4)))
- (set (reg:QI A_REGNUM) (plus:QI (plus:QI (reg:QI CC_REGNUM) (reg:QI A_REGNUM)) (match_dup 5)))
- (parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
- (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])]
- "operands[3] = m68hc11_gen_lowpart (HImode, operands[2]);
- operands[4] = m68hc11_gen_highpart (HImode, operands[2]);
- operands[5] = m68hc11_gen_highpart (QImode, operands[4]);
- operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);")
-
-;;
-;; Instruction generated to propagate the carry of a 16-bit add
-;; to the upper 16-bit part (in register X).
-;;
-(define_insn "*addsi_carry"
- [(set (match_operand:HI 0 "register_operand" "=x")
- (plus:HI (plus:HI (match_operand:HI 1 "register_operand" "0")
- (const_int 0))
- (reg:HI CC_REGNUM)))]
- ""
- "*
-{
- rtx ops[2];
-
- ops[0] = gen_label_rtx ();
- output_asm_insn (\"bcc\\t%l0\", ops);
- output_asm_insn (\"in%0\", operands);
- (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
- CC_STATUS_INIT;
- return \"\";
-}")
-
-;;
-;; - 16-bit Add.
-;;
-(define_expand "addhi3"
- [(set (match_operand:HI 0 "register_operand" "")
- (plus:HI (match_operand:HI 1 "register_operand" "")
- (match_operand:HI 2 "general_operand" "")))]
- ""
- "
-{
- if (TARGET_M6811 && SP_REG_P (operands[0]))
- {
- emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2,
- gen_rtx_SET (VOIDmode,
- operand0,
- gen_rtx_PLUS (HImode,
- operand1, operand2)),
- gen_rtx_CLOBBER (VOIDmode,
- gen_rtx_SCRATCH (HImode)))));
- DONE;
- }
-}")
-
-(define_insn "*addhi3_68hc12"
- [(set (match_operand:HI 0 "register_operand" "=d*A,d,xy*A*w,xy*A*w,xy*A")
- (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0,xy*Aw,0")
- (match_operand:HI 2 "general_operand" "i,m*A*wu,id,id,!mu*A")))]
- "TARGET_M6812"
- "*
-{
- int val;
- const char* insn_code;
-
- if (which_alternative >= 4)
- {
- if (A_REG_P (operands[2]))
- {
- CC_STATUS_INIT;
- output_asm_insn (\"xgd%2\", operands);
- output_asm_insn (\"lea%0 d,%0\", operands);
- return \"xgd%2\";
- }
- return \"#\";
- }
-
- if (D_REG_P (operands[0]))
- {
- if (X_REG_P (operands[2]))
- {
- m68hc11_notice_keep_cc (operands[0]);
- output_asm_insn (\"xgdx\", operands);
- output_asm_insn (\"leax\\td,%2\", operands);
- return \"xgdx\";
- }
- else if (Y_REG_P (operands[2]))
- {
- m68hc11_notice_keep_cc (operands[0]);
- output_asm_insn (\"xgdy\", operands);
- output_asm_insn (\"leay\\td,%2\", operands);
- return \"xgdy\";
- }
- else if (SP_REG_P (operands[2]))
- {
- output_asm_insn (\"sts\\t%t0\", operands);
- return \"addd\\t%t0\";
- }
- return \"addd\\t%2\";
- }
-
- if (GET_CODE (operands[2]) == CONST_INT)
- val = INTVAL (operands[2]);
- else
- val = 1000;
-
- if ((val != -1 && val != 1) || !rtx_equal_p (operands[0], operands[1]))
- {
- m68hc11_notice_keep_cc (operands[0]);
- switch (REGNO (operands[0]))
- {
- case HARD_X_REGNUM:
- return \"leax\\t%i2,%1\";
-
- case HARD_Y_REGNUM:
- return \"leay\\t%i2,%1\";
-
- case HARD_SP_REGNUM:
- return \"leas\\t%i2,%1\";
-
- default:
- fatal_insn (\"Invalid operands in the instruction\", insn);
- }
- }
- if (val > 0)
- {
- insn_code = X_REG_P (operands[0]) ? \"inx\"
- : Y_REG_P (operands[0]) ? \"iny\" : \"ins\";
- }
- else
- {
- val = -val;
- insn_code = X_REG_P (operands[0]) ? \"dex\"
- : Y_REG_P (operands[0]) ? \"dey\" : \"des\";
- }
-
- /* For X and Y increment, the flags are not complete. Only the Z flag
- is updated. For SP increment, flags are not changed. */
- if (SP_REG_P (operands[0]))
- {
- cc_status = cc_prev_status;
- if (INTVAL (operands[2]) < 0)
- {
- while (val > 2)
- {
- output_asm_insn (\"pshx\", operands);
- val -= 2;
- }
- if (val == 0)
- return \"\";
- }
- }
- else
- {
- CC_STATUS_INIT;
- }
-
- while (val)
- {
- output_asm_insn (insn_code, operands);
- val--;
- }
- return \"\";
-}")
-
-;;
-;; Specific pattern to add to the stack pointer.
-;; We also take care of the clobbering of the IY register.
-;;
-(define_insn "addhi_sp"
- [(set (match_operand:HI 0 "stack_register_operand" "=w,w,w,w")
- (plus:HI (match_operand:HI 1 "stack_register_operand" "%0,0,0,0")
- (match_operand:HI 2 "general_operand" "P,im,u,im")))
- (clobber (match_scratch:HI 3 "=X,&y,&y,!&x"))]
- "!TARGET_M6812"
- "*
-{
- HOST_WIDE_INT val;
-
- if (optimize && Y_REG_P (operands[3])
- && dead_register_here (insn, gen_rtx_REG (HImode, HARD_X_REGNUM)))
- operands[3] = gen_rtx_REG (HImode, HARD_X_REGNUM);
-
- if (GET_CODE (operands[2]) == CONST_INT
- && (val = INTVAL (operands[2])) != 0
- && (CONST_OK_FOR_LETTER_P (val, 'P')
- || (val > 0 && val <= 8)))
- {
- while (val > 1 || val < -1)
- {
- if (val > 0)
- {
- if (!H_REG_P (operands[3]))
- break;
-
- output_asm_insn (\"pul%3\", operands);
- val -= 2;
- }
- else
- {
- output_asm_insn (\"pshx\", operands);
- val += 2;
- }
- }
- while (val != 0)
- {
- if (val > 0)
- {
- output_asm_insn (\"ins\", operands);
- val--;
- }
- else
- {
- output_asm_insn (\"des\", operands);
- val++;
- }
- }
- cc_status = cc_prev_status;
- return \"\";
- }
-
- /* Need to transfer to SP to X/Y and then to D register.
- Register X/Y is lost, this is specified by the (clobber) statement. */
- output_asm_insn (\"ts%3\", operands);
- if (GET_CODE (operands[2]) == CONST_INT
- && ((val = INTVAL (operands[2])) >= 0 && val < 0x100)
- && dead_register_here (insn, gen_rtx_REG (HImode, HARD_D_REGNUM)))
- {
- output_asm_insn (\"ldab\\t%2\", operands);
- output_asm_insn (\"ab%3\", operands);
- CC_STATUS_INIT;
- }
- else
- {
- output_asm_insn (\"xgd%3\", operands);
- output_asm_insn (\"addd\\t%2\", operands);
- output_asm_insn (\"xgd%3\", operands);
- }
-
- /* The status flags correspond to the addd. xgdy and tys do not
- modify the flags. */
- return \"t%3s\";
-}")
-
-(define_insn "*addhi3"
- [(set (match_operand:HI 0 "hard_reg_operand" "=A,dA,d,!A,d*A,d,!d*A")
- (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0,0,0,0")
- (match_operand:HI 2 "general_operand" "N,I,i,I,mi*A*d,*u,!u*d*w")))]
- "TARGET_M6811"
- "*
-{
- const char* insn_code;
- int val;
-
- if (D_REG_P (operands[0]) && SP_REG_P (operands[2]))
- {
- output_asm_insn (\"sts\\t%t0\", operands);
- output_asm_insn (\"addd\\t%t0\", operands);
- return \"addd\\t#1\";
- }
- if (GET_CODE (operands[2]) != CONST_INT)
- {
- /* Adding to an address register or with another/same register
- is not possible. This must be replaced. */
- if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
- return \"#\";
-
- return \"addd\\t%2\";
- }
- val = INTVAL (operands[2]);
- if (!SP_REG_P (operands[0]))
- {
- if (D_REG_P (operands[0]))
- {
- if ((val & 0x0ff) == 0 && !next_insn_test_reg (insn, operands[0]))
- {
- CC_STATUS_INIT;
- return \"adda\\t%h2\";
- }
- else
- {
- return \"addd\\t%2\";
- }
- }
- else if (GET_CODE (operands[2]) != CONST_INT
- || INTVAL (operands[2]) < -4
- || INTVAL (operands[2]) > 4)
- return \"#\";
- }
- if (val > 0)
- {
- insn_code = X_REG_P (operands[0]) ? \"inx\"
- : Y_REG_P (operands[0]) ? \"iny\" : \"ins\";
- }
- else
- {
- val = -val;
- insn_code = X_REG_P (operands[0]) ? \"dex\"
- : Y_REG_P (operands[0]) ? \"dey\" : \"des\";
- }
-
- /* For X and Y increment, the flags are not complete. Only the Z flag
- is updated. For SP increment, flags are not changed. */
- if (SP_REG_P (operands[0]))
- {
- cc_status = cc_prev_status;
- if (INTVAL (operands[2]) < 0)
- {
- while (val >= 2)
- {
- output_asm_insn (\"pshx\", operands);
- val -= 2;
- }
- }
- else if (optimize && dead_register_here (insn, ix_reg))
- {
- while (val >= 2)
- {
- output_asm_insn (\"pulx\", operands);
- val -= 2;
- }
- }
- }
- else
- {
- CC_STATUS_INIT;
- }
-
- while (val)
- {
- output_asm_insn (insn_code, operands);
- val--;
- }
- return \"\";
-}")
-
-(define_insn "*addhi3_zext"
- [(set (match_operand:HI 0 "hard_reg_operand" "=A,d")
- (plus:HI (zero_extend:HI
- (match_operand:QI 1 "nonimmediate_operand" "d,um*A"))
- (match_operand:HI 2 "general_operand" "0,0")))]
- ""
- "*
-{
- CC_STATUS_INIT;
- if (A_REG_P (operands[0]))
- return \"ab%0\";
- else if (A_REG_P (operands[1]))
- return \"st%1\\t%t0\\n\\taddb\\t%T0\\n\\tadca\\t#0\";
- else
- return \"addb\\t%b1\\n\\tadca\\t#0\";
-}")
-
-;;
-;; Translate d = d + d into d = << 1
-;; We have to do this because adding a register to itself is not possible.
-;; ??? It's not clear whether this is really necessary.
-;;
-(define_split
- [(set (match_operand:QI 0 "hard_reg_operand" "")
- (plus:QI (match_dup 0)
- (match_dup 0)))]
- "0 && reload_completed"
- [(set (match_dup 0) (ashift:QI (match_dup 0) (const_int 1)))]
- "")
-
-(define_insn "addqi3"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=!d*rm,dq,!*A")
- (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0")
- (match_operand:QI 2 "general_operand" "N,ium*A*d,ium*A*d")))]
- ""
- "*
-{
- if (GET_CODE (operands[2]) == CONST_INT)
- {
- if (INTVAL (operands[2]) == 1)
- {
- if (DA_REG_P (operands[0]))
- {
- return \"inca\";
- }
- else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
- {
- return \"incb\";
-
- }
- else if (A_REG_P (operands[0]))
- {
- /* This applies on the 16-bit register. This should be ok since
- this is not a strict_low_part increment. */
- return \"in%0\";
- }
- else
- {
- return \"inc\\t%b0\";
- }
- }
- else if (INTVAL (operands[2]) == -1)
- {
- if (DA_REG_P (operands[0]))
- {
- return \"deca\";
- }
- else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
- {
- return \"decb\";
- }
- else if (A_REG_P (operands[0]))
- {
- /* This applies on the 16-bit register. This should be ok since
- this is not a strict_low_part decrement. */
- return \"de%0\";
- }
- else
- {
- return \"dec\\t%b0\";
- }
- }
- }
- if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
- return \"#\";
- else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
- return \"addb\\t%b2\";
- else
- return \"adda\\t%b2\";
-}")
-
-;;
-;; add with carry is used for 32-bit add.
-;;
-(define_insn "*adcq"
- [(set (match_operand:QI 0 "register_operand" "=q")
- (plus:QI (plus:QI (reg:QI CC_REGNUM)
- (match_operand:QI 1 "register_operand" "%0"))
- (match_operand:QI 2 "general_operand" "ium")))]
- ""
- "adc%0\\t%b2")
-
-;;--------------------------------------------------------------------
-;;- Subtract instructions.
-;;--------------------------------------------------------------------
-
-(define_expand "subdi3"
- [(set (match_operand:DI 0 "nonimmediate_operand" "")
- (minus:DI (match_operand:DI 1 "nonimmediate_operand" "")
- (match_operand:DI 2 "general_operand" "")))]
- ""
- "m68hc11_emit_libcall (\"___subdi3\", MINUS, DImode, DImode, 3, operands);
- DONE;")
-
-;;
-;; 32-bit Subtract (see addsi3)
-;; Subtract with a constant are handled by addsi3.
-;;
-;;
-;; - 32-bit Add.
-;;
-(define_expand "subsi3"
- [(parallel [(set (match_operand:SI 0 "register_operand" "")
- (minus:SI (match_operand:SI 1 "register_operand" "")
- (match_operand:SI 2 "general_operand" "")))
- (clobber (match_scratch:HI 3 ""))])]
- ""
- "")
-
-(define_insn "*subsi3"
- [(set (match_operand:SI 0 "register_operand" "=D,D,D,D,!u")
- (minus:SI (match_operand:SI 1 "general_operand" "0,oi,0,!u,0")
- (match_operand:SI 2 "general_operand" "oi,D,!u,D,!oui")))
- (clobber (match_scratch:HI 3 "=X,X,X,X,d"))]
- ""
- "#")
-
-(define_insn "*subsi3_zero_extendhi"
- [(set (match_operand:SI 0 "register_operand" "=D")
- (minus:SI (match_operand:SI 1 "register_operand" "0")
- (zero_extend:SI (match_operand:HI 2 "general_operand" "dmui*A"))))
- (clobber (match_scratch:HI 3 "=X"))]
- ""
- "*
-{
- rtx ops[2];
-
- if (A_REG_P (operands[2]))
- {
- if (TARGET_M6812)
- ops[0] = gen_rtx_MEM (HImode,
- gen_rtx_PRE_DEC (HImode,
- gen_rtx_REG (HImode, HARD_SP_REGNUM)));
- else
- ops[0] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
-
- ops[1] = operands[2];
- m68hc11_gen_movhi (insn, ops);
- if (TARGET_M6812)
- operands[2] = gen_rtx_MEM (HImode,
- gen_rtx_POST_INC (HImode,
- gen_rtx_REG (HImode, HARD_SP_REGNUM)));
- else
- operands[2] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
- }
- ops[0] = gen_label_rtx ();
- output_asm_insn (\"subd\\t%2\", operands);
- output_asm_insn (\"bcc\\t%l0\", ops);
- output_asm_insn (\"dex\", ops);
- (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
- CC_STATUS_INIT;
- return \"\";
-}")
-
-(define_insn "*subsi3_zero_extendqi"
- [(set (match_operand:SI 0 "register_operand" "=D")
- (minus:SI (match_operand:SI 1 "register_operand" "0")
- (zero_extend:SI (match_operand:QI 2 "general_operand" "dmui*A"))))
- (clobber (match_scratch:HI 3 "=X"))]
- ""
- "*
-{
- rtx ops[2];
-
- if (A_REG_P (operands[2]))
- {
- ops[0] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
- ops[1] = operands[2];
- m68hc11_gen_movhi (insn, ops);
- operands[2] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
- }
- ops[0] = gen_label_rtx ();
- output_asm_insn (\"subb\\t%b2\", operands);
- output_asm_insn (\"sbca\\t#0\", operands);
- output_asm_insn (\"bcc\\t%l0\", ops);
- output_asm_insn (\"dex\", ops);
- (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
- CC_STATUS_INIT;
- return \"\";
-}")
-
-;;
-;; reg:HI 1 -> d reg:QI 6 -> B
-;; reg:QI 7 -> ccr reg:QI 5 -> A
-;;
-(define_split /* "*subsi3" */
- [(set (match_operand:SI 0 "register_operand" "")
- (minus:SI (match_operand:SI 1 "register_operand" "")
- (match_operand:SI 2 "general_operand" "")))
- (clobber (match_scratch:HI 3 "=X"))]
- "reload_completed && z_replacement_completed == 2
- && X_REG_P (operands[1])"
- [(set (reg:HI D_REGNUM) (minus:HI (reg:HI D_REGNUM) (match_dup 3)))
- (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
- (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
- (set (reg:QI B_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI B_REGNUM)) (match_dup 4)))
- (set (reg:QI A_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI A_REGNUM)) (match_dup 5)))
- (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
- (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])]
- "operands[3] = m68hc11_gen_lowpart (HImode, operands[2]);
- operands[4] = m68hc11_gen_highpart (HImode, operands[2]);
- operands[5] = m68hc11_gen_highpart (QImode, operands[4]);
- operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);")
-
-(define_split /* "*subsi3" */
- [(set (match_operand:SI 0 "register_operand" "")
- (minus:SI (match_operand:SI 1 "general_operand" "")
- (match_operand:SI 2 "register_operand" "")))
- (clobber (match_scratch:HI 3 "=X"))]
- "reload_completed && z_replacement_completed == 2
- && X_REG_P (operands[2])"
- [(set (reg:HI D_REGNUM) (minus:HI (reg:HI D_REGNUM) (match_dup 3)))
- (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
- (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
- (set (reg:QI B_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI B_REGNUM)) (match_dup 4)))
- (set (reg:QI A_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI A_REGNUM)) (match_dup 5)))
- (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
- (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
- (set (reg:SI 0) (neg:SI (reg:SI 0)))]
- "operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);
- operands[4] = m68hc11_gen_highpart (HImode, operands[1]);
- operands[5] = m68hc11_gen_highpart (QImode, operands[4]);
- operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);")
-
-(define_split /* "*subsi3" */
- [(set (match_operand:SI 0 "nonimmediate_operand" "")
- (minus:SI (match_operand:SI 1 "general_operand" "")
- (match_operand:SI 2 "general_operand" "")))
- (clobber (match_scratch:HI 3 "=d"))]
- "reload_completed && z_replacement_completed == 2
- && !X_REG_P (operands[0])"
- [(set (match_dup 3) (match_dup 4))
- (set (match_dup 3) (minus:HI (match_dup 3) (match_dup 5)))
- (set (match_dup 4) (match_dup 3))
- (set (match_dup 3) (match_dup 6))
- (set (reg:QI 6) (minus:QI (minus:QI (reg:QI 7) (reg:QI 6)) (match_dup 7)))
- (set (reg:QI 5) (minus:QI (minus:QI (reg:QI 7) (reg:QI 5)) (match_dup 8)))
- (set (match_dup 6) (match_dup 3))]
- "operands[4] = m68hc11_gen_lowpart (HImode, operands[1]);
- operands[5] = m68hc11_gen_lowpart (HImode, operands[2]);
- operands[6] = m68hc11_gen_highpart (HImode, operands[1]);
- operands[7] = m68hc11_gen_highpart (HImode, operands[2]);
- operands[8] = m68hc11_gen_highpart (QImode, operands[7]);
- operands[7] = m68hc11_gen_lowpart (QImode, operands[7]);")
-
-;;
-;; - 16-bit Subtract.
-;;
-(define_expand "subhi3"
- [(set (match_operand:HI 0 "register_operand" "=r")
- (minus:HI (match_operand:HI 1 "register_operand" "0")
- (match_operand:HI 2 "general_operand" "g")))]
- ""
- "")
-
-;;
-;; Subtract from stack. This is better if we provide a pattern.
-;;
-(define_insn "*subhi3_sp"
- [(set (match_operand:HI 0 "stack_register_operand" "=w,w")
- (minus:HI (match_operand:HI 1 "register_operand" "0,0")
- (match_operand:HI 2 "general_operand" "im*d,!u*A")))
- (clobber (match_scratch:HI 3 "=A*d,A*d"))]
- ""
- "*
-{
- if (X_REG_P (operands[2]))
- {
- operands[2] = m68hc11_soft_tmp_reg;
- output_asm_insn (\"stx\\t%2\", operands);
- }
- else if (Y_REG_P (operands[2]))
- {
- operands[2] = m68hc11_soft_tmp_reg;
- output_asm_insn (\"sty\\t%2\", operands);
- }
- else if (D_REG_P (operands[2]))
- {
- operands[2] = m68hc11_soft_tmp_reg;
- output_asm_insn (\"std\\t%2\", operands);
- }
-
- if (D_REG_P (operands[3]))
- {
- int save_x;
-
- save_x = !dead_register_here (insn, ix_reg);
- if (save_x)
- output_asm_insn (\"xgdx\", operands);
- output_asm_insn (\"tsx\", operands);
- output_asm_insn (\"xgdx\", operands);
- output_asm_insn (\"subd\\t%2\", operands);
- output_asm_insn (\"xgdx\", operands);
-
- /* The status flags correspond to the addd. xgdx/y and tx/ys do not
- modify the flags. */
- output_asm_insn (\"txs\", operands);
- if (save_x)
- return \"xgdx\";
- else
- return \"\";
- }
-
- /* Need to transfer to SP to X,Y and then to D register.
- Register X,Y is lost, this is specified by the (clobber) statement. */
- output_asm_insn (\"ts%3\", operands);
- output_asm_insn (\"xgd%3\", operands);
- output_asm_insn (\"subd\\t%2\", operands);
- output_asm_insn (\"xgd%3\", operands);
-
- /* The status flags correspond to the addd. xgdx/y and tx/ys do not
- modify the flags. */
- return \"t%3s\";
-}")
-
-
-(define_insn "*subhi3"
- [(set (match_operand:HI 0 "register_operand" "=d,*A,d,*A")
- (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
- (match_operand:HI 2 "general_operand" "im*A*d,im*d*A,u,!u")))]
- ""
- "*
-{
- /* Adding to an address register or with another/same register
- is not possible. This must be replaced. */
- if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
- return \"#\";
-
- return \"subd\\t%2\";
-}")
-
-(define_insn "*subhi3_zext"
- [(set (match_operand:HI 0 "hard_reg_operand" "=d,d")
- (minus:HI (match_operand:HI 1 "general_operand" "0,0")
- (zero_extend:HI (match_operand:QI 2 "general_operand" "mi*A,!u"))))]
- ""
- "*
-{
- CC_STATUS_INIT;
- if (A_REG_P (operands[2]))
- {
- rtx ops[2];
-
- ops[0] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
- ops[1] = operands[2];
- m68hc11_gen_movqi (insn, ops);
- return \"subb\\t%T0\\n\\tsbca\\t#0\";
- }
- return \"subb\\t%b2\\n\\tsbca\\t#0\";
-}")
-
-(define_insn "subqi3"
- [(set (match_operand:QI 0 "hard_reg_operand" "=dq,!*x*y")
- (minus:QI (match_operand:QI 1 "general_operand" "0,0")
- (match_operand:QI 2 "general_operand" "uim*A*d,uim*A*d")))]
- ""
- "*
-{
- if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
- return \"#\";
- else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
- return \"subb\\t%b2\";
- else
- return \"suba\\t%b2\";
-}")
-
-;;
-;; subtract with carry is used for 32-bit subtract.
-;;
-(define_insn "*subcq"
- [(set (match_operand:QI 0 "register_operand" "=q")
- (minus:QI (minus:QI (reg:QI CC_REGNUM)
- (match_operand:QI 1 "register_operand" "0"))
- (match_operand:QI 2 "general_operand" "ium")))]
- ""
- "sbc%0\\t%b2")
-
-;;--------------------------------------------------------------------
-;;- Multiply instructions.
-;;--------------------------------------------------------------------
-;;
-;; 32 and 64-bit multiply are handled by the library
-;;
-
-(define_expand "mulsi3"
- [(set (match_operand:SI 0 "nonimmediate_operand" "")
- (mult:SI (match_operand:SI 1 "general_operand" "")
- (match_operand:SI 2 "general_operand" "")))]
- ""
- "m68hc11_emit_libcall (\"__mulsi3\", MULT, SImode, SImode, 3, operands);
- DONE;")
-
-(define_expand "mulhi3"
- [(parallel [(set (match_operand:HI 0 "register_operand" "")
- (mult:HI (match_operand:HI 1 "register_operand" "")
- (match_operand:HI 2 "register_operand" "")))
- (clobber (match_scratch:HI 3 ""))])]
- ""
- "")
-
-(define_insn "mulhi3_m68hc11"
- [(set (match_operand:HI 0 "register_operand" "=d")
- (mult:HI (match_operand:HI 1 "register_operand" "%0")
- (match_operand:HI 2 "register_operand" "x")))
- (clobber (match_scratch:HI 3 "=X"))]
- "TARGET_M6811"
- "*
-{
- CC_STATUS_INIT;
- /* D * X -> D (X and Y are preserved by this function call). */
- return \"jsr\\t___mulhi3\";
-}")
-
-(define_insn "mulhi3_m68hc12"
- [(set (match_operand:HI 0 "register_operand" "=d,d")
- (mult:HI (match_operand:HI 1 "register_operand" "%0,0")
- (match_operand:HI 2 "register_operand" "y,x")))
- (clobber (match_scratch:HI 3 "=2,2"))]
- "TARGET_M6812"
- "*
-{
- CC_STATUS_INIT;
- if (X_REG_P (operands[2]))
- return \"exg\\tx,y\\n\\temul\\n\\texg\\tx,y\";
- else
- return \"emul\";
-}")
-
-(define_insn "umulhisi3"
- [(set (match_operand:SI 0 "register_operand" "=D,D")
- (mult:SI (zero_extend:SI
- (match_operand:HI 1 "register_operand" "%d,d"))
- (zero_extend:SI
- (match_operand:HI 2 "register_operand" "y,x"))))
- (clobber (match_scratch:HI 3 "=2,X"))]
- "TARGET_M6812"
- "*
-{
- if (X_REG_P (operands [2]))
- output_asm_insn (\"exg\\tx,y\", operands);
-
- /* Can't use the carry after that; other flags are ok when testing
- the 32-bit result. */
- cc_status.flags |= CC_NO_OVERFLOW;
- return \"emul\\n\\texg\\tx,y\";
-}")
-
-(define_insn "mulhisi3"
- [(set (match_operand:SI 0 "register_operand" "=D,D")
- (mult:SI (sign_extend:SI
- (match_operand:HI 1 "register_operand" "%d,d"))
- (sign_extend:SI
- (match_operand:HI 2 "register_operand" "y,x"))))
- (clobber (match_scratch:HI 3 "=2,X"))]
- "TARGET_M6812"
- "*
-{
- if (X_REG_P (operands [2]))
- output_asm_insn (\"exg\\tx,y\", operands);
-
- /* Can't use the carry after that; other flags are ok when testing
- the 32-bit result. */
- cc_status.flags |= CC_NO_OVERFLOW;
- return \"emuls\\n\\texg\\tx,y\";
-}")
-
-(define_insn "umulqihi3"
- [(set (match_operand:HI 0 "register_operand" "=d")
- (mult:HI (zero_extend:HI
- (match_operand:QI 1 "nonimmediate_operand" "dm*u"))
- (zero_extend:HI
- (match_operand:QI 2 "nonimmediate_operand" "dm*u*A"))))]
- ""
- "*
-{
- if (D_REG_P (operands[1]) && D_REG_P (operands[2]))
- {
- output_asm_insn (\"tba\", operands);
- }
- else
- {
- rtx ops[2];
-
- if (D_REG_P (operands[2]))
- {
- rtx temp = operands[2];
- operands[2] = operands[1];
- operands[1] = temp;
- }
-
- ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
- ops[1] = operands[2];
- m68hc11_gen_movqi (insn, ops);
-
- if (!D_REG_P (operands[1]))
- {
- output_asm_insn (\"ldab\\t%b1\", operands);
- }
- }
-
- CC_STATUS_INIT;
- return \"mul\";
-}")
-
-(define_insn "mulqi3"
- [(set (match_operand:QI 0 "register_operand" "=d,*x,*y")
- (mult:QI (match_operand:QI 1 "general_operand" "%di*um,0,0")
- (match_operand:QI 2 "general_operand" "di*um,*xium,*yium")))]
- ""
- "*
-{
- if (A_REG_P (operands[0]))
- return \"#\";
-
- if (D_REG_P (operands[1]) && D_REG_P (operands[2]))
- {
- output_asm_insn (\"tba\", operands);
- }
- else
- {
- if (D_REG_P (operands[2]))
- {
- rtx temp = operands[2];
- operands[2] = operands[1];
- operands[1] = temp;
- }
-
- output_asm_insn (\"ldaa\\t%b2\", operands);
-
- if (!D_REG_P (operands[1]))
- {
- output_asm_insn (\"ldab\\t%b1\", operands);
- }
- }
-
- CC_STATUS_INIT;
- return \"mul\";
-}")
-
-(define_split
- [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
- (mult:QI (match_operand:QI 1 "general_operand" "")
- (match_operand:QI 2 "general_operand" "")))]
- "z_replacement_completed == 2"
- [(parallel [(set (reg:HI D_REGNUM) (match_dup 3))
- (set (match_dup 3) (reg:HI D_REGNUM))])
- (set (reg:QI D_REGNUM) (mult:QI (match_dup 5) (match_dup 6)))
- (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
- (set (match_dup 3) (reg:HI D_REGNUM))])]
- "
- operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));
- if (A_REG_P (operands[1]))
- operands[5] = gen_rtx_REG (QImode, HARD_D_REGNUM);
- else
- operands[5] = operands[1];
- if (A_REG_P (operands[2]))
- operands[6] = gen_rtx_REG (QImode, HARD_D_REGNUM);
- else
- operands[6] = operands[2];
- ")
-
-(define_insn "mulqihi3"
- [(set (match_operand:HI 0 "register_operand" "=d,d,d")
- (mult:HI (sign_extend:HI
- (match_operand:QI 1 "register_operand" "%0,0,0"))
- (sign_extend:HI
- (match_operand:QI 2 "general_operand" "mi*u,*A,0"))))]
- ""
- "*
-{
- CC_STATUS_INIT;
-
- /* Special case when multiplying the register with itself. */
- if (D_REG_P (operands[2]))
- {
- output_asm_insn (\"tba\", operands);
- return \"mul\";
- }
-
- if (!H_REG_P (operands[2]))
- {
- output_asm_insn (\"ldaa\\t%b2\", operands);
- }
- else
- {
- rtx ops[2];
-
- ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
- ops[1] = operands[2];
- m68hc11_gen_movqi (insn, ops);
- }
- return \"jsr\\t___mulqi3\";
-}")
-
-;;--------------------------------------------------------------------
-;;- Divide instructions.
-;;--------------------------------------------------------------------
-
-(define_insn "divmodhi4"
- [(set (match_operand:HI 0 "register_operand" "=d,d")
- (div:HI (match_operand:HI 1 "register_operand" "0,0")
- (match_operand:HI 2 "general_operand" "A,ium")))
- (set (match_operand:HI 3 "register_operand" "=&x,&x")
- (mod:HI (match_dup 1) (match_dup 2)))]
- ""
- "*
-{
- if (!X_REG_P (operands[2]))
- {
- if (Y_REG_P (operands[2]))
- {
- output_asm_insn (\"sty\\t%t1\", operands);
- output_asm_insn (\"ldx\\t%t1\", operands);
- }
- else
- {
- output_asm_insn (\"ldx\\t%2\", operands);
- }
- }
- if (TARGET_M6812)
- {
- /* Flags are ok after that. */
- return \"idivs\\n\\txgdx\";
- }
- else
- {
- CC_STATUS_INIT;
- return \"bsr\\t__divmodhi4\";
- }
-}")
-
-(define_insn "udivmodhi4"
- [(set (match_operand:HI 0 "register_operand" "=d,d")
- (udiv:HI (match_operand:HI 1 "register_operand" "0,0")
- (match_operand:HI 2 "general_operand" "A,ium")))
- (set (match_operand:HI 3 "register_operand" "=x,x")
- (umod:HI (match_dup 1) (match_dup 2)))]
- ""
- "*
-{
- if (!X_REG_P (operands[2]))
- {
- if (Y_REG_P (operands[2]))
- {
- output_asm_insn (\"sty\\t%t1\", operands);
- output_asm_insn (\"ldx\\t%t1\", operands);
- }
- else
- {
- output_asm_insn (\"ldx\\t%2\", operands);
- }
- }
-
- /* Z V and C flags are set but N is unchanged.
- Since this is an unsigned divide, we can probably keep the flags
- and indicate this. */
- cc_status.flags |= CC_NOT_NEGATIVE;
- return \"idiv\\n\\txgdx\";
-}")
-
-;;--------------------------------------------------------------------
-;;- and instructions.
-;;--------------------------------------------------------------------
-
-(define_insn_and_split "anddi3"
- [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u")
- (and:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu")
- (match_operand:DI 2 "general_operand" "imu,imu")))
- (clobber (match_scratch:HI 3 "=d,d"))]
- ""
- "#"
- "reload_completed"
- [(const_int 0)]
- "m68hc11_split_logical (SImode, AND, operands);
- DONE;")
-
-(define_insn_and_split "andsi3"
- [(set (match_operand:SI 0 "register_operand" "=D,!u")
- (and:SI (match_operand:SI 1 "register_operand" "%0,0")
- (match_operand:SI 2 "general_operand" "Dimu,imu")))
- (clobber (match_scratch:HI 3 "=X,d"))]
- ""
- "#"
- "reload_completed"
- [(const_int 0)]
- "m68hc11_split_logical (HImode, AND, operands);
- DONE;")
-
-(define_expand "andhi3"
- [(set (match_operand:HI 0 "register_operand" "")
- (and:HI (match_operand:HI 1 "register_operand" "")
- (match_operand:HI 2 "general_operand" "")))]
- ""
- "")
-
-(define_insn "*andhi3_mem"
- [(set (match_operand:HI 0 "memory_operand" "=R,Q")
- (and:HI (match_dup 0)
- (match_operand:HI 1 "immediate_operand" "i,i")))
- (clobber (match_scratch:HI 2 "=X,xy"))]
- "TARGET_RELAX && !TARGET_M6812"
- "*
-{
- int val = INTVAL (operands[1]) & 0x0FFFF;
-
- if (val == 0x0ffff)
- {
- cc_status = cc_prev_status;
- return \"\";
- }
-
- CC_STATUS_INIT;
-
- /* The bclr instruction uses an inverted mask. */
- operands[1] = GEN_INT ((~val) & 0x0FFFF);
-
- /* When destination is a global variable, generate a .relax instruction
- and load the address in the clobber register. That load can be
- eliminated by the linker if the address is in page0. */
- if (which_alternative == 1)
- {
- rtx ops[3];
-
- ops[0] = operands[2];
- ops[1] = XEXP (operands[0], 0);
- ops[2] = gen_label_rtx ();
- output_asm_insn (\".relax\\t%l2\", ops);
- m68hc11_gen_movhi (insn, ops);
- if ((val & 0x0FF) != 0x0FF)
- output_asm_insn (\"bclr\\t1,%2, %b1\", operands);
-
- if ((val & 0x0FF00) != 0x0FF00)
- output_asm_insn (\"bclr\\t0,%2, %h1\", operands);
-
- (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
- CODE_LABEL_NUMBER (ops[2]));
- return \"\";
- }
-
- if ((val & 0x0FF) != 0x0FF)
- output_asm_insn (\"bclr\\t%b0, %b1\", operands);
-
- if ((val & 0x0FF00) != 0x0FF00)
- output_asm_insn (\"bclr\\t%h0, %h1\", operands);
-
- return \"\";
-}")
-
-(define_insn "*andhi3_const"
- [(set (match_operand:HI 0 "reg_or_some_mem_operand" "=R,d,?*A")
- (and:HI (match_operand:HI 1 "reg_or_some_mem_operand" "%0,0,0")
- (match_operand:HI 2 "const_int_operand" "")))]
- ""
- "*
-{
- int val = INTVAL (operands[2]) & 0x0FFFF;
- int lowpart_zero = 0;
- int highpart_zero = 0;
- int lowpart_unknown = 0;
- int highpart_unknown = 0;
-
- if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
- return \"#\";
-
- if (val == 0x0ffff)
- {
- cc_status = cc_prev_status;
- return \"\";
- }
-
- /* First, try to clear the low and high part.
- If that's possible, the second 'and' will give
- the good status flags and we can avoid a tsthi. */
- if ((val & 0x0FF) == 0)
- {
- if (D_REG_P (operands[0]))
- output_asm_insn (\"clrb\", operands);
- else
- output_asm_insn (\"clr\\t%b0\", operands);
- lowpart_zero = 1;
- }
- if ((val & 0x0FF00) == 0)
- {
- if (D_REG_P (operands[0]))
- output_asm_insn (\"clra\", operands);
- else
- output_asm_insn (\"clr\\t%h0\", operands);
- highpart_zero = 1;
- }
-
- if ((val & 0x0FF) == 0x0FF)
- {
- lowpart_unknown = 1;
- }
- else if ((val & 0x0FF) != 0 && !H_REG_P (operands[0]))
- {
- rtx ops[2];
-
- ops[0] = operands[0];
- ops[1] = GEN_INT ((~val) & 0x0FF);
- output_asm_insn (\"bclr\\t%b0, %1\", ops);
- }
- else if ((val & 0x0FF) != 0)
- {
- output_asm_insn (\"andb\\t%b2\", operands);
- }
-
- if ((val & 0x0FF00) == 0x0FF00)
- {
- highpart_unknown = 1;
- }
- else if (((val & 0x0FF00) != 0) && !H_REG_P (operands[0]))
- {
- rtx ops[2];
-
- ops[0] = operands[0];
- ops[1] = GEN_INT (((~val) & 0x0FF00) >> 8);
- output_asm_insn (\"bclr\\t%h0, %1\", ops);
- }
- else if ((val & 0x0FF00) != 0)
- {
- output_asm_insn (\"anda\\t%h2\", operands);
- }
-
- if (highpart_unknown || lowpart_unknown)
- CC_STATUS_INIT;
- else if (highpart_zero == 0 && lowpart_zero == 0)
- CC_STATUS_INIT;
-
- return \"\";
-}")
-
-(define_insn "*andhi3_gen"
- [(set (match_operand:HI 0 "register_operand" "=d,d,!*A")
- (and:HI (match_operand:HI 1 "splitable_operand" "%0,0,0")
- (match_operand:HI 2 "splitable_operand" "mi,!u*A,!um*Ai")))]
- ""
- "*
-{
- if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
- return \"#\";
-
- CC_STATUS_INIT;
- return \"anda\\t%h2\\n\\tandb\\t%b2\";
-}")
-
-(define_expand "andqi3"
- [(set (match_operand:QI 0 "register_operand" "")
- (and:QI (match_operand:QI 1 "register_operand" "")
- (match_operand:QI 2 "general_operand" "")))]
- ""
- "")
-
-(define_insn "*andqi3_mem"
- [(set (match_operand:QI 0 "memory_operand" "=R,Q")
- (and:QI (match_dup 0)
- (match_operand:QI 1 "const_int_operand" "i,i")))
- (clobber (match_scratch:HI 2 "=X,xy"))]
- "TARGET_RELAX && !TARGET_M6812"
- "*
-{
- int val = INTVAL (operands[1]) & 0x0FF;
-
- if (val == 0x0ff)
- {
- cc_status = cc_prev_status;
- return \"\";
- }
-
- /* The bclr instruction uses an inverted mask. */
- operands[1] = GEN_INT ((~val) & 0x0FF);
-
- /* When destination is a global variable, generate a .relax instruction
- and load the address in the clobber register. That load can be
- eliminated by the linker if the address is in page0. */
- if (which_alternative == 1)
- {
- rtx ops[3];
-
- ops[0] = operands[2];
- ops[1] = XEXP (operands[0], 0);
- ops[2] = gen_label_rtx ();
- output_asm_insn (\".relax\\t%l2\", ops);
- m68hc11_gen_movhi (insn, ops);
- output_asm_insn (\"bclr\\t0,%2, %1\", operands);
- (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
- CODE_LABEL_NUMBER (ops[2]));
- return \"\";
- }
- return \"bclr\\t%b0, %1\";
-}")
-
-(define_insn "*andqi3_const"
- [(set (match_operand:QI 0 "reg_or_some_mem_operand" "=R,d,?*A*q")
- (and:QI (match_operand:QI 1 "reg_or_some_mem_operand" "%0,0,0")
- (match_operand:QI 2 "const_int_operand" "")))]
- ""
- "*
-{
- int val = INTVAL (operands[2]) & 0x0FF;
-
- if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
- return \"#\";
-
- if (val == 0x0ff)
- {
- cc_status = cc_prev_status;
- return \"\";
- }
- if (!H_REG_P (operands[0]))
- {
- rtx ops[2];
-
- ops[0] = operands[0];
- ops[1] = GEN_INT ((~val) & 0x0FF);
- output_asm_insn (\"bclr\\t%b0, %b1\", ops);
- return \"\";
- }
- if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
- return \"andb\\t%b2\";
- else if (DA_REG_P (operands[0]))
- return \"anda\\t%b2\";
- else
- fatal_insn (\"Invalid operand in the instruction\", insn);
-}")
-
-(define_insn "*andqi3_gen"
- [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q")
- (and:QI (match_operand:QI 1 "general_operand" "%0,0,0,0,0,0")
- (match_operand:QI 2 "general_operand" "mi,!*u,?*A,!*um,?*A*d,!*um*A")))]
- ""
- "*
-{
- if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
- return \"#\";
-
- if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
- return \"andb\\t%b2\";
- else if (DA_REG_P (operands[0]))
- return \"anda\\t%b2\";
- else
- fatal_insn (\"Invalid operand in the instruction\", insn);
-}")
-
-;;--------------------------------------------------------------------
-;;- Bit set or instructions.
-;;--------------------------------------------------------------------
-
-(define_insn_and_split "iordi3"
- [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u")
- (ior:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu")
- (match_operand:DI 2 "general_operand" "imu,imu")))
- (clobber (match_scratch:HI 3 "=d,d"))]
- ""
- "#"
- "reload_completed"
- [(const_int 0)]
- "m68hc11_split_logical (SImode, IOR, operands);
- DONE;")
-
-(define_insn_and_split "iorsi3"
- [(set (match_operand:SI 0 "register_operand" "=D,!u")
- (ior:SI (match_operand:SI 1 "register_operand" "%0,0")
- (match_operand:SI 2 "general_operand" "Dimu,imu")))
- (clobber (match_scratch:HI 3 "=X,d"))]
- ""
- "#"
- "reload_completed"
- [(const_int 0)]
- "m68hc11_split_logical (HImode, IOR, operands);
- DONE;")
-
-(define_expand "iorhi3"
- [(set (match_operand:HI 0 "register_operand" "")
- (ior:HI (match_operand:HI 1 "register_operand" "")
- (match_operand:HI 2 "splitable_operand" "")))]
- ""
- "")
-
-(define_insn "*iorhi3_mem"
- [(set (match_operand:HI 0 "memory_operand" "=R,Q")
- (ior:HI (match_dup 0)
- (match_operand:HI 1 "const_int_operand" "")))
- (clobber (match_scratch:HI 2 "=X,xy"))]
- "TARGET_RELAX && !TARGET_M6812"
- "*
-{
- int val = INTVAL (operands[1]) & 0x0FFFF;
-
- if (val == 0)
- {
- cc_status = cc_prev_status;
- return \"\";
- }
- CC_STATUS_INIT;
- if (which_alternative == 1)
- {
- rtx ops[3];
-
- ops[0] = operands[2];
- ops[1] = XEXP (operands[0], 0);
- ops[2] = gen_label_rtx ();
- output_asm_insn (\".relax\\t%l2\", ops);
- m68hc11_gen_movhi (insn, ops);
- if ((val & 0x0FF) != 0)
- output_asm_insn (\"bset\\t1,%2, %b1\", operands);
-
- if ((val & 0x0FF00) != 0)
- output_asm_insn (\"bset\\t0,%2, %h1\", operands);
- (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
- CODE_LABEL_NUMBER (ops[2]));
- return \"\";
- }
-
- if ((val & 0x0FF) != 0)
- output_asm_insn (\"bset\\t%b0, %b1\", operands);
-
- if ((val & 0x0FF00) != 0)
- output_asm_insn (\"bset\\t%h0, %h1\", operands);
-
- return \"\";
-}")
-
-(define_insn "*iorhi3_const"
- [(set (match_operand:HI 0 "reg_or_some_mem_operand" "=R,d,?*A")
- (ior:HI (match_operand:HI 1 "reg_or_some_mem_operand" "%0,0,0")
- (match_operand:HI 2 "const_int_operand" "")))]
- ""
- "*
-{
- int val = INTVAL (operands[2]) & 0x0FFFF;
-
- if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
- return \"#\";
-
- if (val == 0)
- {
- cc_status = cc_prev_status;
- return \"\";
- }
-
- if ((val & 0x0FF) != 0)
- {
- if (!H_REG_P (operands[0]))
- output_asm_insn (\"bset\\t%b0, %b2\", operands);
- else
- output_asm_insn (\"orab\\t%b2\", operands);
- }
-
- if ((val & 0x0FF00) != 0)
- {
- if (!H_REG_P (operands[0]))
- output_asm_insn (\"bset\\t%h0, %h2\", operands);
- else
- output_asm_insn (\"oraa\\t%h2\", operands);
- }
-
- CC_STATUS_INIT;
- return \"\";
-}")
-
-(define_insn "*iorhi3_gen"
- [(set (match_operand:HI 0 "register_operand" "=d,d,!*A")
- (ior:HI (match_operand:HI 1 "splitable_operand" "%0,0,0")
- (match_operand:HI 2 "splitable_operand" "mi,!u*A,!um*Ai")))]
- ""
- "*
-{
- if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
- return \"#\";
-
- CC_STATUS_INIT;
- return \"oraa\\t%h2\\n\\torab\\t%b2\";
-}")
-
-(define_expand "iorqi3"
- [(set (match_operand:QI 0 "register_operand" "")
- (ior:QI (match_operand:QI 1 "register_operand" "")
- (match_operand:QI 2 "general_operand" "")))]
- ""
- "")
-
-(define_insn "*iorqi3_mem"
- [(set (match_operand:QI 0 "memory_operand" "=R,Q")
- (ior:QI (match_dup 0)
- (match_operand:QI 1 "const_int_operand" "")))
- (clobber (match_scratch:HI 2 "=X,xy"))]
- "TARGET_RELAX && !TARGET_M6812"
- "*
-{
- int val = INTVAL (operands[1]) & 0x0FF;
-
- if (val == 0)
- {
- cc_status = cc_prev_status;
- return \"\";
- }
- if (which_alternative == 1)
- {
- rtx ops[3];
-
- ops[0] = operands[2];
- ops[1] = XEXP (operands[0], 0);
- ops[2] = gen_label_rtx ();
- output_asm_insn (\".relax\\t%l2\", ops);
- m68hc11_gen_movhi (insn, ops);
- output_asm_insn (\"bset\\t0,%2, %1\", operands);
- (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
- CODE_LABEL_NUMBER (ops[2]));
- return \"\";
- }
- return \"bset\\t%b0, %1\";
-}")
-
-(define_insn "*iorqi3_const"
- [(set (match_operand:QI 0 "reg_or_some_mem_operand" "=R,d,?*A*q")
- (ior:QI (match_operand:QI 1 "reg_or_some_mem_operand" "%0,0,0")
- (match_operand:QI 2 "const_int_operand" "")))]
- ""
- "*
-{
- int val = INTVAL (operands[2]) & 0x0FF;
-
- if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
- return \"#\";
-
- if (val == 0)
- {
- cc_status = cc_prev_status;
- return \"\";
- }
- if (!H_REG_P (operands[0]))
- {
- return \"bset\\t%b0, %2\";
- }
-
- if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
- return \"orab\\t%b2\";
- else if (DA_REG_P (operands[0]))
- return \"oraa\\t%b2\";
- else
- fatal_insn (\"Invalid operand in the instruction\", insn);
-}")
-
-(define_insn "*iorqi3_gen"
- [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q")
- (ior:QI (match_operand:QI 1 "general_operand" "%0,0,0,0,0,0")
- (match_operand:QI 2 "general_operand" "mi,!*u,!*A,!*um,?*A*d,!*um*A")))]
- ""
- "*
-{
- if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
- return \"#\";
-
- if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
- return \"orab\\t%b2\";
- else if (DA_REG_P (operands[0]))
- return \"oraa\\t%b2\";
- else
- fatal_insn (\"Invalid operand in the instruction\", insn);
-}")
-
-
-;;--------------------------------------------------------------------
-;;- xor instructions.
-;;--------------------------------------------------------------------
-
-(define_insn_and_split "xordi3"
- [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u")
- (xor:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu")
- (match_operand:DI 2 "general_operand" "imu,imu")))
- (clobber (match_scratch:HI 3 "=d,d"))]
- ""
- "#"
- "reload_completed"
- [(const_int 0)]
- "m68hc11_split_logical (SImode, XOR, operands);
- DONE;")
-
-(define_insn_and_split "xorsi3"
- [(set (match_operand:SI 0 "register_operand" "=D,!u")
- (xor:SI (match_operand:SI 1 "register_operand" "%0,0")
- (match_operand:SI 2 "general_operand" "Dimu,imu")))
- (clobber (match_scratch:HI 3 "=X,d"))]
- ""
- "#"
- "reload_completed"
- [(const_int 0)]
- "m68hc11_split_logical (HImode, XOR, operands);
- DONE;")
-
-(define_insn "xorhi3"
- [(set (match_operand:HI 0 "register_operand" "=d,d,!*A")
- (xor:HI (match_operand:HI 1 "splitable_operand" "%0,0,0")
- (match_operand:HI 2 "splitable_operand" "im,!u*A,!ium*A")))]
- ""
- "*
-{
- if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
- return \"#\";
-
- if (GET_CODE (operands[2]) == CONST_INT)
- {
- int val = INTVAL (operands[2]) & 0x0FFFF;
-
- if (val == 0)
- {
- cc_status = cc_prev_status;
- return \"\";
- }
- if ((val & 0x0FF) != 0)
- {
- output_asm_insn (\"eorb\\t%b2\", operands);
- }
- else if ((val & 0x0FF) == 0x0FF)
- {
- output_asm_insn (\"comb\", operands);
- }
-
- if ((val & 0x0FF00) != 0)
- {
- output_asm_insn (\"eora\\t%h2\", operands);
- }
- else if ((val & 0x0FF00) == 0x0FF00)
- {
- output_asm_insn (\"coma\", operands);
- }
-
- CC_STATUS_INIT;
- return \"\";
- }
-
- CC_STATUS_INIT;
- return \"eora\\t%h2\\n\\teorb\\t%b2\";
-}")
-
-(define_insn "xorqi3"
- [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q")
- (xor:QI (match_operand:QI 1 "general_operand" "%0,0,0,0,0,0")
- (match_operand:QI 2 "general_operand" "im,!*u,!*A,!i*um,?*A*d,!i*um*A")))]
- ""
- "*
-{
- if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
- return \"#\";
-
- if (GET_CODE (operands[2]) == CONST_INT)
- {
- int val = INTVAL (operands[2]) & 0x0FF;
-
- if (val == 0)
- {
- cc_status = cc_prev_status;
- return \"\";
- }
- if (val == 0x0FF)
- {
- if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
- return \"comb\";
- else
- return \"coma\";
- }
- }
- if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
- return \"eorb\\t%b2\";
- else if (DA_REG_P (operands[0]))
- return \"eora\\t%b2\";
- else
- fatal_insn (\"Invalid operand in the instruction\", insn);
-}")
-
-;;--------------------------------------------------------------------
-;;- Bit set or instructions.
-;;--------------------------------------------------------------------
-
-(define_insn_and_split "*logicalsi3_zexthi"
- [(set (match_operand:SI 0 "register_operand" "=D")
- (match_operator:SI 3 "m68hc11_logical_operator"
- [(zero_extend:SI
- (match_operand:HI 1 "general_operand" "imudA"))
- (match_operand:SI 2 "general_operand" "Dimu")]))]
- ""
- "#"
- "reload_completed"
- [(set (reg:HI D_REGNUM) (match_dup 4))
- (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 5)]))
- (set (reg:HI X_REGNUM) (match_dup 6))]
- "PUT_MODE (operands[3], HImode);
- if (X_REG_P (operands[2]))
- {
- operands[5] = operands[1];
- /* Make all the (set (REG:x) (REG:y)) a nop set. */
- operands[4] = gen_rtx_REG (HImode, HARD_D_REGNUM);
- operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM);
- }
- else
- {
- operands[4] = operands[1];
- operands[5] = m68hc11_gen_lowpart (HImode, operands[2]);
- operands[6] = m68hc11_gen_highpart (HImode, operands[2]);
- }
- /* For an AND, make sure the high 16-bit part is cleared. */
- if (GET_CODE (operands[3]) == AND)
- {
- operands[6] = const0_rtx;
- }
- ")
-
-(define_insn_and_split "*logicalsi3_zextqi"
- [(set (match_operand:SI 0 "register_operand" "=D,D,D")
- (match_operator:SI 3 "m68hc11_logical_operator"
- [(zero_extend:SI
- (match_operand:QI 1 "general_operand" "d,*A,imu"))
- (match_operand:SI 2 "general_operand" "imu,imu,0")]))]
- ""
- "#"
- "z_replacement_completed == 2"
- [(set (reg:QI A_REGNUM) (match_dup 4))
- (set (reg:QI D_REGNUM) (match_dup 7))
- (set (reg:QI B_REGNUM) (match_op_dup 3 [(reg:QI B_REGNUM) (match_dup 5)]))
- (set (reg:HI X_REGNUM) (match_dup 6))]
- "PUT_MODE (operands[3], QImode);
- if (X_REG_P (operands[2]))
- {
- operands[5] = operands[1];
- /* Make all the (set (REG:x) (REG:y)) a nop set. */
- operands[4] = gen_rtx_REG (QImode, HARD_A_REGNUM);
- operands[7] = gen_rtx_REG (QImode, HARD_D_REGNUM);
- operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM);
- }
- else
- {
- operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
- operands[7] = operands[1];
- operands[5] = m68hc11_gen_lowpart (QImode, operands[4]);
- operands[4] = m68hc11_gen_highpart (QImode, operands[4]);
- operands[6] = m68hc11_gen_highpart (HImode, operands[2]);
- }
- /* For an AND, make sure the high 24-bit part is cleared. */
- if (GET_CODE (operands[3]) == AND)
- {
- operands[4] = const0_rtx;
- operands[6] = const0_rtx;
- }
- ")
-
-(define_insn_and_split "*logicalhi3_zexthi_ashift8"
- [(set (match_operand:HI 0 "register_operand" "=d")
- (match_operator:HI 3 "m68hc11_logical_operator"
- [(zero_extend:HI
- (match_operand:QI 1 "general_operand" "imud*A"))
- (ashift:HI
- (match_operand:HI 2 "general_operand" "imud*A")
- (const_int 8))]))]
- ""
- "#"
- "z_replacement_completed == 2"
- [(set (reg:QI A_REGNUM) (match_dup 4))
- (set (reg:QI B_REGNUM) (match_dup 5))]
- "
- if (GET_CODE (operands[3]) == AND)
- {
- emit_insn (gen_movhi (operands[0], const0_rtx));
- DONE;
- }
- else
- {
- operands[5] = operands[1];
- if (D_REG_P (operands[2]))
- {
- operands[4] = gen_rtx_REG (QImode, HARD_B_REGNUM);
- }
- else
- {
- operands[4] = m68hc11_gen_lowpart (QImode, operands[2]);
- }
- }
- ")
-
-(define_insn_and_split "*logicalhi3_zexthi"
- [(set (match_operand:HI 0 "register_operand" "=d,d")
- (match_operator:HI 3 "m68hc11_logical_operator"
- [(zero_extend:HI
- (match_operand:QI 1 "general_operand" "imd*A,?u"))
- (match_operand:HI 2 "general_operand" "dim,?dimu")]))]
- ""
- "#"
- "z_replacement_completed == 2"
- [(set (reg:QI B_REGNUM) (match_dup 6))
- (set (reg:QI A_REGNUM) (match_dup 4))
- (set (reg:QI B_REGNUM) (match_op_dup 3 [(reg:QI B_REGNUM) (match_dup 5)]))]
- "
- PUT_MODE (operands[3], QImode);
- if (D_REG_P (operands[2]))
- {
- operands[4] = gen_rtx_REG (QImode, HARD_A_REGNUM);
- operands[5] = operands[1];
- operands[6] = gen_rtx_REG (QImode, HARD_B_REGNUM);
- }
- else
- {
- operands[4] = m68hc11_gen_highpart (QImode, operands[2]);
- operands[5] = m68hc11_gen_lowpart (QImode, operands[2]);
- if (D_REG_P (operands[1]))
- operands[6] = gen_rtx_REG (QImode, HARD_B_REGNUM);
- else
- operands[6] = operands[1];
- }
- /* For an AND, make sure the high 8-bit part is cleared. */
- if (GET_CODE (operands[3]) == AND)
- {
- operands[4] = const0_rtx;
- }
- ")
-
-
-(define_insn_and_split "*logicalsi3_silshr16"
- [(set (match_operand:SI 0 "register_operand" "=D,D,D,?D")
- (match_operator:SI 3 "m68hc11_logical_operator"
- [(lshiftrt:SI
- (match_operand:SI 1 "general_operand" "uim,uim,0,0")
- (const_int 16))
- (match_operand:SI 2 "general_operand" "uim,0,uim,0")]))]
- ""
- "#"
- "reload_completed"
- [(set (reg:HI D_REGNUM) (match_dup 4))
- (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 5)]))
- (set (reg:HI X_REGNUM) (match_dup 6))]
- "operands[5] = m68hc11_gen_highpart (HImode, operands[1]);
- if (X_REG_P (operands[2]))
- {
- operands[4] = gen_rtx_REG (HImode, HARD_D_REGNUM);
- operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM);
- }
- else
- {
- operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
- operands[6] = m68hc11_gen_highpart (HImode, operands[2]);
- }
- PUT_MODE (operands[3], HImode);
-
- /* For an AND, make sure the high 16-bit part is cleared. */
- if (GET_CODE (operands[3]) == AND)
- {
- operands[6] = const0_rtx;
- }
-")
-
-(define_insn_and_split "*logicalsi3_silshl16"
- [(set (match_operand:SI 0 "register_operand" "=D,D")
- (match_operator:SI 3 "m68hc11_logical_operator"
- [(ashift:SI
- (match_operand:SI 1 "general_operand" "uim,?D")
- (const_int 16))
- (match_operand:SI 2 "general_operand" "0,0")]))]
- ""
- "#"
- "z_replacement_completed == 2"
- [(set (reg:HI X_REGNUM) (match_op_dup 3 [(reg:HI X_REGNUM) (match_dup 4)]))
- (set (reg:HI D_REGNUM) (match_dup 5))]
- "operands[4] = m68hc11_gen_lowpart (HImode, operands[1]);
- PUT_MODE (operands[3], HImode);
-
- if (GET_CODE (operands[3]) == AND)
- operands[5] = const0_rtx;
- else
- operands[5] = gen_rtx_REG (HImode, HARD_D_REGNUM);
- ")
-
-(define_insn_and_split "*logicalsi3_silshl16_zext"
- [(set (match_operand:SI 0 "register_operand" "=D,D,D")
- (match_operator:SI 3 "m68hc11_logical_operator"
- [(ashift:SI
- (zero_extend:SI
- (match_operand:HI 1 "general_operand" "uim,udA,!dA"))
- (const_int 16))
- (zero_extend:SI (match_operand:HI 2 "general_operand" "uidA,um,!dA"))]))]
- ""
- "#"
- ;; Must split before z register replacement
- "reload_completed"
- [(set (match_dup 4) (match_dup 5))
- (set (match_dup 6) (match_dup 7))]
- "
- /* set (X_REGNUM) (d), set (D_REGNUM) (1) */
- if (GET_CODE (operands[1]) == HARD_D_REGNUM
- && GET_CODE (operands[3]) != AND)
- {
- /* This particular case is too early to be split before
- Z register replacement because the cse-reg pass we do
- does not recognize the 'swap_areg'. It is ok to handle
- this case after. */
- if (z_replacement_completed != 2)
- {
- FAIL;
- }
- emit_move_insn (gen_rtx_REG (HImode, HARD_X_REGNUM), operands[2]);
- emit_insn (gen_swap_areg (gen_rtx_REG (HImode, HARD_D_REGNUM),
- gen_rtx_REG (HImode, HARD_X_REGNUM)));
- }
- operands[4] = gen_rtx_REG (HImode, HARD_D_REGNUM);
- operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM);
- operands[5] = operands[2];
- operands[7] = operands[1];
-
- if (GET_CODE (operands[3]) == AND)
- operands[5] = operands[7] = const0_rtx;
- ")
-
-;;--------------------------------------------------------------------
-;; 16-bit Arithmetic and logical operations on X and Y:
-;;
-;; PLUS MINUS AND IOR XOR ASHIFT ASHIFTRT LSHIFTRT ROTATE ROTATERT
-;;
-;; Operations on X or Y registers are split here. Instructions are
-;; changed into:
-;; - xgdx/xgdy instruction pattern,
-;; - The same operation on register D,
-;; - xgdx/xgdy instruction pattern.
-;; This should allow the peephole to merge consecutive xgdx/xgdy instructions.
-;; We also handle the case were the address register is used in both source
-;; operands, such as:
-;;
-;; (set (REG:HI X) (PLUS:HI (REG:HI X) (mem:HI (REG:HI X))))
-;; or
-;; (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X)))
-;;
-;;
-(define_split
- [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
- (match_operator:HI 3 "m68hc11_arith_operator"
- [(match_operand:HI 1 "hard_addr_reg_operand" "")
- (match_operand:HI 2 "general_operand" "")]))]
- "z_replacement_completed == 2
- /* If we are adding a small constant to X or Y, it's
- better to use one or several inx/iny instructions. */
- && !(GET_CODE (operands[3]) == PLUS
- && ((TARGET_M6812
- && (immediate_operand (operands[2], HImode)
- || hard_reg_operand (operands[2], HImode)))
- || (GET_CODE (operands[2]) == CONST_INT
- && INTVAL (operands[2]) >= -4
- && INTVAL (operands[2]) <= 4)))"
- [(set (match_dup 9) (match_dup 0))
- (set (match_dup 4) (match_dup 5))
- (set (match_dup 8) (match_dup 7))
- (set (match_dup 0) (match_dup 1))
- (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
- (set (match_dup 0) (reg:HI D_REGNUM))])
- (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 6)]))
- (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
- (set (match_dup 0) (reg:HI D_REGNUM))])]
- "
- operands[9] = operands[0];
- /* For 68HC12, push the value on the stack and do the operation
- with a pop. */
- if (TARGET_M6812
- && m68hc11_non_shift_operator (operands[3], HImode)
- && (H_REG_P (operands[2])
- || (m68hc11_small_indexed_indirect_p (operands[2], HImode)
- && reg_mentioned_p (operands[0], operands[2]))))
- {
- operands[4] = gen_rtx_MEM (HImode,
- gen_rtx_PRE_DEC (HImode,
- gen_rtx_REG (HImode, HARD_SP_REGNUM)));
- operands[6] = gen_rtx_MEM (HImode,
- gen_rtx_POST_INC (HImode,
- gen_rtx_REG (HImode, HARD_SP_REGNUM)));
- operands[5] = operands[2];
- operands[8] = operands[7] = operands[0];
- }
- /* Save the operand2 in a temporary location and use it. */
- else if ((H_REG_P (operands[2])
- || reg_mentioned_p (operands[0], operands[2]))
- && !(SP_REG_P (operands[2]) && GET_CODE (operands[3]) == PLUS))
- {
- if (GET_CODE (operands[3]) == MINUS
- && reg_mentioned_p (operands[0], operands[2]))
- {
- operands[9] = gen_rtx_MEM (HImode,
- gen_rtx_PRE_DEC (HImode,
- gen_rtx_REG (HImode, HARD_SP_REGNUM)));
- operands[1] = gen_rtx_MEM (HImode,
- gen_rtx_POST_INC (HImode,
- gen_rtx_REG (HImode, HARD_SP_REGNUM)));
- operands[8] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
- operands[4] = operands[7] = operands[0];
- operands[6] = operands[8];
- operands[5] = operands[2];
- }
- else
- {
- operands[4] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
- operands[6] = operands[4];
- if (!H_REG_P (operands[2]))
- {
- operands[5] = operands[0];
- operands[7] = operands[2];
- operands[8] = operands[0];
- }
- else
- {
- operands[5] = operands[2];
- operands[8] = operands[7] = operands[0];
- }
- }
- }
- else
- {
- operands[4] = operands[5] = operands[0];
- operands[6] = operands[2];
- operands[8] = operands[7] = operands[0];
- }
- ")
-
-(define_split
- [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
- (match_operator:HI 3 "m68hc11_arith_operator"
- [(match_operand:HI 1 "general_operand" "")
- (match_operand:HI 2 "general_operand" "")]))]
- "z_replacement_completed == 2
- /* If we are adding a small constant to X or Y, it's
- better to use one or several inx/iny instructions. */
- && !(GET_CODE (operands[3]) == PLUS
- && ((TARGET_M6812
- && (immediate_operand (operands[2], HImode)
- || hard_reg_operand (operands[2], HImode)))
- || (GET_CODE (operands[2]) == CONST_INT
- && INTVAL (operands[2]) >= -4
- && INTVAL (operands[2]) <= 4)))"
- [(set (match_dup 0) (match_dup 1))
- (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
- (set (match_dup 0) (reg:HI D_REGNUM))])
- (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 2)]))
- (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
- (set (match_dup 0) (reg:HI D_REGNUM))])]
- "
- ")
-
-;;
-;; Next split handles the logical operations on D register with
-;; another hard register for the second operand. For this, we
-;; have to save the second operand in a scratch location and use
-;; it instead. This must be supported because in some (rare) cases
-;; the second operand can come in a hard register and the reload
-;; pass doesn't know how to reload it in a memory location.
-;;
-;; PLUS MINUS AND IOR XOR
-;;
-;; The shift operators are special and must not appear here.
-;;
-(define_split
- [(set (match_operand:HI 0 "d_register_operand" "")
- (match_operator:HI 3 "m68hc11_non_shift_operator"
- [(match_operand:HI 1 "d_register_operand" "")
- (match_operand:HI 2 "hard_reg_operand" "")]))]
- "TARGET_M6811
- && z_replacement_completed == 2 && !SP_REG_P (operands[2])"
- [(set (match_dup 4) (match_dup 2))
- (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 4)]))]
- "operands[4] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);")
-
-;;
-;; For 68HC12, push the operand[2] value on the stack and do the
-;; logical/arithmetic operation with a pop.
-;;
-(define_split
- [(set (match_operand:HI 0 "d_register_operand" "")
- (match_operator:HI 3 "m68hc11_non_shift_operator"
- [(match_operand:HI 1 "d_register_operand" "")
- (match_operand:HI 2 "hard_reg_operand" "")]))]
- "TARGET_M6812
- && z_replacement_completed == 2 && !SP_REG_P (operands[2])"
- [(set (match_dup 4) (match_dup 2))
- (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 5)]))]
- "operands[4] = gen_rtx_MEM (HImode,
- gen_rtx_PRE_DEC (HImode,
- gen_rtx_REG (HImode, HARD_SP_REGNUM)));
- operands[5] = gen_rtx_MEM (HImode,
- gen_rtx_POST_INC (HImode,
- gen_rtx_REG (HImode, HARD_SP_REGNUM)));
- ")
-
-;;--------------------------------------------------------------------
-;; 16-bit Unary operations on X and Y:
-;;
-;; NOT NEG
-;;
-;; Operations on X or Y registers are split here. Instructions are
-;; changed into:
-;; - xgdx/xgdy instruction pattern,
-;; - The same operation on register D,
-;; - xgdx/xgdy instruction pattern.
-;; This should allow the peephole to merge consecutive xgdx/xgdy instructions.
-;; We also handle the case were the address register is used in both source
-;; operands, such as:
-;;
-;; (set (REG:HI X) (PLUS:HI (REG:HI X) (mem:HI (REG:HI X))))
-;; or
-;; (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X)))
-;;
-(define_split
- [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
- (match_operator:HI 2 "m68hc11_unary_operator"
- [(match_operand 1 "general_operand" "")]))]
- "z_replacement_completed == 2"
- [(set (match_dup 4) (match_dup 5))
- (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
- (set (match_dup 0) (reg:HI D_REGNUM))])
- (set (reg:HI D_REGNUM) (match_op_dup 2 [(match_dup 3)]))
- (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
- (set (match_dup 0) (reg:HI D_REGNUM))])]
- "
-{
- if ((H_REG_P (operands[1])
- && !rtx_equal_p (operands[0], operands[1]))
- || reg_mentioned_p (operands[0], operands[1]))
- {
- /* Move to the destination register, before the xgdx. */
- operands[4] = gen_rtx_REG (GET_MODE (operands[1]),
- REGNO (operands[0]));
- operands[5] = operands[1];
-
- /* Apply the operation on D. */
- operands[3] = gen_rtx_REG (GET_MODE (operands[1]), HARD_D_REGNUM);
- }
- else
- {
- /* Generate a copy to same register (nop). */
- operands[4] = operands[5] = operands[0];
- operands[3] = operands[1];
- }
-}")
-
-;;
-;; 8-bit operations on address registers.
-;;
-;; We have to take care that the address register is not used for the
-;; source of operand2. If operand2 is the D register, we have to save
-;; that register in a temporary location.
-;;
-;; AND OR XOR PLUS MINUS ASHIFT ASHIFTRT LSHIFTRT ROTATE ROTATERT
-;;
-(define_split
- [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
- (match_operator:QI 3 "m68hc11_arith_operator"
- [(match_operand:QI 1 "hard_addr_reg_operand" "")
- (match_operand:QI 2 "general_operand" "")]))]
- "z_replacement_completed == 2
- /* Reject a (plus:QI (reg:QI X) (const_int 1|-1)) because the
- incqi pattern generates a better code. */
- && !(GET_CODE (operands[3]) == PLUS
- && GET_CODE (operands[2]) == CONST_INT
- && (INTVAL (operands[2]) == 1 || INTVAL (operands[2]) == -1))"
- [(set (match_dup 5) (match_dup 6))
- (parallel [(set (reg:HI D_REGNUM) (match_dup 4))
- (set (match_dup 4) (reg:HI D_REGNUM))])
- (set (reg:QI D_REGNUM) (match_op_dup 3 [(reg:QI D_REGNUM) (match_dup 7)]))
- (parallel [(set (reg:HI D_REGNUM) (match_dup 4))
- (set (match_dup 4) (reg:HI D_REGNUM))])]
- "operands[4] = gen_rtx_REG (HImode, REGNO (operands[0]));
-
- /* For the second operand is a hard register or if the address
- register appears in the source, we have to save the operand[2]
- value in a temporary location and then use that temp.
- Otherwise, it's ok and we generate a (set (D) (D)) that
- will result in a nop. */
- if (H_REG_P (operands[2]))
- {
- operands[5] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
- operands[6] = gen_rtx_REG (HImode, REGNO (operands[2]));
- operands[7] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
- }
- else if (reg_mentioned_p (operands[0], operands[2]))
- {
- operands[5] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
- operands[6] = operands[2];
- operands[7] = operands[5];
- }
- else
- {
- operands[5] = operands[6] = gen_rtx_REG (QImode, HARD_D_REGNUM);
- operands[7] = operands[2];
- }
- ")
-
-;;
-;; Next split handles the logical operations on D register with
-;; another hard register for the second operand. For this, we
-;; have to save the second operand in a scratch location and use
-;; it instead. This must be supported because in some (rare) cases
-;; the second operand can come in a hard register and the reload
-;; pass doesn't know how to reload it in a memory location.
-;;
-;; PLUS MINUS AND IOR XOR
-;;
-;; The shift operators are special and must not appear here.
-;;
-(define_split
- [(set (match_operand:QI 0 "d_register_operand" "")
- (match_operator:QI 3 "m68hc11_non_shift_operator"
- [(match_operand:QI 1 "d_register_operand" "")
- (match_operand:QI 2 "hard_reg_operand" "")]))]
- "reload_completed"
- [(set (match_dup 5) (match_dup 6))
- (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 4)]))]
- "operands[4] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
- operands[5] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
- operands[6] = gen_rtx_REG (HImode, REGNO (operands[2]));")
-
-;;--------------------------------------------------------------------
-;; 8-bit Unary operations on X and Y:
-;;
-;; NOT NEG
-;;
-;; Operations on X or Y registers are split here. Instructions are
-;; changed into:
-;; - xgdx/xgdy instruction pattern,
-;; - The same operation on register D,
-;; - xgdx/xgdy instruction pattern.
-;; This should allow the peephole to merge consecutive xgdx/xgdy instructions.
-;; We also handle the case were the address register is used in both source
-;; operands, such as:
-;;
-;; (set (REG:HI X) (PLUS:HI (REG:HI X) (mem:HI (REG:HI X))))
-;; or
-;; (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X)))
-;;
-(define_split
- [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
- (match_operator:QI 2 "m68hc11_unary_operator"
- [(match_operand:QI 1 "general_operand" "")]))]
- "z_replacement_completed == 2"
- [(set (match_dup 4) (match_dup 5))
- (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
- (set (match_dup 3) (reg:HI D_REGNUM))])
- (set (reg:QI D_REGNUM) (match_op_dup 2 [(match_dup 6)]))
- (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
- (set (match_dup 3) (reg:HI D_REGNUM))])]
- "
-{
- operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));
- if ((H_REG_P (operands[1])
- && !rtx_equal_p (operands[0], operands[1]))
- || reg_mentioned_p (operands[0], operands[1]))
- {
- /* Move to the destination register, before the xgdx. */
- operands[4] = operands[0];
- operands[5] = operands[1];
-
- /* Apply the operation on D. */
- operands[6] = gen_rtx_REG (QImode, HARD_D_REGNUM);
- }
- else
- {
- operands[4] = operands[5] = operands[0];
- operands[6] = operands[1];
- }
-}")
-
-
-;;--------------------------------------------------------------------
-;;- Complements
-;;--------------------------------------------------------------------
-
-(define_expand "negdi2"
- [(set (match_operand:DI 0 "nonimmediate_operand" "")
- (neg:DI (match_operand:DI 1 "general_operand" "")))]
- ""
- "m68hc11_emit_libcall (\"__negdi2\", NEG, DImode, DImode, 2, operands);
- DONE;")
-
-
-(define_insn "negsi2"
- [(set (match_operand:SI 0 "register_operand" "=D")
- (neg:SI (match_operand:SI 1 "general_operand" "0")))]
- ""
- "*
-{
- rtx ops[1];
-
- CC_STATUS_INIT;
-
- /* With -Os or without -O, use a special library call. */
- if (optimize_size || optimize == 0)
- return \"bsr\\t___negsi2\";
-
- ops[0] = gen_label_rtx ();
-
- /* 32-bit complement and add 1. */
- output_asm_insn (\"comb\\n\\tcoma\\n\\txgdx\", operands);
- output_asm_insn (\"comb\\n\\tcoma\\n\\tinx\\n\\txgdx\", operands);
- output_asm_insn (\"bne\\t%l0\", ops);
- output_asm_insn (\"inx\", operands);
- (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
- return \"\";
-}")
-
-(define_insn "neghi2"
- [(set (match_operand:HI 0 "register_operand" "=d,d,x*y")
- (neg:HI (match_operand:HI 1 "general_operand" "0,!duim,0")))]
- ""
- "@
- coma\\n\\tcomb\\n\\taddd\\t#1
- clra\\n\\tclrb\\n\\tsubd\\t%1
- xgd%0\\n\\tcoma\\n\\tcomb\\n\\txgd%0\\n\\tin%0")
-
-(define_insn "negqi2"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m,!u,!*A")
- (neg:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0")))]
- ""
- "@
- negb
- neg\\t%b0
- neg\\t%b0
- #")
-
-;;
-;; - 32-bit complement. GCC knows how to translate them but providing a
-;; pattern generates better/smaller code.
-;;
-(define_expand "one_cmpldi2"
- [(set (match_operand:DI 0 "nonimmediate_operand" "")
- (not:DI (match_operand:DI 1 "general_operand" "")))]
- ""
- "m68hc11_emit_libcall (\"___notdi2\", NOT, DImode, DImode, 2, operands);
- DONE;")
-
-(define_insn "one_cmplsi2"
- [(set (match_operand:SI 0 "non_push_operand" "=D,m,!u")
- (not:SI (match_operand:SI 1 "general_operand" "0,m,0")))
- (clobber (match_scratch:HI 2 "=X,d,X"))]
- ""
- "@
- bsr\\t___one_cmplsi2
- #
- #")
-
-(define_insn "one_cmplhi2"
- [(set (match_operand:HI 0 "non_push_operand" "=d,m,*A,u")
- (not:HI (match_operand:HI 1 "general_operand" "0,0,0,0")))]
- ""
- "@
- comb\\n\\tcoma
- com\\t%b0\\n\\tcom\\t%h0
- #
- com\\t%b0\\n\\tcom\\t%h0")
-
-(define_insn "one_cmplqi2"
- [(set (match_operand:QI 0 "non_push_operand" "=d,m,*A,u")
- (not:QI (match_operand:QI 1 "general_operand" "0,0,0,0")))]
- ""
- "@
- comb
- com\\t%b0
- #
- com\\t%b0")
-
-(define_split /* "*one_cmplsi2" */
- [(set (match_operand:SI 0 "non_push_operand" "")
- (not:SI (match_dup 0)))
- (clobber (match_scratch:HI 1 ""))]
- "z_replacement_completed == 2
- && (!X_REG_P (operands[0]) || (optimize && optimize_size == 0))"
- [(set (match_dup 2) (not:HI (match_dup 2)))
- (set (match_dup 3) (not:HI (match_dup 3)))]
- "operands[2] = m68hc11_gen_lowpart (HImode, operands[0]);
- operands[3] = m68hc11_gen_highpart (HImode, operands[0]);")
-
-(define_split /* "*one_cmplsi2" */
- [(set (match_operand:SI 0 "non_push_operand" "")
- (not:SI (match_operand:SI 1 "non_push_operand" "")))
- (clobber (match_operand:HI 2 "d_register_operand" ""))]
- "z_replacement_completed == 2
- && (!X_REG_P (operands[0]) || (optimize && optimize_size == 0))"
- [(set (match_dup 2) (match_dup 3))
- (set (match_dup 2) (not:HI (match_dup 2)))
- (set (match_dup 4) (match_dup 2))
- (set (match_dup 2) (match_dup 5))
- (set (match_dup 2) (not:HI (match_dup 2)))
- (set (match_dup 6) (match_dup 2))]
- "operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);
- operands[5] = m68hc11_gen_highpart (HImode, operands[1]);
- operands[4] = m68hc11_gen_lowpart (HImode, operands[0]);
- operands[6] = m68hc11_gen_highpart (HImode, operands[0]);")
-
-;;--------------------------------------------------------------------
-;;- arithmetic shifts
-;;--------------------------------------------------------------------
-;;
-;; Provide some 64-bit shift patterns.
-(define_expand "ashldi3"
- [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
- (ashift:DI (match_operand:DI 1 "general_operand" "")
- (match_operand:HI 2 "general_operand" "")))
- (clobber (match_scratch:HI 3 ""))])]
- ""
- "
-{
- if (GET_CODE (operands[2]) != CONST_INT
- || (INTVAL (operands[2]) != 32 && INTVAL (operands[2]) != 1))
- {
- FAIL;
- }
-}")
-
-(define_insn_and_split "*ashldi3_const32"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=<,m,u")
- (ashift:DI (match_operand:DI 1 "general_operand" "umi,umi,umi")
- (const_int 32)))
- (clobber (match_scratch:HI 2 "=&A,d,d"))]
- ""
- "#"
- "reload_completed"
- [(const_int 0)]
- "/* Move the lowpart in the highpart first in case the shift
- is applied on the source. */
- if (IS_STACK_PUSH (operands[0]))
- {
- m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]),
- const0_rtx, operands[2]);
-
- /* Adjust first operand if it uses SP so that we take into
- account the above push. Can occur only for 68HC12. */
- if (reg_mentioned_p (gen_rtx_REG (HImode, HARD_SP_REGNUM),
- operands[1]))
- operands[1] = adjust_address (operands[1],
- GET_MODE (operands[0]), 4);
- }
- m68hc11_split_move (m68hc11_gen_highpart (SImode, operands[0]),
- m68hc11_gen_lowpart (SImode, operands[1]),
- operands[2]);
- if (!IS_STACK_PUSH (operands[0]))
- {
- m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]),
- const0_rtx, operands[2]);
- }
- DONE;")
-
-(define_insn_and_split "*ashldi3_const1"
- [(set (match_operand:DI 0 "non_push_operand" "=m,m,u")
- (ashift:DI (match_operand:DI 1 "general_operand" "mi,u,umi")
- (const_int 1)))
- (clobber (match_scratch:HI 2 "=d,d,d"))]
- ""
- "#"
- "z_replacement_completed == 2"
- [(set (match_dup 2) (match_dup 3))
- (set (match_dup 2) (ashift:HI (match_dup 2) (const_int 1)))
- (set (match_dup 4) (match_dup 2))
-
- (set (match_dup 2) (match_dup 5))
- (parallel [(set (match_dup 2)
- (rotate:HI (match_dup 2) (const_int 1)))
- (clobber (reg:HI CC_REGNUM))])
- (set (match_dup 6) (match_dup 2))
-
- (set (match_dup 2) (match_dup 7))
- (parallel [(set (match_dup 2)
- (rotate:HI (match_dup 2) (const_int 1)))
- (clobber (reg:HI CC_REGNUM))])
- (set (match_dup 8) (match_dup 2))
-
- (set (match_dup 2) (match_dup 9))
- (parallel [(set (match_dup 2)
- (rotate:HI (match_dup 2) (const_int 1)))
- (clobber (reg:HI CC_REGNUM))])
- (set (match_dup 10) (match_dup 2))]
- "operands[3] = m68hc11_gen_lowpart (SImode, operands[1]);
- operands[5] = m68hc11_gen_highpart (HImode, operands[3]);
- operands[3] = m68hc11_gen_lowpart (HImode, operands[3]);
-
- operands[4] = m68hc11_gen_lowpart (SImode, operands[0]);
- operands[6] = m68hc11_gen_highpart (HImode, operands[4]);
- operands[4] = m68hc11_gen_lowpart (HImode, operands[4]);
-
- operands[7] = m68hc11_gen_highpart (SImode, operands[1]);
- operands[9] = m68hc11_gen_highpart (HImode, operands[7]);
- operands[7] = m68hc11_gen_lowpart (HImode, operands[7]);
-
- operands[8] = m68hc11_gen_highpart (SImode, operands[0]);
- operands[10] = m68hc11_gen_highpart (HImode, operands[8]);
- operands[8] = m68hc11_gen_lowpart (HImode, operands[8]);")
-
-(define_insn "addsi_silshr16"
- [(set (match_operand:SI 0 "register_operand" "=D,D,!D")
- (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "!*uim,0,0")
- (const_int 16))
- (match_operand:SI 2 "general_operand" "0,m!*u,0")))]
- ""
- "#")
-
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "")
- (const_int 16))
- (match_operand:SI 2 "general_operand" "")))]
- "z_replacement_completed == 2 && !X_REG_P (operands[1])"
- [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3)))
- (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM)
- (const_int 0))
- (reg:HI CC_REGNUM)))]
- "operands[3] = m68hc11_gen_highpart (HImode, operands[1]);")
-
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "")
- (const_int 16))
- (match_operand:SI 2 "general_operand" "")))]
- "z_replacement_completed == 2 && X_REG_P (operands[1])"
- [(set (reg:HI D_REGNUM) (match_dup 5))
- (set (reg:HI X_REGNUM) (match_dup 3))
- (set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 4)))
- (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM)
- (const_int 0))
- (reg:HI CC_REGNUM)))]
- "operands[3] = m68hc11_gen_highpart (HImode, operands[2]);
- if (X_REG_P (operands[2]))
- {
- operands[4] = gen_rtx_REG (HImode, HARD_X_REGNUM);
- operands[5] = gen_rtx_REG (HImode, HARD_D_REGNUM);
- }
- else
- {
- operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
- operands[5] = gen_rtx_REG (HImode, HARD_X_REGNUM);
- }
-")
-
-(define_insn "addsi_ashift16"
- [(set (match_operand:SI 0 "register_operand" "=D")
- (plus:SI
- (mult:SI (match_operand:SI 2 "general_operand" "uim")
- (const_int 65536))
- (match_operand:SI 1 "general_operand" "0")))
- (clobber (match_scratch:HI 3 "=X"))]
- "0"
- "#")
-
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (plus:SI
- (mult:SI (match_operand:SI 2 "general_operand" "")
- (const_int 65536))
- (match_operand:SI 1 "general_operand" "")))
- (clobber (match_scratch:HI 3 "=X"))]
- "0 && reload_completed && z_replacement_completed == 2"
- [(set (reg:HI X_REGNUM) (plus:HI (reg:HI X_REGNUM) (match_dup 4)))]
- "
-{
- operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
-}")
-
-(define_insn_and_split "addsi_andshr16"
- [(set (match_operand:SI 0 "register_operand" "=D")
- (plus:SI (and:SI (match_operand:SI 1 "general_operand" "%uim")
- (const_int 65535))
- (match_operand:SI 2 "general_operand" "0")))]
- ""
- "#"
- "z_replacement_completed == 2"
- [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3)))
- (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM) (const_int 0)) (reg:HI CC_REGNUM)))]
- "operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);")
-
-;;
-;; 32-bit shifts are made by a small library routine that uses
-;; a specific passing convention for parameters (for efficiency reasons).
-;;
-;; [D + X] -> Value to be shifted
-;; Y -> Shift count
-;;
-;; The shift count is clobbered by the routine.
-;;
-(define_expand "ashlsi3"
- [(parallel
- [(set (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "general_operand" ""))
- (clobber (scratch:HI))])
- (parallel
- [(set (match_dup 0) (ashift:SI (match_dup 0)
- (match_operand:HI 2 "nonmemory_operand" "")))
- (clobber (scratch:HI))])]
- ""
- "")
-
-(define_split
- [(set (match_operand:SI 0 "nonimmediate_operand" "")
- (ashift:SI (match_operand:SI 1 "general_operand" "")
- (const_int 16)))
- (clobber (match_scratch:HI 3 ""))]
- ""
- [(set (match_dup 2) (match_dup 3))
- (set (match_dup 4) (const_int 0))]
- "operands[2] = m68hc11_gen_highpart (HImode, operands[0]);
- operands[4] = m68hc11_gen_lowpart (HImode, operands[0]);
- operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);")
-
-(define_insn "*ashlsi3_const16"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=D,m,*u")
- (ashift:SI (match_operand:SI 1 "general_operand" "Duim,D,D")
- (const_int 16)))
- (clobber (match_scratch:HI 2 "=X,X,X"))]
- ""
- "#")
-
-(define_insn_and_split "*ashlsi3_const16_zexthi"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=D")
- (ashift:SI (zero_extend:HI
- (match_operand:HI 1 "general_operand" "duim*A"))
- (const_int 16)))
- (clobber (match_scratch:HI 2 "=X"))]
- ""
- "#"
- "reload_completed"
- [(set (reg:HI X_REGNUM) (match_dup 1))
- (set (reg:HI D_REGNUM) (const_int 0))]
- "")
-
-(define_insn "*ashlsi3_const1"
- [(set (match_operand:SI 0 "non_push_operand" "=D,D,D,m,*u,*u")
- (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0,m,*u,m,*u,m")
- (const_int 1)))
- (clobber (match_scratch:HI 2 "=X,X,X,&d,&d,&d"))]
- ""
- "*
-{
- CC_STATUS_INIT;
- if (X_REG_P (operands[1]))
- {
- return \"lsld\\n\\txgdx\\n\\trolb\\n\\trola\\n\\txgdx\";
- }
- else
- {
- rtx ops[2];
-
- ops[1] = m68hc11_gen_lowpart (HImode, operands[1]);
- ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
- m68hc11_gen_movhi (insn, ops);
- output_asm_insn (\"lsld\", ops);
- if (!X_REG_P (operands[0]))
- {
- ops[1] = ops[0];
- ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
- m68hc11_gen_movhi (insn, ops);
- ops[0] = ops[1];
- ops[1] = m68hc11_gen_highpart (HImode, operands[1]);
- m68hc11_gen_movhi (insn, ops);
- }
- else
- {
- /* Load the high part in X in case the source operand
- uses X as a memory pointer. */
- ops[0] = gen_rtx_REG (HImode, HARD_X_REGNUM);
- ops[1] = m68hc11_gen_highpart (HImode, operands[1]);
- m68hc11_gen_movhi (insn, ops);
- output_asm_insn (\"xgdx\", ops);
- }
- output_asm_insn (\"rolb\", ops);
- output_asm_insn (\"rola\", ops);
- if (!X_REG_P (operands[0]))
- {
- ops[1] = ops[0];
- ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
- m68hc11_gen_movhi (insn, ops);
- }
- else
- {
- output_asm_insn (\"xgdx\", ops);
- }
- return \"\";
- }
-}")
-
-(define_insn "*ashlsi3_const"
- [(set (match_operand:SI 0 "register_operand" "+D")
- (ashift:SI (match_dup 0)
- (match_operand:HI 1 "const_int_operand" "")))
- (clobber (match_scratch:HI 2 "=y"))]
- "TARGET_M6811 /* See *ashlsi3 note. */"
- "*
-{
- CC_STATUS_INIT;
- return \"ldy\\t%1\\n\\tbsr\\t___ashlsi3\";
-}")
-
-(define_insn "*ashlsi3"
- [(set (match_operand:SI 0 "register_operand" "+D,D")
- (ashift:SI (match_dup 0)
- (match_operand:HI 1 "general_operand" "y,mi")))
- (clobber (match_scratch:HI 2 "=1,X"))]
- ""
- "*
-{
- CC_STATUS_INIT;
-
- /* There is a reload problem if we don't accept 'm' for the shift value.
- A RELOAD_OTHER reload can be generated for operand 0 (class A_REGS)
- and this conflicts with all reloads. Since X, Y, Z are used there
- is not enough register in class A_REGS.
-
- Assuming that 'operands[1]' does not refer to the stack (which
- is true for 68hc11 only, we save temporary the value of Y.
-
- For 68HC12 we must also accept a constant because Z register is
- disabled when compiling with -fomit-frame-pointer. We can come up
- with a reload problem and the *lshrsi3_const pattern was disabled
- for that reason. */
- if (!Y_REG_P (operands[2]))
- {
- rtx ops[1];
- int y_dead = dead_register_here (insn, iy_reg);
-
- ops[0] = operands[1];
- if (y_dead == 0)
- {
- output_asm_insn (\"pshy\", operands);
- if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
- ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2);
- }
- output_asm_insn (\"ldy\\t%0\", ops);
- output_asm_insn (\"bsr\\t___ashlsi3\", operands);
- return y_dead == 0 ? \"puly\" : \"\";
- }
- return \"bsr\\t___ashlsi3\";
-}")
-
-(define_expand "ashlhi3"
- [(set (match_operand:HI 0 "register_operand" "")
- (ashift:HI (match_operand:HI 1 "register_operand" "")
- (match_operand:HI 2 "general_operand" "")))]
- ""
- "
-{
- if (GET_CODE (operands[2]) != CONST_INT)
- {
- rtx scratch = gen_reg_rtx (HImode);
- emit_move_insn (scratch, operands[2]);
- emit_insn (gen_rtx_PARALLEL (VOIDmode,
- gen_rtvec (2, gen_rtx_SET (VOIDmode,
- operand0,
- gen_rtx_ASHIFT (HImode,
- operand1, scratch)),
- gen_rtx_CLOBBER (VOIDmode, scratch))));
- DONE;
- }
-}")
-
-(define_insn "*ashlhi3_const1"
- [(set (match_operand:HI 0 "non_push_operand" "=dm,!*u*A")
- (ashift:HI (match_operand:HI 1 "non_push_operand" "0,0")
- (const_int 1)))]
- ""
- "*
-{
- if (A_REG_P (operands[0]))
- return \"#\";
-
- if (D_REG_P (operands[0]))
- {
- return \"asld\";
- }
-
- output_asm_insn (\"asl\\t%b0\", operands);
- output_asm_insn (\"rol\\t%h0\", operands);
- CC_STATUS_INIT;
- return \"\";
-}")
-
-
-(define_insn "*ashlhi3_2"
- [(set (match_operand:HI 0 "register_operand" "=d,*x")
- (ashift:HI (match_operand:HI 1 "register_operand" "0,0")
- (match_operand:HI 2 "register_operand" "+x,+d")))
- (clobber (match_dup 2))]
- ""
- "*
-{
- if (A_REG_P (operands[0]))
- return \"#\";
-
- CC_STATUS_INIT;
- return \"bsr\\t___lshlhi3\";
-}")
-
-(define_insn "*ashlhi3"
- [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
- (ashift:HI (match_dup 0)
- (match_operand:HI 1 "register_operand" "+x")))
- (clobber (match_dup 1))]
- ""
- "*
-{
- CC_STATUS_INIT;
- return \"bsr\\t___lshlhi3\";
-}")
-
-(define_insn "*ashlhi3"
- [(set (match_operand:HI 0 "register_operand" "=d,!*A")
- (ashift:HI (match_operand:HI 1 "register_operand" "0,0")
- (match_operand:HI 2 "const_int_operand" "")))]
- ""
- "*
-{
- int i;
-
- if (A_REG_P (operands[0]))
- return \"#\";
-
- i = INTVAL (operands[2]);
- if (i >= 8)
- {
- CC_STATUS_INIT;
- output_asm_insn (\"tba\", operands);
- if (i == 15)
- {
- output_asm_insn (\"rora\", operands);
- output_asm_insn (\"anda\\t#0\", operands);
- output_asm_insn (\"rora\", operands);
- }
- else
- while (i != 8 )
- {
- output_asm_insn (\"asla\", operands);
- i--;
- }
- return \"clrb\";
- }
- for (i = 0; i < INTVAL (operands[2]) - 1; i++)
- {
- output_asm_insn (\"asld\", operands);
- }
- return \"asld\";
-}")
-
-(define_expand "ashlqi3"
- [(set (match_operand:QI 0 "register_operand" "")
- (ashift:QI (match_operand:QI 1 "register_operand" "")
- (match_operand:QI 2 "general_operand" "")))]
- ""
- "")
-
-(define_insn "*ashlqi3_const1"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m,!u,!*q,!*A")
- (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0,0")
- (const_int 1)))]
- ""
- "@
- aslb
- asl\\t%b0
- asl\\t%b0
- asl%0
- #")
-
-(define_insn "*ashlqi3_const"
- [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
- (ashift:QI (match_operand:QI 1 "register_operand" "0,0,0")
- (match_operand:QI 2 "const_int_operand" "")))]
- ""
- "*
-{
- int i;
- const char* insn_code;
-
- if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
- insn_code = \"aslb\";
- else if (DA_REG_P (operands[0]))
- insn_code = \"asla\";
- else
- return \"#\";
-
- i = INTVAL (operands[2]);
- if (i >= 8)
- {
- if (DA_REG_P (operands[0]))
- return \"clra\";
- else
- return \"clrb\";
- }
- else if (i == 7)
- {
- if (DA_REG_P (operands[0]))
- {
- output_asm_insn (\"rora\", operands);
- output_asm_insn (\"ldaa\\t#0\", operands);
- return \"rora\";
- }
- else
- {
- output_asm_insn (\"rorb\", operands);
- output_asm_insn (\"ldab\\t#0\", operands);
- return \"rorb\";
- }
- }
- else if (i == 6)
- {
- if (DA_REG_P (operands[0]))
- {
- output_asm_insn (\"rora\", operands);
- output_asm_insn (\"rora\", operands);
- output_asm_insn (\"rora\", operands);
- return \"anda\\t#0xC0\";
- }
- else
- {
- output_asm_insn (\"rorb\", operands);
- output_asm_insn (\"rorb\", operands);
- output_asm_insn (\"rorb\", operands);
- return \"andb\\t#0xC0\";
- }
- }
- while (--i >= 0)
- {
- output_asm_insn (insn_code, operands);
- }
- return \"\";
-}")
-
-(define_insn "*ashlqi3"
- [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
- (ashift:QI (match_operand:QI 1 "register_operand" "0,0,0")
- (match_operand:QI 2 "nonimmediate_operand"
- "m*u*d*A,m*u*d*A,m*u")))]
- ""
- "*
-{
- rtx ops[2];
-
- if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0]))
- return \"#\";
-
- ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
- ops[1] = operands[2];
- m68hc11_gen_movqi (insn, ops);
-
- CC_STATUS_INIT;
- return \"bsr\\t___lshlqi3\";
-}")
-
-(define_expand "ashrhi3"
- [(set (match_operand:HI 0 "register_operand" "")
- (ashiftrt:HI (match_operand:HI 1 "register_operand" "")
- (match_operand:HI 2 "general_operand" "")))]
- ""
- "
-{
- if (GET_CODE (operands[2]) != CONST_INT)
- {
- rtx scratch = gen_reg_rtx (HImode);
-
- emit_move_insn (scratch, operands[2]);
- emit_insn (gen_rtx_PARALLEL (VOIDmode,
- gen_rtvec (2, gen_rtx_SET (VOIDmode,
- operand0,
- gen_rtx_ASHIFTRT (HImode,
- operand1, scratch)),
- gen_rtx_CLOBBER (VOIDmode, scratch))));
- DONE;
- }
-}")
-
-(define_insn "*ashrhi3_const1"
- [(set (match_operand:HI 0 "non_push_operand" "=dm,!*u*A")
- (ashiftrt:HI (match_operand:HI 1 "non_push_operand" "0,0")
- (const_int 1)))]
- ""
- "*
-{
- if (A_REG_P (operands[0]))
- return \"#\";
-
- CC_STATUS_INIT;
- if (D_REG_P (operands[0]))
- {
- return \"asra\\n\\trorb\";
- }
-
- output_asm_insn (\"asr\\t%h0\", operands);
- output_asm_insn (\"ror\\t%b0\", operands);
- return \"\";
-}")
-
-
-(define_insn "*ashrhi3_const"
- [(set (match_operand:HI 0 "register_operand" "=d,!*A")
- (ashiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
- (match_operand:HI 2 "const_int_operand" "")))]
- ""
- "*
-{
- rtx ops[2];
- int val = INTVAL (operands[2]);
-
- if (A_REG_P (operands[0]))
- return \"#\";
-
- if (val >= 15)
- {
- ops[0] = gen_label_rtx ();
-
- output_asm_insn (\"clrb\", operands);
- output_asm_insn (\"rola\", operands);
-
- /* Clear A without clearing the carry flag. */
- output_asm_insn (\"tba\", operands);
- output_asm_insn (\"bcc\\t%l0\", ops);
- output_asm_insn (\"coma\", operands);
- output_asm_insn (\"comb\", operands);
-
- CC_STATUS_INIT;
- (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
- CODE_LABEL_NUMBER (ops[0]));
- return \"\";
- }
- if (val >= 8)
- {
- ops[0] = gen_label_rtx ();
-
- output_asm_insn (\"tab\", operands);
- output_asm_insn (\"clra\", operands);
- output_asm_insn (\"tstb\", operands);
- output_asm_insn (\"bge\\t%l0\", ops);
- output_asm_insn (\"deca\", operands);
-
- (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
- CODE_LABEL_NUMBER (ops[0]));
-
- val -= 8;
-
- while (val > 0)
- {
- output_asm_insn (\"asrb\", operands);
- val--;
- }
- /* Status is ok. */
- return \"\";
- }
- if (val == 7)
- {
- ops[0] = gen_label_rtx ();
- output_asm_insn (\"rolb\", operands);
- output_asm_insn (\"rola\", operands);
- output_asm_insn (\"tab\", operands);
- output_asm_insn (\"anda\\t#0\", operands);
- output_asm_insn (\"bcc\\t%l0\", ops);
- output_asm_insn (\"coma\", ops);
-
- (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
- CODE_LABEL_NUMBER (ops[0]));
- return \"\";
- }
- while (val > 0)
- {
- output_asm_insn (\"asra\", operands);
- output_asm_insn (\"rorb\", operands);
- val--;
- }
- CC_STATUS_INIT;
-
- return \"\";
-}")
-
-(define_insn "*ashrhi3"
- [(set (match_operand:HI 0 "register_operand" "=d,*x")
- (ashiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
- (match_operand:HI 2 "register_operand" "+x,+d")))
- (clobber (match_dup 2))]
- ""
- "*
-{
- if (A_REG_P (operands[0]))
- return \"#\";
-
- output_asm_insn (\"bsr\\t___ashrhi3\", operands);
- return \"\";
-}")
-
-(define_expand "ashrsi3"
- [(parallel
- [(set (match_dup 0) (match_operand:SI 1 "general_operand" ""))
- (clobber (scratch:HI))])
- (parallel
- [(set (match_operand:SI 0 "register_operand" "")
- (ashiftrt:SI (match_dup 0)
- (match_operand:HI 2 "general_operand" "")))
- (clobber (scratch:HI))])]
- ""
- "")
-
-(define_insn "*ashrsi3_const"
- [(set (match_operand:SI 0 "register_operand" "+D")
- (ashiftrt:SI (match_dup 0)
- (match_operand:HI 1 "const_int_operand" "")))
- (clobber (match_scratch:HI 2 "=y"))]
- "TARGET_M6811 /* See *ashrsi3 note. */"
- "*
-{
- CC_STATUS_INIT;
- return \"ldy\\t%1\\n\\tbsr\\t___ashrsi3\";
-}")
-
-(define_insn "*ashrsi3"
- [(set (match_operand:SI 0 "register_operand" "+D,D")
- (ashiftrt:SI (match_dup 0)
- (match_operand:HI 1 "general_operand" "y,mi")))
- (clobber (match_scratch:HI 2 "=1,X"))]
- ""
- "*
-{
- CC_STATUS_INIT;
- /* There is a reload problem if we don't accept 'm' for the shift value.
- A RELOAD_OTHER reload can be generated for operand 0 (class A_REGS)
- and this conflicts with all reloads. Since X, Y, Z are used there
- is not enough register in class A_REGS.
-
- Assuming that 'operands[1]' does not refer to the stack (which
- is true for 68hc11 only, we save temporary the value of Y.
-
- For 68HC12 we must also accept a constant because Z register is
- disabled when compiling with -fomit-frame-pointer. We can come up
- with a reload problem and the *lshrsi3_const pattern was disabled
- for that reason. */
- if (!Y_REG_P (operands[2]))
- {
- rtx ops[1];
- int y_dead = dead_register_here (insn, iy_reg);
-
- ops[0] = operands[1];
- if (y_dead == 0)
- {
- output_asm_insn (\"pshy\", operands);
- if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
- ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2);
- }
- output_asm_insn (\"ldy\\t%0\", ops);
- output_asm_insn (\"bsr\\t___ashrsi3\", operands);
- return y_dead == 0 ? \"puly\" : \"\";
- }
- return \"bsr\\t___ashrsi3\";
-}")
-
-(define_expand "ashrqi3"
- [(set (match_operand:QI 0 "register_operand" "")
- (ashiftrt:QI (match_operand:QI 1 "register_operand" "")
- (match_operand:QI 2 "general_operand" "")))]
- ""
- "")
-
-(define_insn "*ashrqi3_const1"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m,!u,!*q,!*A")
- (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0,0")
- (const_int 1)))]
- ""
- "@
- asrb
- asr\\t%b0
- asr\\t%b0
- asr%0
- #")
-
-(define_insn "*ashrqi3_const"
- [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
- (ashiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
- (match_operand:QI 2 "const_int_operand" "")))]
- ""
- "*
-{
- int i;
- const char* insn_code;
-
- if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
- insn_code = \"asrb\";
- else if (DA_REG_P (operands[0]))
- insn_code = \"asra\";
- else
- return \"#\";
-
- i = INTVAL (operands[2]);
- if (i > 8)
- i = 8;
- while (--i >= 0)
- {
- output_asm_insn (insn_code, operands);
- }
- return \"\";
-}")
-
-(define_insn "*ashrqi3"
- [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
- (ashiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
- (match_operand:QI 2 "nonimmediate_operand"
- "m*u*d*A,m*u*d*A,m*u")))]
- ""
- "*
-{
- rtx ops[2];
-
- if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0]))
- return \"#\";
-
- ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
- ops[1] = operands[2];
- m68hc11_gen_movqi (insn, ops);
-
- CC_STATUS_INIT;
- return \"bsr\\t___ashrqi3\";
-}")
-
-;;--------------------------------------------------------------------
-;; logical shift instructions
-;;--------------------------------------------------------------------
-(define_expand "lshrdi3"
- [(parallel [(set (match_operand:DI 0 "general_operand" "")
- (lshiftrt:DI (match_operand:DI 1 "general_operand" "")
- (match_operand:HI 2 "general_operand" "")))
- (clobber (match_scratch:HI 3 ""))])]
- ""
- "
-{
- if (GET_CODE (operands[2]) != CONST_INT
- || (INTVAL (operands[2]) != 32 && INTVAL (operands[2]) < 48
- && INTVAL (operands[2]) != 1))
- {
- FAIL;
- }
-}")
-
-(define_insn_and_split "*lshrdi3_const32"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=<,m,u")
- (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi,umi")
- (const_int 32)))
- (clobber (match_scratch:HI 2 "=&A,d,d"))]
- ""
- "#"
- "reload_completed"
- [(const_int 0)]
- "m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]),
- m68hc11_gen_highpart (SImode, operands[1]),
- operands[2]);
- m68hc11_split_move (m68hc11_gen_highpart (SImode, operands[0]),
- const0_rtx, operands[2]);
- DONE;")
-
-(define_insn "*lshrdi3_const63"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=m,u")
- (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi")
- (match_operand:DI 2 "const_int_operand" "")))
- (clobber (match_scratch:HI 3 "=d,d"))]
- "INTVAL (operands[2]) >= 48"
- "#")
-
-(define_split
- [(set (match_operand:DI 0 "nonimmediate_operand" "")
- (lshiftrt:DI (match_operand:DI 1 "general_operand" "")
- (match_operand:DI 2 "const_int_operand" "")))
- (clobber (match_scratch:HI 3 "=d"))]
- "z_replacement_completed && INTVAL (operands[2]) >= 56"
- [(set (reg:QI D_REGNUM) (match_dup 9))
- (set (reg:QI D_REGNUM) (lshiftrt:QI (reg:QI D_REGNUM) (match_dup 8)))
- (set (reg:HI D_REGNUM) (zero_extend:HI (reg:QI D_REGNUM)))
- (set (match_dup 4) (reg:HI D_REGNUM))
- (set (reg:QI D_REGNUM) (const_int 0))
- (set (match_dup 5) (reg:HI D_REGNUM))
- (set (match_dup 6) (reg:HI D_REGNUM))
- (set (match_dup 7) (reg:HI D_REGNUM))]
- "operands[8] = GEN_INT (INTVAL (operands[2]) - 56);
- operands[4] = m68hc11_gen_lowpart (SImode, operands[0]);
- operands[5] = m68hc11_gen_highpart (HImode, operands[4]);
- operands[4] = m68hc11_gen_lowpart (HImode, operands[4]);
-
- operands[9] = m68hc11_gen_highpart (SImode, operands[1]);
- operands[9] = m68hc11_gen_highpart (HImode, operands[9]);
- operands[9] = m68hc11_gen_highpart (QImode, operands[9]);
-
- operands[6] = m68hc11_gen_highpart (SImode, operands[0]);
- operands[7] = m68hc11_gen_highpart (HImode, operands[6]);
- operands[6] = m68hc11_gen_lowpart (HImode, operands[6]);")
-
-(define_split
- [(set (match_operand:DI 0 "nonimmediate_operand" "")
- (lshiftrt:DI (match_operand:DI 1 "general_operand" "")
- (match_operand:DI 2 "const_int_operand" "")))
- (clobber (match_scratch:HI 3 "=d"))]
- "z_replacement_completed && INTVAL (operands[2]) >= 48
- && INTVAL (operands[2]) < 56"
- [(set (reg:HI D_REGNUM) (match_dup 9))
- (set (reg:HI D_REGNUM) (lshiftrt:HI (reg:HI D_REGNUM) (match_dup 8)))
- (set (match_dup 4) (reg:HI D_REGNUM))
- (set (reg:HI D_REGNUM) (const_int 0))
- (set (match_dup 5) (reg:HI D_REGNUM))
- (set (match_dup 6) (reg:HI D_REGNUM))
- (set (match_dup 7) (reg:HI D_REGNUM))]
- "operands[8] = GEN_INT (INTVAL (operands[2]) - 48);
- operands[4] = m68hc11_gen_lowpart (SImode, operands[0]);
- operands[5] = m68hc11_gen_highpart (HImode, operands[4]);
- operands[4] = m68hc11_gen_lowpart (HImode, operands[4]);
-
- operands[9] = m68hc11_gen_highpart (SImode, operands[1]);
- operands[9] = m68hc11_gen_highpart (HImode, operands[1]);
- operands[6] = m68hc11_gen_highpart (SImode, operands[0]);
- operands[7] = m68hc11_gen_highpart (HImode, operands[6]);
- operands[6] = m68hc11_gen_lowpart (HImode, operands[6]);")
-
-(define_insn_and_split "*lshrdi_const1"
- [(set (match_operand:DI 0 "non_push_operand" "=m,u")
- (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi")
- (const_int 1)))
- (clobber (match_scratch:HI 2 "=d,d"))]
- ""
- "#"
- "z_replacement_completed == 2"
- [(set (match_dup 2) (match_dup 3))
- (set (match_dup 2) (lshiftrt:HI (match_dup 2) (const_int 1)))
- (set (match_dup 4) (match_dup 2))
-
- (set (match_dup 2) (match_dup 5))
- (parallel [(set (match_dup 2) (rotatert:HI (match_dup 2) (const_int 1)))
- (clobber (reg:HI CC_REGNUM))])
- (set (match_dup 6) (match_dup 2))
-
- (set (match_dup 2) (match_dup 7))
- (parallel [(set (match_dup 2) (rotatert:HI (match_dup 2) (const_int 1)))
- (clobber (reg:HI CC_REGNUM))])
- (set (match_dup 8) (match_dup 2))
-
- (set (match_dup 2) (match_dup 9))
- (parallel [(set (match_dup 2) (rotatert:HI (match_dup 2) (const_int 1)))
- (clobber (reg:HI CC_REGNUM))])
- (set (match_dup 10) (match_dup 2))]
- "operands[3] = m68hc11_gen_highpart (SImode, operands[1]);
- operands[5] = m68hc11_gen_lowpart (HImode, operands[3]);
- operands[3] = m68hc11_gen_highpart (HImode, operands[3]);
-
- operands[4] = m68hc11_gen_highpart (SImode, operands[0]);
- operands[6] = m68hc11_gen_lowpart (HImode, operands[4]);
- operands[4] = m68hc11_gen_highpart (HImode, operands[4]);
-
- operands[7] = m68hc11_gen_lowpart (SImode, operands[1]);
- operands[9] = m68hc11_gen_lowpart (HImode, operands[7]);
- operands[7] = m68hc11_gen_highpart (HImode, operands[7]);
-
- operands[8] = m68hc11_gen_lowpart (SImode, operands[0]);
- operands[10] = m68hc11_gen_lowpart (HImode, operands[8]);
- operands[8] = m68hc11_gen_highpart (HImode, operands[8]);")
-
-(define_expand "lshrsi3"
- [(parallel
- [(set (match_dup 0) (match_operand:SI 1 "general_operand" ""))
- (clobber (scratch:HI))])
- (parallel
- [(set (match_operand:SI 0 "register_operand" "")
- (lshiftrt:SI (match_dup 0)
- (match_operand:HI 2 "general_operand" "")))
- (clobber (scratch:HI))])]
- ""
- "")
-
-(define_split
- [(set (match_operand:SI 0 "non_push_operand" "")
- (lshiftrt:SI (match_operand:SI 1 "general_operand" "")
- (const_int 16)))
- (clobber (match_scratch:HI 3 ""))]
- "reload_completed && !(X_REG_P (operands[0]) && X_REG_P (operands[1]))"
- [(set (match_dup 2) (match_dup 3))
- (set (match_dup 4) (const_int 0))]
- "operands[4] = m68hc11_gen_highpart (HImode, operands[0]);
- operands[2] = m68hc11_gen_lowpart (HImode, operands[0]);
- operands[3] = m68hc11_gen_highpart (HImode, operands[1]);")
-
-(define_insn "*lshrsi3_const16"
- [(set (match_operand:SI 0 "non_push_operand" "=D,D,m,u")
- (lshiftrt:SI (match_operand:SI 1 "general_operand" "uim,0,D,D")
- (const_int 16)))
- (clobber (match_scratch:HI 2 "=X,X,X,X"))]
- ""
- "@
- #
- xgdx\\n\\tldx\\t#0
- #
- #")
-
-(define_insn "*lshrsi3_const1"
- [(set (match_operand:SI 0 "non_push_operand" "=D,D,D,m,*u,*u")
- (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0,m,*u,m,*u,m")
- (const_int 1)))
- (clobber (match_scratch:HI 2 "=X,X,X,&d,&d,&d"))]
- ""
- "*
-{
- CC_STATUS_INIT;
- if (X_REG_P (operands[1]))
- {
- return \"xgdx\\n\\tlsrd\\n\\txgdx\\n\\trora\\n\\trorb\";
- }
- else
- {
- rtx ops[2];
-
- ops[1] = m68hc11_gen_highpart (HImode, operands[1]);
- ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
- m68hc11_gen_movhi (insn, ops);
- output_asm_insn (\"lsrd\", ops);
- if (!X_REG_P (operands[0]))
- {
- ops[1] = ops[0];
- ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
- m68hc11_gen_movhi (insn, ops);
- ops[0] = ops[1];
- ops[1] = m68hc11_gen_lowpart (HImode, operands[1]);
- m68hc11_gen_movhi (insn, ops);
- }
- else
- {
- /* Load the lowpart in X in case the operands is some N,x. */
- ops[0] = gen_rtx_REG (HImode, HARD_X_REGNUM);
- ops[1] = m68hc11_gen_lowpart (HImode, operands[1]);
- m68hc11_gen_movhi (insn, ops);
- output_asm_insn (\"xgdx\", ops);
- }
- output_asm_insn (\"rora\", ops);
- output_asm_insn (\"rorb\", ops);
- if (!X_REG_P (operands[0]))
- {
- ops[1] = ops[0];
- ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
- m68hc11_gen_movhi (insn, ops);
- }
- return \"\";
- }
-}")
-
-(define_insn "*lshrsi3_const"
- [(set (match_operand:SI 0 "register_operand" "+D")
- (lshiftrt:SI (match_dup 0)
- (match_operand:HI 1 "const_int_operand" "")))
- (clobber (match_scratch:HI 2 "=y"))]
- "TARGET_M6811 /* See *lshrsi3 note. */"
- "*
-{
- CC_STATUS_INIT;
- return \"ldy\\t%1\\n\\tbsr\\t___lshrsi3\";
-}")
-
-(define_insn "*lshrsi3"
- [(set (match_operand:SI 0 "register_operand" "+D,D")
- (lshiftrt:SI (match_dup 0)
- (match_operand:HI 1 "general_operand" "y,mi")))
- (clobber (match_scratch:HI 2 "=1,X"))]
- ""
- "*
-{
- CC_STATUS_INIT;
- /* There is a reload problem if we don't accept 'm' for the shift value.
- A RELOAD_OTHER reload can be generated for operand 0 (class A_REGS)
- and this conflicts with all reloads. Since X, Y, Z are used there
- is not enough register in class A_REGS.
-
- Assuming that 'operands[1]' does not refer to the stack (which
- is true for 68hc11 only, we save temporary the value of Y.
-
- For 68HC12 we must also accept a constant because Z register is
- disabled when compiling with -fomit-frame-pointer. We can come up
- with a reload problem and the *lshrsi3_const pattern was disabled
- for that reason. */
- if (!Y_REG_P (operands[2]))
- {
- rtx ops[1];
- int y_dead = dead_register_here (insn, iy_reg);
-
- ops[0] = operands[1];
- if (y_dead == 0)
- {
- output_asm_insn (\"pshy\", operands);
- if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
- ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2);
- }
- output_asm_insn (\"ldy\\t%0\", ops);
- output_asm_insn (\"bsr\\t___lshrsi3\", operands);
- return y_dead == 0 ? \"puly\" : \"\";
- }
- return \"bsr\\t___lshrsi3\";
-}")
-
-(define_expand "lshrhi3"
- [(set (match_operand:HI 0 "register_operand" "")
- (lshiftrt:HI (match_operand:HI 1 "general_operand" "")
- (match_operand:HI 2 "general_operand" "")))]
- ""
- "
-{
- if (GET_CODE (operands[2]) != CONST_INT)
- {
- rtx scratch = gen_reg_rtx (HImode);
- operand1 = force_reg (HImode, operand1);
-
- emit_move_insn (scratch, operands[2]);
- emit_insn (gen_rtx_PARALLEL (VOIDmode,
- gen_rtvec (2, gen_rtx_SET (VOIDmode,
- operand0,
- gen_rtx_LSHIFTRT (HImode,
- operand1, scratch)),
- gen_rtx_CLOBBER (VOIDmode, scratch))));
- DONE;
- }
-}")
-
-(define_insn "lshrhi3_const1"
- [(set (match_operand:HI 0 "non_push_operand" "=dm,!*u*A")
- (lshiftrt:HI (match_operand:HI 1 "non_push_operand" "0,0")
- (const_int 1)))]
- ""
- "*
-{
- if (A_REG_P (operands[0]))
- return \"#\";
-
- if (D_REG_P (operands[0]))
- return \"lsrd\";
-
- CC_STATUS_INIT;
- return \"lsr\\t%h0\\n\\tror\\t%b0\";
-}")
-
-(define_insn "lshrhi3_const"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,!*A,!*A")
- (lshiftrt:HI (match_operand:HI 1 "general_operand" "dm*A,!u,dm,!u")
- (match_operand:HI 2 "const_int_operand" "i,i,i,i")))]
- ""
- "*
-{
- int val = INTVAL (operands[2]);
-
- if (A_REG_P (operands[0]))
- return \"#\";
-
- if (val >= 8)
- {
- if (val == 8)
- CC_STATUS_INIT;
-
- if (!H_REG_P (operands[1]))
- {
- output_asm_insn (\"clra\", operands);
- output_asm_insn (\"ldab\\t%h1\", operands);
- }
- else if (A_REG_P (operands[1]))
- {
- output_asm_insn (\"st%1\\t%t0\", operands);
- output_asm_insn (\"ldab\\t%t0\", operands);
- output_asm_insn (\"clra\", operands);
- }
- else
- {
- output_asm_insn (\"tab\", operands);
- output_asm_insn (\"clra\", operands);
- }
- val -= 8;
- switch (val)
- {
- case 7:
- output_asm_insn (\"rolb\", operands);
- output_asm_insn (\"tab\", operands);
- output_asm_insn (\"rolb\", operands);
- break;
-
- case 6:
- output_asm_insn (\"rolb\", operands);
- output_asm_insn (\"rolb\", operands);
- output_asm_insn (\"rolb\", operands);
- output_asm_insn (\"andb\\t#3\", operands);
- break;
-
- default:
- while (val > 0)
- {
- val --;
- output_asm_insn (\"lsrb\", operands);
- }
- break;
- }
- return \"\";
- }
-
- if (!D_REG_P (operands[1]))
- m68hc11_gen_movhi (insn, operands);
- switch (val)
- {
- case 7:
- output_asm_insn (\"rolb\", operands);
- output_asm_insn (\"tab\", operands);
- output_asm_insn (\"rolb\", operands);
- output_asm_insn (\"rola\", operands);
- output_asm_insn (\"rola\", operands);
- output_asm_insn (\"anda\\t#1\", operands);
- CC_STATUS_INIT;
- break;
-
- default:
- while (val > 0)
- {
- val --;
- output_asm_insn (\"lsrd\", operands);
- }
- }
- return \"\";
-}")
-
-(define_insn "*lshrhi3"
- [(set (match_operand:HI 0 "register_operand" "=d,*x")
- (lshiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
- (match_operand:HI 2 "register_operand" "+x,+d")))
- (clobber (match_dup 2))]
- ""
- "*
-{
- if (A_REG_P (operands[0]))
- return \"#\";
-
- return \"bsr\\t___lshrhi3\";
-}")
-
-(define_expand "lshrqi3"
- [(set (match_operand:QI 0 "register_operand" "")
- (lshiftrt:QI (match_operand:QI 1 "register_operand" "")
- (match_operand:QI 2 "general_operand" "")))]
- ""
- "")
-
-(define_insn "*lshrqi3_const1"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=m,d,!u,!*q,!*A")
- (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0,0")
- (const_int 1)))]
- ""
- "@
- lsr\\t%b0
- lsrb
- lsr\\t%b0
- lsr%0
- #")
-
-(define_insn "*lshrqi3_const"
- [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
- (lshiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
- (match_operand:QI 2 "const_int_operand" "")))]
- ""
- "*
-{
- int i;
- const char* insn_code;
-
- if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
- insn_code = \"lsrb\";
- else if (DA_REG_P (operands[0]))
- insn_code = \"lsra\";
- else
- return \"#\";
-
- i = INTVAL (operands[2]);
- if (i >= 8)
- {
- if (DA_REG_P (operands[0]))
- return \"clra\";
- else
- return \"clrb\";
- }
- else if (i == 7)
- {
- if (DA_REG_P (operands[0]))
- {
- output_asm_insn (\"rola\", operands);
- output_asm_insn (\"ldaa\\t#0\", operands);
- return \"rola\";
- }
- else
- {
- output_asm_insn (\"rolb\", operands);
- output_asm_insn (\"ldab\\t#0\", operands);
- return \"rolb\";
- }
- }
- else if (i == 6)
- {
- if (DA_REG_P (operands[0]))
- {
- output_asm_insn (\"rola\", operands);
- output_asm_insn (\"rola\", operands);
- output_asm_insn (\"rola\", operands);
- return \"anda\\t#3\";
- }
- else
- {
- output_asm_insn (\"rolb\", operands);
- output_asm_insn (\"rolb\", operands);
- output_asm_insn (\"rolb\", operands);
- return \"andb\\t#3\";
- }
- }
- while (--i >= 0)
- {
- output_asm_insn (insn_code, operands);
- }
- return \"\";
-}")
-
-(define_insn "*lshrqi3"
- [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
- (lshiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
- (match_operand:QI 2 "nonimmediate_operand"
- "m*u*d*A,m*u*d*A,m*u")))]
- ""
- "*
-{
- rtx ops[2];
-
- if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0]))
- return \"#\";
-
- CC_STATUS_INIT;
- ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
- ops[1] = operands[2];
- m68hc11_gen_movqi (insn, ops);
-
- if (!optimize || optimize_size)
- {
- return \"bsr\\t___lshrqi3\";
- }
-
- ops[0] = gen_label_rtx ();
- ops[1] = gen_label_rtx ();
- output_asm_insn (\"ble\\t%l1\", ops);
-
- (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
- CODE_LABEL_NUMBER (ops[0]));
-
- output_asm_insn (\"lsrb\", operands);
- output_asm_insn (\"deca\", operands);
- output_asm_insn (\"bne\\t%l0\", ops);
-
- (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
- CODE_LABEL_NUMBER (ops[1]));
- return \"\";
-}")
-
-(define_insn "*rotlqi3_with_carry"
- [(set (match_operand:QI 0 "register_operand" "=d,!q")
- (rotate:QI (match_operand:QI 1 "register_operand" "0,0")
- (reg:QI CC_REGNUM)))]
- ""
- "*
-{
- if (DA_REG_P (operands[0]))
- return \"rola\";
- else
- return \"rolb\";
-}")
-
-(define_insn "*rotlhi3_with_carry"
- [(set (match_operand:HI 0 "register_operand" "=d")
- (rotate:HI (match_operand:HI 1 "register_operand" "0")
- (const_int 1)))
- (clobber (reg:HI CC_REGNUM))]
- ""
- "*
-{
- CC_STATUS_INIT;
- return \"rolb\\n\\trola\";
-}")
-
-(define_insn "*rotrhi3_with_carry"
- [(set (match_operand:HI 0 "register_operand" "=d")
- (rotatert:HI (match_operand:HI 1 "register_operand" "0")
- (const_int 1)))
- (clobber (reg:HI CC_REGNUM))]
- ""
- "*
-{
- CC_STATUS_INIT;
- return \"rora\\n\\trorb\";
-}")
-
-(define_insn "rotlqi3"
- [(set (match_operand:QI 0 "register_operand" "=d,!q")
- (rotate:QI (match_operand:QI 1 "register_operand" "0,0")
- (match_operand:QI 2 "const_int_operand" "i,i")))]
- ""
- "*
-{
- m68hc11_gen_rotate (ROTATE, insn, operands);
- return \"\";
-}")
-
-(define_insn "rotrqi3"
- [(set (match_operand:QI 0 "register_operand" "=d,!q")
- (rotatert:QI (match_operand:QI 1 "register_operand" "0,0")
- (match_operand:QI 2 "const_int_operand" "i,i")))]
- ""
- "*
-{
- m68hc11_gen_rotate (ROTATERT, insn, operands);
- return \"\";
-}")
-
-(define_expand "rotlhi3"
- [(set (match_operand:HI 0 "register_operand" "")
- (rotate:HI (match_operand:HI 1 "register_operand" "")
- (match_operand:HI 2 "general_operand" "")))]
- ""
- "
-{
- if (GET_CODE (operands[2]) != CONST_INT)
- {
- rtx scratch = gen_reg_rtx (HImode);
- operand1 = force_reg (HImode, operand1);
-
- emit_move_insn (scratch, operands[2]);
- emit_insn (gen_rtx_PARALLEL (VOIDmode,
- gen_rtvec (2, gen_rtx_SET (VOIDmode,
- operand0,
- gen_rtx_ROTATE (HImode,
- operand1, scratch)),
- gen_rtx_CLOBBER (VOIDmode, scratch))));
- DONE;
- }
-}")
-
-(define_insn "rotlhi3_const"
- [(set (match_operand:HI 0 "register_operand" "=d")
- (rotate:HI (match_operand:HI 1 "register_operand" "0")
- (match_operand:HI 2 "const_int_operand" "i")))]
- ""
- "*
-{
- m68hc11_gen_rotate (ROTATE, insn, operands);
- return \"\";
-}")
-
-(define_insn "*rotlhi3"
- [(set (match_operand:HI 0 "register_operand" "=d,*x")
- (rotate:HI (match_operand:HI 1 "register_operand" "0,0")
- (match_operand:HI 2 "general_operand" "+x,+d")))
- (clobber (match_dup 2))]
- ""
- "*
-{
- if (A_REG_P (operands[0]))
- return \"#\";
-
- return \"bsr\\t___rotlhi3\";
-}")
-
-(define_expand "rotrhi3"
- [(set (match_operand:HI 0 "register_operand" "")
- (rotatert:HI (match_operand:HI 1 "general_operand" "")
- (match_operand:HI 2 "general_operand" "")))]
- ""
- "
-{
- if (GET_CODE (operands[2]) != CONST_INT)
- {
- rtx scratch = gen_reg_rtx (HImode);
- operand1 = force_reg (HImode, operand1);
-
- emit_move_insn (scratch, operands[2]);
- emit_insn (gen_rtx_PARALLEL (VOIDmode,
- gen_rtvec (2, gen_rtx_SET (VOIDmode,
- operand0,
- gen_rtx_ROTATERT (HImode,
- operand1, scratch)),
- gen_rtx_CLOBBER (VOIDmode, scratch))));
- DONE;
- }
-}")
-
-(define_insn "rotrhi3_const"
- [(set (match_operand:HI 0 "register_operand" "=d")
- (rotatert:HI (match_operand:HI 1 "register_operand" "0")
- (match_operand:HI 2 "const_int_operand" "i")))]
- ""
- "*
-{
- m68hc11_gen_rotate (ROTATERT, insn, operands);
- return \"\";
-}")
-
-(define_insn "*rotrhi3"
- [(set (match_operand:HI 0 "register_operand" "=d,*x")
- (rotatert:HI (match_operand:HI 1 "register_operand" "0,0")
- (match_operand:HI 2 "general_operand" "+x,+d")))
- (clobber (match_dup 2))]
- ""
- "*
-{
- if (A_REG_P (operands[0]))
- return \"#\";
-
- return \"bsr\\t___rotrhi3\";
-}")
-
-;; Split a shift operation on an address register in a shift
-;; on D_REGNUM.
-(define_split /* "*rotrhi3_addr" */
- [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
- (match_operator:HI 3 "m68hc11_shift_operator"
- [(match_operand:HI 1 "register_operand" "")
- (match_operand:HI 2 "register_operand" "")]))
- (clobber (match_dup 2))]
- "z_replacement_completed == 2"
- [(parallel [(set (reg:HI D_REGNUM) (match_dup 0))
- (set (match_dup 0) (reg:HI D_REGNUM))])
- (parallel [(set (reg:HI D_REGNUM)
- (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 0)]))
- (clobber (match_dup 0))])
- (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
- (set (match_dup 0) (reg:HI D_REGNUM))])]
- "")
-
-;;--------------------------------------------------------------------
-;;- 68HC12 Decrement/Increment and branch
-;;--------------------------------------------------------------------
-;; These patterns are used by loop optimization as well as peephole2
-;; They must handle reloading themselves and the scratch register
-;; is used for that. Even if we accept memory operand, we must not
-;; accept them on the predicate because it might create too many reloads.
-;; (specially on HC12 due to its auto-incdec addressing modes).
-;;
-(define_expand "decrement_and_branch_until_zero"
- [(parallel [(set (pc)
- (if_then_else
- (ne (plus:HI (match_operand:HI 0 "register_operand" "")
- (const_int 0))
- (const_int 1))
- (label_ref (match_operand 1 "" ""))
- (pc)))
- (set (match_dup 0)
- (plus:HI (match_dup 0)
- (const_int -1)))
- (clobber (match_scratch:HI 2 ""))])]
- "TARGET_M6812"
- "")
-
-(define_expand "doloop_end"
- [(use (match_operand 0 "" "")) ; loop pseudo
- (use (match_operand 1 "" "")) ; iterations; zero if unknown
- (use (match_operand 2 "" "")) ; max iterations
- (use (match_operand 3 "" "")) ; loop level
- (use (match_operand 4 "" ""))] ; label
- "TARGET_M6812"
- "
-{
- /* Reject non-constant loops as it generates bigger code due to
- the handling of the loop register. We can do better by using
- the peephole2 dbcc/ibcc patterns. */
- if (INTVAL (operands[1]) == 0)
- {
- FAIL;
- }
-
- /* Note that for xxx_dbcc_dec_yy the gen_rtx_NE is only used to pass
- the operator and its operands are not relevant. */
- if (GET_MODE (operands[0]) == HImode)
- {
- emit_jump_insn (gen_m68hc12_dbcc_dec_hi (operands[0],
- gen_rtx_NE (HImode,
- operands[0],
- const1_rtx),
- operands[4]));
- DONE;
- }
- if (GET_MODE (operands[0]) == QImode)
- {
- emit_jump_insn (gen_m68hc12_dbcc_dec_qi (operands[0],
- gen_rtx_NE (QImode,
- operands[0],
- const1_rtx),
- operands[4]));
- DONE;
- }
-
- FAIL;
-}")
-
-;; Decrement-and-branch insns.
-(define_insn "m68hc12_dbcc_dec_hi"
- [(set (pc)
- (if_then_else
- (match_operator 1 "m68hc11_eq_compare_operator"
- [(match_operand:HI 0 "register_operand" "+dxy,m*u*z")
- (const_int 1)])
- (label_ref (match_operand 2 "" ""))
- (pc)))
- (set (match_dup 0)
- (plus:HI (match_dup 0) (const_int -1)))
- (clobber (match_scratch:HI 3 "=X,dxy"))]
- "TARGET_M6812"
- "*
-{
- if (!H_REG_P (operands[0]))
- return \"#\";
-
- CC_STATUS_INIT;
- if (GET_CODE (operands[1]) == EQ)
- return \"dbeq\\t%0,%l2\";
- else
- return \"dbne\\t%0,%l2\";
-}")
-
-;; Decrement-and-branch insns.
-(define_insn "m68hc12_dbcc_inc_hi"
- [(set (pc)
- (if_then_else
- (match_operator 1 "m68hc11_eq_compare_operator"
- [(match_operand:HI 0 "register_operand" "+dxy,m*u*z")
- (const_int -1)])
- (label_ref (match_operand 2 "" ""))
- (pc)))
- (set (match_dup 0)
- (plus:HI (match_dup 0) (const_int 1)))
- (clobber (match_scratch:HI 3 "=X,dxy"))]
- "TARGET_M6812"
- "*
-{
- if (!H_REG_P (operands[0]))
- return \"#\";
-
- CC_STATUS_INIT;
- if (GET_CODE (operands[1]) == EQ)
- return \"ibeq\\t%0,%l2\";
- else
- return \"ibeq\\t%0,%l2\";
-}")
-
-;; Decrement-and-branch (QImode).
-(define_insn "m68hc12_dbcc_dec_qi"
- [(set (pc)
- (if_then_else
- (match_operator 1 "m68hc11_eq_compare_operator"
- [(match_operand:QI 0 "register_operand" "+d,m*u*A")
- (const_int 1)])
- (label_ref (match_operand 2 "" ""))
- (pc)))
- (set (match_dup 0)
- (plus:QI (match_dup 0) (const_int -1)))
- (clobber (match_scratch:QI 3 "=X,d"))]
- "TARGET_M6812"
- "*
-{
- if (!D_REG_P (operands[0]))
- return \"#\";
-
- CC_STATUS_INIT;
- if (GET_CODE (operands[1]) == EQ)
- return \"dbeq\\tb,%l2\";
- else
- return \"dbne\\tb,%l2\";
-}")
-
-;; Increment-and-branch (QImode).
-(define_insn "m68hc12_dbcc_inc_qi"
- [(set (pc)
- (if_then_else
- (match_operator 1 "m68hc11_eq_compare_operator"
- [(match_operand:QI 0 "register_operand" "+d,m*u*A")
- (const_int -1)])
- (label_ref (match_operand 2 "" ""))
- (pc)))
- (set (match_dup 0)
- (plus:QI (match_dup 0) (const_int 1)))
- (clobber (match_scratch:QI 3 "=X,d"))]
- "TARGET_M6812"
- "*
-{
- if (!D_REG_P (operands[0]))
- return \"#\";
-
- CC_STATUS_INIT;
- if (GET_CODE (operands[1]) == EQ)
- return \"ibeq\\tb,%l2\";
- else
- return \"ibeq\\tb,%l2\";
-}")
-
-;; Split the above to handle the case where operand 0 is in memory
-;; (a register that couldn't get a hard register)
-(define_split
- [(set (pc)
- (if_then_else
- (match_operator 3 "m68hc11_eq_compare_operator"
- [(match_operand:HI 0 "general_operand" "")
- (match_operand:HI 1 "const_int_operand" "")])
- (label_ref (match_operand 4 "" ""))
- (pc)))
- (set (match_dup 0)
- (plus:HI (match_dup 0) (match_operand 2 "const_int_operand" "")))
- (clobber (match_operand:HI 5 "hard_reg_operand" ""))]
- "TARGET_M6812 && reload_completed"
- [(set (match_dup 5) (match_dup 0))
- (set (match_dup 5) (plus:HI (match_dup 5) (match_dup 2)))
- (set (match_dup 0) (match_dup 5))
- (set (pc)
- (if_then_else (match_op_dup 3
- [(match_dup 5) (const_int 0)])
- (label_ref (match_dup 4)) (pc)))]
- "")
-
-;; Split the above to handle the case where operand 0 is in memory
-;; (a register that couldn't get a hard register)
-(define_split
- [(set (pc)
- (if_then_else
- (match_operator 3 "m68hc11_eq_compare_operator"
- [(match_operand:QI 0 "general_operand" "")
- (match_operand:QI 1 "const_int_operand" "")])
- (label_ref (match_operand 4 "" ""))
- (pc)))
- (set (match_dup 0)
- (plus:QI (match_dup 0) (match_operand 2 "const_int_operand" "")))
- (clobber (match_operand:QI 5 "hard_reg_operand" ""))]
- "TARGET_M6812 && reload_completed"
- [(set (match_dup 5) (match_dup 0))
- (set (match_dup 5) (plus:QI (match_dup 5) (match_dup 2)))
- (set (match_dup 0) (match_dup 5))
- (set (pc)
- (if_then_else (match_op_dup 3
- [(match_dup 5) (const_int 0)])
- (label_ref (match_dup 4)) (pc)))]
- "")
-
-;;--------------------------------------------------------------------
-;;- Jumps and transfers
-;;--------------------------------------------------------------------
-(define_insn "jump"
- [(set (pc)
- (label_ref (match_operand 0 "" "")))]
- ""
- "bra\\t%l0")
-
-(define_expand "cbranchsi4"
- [(set (cc0)
- (compare (match_operand:SI 1 "tst_operand" "")
- (match_operand:SI 2 "cmp_operand" "")))
- (set (pc)
- (if_then_else (match_operator 0 "ordered_comparison_operator"
- [(cc0) (const_int 0)])
- (label_ref (match_operand 3 "" ""))
- (pc)))]
- ""
- "
-{
- if (GET_CODE (operands[1]) == MEM && GET_CODE (operands[2]) == MEM)
- operands[1] = force_reg (SImode, operands[1]);
-
- m68hc11_expand_compare_and_branch (GET_CODE (operands[0]), operands[1],
- operands[2], operands[3]);
- DONE;
-}")
-
-(define_expand "cbranchhi4"
- [(set (cc0)
- (compare (match_operand:HI 1 "tst_operand" "")
- (match_operand:HI 2 "cmp_operand" "")))
- (set (pc)
- (if_then_else (match_operator 0 "ordered_comparison_operator"
- [(cc0) (const_int 0)])
- (label_ref (match_operand 3 "" ""))
- (pc)))]
- ""
- "
-{
- if (GET_CODE (operands[1]) == MEM && GET_CODE (operands[2]) == MEM)
- operands[1] = force_reg (HImode, operands[1]);
-
- m68hc11_expand_compare_and_branch (GET_CODE (operands[0]), operands[1],
- operands[2], operands[3]);
- DONE;
-}")
-
-(define_expand "cbranchqi4"
- [(set (cc0)
- (compare (match_operand:QI 1 "tst_operand" "")
- (match_operand:QI 2 "cmp_operand" "")))
- (set (pc)
- (if_then_else (match_operator 0 "ordered_comparison_operator"
- [(cc0) (const_int 0)])
- (label_ref (match_operand 3 "" ""))
- (pc)))]
- ""
- "
-{
- if (GET_CODE (operands[1]) == MEM && GET_CODE (operands[2]) == MEM)
- operands[1] = force_reg (QImode, operands[1]);
-
- m68hc11_expand_compare_and_branch (GET_CODE (operands[0]), operands[1],
- operands[2], operands[3]);
- DONE;
-}")
-
-
-;;
-;; Test and branch instructions for 68HC12 for EQ and NE.
-;; 'z' must not appear in the constraints because the z replacement
-;; pass does not know how to restore the replacement register.
-;;
-(define_insn "*tbeq"
- [(set (pc)
- (if_then_else (eq (match_operand:HI 0 "register_operand" "dxy")
- (const_int 0))
- (label_ref (match_operand 1 "" ""))
- (pc)))]
- "TARGET_M6812"
- "*
-{
- /* If the flags are already set correctly, use 'bne/beq' which are
- smaller and a little bit faster. This happens quite often due
- to reloading of operands[0]. In that case, flags are set correctly
- due to the load instruction. */
- if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
- || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
- return \"beq\\t%l1\";
- else
- return \"tbeq\\t%0,%l1\";
-}")
-
-(define_insn "*tbne"
- [(set (pc)
- (if_then_else (ne (match_operand:HI 0 "register_operand" "dxy")
- (const_int 0))
- (label_ref (match_operand 1 "" ""))
- (pc)))]
- "TARGET_M6812"
- "*
-{
- if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
- || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
- return \"bne\\t%l1\";
- else
- return \"tbne\\t%0,%l1\";
-}")
-
-;;
-;; Test and branch with 8-bit register. Register must be B (or A).
-;;
-(define_insn "*tbeq8"
- [(set (pc)
- (if_then_else (eq (match_operand:QI 0 "register_operand" "d")
- (const_int 0))
- (label_ref (match_operand 1 "" ""))
- (pc)))]
- "TARGET_M6812"
- "*
-{
- if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
- || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
- return \"beq\\t%l1\";
- else
- return \"tbeq\\tb,%l1\";
-}")
-
-(define_insn "*tbne8"
- [(set (pc)
- (if_then_else (ne (match_operand:QI 0 "register_operand" "d")
- (const_int 0))
- (label_ref (match_operand 1 "" ""))
- (pc)))]
- "TARGET_M6812"
- "*
-{
- if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
- || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
- return \"bne\\t%l1\";
- else
- return \"tbne\\tb,%l1\";
-}")
-
-(define_insn "*beq"
- [(set (pc)
- (if_then_else (eq (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "beq\\t%l0")
-
-(define_insn "*bne"
- [(set (pc)
- (if_then_else (ne (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "bne\\t%l0")
-
-(define_insn "*bgt"
- [(set (pc)
- (if_then_else (gt (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "bgt\\t%l0")
-
-(define_insn "*bgtu"
- [(set (pc)
- (if_then_else (gtu (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "bhi\\t%l0")
-
-(define_insn "*blt"
- [(set (pc)
- (if_then_else (lt (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "*
-{
- if (cc_prev_status.flags & CC_NO_OVERFLOW)
- return \"bmi\\t%l0\";
- else
- return \"blt\\t%l0\";
-}")
-
-(define_insn "*bltu"
- [(set (pc)
- (if_then_else (ltu (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "blo\\t%l0")
-
-(define_insn "*bge"
- [(set (pc)
- (if_then_else (ge (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "*
-{
- if (cc_prev_status.flags & CC_NO_OVERFLOW)
- return \"bpl\\t%l0\";
- else
- return \"bge\\t%l0\";
-}")
-
-(define_insn "*bgeu"
- [(set (pc)
- (if_then_else (geu (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "bhs\\t%l0")
-
-(define_insn "*ble"
- [(set (pc)
- (if_then_else (le (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "*
-{
- if (cc_prev_status.flags & CC_NO_OVERFLOW)
- return \"bmi\\t%l0\\n\\tbeq\\t%l0\";
- else
- return \"ble\\t%l0\";
-}")
-
-(define_insn "*bleu"
- [(set (pc)
- (if_then_else (leu (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "bls\\t%l0")
-
-;;--------------------------------------------------------------------
-;;- Negative test and branch
-;;--------------------------------------------------------------------
-(define_insn ""
- [(set (pc)
- (if_then_else (eq (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "bne\\t%l0")
-
-(define_insn ""
- [(set (pc)
- (if_then_else (ne (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "beq\\t%l0")
-
-(define_insn ""
- [(set (pc)
- (if_then_else (gt (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "*
-{
- if (cc_prev_status.flags & CC_NO_OVERFLOW)
- return \"bmi\\t%l0\\n\\tbeq\\t%l0\";
- else
- return \"ble\\t%l0\";
-}")
-
-(define_insn ""
- [(set (pc)
- (if_then_else (gtu (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "bls\\t%l0")
-
-(define_insn ""
- [(set (pc)
- (if_then_else (lt (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "*
-{
- if (cc_prev_status.flags & CC_NO_OVERFLOW)
- return \"bpl\\t%l0\";
- else
- return \"bge\\t%l0\";
-}")
-
-(define_insn ""
- [(set (pc)
- (if_then_else (ltu (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "bhs\\t%l0")
-
-(define_insn ""
- [(set (pc)
- (if_then_else (ge (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "*
-{
- if (cc_prev_status.flags & CC_NO_OVERFLOW)
- return \"bmi\\t%l0\";
- else
- return \"blt\\t%l0\";
-}")
-
-(define_insn ""
- [(set (pc)
- (if_then_else (geu (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "blo\\t%l0")
-
-(define_insn ""
- [(set (pc)
- (if_then_else (le (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "bgt\\t%l0")
-
-(define_insn ""
- [(set (pc)
- (if_then_else (leu (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "bhi\\t%l0")
-
-;;--------------------------------------------------------------------
-;;- Calls
-;;--------------------------------------------------------------------
-;;
-;;- Call a function that returns no value.
-(define_insn "call"
- [(call (match_operand:QI 0 "memory_operand" "m")
- (match_operand:SI 1 "general_operand" "g"))]
- ;; Operand 1 not really used on the m68hc11.
- ""
- "*
-{
- if (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
- {
- if (m68hc11_is_far_symbol (operands[0]))
- {
- if (TARGET_M6812)
- {
- output_asm_insn (\"call\\t%0\", operands);
- return \"\";
- }
- else
- {
- output_asm_insn (\"pshb\", operands);
- output_asm_insn (\"ldab\\t#%%page(%0)\", operands);
- output_asm_insn (\"ldy\\t#%%addr(%0)\", operands);
- return \"jsr\\t__call_a32\";
- }
- }
- if (m68hc11_is_trap_symbol (operands[0]))
- return \"swi\";
- else
- return \"bsr\\t%0\";
- }
- else
- {
- return \"jsr\\t%0\";
- }
-}")
-
-(define_insn "call_value"
- [(set (match_operand 0 "" "=g")
- (call (match_operand:QI 1 "memory_operand" "m")
- (match_operand:SI 2 "general_operand" "g")))]
- ""
- "*
-{
- if (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
- {
- if (m68hc11_is_far_symbol (operands[1]))
- {
- if (TARGET_M6812)
- {
- output_asm_insn (\"call\\t%1\", operands);
- return \"\";
- }
- else
- {
- output_asm_insn (\"pshb\", operands);
- output_asm_insn (\"ldab\\t#%%page(%1)\", operands);
- output_asm_insn (\"ldy\\t#%%addr(%1)\", operands);
- return \"jsr\\t__call_a32\";
- }
- }
- if (m68hc11_is_trap_symbol (operands[1]))
- return \"swi\";
- else
- return \"bsr\\t%1\";
- }
- else
- {
- return \"jsr\\t%1\";
- }
-}")
-
-;; Call subroutine returning any type.
-
-(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));
-
- 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")
-
-(define_expand "prologue"
- [(const_int 0)]
- ""
- "
-{
- expand_prologue ();
- DONE;
-}")
-
-(define_expand "epilogue"
- [(return)]
- ""
- "
-{
- expand_epilogue ();
- DONE;
-}")
-
-;; Used for frameless functions which save no regs and allocate no locals.
-(define_expand "return"
- [(return)]
- "reload_completed && m68hc11_total_frame_size () == 0"
- "
-{
- int ret_size = 0;
-
- if (crtl->return_rtx)
- ret_size = GET_MODE_SIZE (GET_MODE (crtl->return_rtx));
-
- /* Emit use notes only when HAVE_return is true. */
- if (m68hc11_total_frame_size () != 0)
- ret_size = 0;
-
- if (ret_size && ret_size <= 2)
- {
- emit_jump_insn (gen_rtx_PARALLEL (VOIDmode,
- gen_rtvec (2, gen_rtx_RETURN (VOIDmode),
- gen_rtx_USE (VOIDmode,
- gen_rtx_REG (HImode, 1)))));
- DONE;
- }
- if (ret_size)
- {
- emit_jump_insn (gen_rtx_PARALLEL (VOIDmode,
- gen_rtvec (2, gen_rtx_RETURN (VOIDmode),
- gen_rtx_USE (VOIDmode,
- gen_rtx_REG (SImode, 0)))));
- DONE;
- }
-}")
-
-(define_insn "*return_void"
- [(return)]
- "reload_completed"
- "*
-{
- rtx next = next_active_insn (insn);
-
- if (next
- && GET_CODE (next) == JUMP_INSN
- && GET_CODE (PATTERN (next)) == RETURN)
- return \"\";
- if (current_function_interrupt || current_function_trap)
- return \"rti\";
- else if (!current_function_far)
- return \"rts\";
- else if (TARGET_M6812)
- return \"rtc\";
- else
- {
- int ret_size = 0;
-
- if (crtl->return_rtx)
- ret_size = GET_MODE_SIZE (GET_MODE (crtl->return_rtx));
-
- if (ret_size == 0)
- return \"jmp\\t__return_void\";
- if (ret_size <= 2)
- return \"jmp\\t__return_16\";
- if (ret_size <= 4)
- return \"jmp\\t__return_32\";
- return \"jmp\\t__return_16\";
- }
-}")
-
-(define_insn "*return_16bit"
- [(return)
- (use (reg:HI D_REGNUM))]
- "reload_completed && m68hc11_total_frame_size () == 0"
- "*
-{
- rtx next = next_active_insn (insn);
-
- if (next
- && GET_CODE (next) == JUMP_INSN
- && GET_CODE (PATTERN (next)) == RETURN)
- return \"\";
- if (current_function_interrupt || current_function_trap)
- return \"rti\";
- else if (!current_function_far)
- return \"rts\";
- else if (TARGET_M6812)
- return \"rtc\";
- else
- return \"jmp\\t__return_16\";
-}")
-
-(define_insn "*return_32bit"
- [(return)
- (use (reg:SI 0))]
- "reload_completed && m68hc11_total_frame_size () == 0"
- "*
-{
- rtx next = next_active_insn (insn);
-
- if (next
- && GET_CODE (next) == JUMP_INSN
- && GET_CODE (PATTERN (next)) == RETURN)
- return \"\";
- if (current_function_interrupt || current_function_trap)
- return \"rti\";
- else if (!current_function_far)
- return \"rts\";
- else if (TARGET_M6812)
- return \"rtc\";
- else
- return \"jmp\\t__return_32\";
-}")
-
-(define_insn "indirect_jump"
- [(set (pc) (match_operand:HI 0 "nonimmediate_operand" "xy"))]
- ""
- "jmp\\t0,%0")
-
-;;--------------------------------------------------------------------
-;;- Table jump
-;;--------------------------------------------------------------------
-;;
-;; Operand 0 is the address of the table element to use
-;; operand 1 is the CODE_LABEL for the table
-;;--------------------------------------------------------------------
-(define_expand "tablejump"
- [(parallel [(set (pc) (match_operand 0 "" ""))
- (use (label_ref (match_operand 1 "" "")))])]
- ""
- "")
-
-(define_insn "*jump_indirect"
- [(parallel [
- (set (pc) (match_operand:HI 0 "register_operand" "xy"))
- (use (label_ref (match_operand 1 "" "")))])]
- ""
- "jmp\\t0,%0")
-
-;;--------------------------------------------------------------------
-;;- Peepholes
-;;--------------------------------------------------------------------
-
-;;--------------------------------------------------------------------
-;;- 68HC12 dbcc/ibcc peepholes
-;;--------------------------------------------------------------------
-;;
-;; Replace: "addd #-1; bne L1" into "dbne d,L1"
-;; "addd #-1; beq L1" into "dbeq d,L1"
-;; "addd #1; bne L1" into "ibne d,L1"
-;; "addd #1; beq L1" into "ibeq d,L1"
-;;
-(define_peephole2
- [(set (match_operand:HI 0 "hard_reg_operand" "")
- (plus:HI (match_dup 0)
- (match_operand:HI 1 "const_int_operand" "")))
- (set (pc)
- (if_then_else (match_operator 2 "m68hc11_eq_compare_operator"
- [(match_dup 0)
- (const_int 0)])
- (label_ref (match_operand 3 "" "")) (pc)))]
- "TARGET_M6812 && (INTVAL (operands[1]) == 1 || INTVAL (operands[1]) == -1)"
- [(parallel [
- (set (pc) (if_then_else (match_op_dup 2 [(match_dup 0) (match_dup 5)])
- (label_ref (match_dup 3)) (pc)))
- (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))
- (clobber (match_dup 4))])]
- "operands[4] = gen_rtx_SCRATCH(HImode);
- operands[5] = GEN_INT (-INTVAL (operands[1]));")
-
-
-;;
-;; Replace: "addb #-1; bne L1" into "dbne b,L1"
-;; "addb #-1; beq L1" into "dbeq b,L1"
-;;
-(define_peephole2
- [(set (match_operand:QI 0 "hard_reg_operand" "")
- (plus:QI (match_dup 0)
- (match_operand:QI 1 "const_int_operand" "")))
- (set (pc)
- (if_then_else (match_operator 2 "m68hc11_eq_compare_operator"
- [(match_dup 0)
- (const_int 0)])
- (label_ref (match_operand 3 "" "")) (pc)))]
- "TARGET_M6812 && D_REG_P (operands[0])
- && (INTVAL (operands[1]) == 1 || INTVAL (operands[1]) == -1)"
- [(parallel [
- (set (pc) (if_then_else (match_op_dup 2 [(match_dup 0) (match_dup 5)])
- (label_ref (match_dup 3)) (pc)))
- (set (match_dup 0) (plus:QI (match_dup 0) (match_dup 1)))
- (clobber (match_dup 4))])]
- "operands[4] = gen_rtx_SCRATCH(QImode);
- operands[5] = GEN_INT (-INTVAL (operands[1]));")
-
-
-;;--------------------------------------------------------------------
-;;- Move peephole2
-;;--------------------------------------------------------------------
-
-;;
-;; Replace "leas 2,sp" with a "pulx" or a "puly".
-;; On 68HC12, this is one cycle slower but one byte smaller.
-;; pr target/6899: This peephole was not valid because a register CSE
-;; pass removes the pulx/puly. The 'use' clause ensure that the pulx is
-;; not removed.
-;;
-(define_peephole2
- [(set (reg:HI SP_REGNUM) (plus:HI (reg:HI SP_REGNUM) (const_int 2)))
- (match_scratch:HI 0 "xy")]
- "TARGET_M6812 && optimize_size"
- [(set (match_dup 0) (match_dup 1))
- (use (match_dup 0))]
- "operands[1] = gen_rtx_MEM (HImode,
- gen_rtx_POST_INC (HImode,
- gen_rtx_REG (HImode, HARD_SP_REGNUM)));")
-
-;; Replace: "pshx; tfr d,x; stx 0,sp" into "pshd; tfr d,x"
-;;
-;; PR 14542: emit a use to pretend we need the value of initial register.
-;; Otherwise verify_local_live_at_start will die due to a live change
-;; of that register.
-;;
-(define_peephole2
- [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
- (match_operand:HI 0 "hard_reg_operand" ""))
- (set (match_dup 0)
- (match_operand:HI 1 "hard_reg_operand" ""))
- (set (mem:HI (reg:HI SP_REGNUM))
- (match_dup 0))]
- "TARGET_M6812"
- [(use (match_dup 0))
- (set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
- (match_dup 1))
- (set (match_dup 0) (match_dup 1))]
- "")
-
-;;
-;; Change: "ldd 0,sp; pulx" into "puld"
-;; This sequence usually appears at end a functions.
-(define_peephole2
- [(set (match_operand:HI 0 "hard_reg_operand" "")
- (mem:HI (reg:HI SP_REGNUM)))
- (use (match_dup 0))
- (set (match_operand:HI 1 "hard_reg_operand" "")
- (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
- "peep2_reg_dead_p (2, operands[1])"
- [(set (match_dup 0) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))
- (use (match_dup 0))]
- "")
-
-;; Replace: "pshx; clr 0,sp; clr 1,sp" by "clr 1,-sp; clr 1,-sp"
-;; Appears to allocate local variables.
-(define_peephole2
- [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
- (match_operand:HI 0 "hard_reg_operand" ""))
- (set (mem:QI (plus:HI (reg:HI SP_REGNUM) (const_int 1)))
- (const_int 0))
- (set (mem:QI (reg:HI SP_REGNUM))
- (const_int 0))]
- "TARGET_M6812"
- [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
- (const_int 0))]
- "")
-
-;; Likewise for HI mode
-(define_peephole2
- [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
- (match_operand:HI 0 "hard_reg_operand" ""))
- (set (mem:HI (reg:HI SP_REGNUM))
- (const_int 0))]
- "TARGET_M6812"
- [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
- (const_int 0))]
- "")
-;;--------------------------------------------------------------------
-;;-
-;;--------------------------------------------------------------------
-;;
-;; Optimize memory<->memory moves when the value is also loaded in
-;; a register.
-;;
-(define_peephole2
- [(set (match_operand:QI 0 "memory_operand" "")
- (match_operand:QI 1 "memory_operand" ""))
- (set (reg:QI D_REGNUM)
- (match_operand:QI 2 "memory_operand" ""))]
- "(rtx_equal_p (operands[0], operands[2]) && !side_effects_p (operands[0]))
- || (GET_CODE (XEXP (operands[0], 0)) == REG
- && GET_CODE (XEXP (operands[2], 0)) == POST_INC
- && rtx_equal_p (XEXP (operands[0], 0), XEXP (XEXP (operands[2], 0), 0)))"
- [(set (reg:QI D_REGNUM) (match_dup 1))
- (set (match_dup 2) (reg:QI D_REGNUM))]
- "")
-
-;;
-;; Remove a possible move before a compare instruction when that
-;; move will go in a dead register. Compare with the source then.
-;;
-(define_peephole2
- [(set (match_operand:HI 0 "hard_reg_operand" "")
- (match_operand:HI 1 "hard_reg_operand" ""))
- (set (cc0)
- (compare (match_dup 0)
- (match_operand:HI 2 "cmp_operand" "")))]
- "(X_REG_P (operands[1]) || Y_REG_P (operands[1]))
- && peep2_reg_dead_p (2, operands[0])
- && !reg_mentioned_p (operands[0], operands[2])"
- [(set (cc0) (compare (match_dup 1) (match_dup 2)))]
- "")
-
-;;
-;; Optimize loading a constant to memory when that same constant
-;; is loaded to a hard register. Switch the two to use the register
-;; for memory initialization. In most cases, the constant is 0.
-;;
-(define_peephole2
- [(set (match_operand:HI 0 "memory_operand" "")
- (match_operand:HI 1 "immediate_operand" ""))
- (set (match_operand:HI 2 "hard_reg_operand" "")
- (match_dup 1))]
- "(D_REG_P (operands[2]) || X_REG_P (operands[2]) || Y_REG_P (operands[2]))
- && !reg_mentioned_p (operands[2], operands[0])"
- [(set (match_dup 2) (match_dup 1))
- (set (match_dup 0) (match_dup 2))]
- "")
-
-;;
-;; Reorganize to optimize address computations.
-;;
-(define_peephole2
- [(set (match_operand:HI 0 "hard_reg_operand" "")
- (match_operand:HI 1 "const_int_operand" ""))
- (set (match_dup 0)
- (plus:HI (match_dup 0)
- (match_operand:HI 2 "general_operand" "")))]
- "(INTVAL (operands[1]) >= -2 && INTVAL (operands[1]) <= 2)"
- [(set (match_dup 0) (match_dup 2))
- (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
- "")
-
-;;
-;; Replace: "ldx #N; xgdx; addd <var>; xgdx" by "ldab #N; ldx <var>; abx"
-;;
-(define_peephole2
- [(set (match_operand:HI 0 "hard_reg_operand" "")
- (match_operand:HI 1 "const_int_operand" ""))
- (set (match_dup 0)
- (plus:HI (match_dup 0)
- (match_operand:HI 2 "general_operand" "")))
- (match_scratch:QI 3 "d")]
- "TARGET_M6811 && (INTVAL (operands[1]) >= 0 && INTVAL (operands[1]) <= 0x0ff)"
- [(set (match_dup 3) (match_dup 4))
- (set (match_dup 0) (match_dup 2))
- (set (match_dup 0) (plus:HI (zero_extend:HI (match_dup 3)) (match_dup 0)))]
- "operands[4] = m68hc11_gen_lowpart (QImode, operands[1]);")
-
-;;
-;; Replace: "ldx #N; xgdx; addd <var>; xgdx" by "ldab #N; ldx <var>; abx"
-;;
-(define_peephole2
- [(set (match_operand:HI 0 "hard_reg_operand" "")
- (match_operand:HI 1 "const_int_operand" ""))
- (set (match_dup 0)
- (plus:HI (match_dup 0)
- (match_operand:HI 2 "general_operand" "")))]
- "TARGET_M6812"
- [(set (match_dup 0) (match_dup 2))
- (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
- "")
-
-;;
-;; Optimize an address register increment and a compare to use
-;; a PRE_INC or PRE_DEC addressing mode (disabled on the tst insn
-;; before reload, but can be enabled after).
-;;
-(define_peephole2
- [(set (match_operand:HI 0 "hard_reg_operand" "")
- (plus:HI (match_dup 0)
- (match_operand:HI 1 "const_int_operand" "")))
- (set (cc0)
- (compare (match_operand:QI 2 "memory_operand" "")
- (const_int 0)))]
- "TARGET_AUTO_INC_DEC
- && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1)
- && reg_mentioned_p (operands[0], operands[2])"
- [(set (cc0)
- (compare (match_dup 3)
- (const_int 0)))]
- "if (INTVAL (operands[1]) == 1)
- operands[3] = gen_rtx_MEM (QImode,
- gen_rtx_PRE_INC (HImode, operands[0]));
- else
- operands[3] = gen_rtx_MEM (QImode,
- gen_rtx_PRE_DEC (HImode, operands[0]));
- ")
-
-;;
-;; Likewise for compare.
-;;
-(define_peephole2
- [(set (match_operand:HI 0 "hard_reg_operand" "")
- (plus:HI (match_dup 0)
- (match_operand:HI 1 "const_int_operand" "")))
- (set (cc0)
- (compare (match_operand:QI 2 "hard_reg_operand" "")
- (match_operand:QI 3 "memory_operand" "")))]
- "TARGET_AUTO_INC_DEC
- && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1)
- && reg_mentioned_p (operands[0], operands[3])"
- [(set (cc0) (compare (match_dup 2) (match_dup 4)))]
- "if (INTVAL (operands[1]) == 1)
- operands[4] = gen_rtx_MEM (QImode,
- gen_rtx_PRE_INC (HImode, operands[0]));
- else
- operands[4] = gen_rtx_MEM (QImode,
- gen_rtx_PRE_DEC (HImode, operands[0]));
- ")
-
-(define_peephole2
- [(set (match_operand:HI 0 "hard_reg_operand" "")
- (plus:HI (match_dup 0)
- (match_operand:HI 1 "const_int_operand" "")))
- (set (cc0)
- (compare (match_operand:QI 2 "memory_operand" "")
- (match_operand:QI 3 "hard_reg_operand" "")))]
- "TARGET_AUTO_INC_DEC
- && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1)
- && reg_mentioned_p (operands[0], operands[2])"
- [(set (cc0) (compare (match_dup 4) (match_dup 3)))]
- "if (INTVAL (operands[1]) == 1)
- operands[4] = gen_rtx_MEM (QImode,
- gen_rtx_PRE_INC (HImode, operands[0]));
- else
- operands[4] = gen_rtx_MEM (QImode,
- gen_rtx_PRE_DEC (HImode, operands[0]));
- ")
-
-;;
-;; Replace a "ldx #N; addx <sp>" with a "ldx <sp>; addx #n"
-;; (avoids many temporary moves because we can't add sp to another reg easily)
-;;
-(define_peephole2
- [(set (match_operand:HI 0 "hard_reg_operand" "")
- (match_operand:HI 1 "const_int_operand" ""))
- (set (match_dup 0) (plus:HI (match_dup 0) (reg:HI SP_REGNUM)))]
- ""
- [(set (match_dup 0) (reg:HI SP_REGNUM))
- (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
- "")
-
-;;
-;; Replace "ldd #N; addd <op>" with "ldd <op>; addd #N".
-;;
-(define_peephole2
- [(set (match_operand:HI 0 "hard_reg_operand" "")
- (match_operand:HI 1 "const_int_operand" ""))
- (set (match_dup 0)
- (plus:HI (match_dup 0)
- (match_operand:HI 2 "general_operand" "")))]
- "(INTVAL (operands[1]) >= -2 && INTVAL (operands[1]) <= 2)"
- [(set (match_dup 0) (match_dup 2))
- (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
- "")
-
-;;
-;;
-;;
-(define_peephole2
- [(parallel
- [(set (match_operand:SI 0 "hard_reg_operand" "")
- (ashift:SI (match_operand:SI 1 "general_operand" "")
- (const_int 1)))
- (clobber (match_scratch:HI 2 ""))])
- (set (match_operand:HI 3 "nonimmediate_operand" "") (reg:HI D_REGNUM))
- (set (match_operand:HI 4 "nonimmediate_operand" "") (reg:HI X_REGNUM))]
- "!X_REG_P (operands[1])
- && peep2_reg_dead_p (2, gen_rtx_REG (HImode, D_REGNUM))
- && peep2_reg_dead_p (3, gen_rtx_REG (HImode, X_REGNUM))"
- [(set (reg:HI D_REGNUM) (match_dup 5))
- (set (reg:HI D_REGNUM) (ashift:HI (reg:HI D_REGNUM) (const_int 1)))
- (set (match_dup 3) (reg:HI D_REGNUM))
- (set (reg:HI D_REGNUM) (match_dup 6))
- (parallel [(set (reg:HI D_REGNUM)
- (rotate:HI (reg:HI D_REGNUM) (const_int 1)))
- (clobber (reg:HI CC_REGNUM))])
- (set (match_dup 4) (reg:HI D_REGNUM))]
- "operands[5] = m68hc11_gen_lowpart (HImode, operands[1]);
- operands[6] = m68hc11_gen_highpart (HImode, operands[1]);")
-
-;;
-;; Replace a "ldd <mem>; psha; pshb" with a "ldx <mem>; pshx".
-;;
-(define_peephole2
- [(set (match_operand:HI 0 "hard_reg_operand" "")
- (match_operand:HI 1 "memory_operand" ""))
- (set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
- (match_dup 0))
- (match_scratch:HI 2 "x")]
- "TARGET_M6811 && D_REG_P (operands[0]) && peep2_reg_dead_p (2, operands[0])"
- [(set (match_dup 2) (match_dup 1))
- (set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))]
- "")
-
-;;
-;; Remove one load when copying a value to/from memory and also
-;; to a register. Take care not clobbering a possible register used
-;; by operand 2.
-;; Replace: "ldd 0,y; std 2,y; ldx 0,y" into "ldx 0,y; stx 2,y"
-;;
-(define_peephole2
- [(set (match_operand:HI 0 "hard_reg_operand" "")
- (match_operand:HI 1 "general_operand" ""))
- (set (match_operand:HI 2 "nonimmediate_operand" "") (match_dup 0))
- (set (match_operand:HI 3 "hard_reg_operand" "") (match_dup 1))]
- "peep2_reg_dead_p (2, operands[0])
- && !side_effects_p (operands[1])
- && !side_effects_p (operands[2])
- && !reg_mentioned_p (operands[3], operands[2])"
- [(set (match_dup 3) (match_dup 1))
- (set (match_dup 2) (match_dup 3))]
- "")
-
-;;
-;; Replace a "ldd <mem>; addd #N; std <mem>" into a
-;; "ldx <mem>; leax; stx <mem>" if we have a free X/Y register
-;; and the constant is small.
-;;
-(define_peephole2
- [(set (match_operand:HI 0 "hard_reg_operand" "")
- (match_operand:HI 1 "general_operand" ""))
- (set (match_dup 0) (plus:HI (match_dup 0)
- (match_operand:HI 2 "const_int_operand" "")))
- (set (match_operand:HI 3 "nonimmediate_operand" "")
- (match_dup 0))
- (match_scratch:HI 4 "xy")]
- "D_REG_P (operands[0])
- && (TARGET_M6812
- || (INTVAL (operands[2]) >= -2 && INTVAL (operands[2]) <= 2))
- && peep2_reg_dead_p (3, operands[0])"
- [(set (match_dup 4) (match_dup 1))
- (set (match_dup 4) (plus:HI (match_dup 4) (match_dup 2)))
- (set (match_dup 3) (match_dup 4))]
- "if (reg_mentioned_p (operands[4], operands[1])) FAIL;
- if (reg_mentioned_p (operands[4], operands[3])) FAIL;")
-
-;;--------------------------------------------------------------------
-;;- Bset peephole2
-;;--------------------------------------------------------------------
-;; These peepholes try to replace some logical sequences by 'bset' and 'bclr'.
-;;
-;; Replace 'ldab <mem>; orab #N; stab <mem>' by 'bset <mem> #N'.
-;; Register D must be dead and there must be no register side effects for mem.
-;; The <mem> *can* be volatile this is why we must not use 'side_effects_p'.
-;; The good side effect is that it makes the sequence atomic.
-;;
-(define_peephole2
- [(set (match_operand:QI 0 "hard_reg_operand" "")
- (match_operand:QI 1 "nonimmediate_operand" ""))
- (set (match_dup 0) (ior:QI (match_dup 0)
- (match_operand:QI 2 "const_int_operand" "")))
- (set (match_dup 1) (match_dup 0))]
- "(TARGET_M6812 || m68hc11_indirect_p (operands[1], QImode))
- && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
- && peep2_reg_dead_p (3, operands[0])"
- [(set (match_dup 1) (ior:QI (match_dup 1) (match_dup 2)))]
- "")
-
-(define_peephole2
- [(set (match_operand:HI 0 "hard_reg_operand" "")
- (match_operand:HI 1 "nonimmediate_operand" ""))
- (set (match_dup 0) (ior:HI (match_dup 0)
- (match_operand:HI 2 "const_int_operand" "")))
- (set (match_dup 1) (match_dup 0))]
- "(TARGET_M6812 || m68hc11_indirect_p (operands[1], HImode))
- && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
- && peep2_reg_dead_p (3, operands[0])"
- [(set (match_dup 1) (ior:HI (match_dup 1) (match_dup 2)))]
- "")
-
-;;--------------------------------------------------------------------
-;;- Bclr peephole2
-;;--------------------------------------------------------------------
-;; Replace 'ldab <mem>; andab #N; stab <mem>' by 'bclr <mem> #N'.
-;; See Bset peephole2.
-;;
-(define_peephole2
- [(set (match_operand:QI 0 "hard_reg_operand" "")
- (match_operand:QI 1 "nonimmediate_operand" ""))
- (set (match_dup 0) (and:QI (match_dup 0)
- (match_operand:QI 2 "const_int_operand" "")))
- (set (match_dup 1) (match_dup 0))]
- "(TARGET_M6812 || m68hc11_indirect_p (operands[1], QImode))
- && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
- && peep2_reg_dead_p (3, operands[0])"
- [(set (match_dup 1) (and:QI (match_dup 1) (match_dup 2)))]
- "")
-
-(define_peephole2
- [(set (match_operand:HI 0 "hard_reg_operand" "")
- (match_operand:HI 1 "nonimmediate_operand" ""))
- (set (match_dup 0) (and:HI (match_dup 0)
- (match_operand:HI 2 "const_int_operand" "")))
- (set (match_dup 1) (match_dup 0))]
- "(TARGET_M6812 || m68hc11_indirect_p (operands[1], HImode))
- && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
- && peep2_reg_dead_p (3, operands[0])"
- [(set (match_dup 1) (and:HI (match_dup 1) (match_dup 2)))]
- "")
-
-
-;;--------------------------------------------------------------------
-;;- Compare peephole2
-;;--------------------------------------------------------------------
-(define_peephole2
- [(set (match_operand:HI 0 "hard_reg_operand" "")
- (match_operand:HI 1 "hard_reg_operand" ""))
- (set (match_dup 1) (plus:HI (match_dup 1)
- (match_operand:HI 2 "const_int_operand" "")))
- (set (cc0) (compare (match_dup 0)
- (const_int 0)))]
- "peep2_reg_dead_p (3, operands[0]) && !Z_REG_P (operands[1])"
- [(set (match_dup 1) (plus:HI (match_dup 1) (match_dup 2)))
- (set (cc0) (compare (match_dup 1) (match_dup 2)))]
- "")
-
-(define_peephole2
- [(set (match_operand:HI 0 "hard_reg_operand" "")
- (match_operand:HI 1 "hard_reg_operand" ""))
- (set (match_operand:HI 2 "hard_reg_operand" "")
- (plus:HI (match_dup 2)
- (match_operand:HI 3 "const_int_operand" "")))
- (set (match_operand:HI 4 "memory_operand" "") (match_dup 2))
- (set (cc0) (compare (match_operand:HI 5 "hard_reg_operand" "")
- (const_int 0)))]
- "peep2_reg_dead_p (4, operands[5]) && !Z_REG_P (operands[2])
- && !reg_mentioned_p (operands[2], operands[4])
-
- && ((rtx_equal_p (operands[5], operands[0])
- && rtx_equal_p (operands[2], operands[1]))
-
- || (rtx_equal_p (operands[5], operands[1])
- && rtx_equal_p (operands[2], operands[0])))"
- [(set (match_dup 2) (match_dup 1))
- (set (match_dup 2) (plus:HI (match_dup 2) (match_dup 3)))
- (set (match_dup 4) (match_dup 2))
- (set (cc0) (compare (match_dup 2) (match_dup 3)))]
- "")
-
-
-;;--------------------------------------------------------------------
-;;- Load peephole2
-;;--------------------------------------------------------------------
-;;
-;; Optimize initialization of 2 hard regs from the same memory location
-;; Since we can't copy easily X, Y and D to each other, load the 2 registers
-;; from the same memory location.
-;;
-(define_peephole2
- [(set (match_operand:HI 0 "hard_reg_operand" "")
- (match_operand:HI 1 "memory_operand" ""))
- (set (match_operand:HI 2 "hard_reg_operand" "") (match_dup 0))]
- "TARGET_M6811
- && !side_effects_p (operands[1])
- && !reg_mentioned_p (operands[0], operands[1])"
- [(set (match_dup 0) (match_dup 1))
- (set (match_dup 2) (match_dup 1))]
- "")
-
-;; Replace "ldd #N; addd <op>" with "ldd <op>; addd #N".
-;;
-(define_peephole2
- [(set (match_operand:HI 0 "nonimmediate_operand" "") (const_int 0))
- (set (match_operand:HI 1 "nonimmediate_operand" "") (const_int 0))
- (set (match_operand:HI 2 "nonimmediate_operand" "") (const_int 0))
- (set (match_operand:HI 3 "nonimmediate_operand" "") (const_int 0))
- (match_scratch:HI 4 "d")]
- ""
- [(set (match_dup 4) (const_int 0))
- (set (match_dup 0) (match_dup 4))
- (set (match_dup 1) (match_dup 4))
- (set (match_dup 2) (match_dup 4))
- (set (match_dup 3) (match_dup 4))]
- "")
-
-;;
-;; Replace "ldd #N; addd <op>" with "ldd <op>; addd #N".
-;;
-(define_peephole2
- [(set (match_operand:HI 0 "nonimmediate_operand" "") (const_int 0))
- (set (match_operand:HI 1 "nonimmediate_operand" "") (const_int 0))
- (set (match_operand:HI 2 "nonimmediate_operand" "") (const_int 0))
- (match_scratch:HI 3 "d")]
- ""
- [(set (match_dup 3) (const_int 0))
- (set (match_dup 0) (match_dup 3))
- (set (match_dup 1) (match_dup 3))
- (set (match_dup 2) (match_dup 3))]
- "")
-
-;;
-;; Replace "ldd #N; addd <op>" with "ldd <op>; addd #N".
-;;
-(define_peephole2
- [(set (match_operand:HI 0 "hard_reg_operand" "") (const_int 0))
- (set (match_operand:HI 1 "push_operand" "") (match_dup 0))
- (set (match_operand:HI 2 "push_operand" "") (match_dup 0))
- (set (match_operand:HI 3 "push_operand" "") (match_dup 0))
- (match_scratch:HI 4 "x")]
- "TARGET_M6811 && D_REG_P (operands[0]) && peep2_reg_dead_p (4, operands[0])"
- [(set (match_dup 4) (const_int 0))
- (set (match_dup 1) (match_dup 4))
- (set (match_dup 2) (match_dup 4))
- (set (match_dup 3) (match_dup 4))]
- "")
-
-;;
-;; This peephole catches the address computations generated by the reload
-;; pass.
-(define_peephole
- [(set (match_operand:HI 0 "hard_reg_operand" "xy")
- (match_operand:HI 1 "const_int_operand" ""))
- (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
- (set (match_dup 0) (reg:HI D_REGNUM))])
- (set (reg:HI D_REGNUM)
- (plus (reg:HI D_REGNUM)
- (match_operand:HI 2 "general_operand" "")))
- (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
- (set (match_dup 0) (reg:HI D_REGNUM))])]
- "(INTVAL (operands[1]) & 0x0FF) == 0"
- "*
-{
- int value_loaded = 1;
-
- if (X_REG_P (operands[0]) || SP_REG_P (operands[2]))
- {
- rtx ops[2];
-
- ops[0] = operands[0];
- ops[1] = operands[2];
- m68hc11_gen_movhi (insn, ops);
- output_asm_insn (\"xgd%0\", operands);
- }
- else if (Y_REG_P (operands[0]))
- {
- if (reg_mentioned_p (iy_reg, operands[2]))
- output_asm_insn (\"ldy\\t%2\", operands);
- else
- value_loaded = 0;
- output_asm_insn (\"xgdy\", operands);
- }
- else
- {
- output_asm_insn (\"ldd\\t%2\", operands);
- }
-
- if (value_loaded == 0)
- output_asm_insn (\"ldd\\t%2\", operands);
- if ((INTVAL (operands[1]) & 0x0ff00) == 0x100)
- output_asm_insn (\"inca\", operands);
- else if ((INTVAL (operands[1]) & 0x0ff00) == 0xff00)
- output_asm_insn (\"deca\", operands);
- else if (INTVAL (operands[1]) != 0)
- output_asm_insn (\"adda\\t%h1\", operands);
-
- if (X_REG_P (operands[0]))
- return \"xgdx\";
- else if (Y_REG_P (operands[0]))
- return \"xgdy\";
- else
- return \"\";
-}
-")
-
-(define_peephole
- [(set (match_operand:HI 0 "hard_reg_operand" "h")
- (match_operand:HI 1 "non_push_operand" "g"))
- (set (match_operand:HI 2 "hard_reg_operand" "h")
- (match_dup 0))]
- "find_regno_note (insn, REG_DEAD, REGNO (operands[0]))
- && !S_REG_P (operands[2])"
- "*
-{
- rtx ops[2];
-
- ops[0] = operands[2];
- ops[1] = operands[1];
- m68hc11_gen_movhi (insn, ops);
- return \"\";
-}
-")
-
-(define_peephole
- [(set (match_operand:HI 0 "hard_reg_operand" "h")
- (match_operand:HI 1 "hard_reg_operand" "h"))
- (set (match_operand:HI 2 "non_push_operand" "g")
- (match_dup 0))]
- "find_regno_note (insn, REG_DEAD, REGNO (operands[0]))
- && !S_REG_P (operands[2])"
- "*
-{
- rtx ops[2];
-
- ops[0] = operands[2];
- ops[1] = operands[1];
- m68hc11_gen_movhi (insn, ops);
- return \"\";
-}
-")
-
-;;
-;; Catch a (set X/Y D) followed by a swap. In this form, D is dead after
-;; the set, so we don't need to emit anything. 'ins1' refers to the
-;; (set ...) insn.
-;;
-(define_peephole
- [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM))
- (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
- (set (match_dup 0) (reg:HI D_REGNUM))])]
- "find_regno_note (ins1, REG_DEAD, HARD_D_REGNUM)"
- "*
-{
- cc_status = cc_prev_status;
- return \"\";
-}
-")
-
-;; Same as above but due to some split, there may be a noop set
-;; between the two.
-(define_peephole
- [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM))
- (set (match_dup 0) (match_dup 0))
- (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
- (set (match_dup 0) (reg:HI D_REGNUM))])]
- "find_regno_note (ins1, REG_DEAD, HARD_D_REGNUM)"
- "*
-{
- cc_status = cc_prev_status;
- return \"\";
-}
-")
-
-;;
-;; Catch a (set X/Y D) followed by an xgdx/xgdy. D is not dead
-;; and we must, at least, setup X/Y with value of D.
-;;
-(define_peephole
- [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM))
- (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
- (set (match_dup 0) (reg:HI D_REGNUM))])]
- ""
- "*
-{
- rtx ops[2];
-
- ops[0] = operands[0];
- ops[1] = gen_rtx_REG (HImode, HARD_D_REGNUM);
- m68hc11_gen_movhi (insn, ops);
- return \"\";
-}
-")
-
-;;;
-;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't
-;;; need to emit anything. Otherwise, we just need a copy of D to X/Y.
-;;;
-(define_peephole
- [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
- (set (match_dup 0) (reg:HI D_REGNUM))])
- (set (reg:HI D_REGNUM) (match_dup 0))]
- "find_regno_note (insn, REG_DEAD, REGNO (operands[0]))"
- "*
-{
- cc_status = cc_prev_status;
- return \"\";
-}
-")
-
-;;;
-;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't
-;;; need to emit anything. Otherwise, we just need a copy of D to X/Y.
-;;;
-(define_peephole
- [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
- (set (match_dup 0) (reg:HI D_REGNUM))])
- (set (reg:QI D_REGNUM) (match_operand:QI 1 "hard_reg_operand" "A"))]
- "REGNO (operands[0]) == REGNO (operands[1])
- && find_regno_note (insn, REG_DEAD, REGNO (operands[0]))"
- "*
-{
- cc_status = cc_prev_status;
- return \"\";
-}
-")
-
-;;;
-;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't
-;;; need to emit anything. Otherwise, we just need a copy of D to X/Y.
-;;;
-(define_peephole
- [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
- (set (match_dup 0) (reg:HI D_REGNUM))])
- (set (reg:HI D_REGNUM) (match_dup 0))]
- ""
- "*
-{
- rtx ops[2];
-
- ops[0] = operands[0];
- ops[1] = gen_rtx_REG (HImode, HARD_D_REGNUM);
- m68hc11_gen_movhi (insn, ops);
- return \"\";
-}
-")
-
-;;;
-;;; Same peephole with a QI set. The copy is made as 16-bit to comply
-;;; with the xgdx.
-;;;
-(define_peephole
- [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
- (set (match_dup 0) (reg:HI D_REGNUM))])
- (set (reg:QI D_REGNUM) (match_operand:QI 1 "hard_reg_operand" "A"))]
- "REGNO (operands[0]) == REGNO (operands[1])"
- "*
-{
- rtx ops[2];
-
- ops[0] = operands[0];
- ops[1] = gen_rtx_REG (HImode, HARD_D_REGNUM);
- m68hc11_gen_movhi (insn, ops);
- return \"\";
-}
-")
-
-;;;
-;;; Catch two consecutive xgdx or xgdy, emit nothing.
-;;;
-(define_peephole
- [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
- (set (match_dup 0) (reg:HI D_REGNUM))])
- (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
- (set (match_dup 0) (reg:HI D_REGNUM))])]
- ""
- "*
-{
- cc_status = cc_prev_status;
- return \"\";
-}
-")
-
-(define_peephole
- [(set (match_operand:HI 0 "hard_reg_operand" "")
- (match_operand:HI 1 "stack_register_operand" ""))
- (set (match_operand:HI 2 "hard_reg_operand" "")
- (match_operand:HI 3 "memory_operand" "m"))
- (set (match_dup 0)
- (match_operand:HI 4 "memory_operand" "m"))]
- "IS_STACK_POP (operands[4])
- && (GET_CODE (operands[3]) == MEM &&
- rtx_equal_p (operands[0], XEXP (operands[3], 0)))"
- "*
-{
- rtx ops[2];
-
- ops[0] = operands[2];
- ops[1] = gen_rtx_MEM (HImode,
- gen_rtx_POST_INC (HImode, stack_pointer_rtx));
- m68hc11_gen_movhi (insn, ops);
- return \"\";
-}
-")
-
-;;
-;; Catch (d = -1) (d = d + sp) to avoid 2 adjust of SP.
-;;
-(define_peephole
- [(set (match_operand:HI 0 "hard_reg_operand" "dA") (const_int -1))
- (set (match_dup 0) (plus:HI (match_dup 0) (reg:HI SP_REGNUM)))]
- "TARGET_M6811"
- "*
-{
- return \"sts\\t%t0\\n\\tld%0\\t%t0\";
-}
-")
-
-(define_peephole
- [(set (match_operand:HI 0 "hard_reg_operand" "")
- (match_operand:HI 1 "memory_operand" ""))
- (set (match_operand:HI 2 "hard_reg_operand" "") (match_dup 0))]
- "TARGET_M6811
- && !side_effects_p (operands[1])
- && !reg_mentioned_p (operands[0], operands[1])"
- "*
-{
- rtx ops[2];
-
- ops[0] = operands[0];
- ops[1] = operands[1];
- m68hc11_gen_movhi (insn, ops);
- ops[0] = operands[2];
- m68hc11_gen_movhi (insn, ops);
- return \"\";
-}")
-
-;; Peephole for Z register replacement.
-;; Avoid to use _.tmp register when comparing D and X if we can compare
-;; with soft register
-(define_peephole
- [(set (match_operand:HI 0 "hard_reg_operand" "") (reg:HI SOFT_XY_REGNUM))
- (set (reg:HI SOFT_TMP_REGNUM) (match_dup 0))
- (set (cc0) (compare (match_operand:HI 2 "hard_reg_operand" "")
- (reg:HI SOFT_TMP_REGNUM)))]
- "X_REG_P (operands[0]) || Y_REG_P (operands[0])"
- "*
-{
- rtx ops[2];
-
- ops[0] = operands[0];
- ops[1] = operands[1];
- m68hc11_gen_movhi (insn, ops);
- return \"cp%2\\t%1\";
-}")
+++ /dev/null
-; Options for the Motorola 68HC11 and 68HC12 port of the compiler.
-
-; Copyright (C) 2005, 2007 Free Software Foundation, Inc.
-;
-; This file is part of GCC.
-;
-; GCC is free software; you can redistribute it and/or modify it under
-; the terms of the GNU General Public License as published by the Free
-; Software Foundation; either version 3, or (at your option) any later
-; version.
-;
-; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-; WARRANTY; without even the implied warranty of MERCHANTABILITY or
-; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-; for more details.
-;
-; You should have received a copy of the GNU General Public License
-; along with GCC; see the file COPYING3. If not see
-; <http://www.gnu.org/licenses/>.
-
-m6811
-Target RejectNegative InverseMask(M6812, M6811)
-Compile for a 68HC11
-
-m6812
-Target RejectNegative Mask(M6812)
-Compile for a 68HC12
-
-m68hc11
-Target RejectNegative InverseMask(M6812)
-Compile for a 68HC11
-
-m68hc12
-Target RejectNegative Mask(M6812) MaskExists
-Compile for a 68HC12
-
-; At the moment, there is no difference between the code generated
-; for -m68hc12 and -m68hcs12.
-m68hcs12
-Target RejectNegative Mask(M6812) MaskExists
-Compile for a 68HCS12
-
-m68s12
-Target RejectNegative Mask(M6812) MaskExists
-Compile for a 68HCS12
-
-mauto-incdec
-Target RejectNegative Report Mask(AUTO_INC_DEC)
-Auto pre/post decrement increment allowed
-
-minmax
-Target RejectNegative Report Mask(MIN_MAX)
-Min/max instructions allowed
-
-mlong-calls
-Target RejectNegative Report Mask(LONG_CALLS)
-Use call and rtc for function calls and returns
-
-mnoauto-incdec
-Target RejectNegative Report InverseMask(AUTO_INC_DEC)
-Auto pre/post decrement increment not allowed
-
-mnolong-calls
-Target RejectNegative Report InverseMask(LONG_CALLS)
-Use jsr and rts for function calls and returns
-
-mnominmax
-Target RejectNegative Report InverseMask(MIN_MAX)
-Min/max instructions not allowed
-
-mnorelax
-Target RejectNegative Report InverseMask(NO_DIRECT_MODE)
-Use direct addressing mode for soft registers
-
-mnoshort
-Target RejectNegative Report InverseMask(SHORT)
-Compile with 32-bit integer mode
-
-; Currently ignored.
-mreg-alloc=
-Target RejectNegative Joined
-Specify the register allocation order
-
-mrelax
-Target RejectNegative Report Mask(NO_DIRECT_MODE)
-Do not use direct addressing mode for soft registers
-
-mshort
-Target RejectNegative Report Mask(SHORT)
-Compile with 16-bit integer mode
-
-msoft-reg-count=
-Target RejectNegative Joined UInteger Var(m68hc11_soft_reg_count) Init(-1)
-Indicate the number of soft registers available
+++ /dev/null
-/* Definitions of target machine for GNU compiler, for m68hc12.
- Copyright (C) 1999, 2000, 2001, 2003, 2007 Free Software Foundation, Inc.
- Contributed by Stephane Carrez (stcarrez@nerim.fr).
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-/* Compile and assemble for a 68hc12 unless there is a -m68hc11 option. */
-#define ASM_SPEC \
-"%{m68hc11:-m68hc11}" \
-"%{m68hcs12:-m68hcs12}" \
-"%{!m68hc11:%{!m68hcs12:-m68hc12}}"
-#define LIB_SPEC ""
-#define CC1_SPEC ""
-
-/* We need to tell the linker the target elf format. Just pass an
- emulation option. This can be overridden by -Wl option of gcc. */
-#define LINK_SPEC \
-"%{m68hc11:-m m68hc11elf}" \
-"%{m68hcs12:-m m68hc12elf}" \
-"%{!m68hc11:%{!m68hcs12:-m m68hc11elf}} %{mrelax:-relax}"
-
-#define CPP_SPEC \
-"%{mshort:-D__HAVE_SHORT_INT__ -D__INT__=16}\
- %{!mshort:-D__INT__=32}\
- %{m68hc11:-Dmc6811 -DMC6811 -Dmc68hc11}\
- %{!m68hc11:%{!m68hc12:-Dmc6812 -DMC6812 -Dmc68hc12}}\
- %{m68hcs12:-Dmc6812 -DMC6812 -Dmc68hcs12}\
- %{fshort-double:-D__HAVE_SHORT_DOUBLE__}"
-
-/* Default target_flags if no switches specified. */
-#define TARGET_DEFAULT (MASK_M6812)
+++ /dev/null
-;; Predicate definitions for Motorola 68HC11 and 68HC12.
-;; Copyright (C) 2005, 2007, 2009 Free Software Foundation, Inc.
-;;
-;; This file is part of GCC.
-;;
-;; GCC is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 3, or (at your option)
-;; any later version.
-;;
-;; GCC is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with GCC; see the file COPYING3. If not see
-;; <http://www.gnu.org/licenses/>.
-
-;; TODO: Add a comment here.
-
-(define_predicate "stack_register_operand"
- (match_code "subreg,reg")
-{
- return SP_REG_P (op);
-})
-
-;; TODO: Add a comment here.
-
-(define_predicate "d_register_operand"
- (match_code "subreg,reg")
-{
- if (GET_MODE (op) != mode && mode != VOIDmode)
- return 0;
-
- if (GET_CODE (op) == SUBREG)
- op = XEXP (op, 0);
-
- return GET_CODE (op) == REG
- && (REGNO (op) >= FIRST_PSEUDO_REGISTER
- || REGNO (op) == HARD_D_REGNUM
- || (mode == QImode && REGNO (op) == HARD_B_REGNUM));
-})
-
-;; TODO: Add a comment here.
-
-(define_predicate "hard_addr_reg_operand"
- (match_code "subreg,reg")
-{
- if (GET_MODE (op) != mode && mode != VOIDmode)
- return 0;
-
- if (GET_CODE (op) == SUBREG)
- op = XEXP (op, 0);
-
- return GET_CODE (op) == REG
- && (REGNO (op) == HARD_X_REGNUM
- || REGNO (op) == HARD_Y_REGNUM
- || REGNO (op) == HARD_Z_REGNUM);
-})
-
-;; TODO: Add a comment here.
-
-(define_predicate "hard_reg_operand"
- (match_code "subreg,reg")
-{
- if (GET_MODE (op) != mode && mode != VOIDmode)
- return 0;
-
- if (GET_CODE (op) == SUBREG)
- op = XEXP (op, 0);
-
- return GET_CODE (op) == REG
- && (REGNO (op) >= FIRST_PSEUDO_REGISTER
- || H_REGNO_P (REGNO (op)));
-})
-
-;; TODO: Add a comment here.
-
-(define_predicate "m68hc11_logical_operator"
- (match_code "and,ior,xor")
-{
- return GET_CODE (op) == AND || GET_CODE (op) == IOR || GET_CODE (op) == XOR;
-})
-
-;; TODO: Add a comment here.
-
-(define_predicate "m68hc11_arith_operator"
- (match_code "and,ior,xor,plus,minus,ashift,ashiftrt,lshiftrt,rotate,rotatert")
-{
- return GET_CODE (op) == AND || GET_CODE (op) == IOR || GET_CODE (op) == XOR
- || GET_CODE (op) == PLUS || GET_CODE (op) == MINUS
- || GET_CODE (op) == ASHIFT || GET_CODE (op) == ASHIFTRT
- || GET_CODE (op) == LSHIFTRT || GET_CODE (op) == ROTATE
- || GET_CODE (op) == ROTATERT;
-})
-
-;; TODO: Add a comment here.
-
-(define_predicate "m68hc11_non_shift_operator"
- (match_code "and,ior,xor,plus,minus")
-{
- return GET_CODE (op) == AND || GET_CODE (op) == IOR || GET_CODE (op) == XOR
- || GET_CODE (op) == PLUS || GET_CODE (op) == MINUS;
-})
-
-;; TODO: Add a comment here.
-
-(define_predicate "m68hc11_unary_operator"
- (match_code "neg,not,sign_extend,zero_extend")
-{
- return GET_CODE (op) == NEG || GET_CODE (op) == NOT
- || GET_CODE (op) == SIGN_EXTEND || GET_CODE (op) == ZERO_EXTEND;
-})
-
-;; Return true if op is a shift operator.
-
-(define_predicate "m68hc11_shift_operator"
- (match_code "ashift,ashiftrt,lshiftrt,rotate,rotatert")
-{
- return GET_CODE (op) == ROTATE || GET_CODE (op) == ROTATERT
- || GET_CODE (op) == LSHIFTRT || GET_CODE (op) == ASHIFT
- || GET_CODE (op) == ASHIFTRT;
-})
-
-;; TODO: Add a comment here.
-
-(define_predicate "m68hc11_eq_compare_operator"
- (match_code "eq,ne")
-{
- return GET_CODE (op) == EQ || GET_CODE (op) == NE;
-})
-
-;; TODO: Add a comment here.
-
-(define_predicate "non_push_operand"
- (match_code "subreg,reg,mem")
-{
- if (general_operand (op, mode) == 0)
- return 0;
-
- if (push_operand (op, mode) == 1)
- return 0;
- return 1;
-})
-
-;; TODO: Add a comment here.
-
-(define_predicate "splitable_operand"
- (match_code "subreg,reg,mem,symbol_ref,label_ref,const_int,const_double")
-{
- if (general_operand (op, mode) == 0)
- return 0;
-
- if (push_operand (op, mode) == 1)
- return 0;
-
- /* Reject a (MEM (MEM X)) because the patterns that use non_push_operand
- need to split such addresses to access the low and high part but it
- is not possible to express a valid address for the low part. */
- if (mode != QImode && GET_CODE (op) == MEM
- && GET_CODE (XEXP (op, 0)) == MEM)
- return 0;
- return 1;
-})
-
-;; TODO: Add a comment here.
-
-(define_predicate "reg_or_some_mem_operand"
- (match_code "subreg,reg,mem")
-{
- if (GET_CODE (op) == MEM)
- {
- rtx op0 = XEXP (op, 0);
- int addr_mode;
-
- if (symbolic_memory_operand (op0, mode))
- return 1;
-
- if (IS_STACK_PUSH (op))
- return 1;
-
- if (GET_CODE (op) == REG && reload_in_progress
- && REGNO (op) >= FIRST_PSEUDO_REGISTER
- && reg_equiv_memory_loc[REGNO (op)])
- {
- op = reg_equiv_memory_loc[REGNO (op)];
- op = eliminate_regs (op, VOIDmode, NULL_RTX);
- }
- if (GET_CODE (op) != MEM)
- return 0;
-
- op0 = XEXP (op, 0);
- addr_mode = m68hc11_addr_mode | (reload_completed ? ADDR_STRICT : 0);
- addr_mode &= ~ADDR_INDIRECT;
- return m68hc11_valid_addressing_p (op0, mode, addr_mode);
- }
-
- return register_operand (op, mode);
-})
-
-;; TODO: Add a comment here.
-
-(define_predicate "tst_operand"
- (match_code "subreg,reg,mem")
-{
- if (GET_CODE (op) == MEM && reload_completed == 0)
- {
- rtx addr = XEXP (op, 0);
- if (m68hc11_auto_inc_p (addr))
- return 0;
- }
- return nonimmediate_operand (op, mode);
-})
-
-;; TODO: Add a comment here.
-
-(define_predicate "cmp_operand"
- (match_code "subreg,reg,mem,symbol_ref,label_ref,const_int,const_double")
-{
- if (GET_CODE (op) == MEM)
- {
- rtx addr = XEXP (op, 0);
- if (m68hc11_auto_inc_p (addr))
- return 0;
- }
- return general_operand (op, mode);
-})
+++ /dev/null
-# Copyright (C) 2000, 2001, 2002, 2003, 2005,
-# 2008 Free Software Foundation, Inc.
-#
-# This file is part of GCC.
-#
-# GCC is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3, or (at your option)
-# any later version.
-#
-# GCC is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with GCC; see the file COPYING3. If not see
-# <http://www.gnu.org/licenses/>.
-
-RANLIB_FOR_TARGET = ` \
- if [ -f $(objdir)/../binutils/ranlib ] ; then \
- echo $(objdir)/../binutils/ranlib ; \
- else \
- if [ "$(host)" = "$(target)" ] ; then \
- echo ranlib; \
- else \
- if [ -f $(bindir)/$(target_noncanonical)-ranlib ] ; then \
- echo $(bindir)/$(target_noncanonical)-ranlib ; \
- else \
- t='$(program_transform_cross_name)'; echo ranlib | sed -e $$t ; \
- fi; \
- fi; \
- fi`
-
-LIB1ASMSRC = m68hc11/larith.asm
-LIB1ASMFUNCS = _mulsi3 \
- _mulqi3 _ashlsi3 _ashrsi3 _lshrsi3 \
- _divmodhi4 _mulhi3 _mulhi32 \
- _memcpy _memset _negsi2 _one_cmplsi2 \
- _regs_min _regs_frame _regs_d1_2 \
- _regs_d3_4 _regs_d5_6 _regs_d7_8 _regs_d9_16 _regs_d17_32 \
- _premain __exit _abort _cleanup \
- _adddi3 _subdi3 _notdi2 _rotlhi3 _rotrhi3 \
- _ashrhi3 _lshrhi3 _lshlhi3 _ashrqi3 _lshlqi3 _map_data _init_bss \
- _ctor _dtor _far_tramp _call_far _return_far
-
-TARGET_LIBGCC2_CFLAGS = -DUSE_GAS -DIN_GCC -Dinhibit_libc
-
-# C implementation of 32-bit div/mod.
-LIB2FUNCS_EXTRA = $(srcdir)/config/udivmodsi4.c \
- $(srcdir)/config/divmod.c $(srcdir)/config/udivmod.c
-
-# Don't compile with -g1 this reduces the size of some sections (.eh_frame).
-LIBGCC2_DEBUG_CFLAGS =-g
-LIBGCC2_CFLAGS = -Os -mrelax $(LIBGCC2_INCLUDES) $(TARGET_LIBGCC2_CFLAGS) $(LIBGCC2_DEBUG_CFLAGS) $(GTHREAD_FLAGS) -DIN_LIBGCC2
-
-MULTILIB_OPTIONS = m68hc11/m68hc12 mshort fshort-double
-MULTILIB_DIRNAMES =
-MULTILIB_MATCHES = m68hc11=m6811 m68hc12=m6812 m68hc12=m68hcs12
-MULTILIB_EXCEPTIONS = -mnoshort -mno68hc11
-
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
-
-# 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 SMALL_MACHINE' >> dp-bit.c
- echo '#define CMPtype HItype' >> dp-bit.c
- echo '#ifdef __LITTLE_ENDIAN__' >> dp-bit.c
- echo '#define FLOAT_BIT_ORDER_MISMATCH' >>dp-bit.c
- echo '#endif' >> 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 CMPtype HItype' >> fp-bit.c
- echo '#define SMALL_MACHINE' >> fp-bit.c
- echo '#ifdef __LITTLE_ENDIAN__' >> fp-bit.c
- echo '#define FLOAT_BIT_ORDER_MISMATCH' >>fp-bit.c
- echo '#endif' >> fp-bit.c
- cat $(srcdir)/config/fp-bit.c >> fp-bit.c
-
-CRT0_S = $(srcdir)/config/m68hc11/m68hc11-crt0.S
-MCRT0_S= $(srcdir)/config/m68hc11/m68hc11-crt0.S
-
-CRT0STUFF_T_CFLAGS =
-
-# Assemble startup files.
-$(T)crt1.o: $(CRT0_S) $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -c -o $(T)crt1.o -x assembler-with-cpp $(CRT0_S)
-
-EXTRA_MULTILIB_PARTS = crt1.o
+++ /dev/null
-/* Definitions of target machine for GCC. m68k/ColdFire based uClinux system
- using ELF objects with special linker post-processing to produce FLAT
- executables.
-
- Copyright (C) 2003, 2007 Free Software Foundation, Inc.
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-
-/* The old uClinux ABI used 80-byte "long double"s for ColdFire too. */
-#undef LONG_DOUBLE_TYPE_SIZE
-#define LONG_DOUBLE_TYPE_SIZE 80
-#undef LIBGCC2_LONG_DOUBLE_TYPE_SIZE
-#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 80
-
-/* Undo the definition of STARTFILE_SPEC from m68kelf.h so we'll
- pick the default from gcc.c (just link crt0.o from multilib dir). */
-#undef STARTFILE_SPEC
-
-/* Override the default LIB_SPEC from gcc.c. We don't currently support
- profiling, or libg.a. */
-#undef LIB_SPEC
-#define LIB_SPEC "\
-%{mid-shared-library:-R libc.gdb%s -elf2flt -shared-lib-id 0} -lc \
-"
-
-/* we don't want a .eh_frame section. */
-#define EH_FRAME_IN_DATA_SECTION
-
-/* ??? Quick hack to get constructors working. Make this look more like a
- COFF target, so the existing dejagnu/libgloss support works. A better
- solution would be to make the necessary dejagnu and libgloss changes so
- that we can use normal the ELF constructor mechanism. */
-#undef INIT_SECTION_ASM_OP
-#undef FINI_SECTION_ASM_OP
-#undef ENDFILE_SPEC
-#define ENDFILE_SPEC ""
-
-/* Bring in standard linux defines */
-#undef TARGET_OS_CPP_BUILTINS
-#define TARGET_OS_CPP_BUILTINS() \
- do \
- { \
- builtin_define_std ("mc68000"); \
- builtin_define ("__uClinux__"); \
- builtin_define_std ("linux"); \
- builtin_define_std ("unix"); \
- builtin_define ("__gnu_linux__"); \
- builtin_assert ("system=linux"); \
- builtin_assert ("system=unix"); \
- builtin_assert ("system=posix"); \
- if (TARGET_ID_SHARED_LIBRARY) \
- builtin_define ("__ID_SHARED_LIBRARY__"); \
- } \
- while (0)
-
+++ /dev/null
-/* Definitions of target machine for GNU compiler, for MCore using COFF/PE.
- Copyright (C) 1994, 1999, 2000, 2002, 2003, 2004, 2007
- Free Software Foundation, Inc.
- Contributed by Michael Tiemann (tiemann@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 3, or (at your option)
-any later version.
-
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-/* Run-time Target Specification. */
-#define TARGET_VERSION fputs (" (MCORE/pe)", stderr)
-
-#define TARGET_OS_CPP_BUILTINS() \
- do \
- { \
- builtin_define ("__pe__"); \
- } \
- while (0)
-
-/* The MCore ABI says that bitfields are unsigned by default. */
-/* The EPOC C++ environment does not support exceptions. */
-#undef CC1_SPEC
-#define CC1_SPEC "-funsigned-bitfields %{!DIN_GCC:-fno-rtti} %{!DIN_GCC:-fno-exceptions}"
-
-#undef SDB_DEBUGGING_INFO
-#define DBX_DEBUGGING_INFO 1
-
-/* Computed in toplev.c. */
-#undef PREFERRED_DEBUGGING_TYPE
-
-#define READONLY_DATA_SECTION_ASM_OP "\t.section .rdata"
-
-#define MCORE_EXPORT_NAME(STREAM, NAME) \
- do \
- { \
- fprintf (STREAM, "\t.section .drectve\n"); \
- fprintf (STREAM, "\t.ascii \" -export:%s\"\n", \
- (* targetm.strip_name_encoding) (NAME)); \
- in_section = NULL; \
- } \
- while (0);
-
-/* Output the label for an initialized variable. */
-#undef ASM_DECLARE_OBJECT_NAME
-#define ASM_DECLARE_OBJECT_NAME(STREAM, NAME, DECL) \
- do \
- { \
- if (mcore_dllexport_name_p (NAME)) \
- { \
- section *save_section = in_section; \
- MCORE_EXPORT_NAME (STREAM, NAME); \
- switch_to_section (save_section); \
- } \
- ASM_OUTPUT_LABEL ((STREAM), (NAME)); \
- } \
- while (0)
-
-/* Output a function label definition. */
-#define ASM_DECLARE_FUNCTION_NAME(STREAM, NAME, DECL) \
- do \
- { \
- if (mcore_dllexport_name_p (NAME)) \
- { \
- MCORE_EXPORT_NAME (STREAM, NAME); \
- switch_to_section (function_section (DECL)); \
- } \
- ASM_OUTPUT_LABEL ((STREAM), (NAME)); \
- } \
- while (0);
-
-#define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
-
-#define DBX_LINES_FUNCTION_RELATIVE 1
-
-#define STARTFILE_SPEC "crt0.o%s"
-#define ENDFILE_SPEC "%{!mno-lsim:-lsim}"
-
-/* __CTOR_LIST__ and __DTOR_LIST__ must be defined by the linker script. */
-#define CTOR_LISTS_DEFINED_EXTERNALLY
-
-#undef DO_GLOBAL_CTORS_BODY
-#undef DO_GLOBAL_DTORS_BODY
-#undef INIT_SECTION_ASM_OP
-#undef DTORS_SECTION_ASM_OP
-
-#define SUPPORTS_ONE_ONLY 1
-
-/* Switch into a generic section. */
-#undef TARGET_ASM_NAMED_SECTION
-#define TARGET_ASM_NAMED_SECTION default_pe_asm_named_section
+++ /dev/null
-# Copyright (C) 2000, 2001, 2002, 2008 Free Software Foundation, Inc.
-#
-# This file is part of GCC.
-#
-# GCC is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3, or (at your option)
-# any later version.
-#
-# GCC is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with GCC; see the file COPYING3. If not see
-# <http://www.gnu.org/licenses/>.
-
-LIB1ASMSRC = mcore/lib1.asm
-LIB1ASMFUNCS = _divsi3 _udivsi3 _modsi3 _umodsi3
-
-# 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 $(srcdir)/config/mcore/t-mcore
- rm -f dp-bit.c
- echo '' > dp-bit.c
- cat $(srcdir)/config/fp-bit.c >> dp-bit.c
-
-fp-bit.c: $(srcdir)/config/fp-bit.c $(srcdir)/config/mcore/t-mcore
- rm -f fp-bit.c
- echo '' > fp-bit.c
- echo '#define FLOAT' > fp-bit.c
- cat $(srcdir)/config/fp-bit.c >> fp-bit.c
-
-# could use -msifilter to be safe from interrupt/jmp interactions and others.
-TARGET_LIBGCC2_CFLAGS=-O3 -DNO_FLOATLIB_FIXUNSDFSI #-msifilter
-
-# We have values for float.h.
-CROSS_FLOAT_H = $(srcdir)/config/mcore/gfloat.h
-
-MULTILIB_OPTIONS = mbig-endian/mlittle-endian m210/m340
-MULTILIB_DIRNAMES = big little m210 m340
-MULTILIB_MATCHES =
-MULTILIB_EXTRA_OPTS =
-MULTILIB_EXCEPTIONS =
-
-# EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
-
-# If EXTRA_MULTILIB_PARTS is not defined above then define EXTRA_PARTS here
-# EXTRA_PARTS = crtbegin.o crtend.o
-
+++ /dev/null
-/* Common configuration file for NetBSD a.out targets.
- Copyright (C) 2002, 2007, 2010 Free Software Foundation, Inc.
- Contributed by Wasabi Systems, Inc.
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-/* TARGET_OS_CPP_BUILTINS() common to all NetBSD a.out targets. */
-#define NETBSD_OS_CPP_BUILTINS_AOUT() \
- do \
- { \
- NETBSD_OS_CPP_BUILTINS_COMMON(); \
- } \
- while (0)
-
-
-/* Provide an ASM_SPEC appropriate for NetBSD. Currently we only deal
- with the options for generating PIC code. */
-
-#undef ASM_SPEC
-#define ASM_SPEC "%{fpic|fpie:-k} %{fPIC|fPIE:-k -K}"
-
-#define AS_NEEDS_DASH_FOR_PIPED_INPUT
-
-
-/* Provide a STARTFILE_SPEC appropriate for NetBSD a.out. Here we
- provide support for the special GCC option -static. */
-
-#undef STARTFILE_SPEC
-#define STARTFILE_SPEC \
- "%{!shared: \
- %{pg:gcrt0%O%s} \
- %{!pg: \
- %{p:mcrt0%O%s} \
- %{!p: \
- %{!static:crt0%O%s} \
- %{static:scrt0%O%s}}}}"
-
-/* Provide a LINK_SPEC appropriate for NetBSD a.out. Here we provide
- support for the special GCC options -static, -assert, and -nostdlib. */
-
-#undef NETBSD_LINK_SPEC_AOUT
-#define NETBSD_LINK_SPEC_AOUT \
- "%{nostdlib:-nostdlib} \
- %{!shared: \
- %{!nostdlib: \
- %{!r: \
- %{!e*:-e start}}} \
- -dc -dp \
- %{static:-Bstatic}} \
- %{shared:-Bshareable} \
- %{R*} \
- %{assert*}"
-
-/* Default LINK_SPEC. */
-#undef LINK_SPEC
-#define LINK_SPEC NETBSD_LINK_SPEC_AOUT
-
-/* Define the strings used for the .type, .size, and .set directives.
- These strings generally do not vary from one system running NetBSD
- to another, but if a given system needs to use different pseudo-op
- names for these, they may be overridden in the file included after
- this one. */
-
-#undef TYPE_ASM_OP
-#undef SIZE_ASM_OP
-#undef SET_ASM_OP
-#define TYPE_ASM_OP "\t.type\t"
-#define SIZE_ASM_OP "\t.size\t"
-#define SET_ASM_OP "\t.set\t"
-
-
-/* This is how we tell the assembler that a symbol is weak. */
-
-#undef ASM_WEAKEN_LABEL
-#define ASM_WEAKEN_LABEL(FILE,NAME) \
- do \
- { \
- fputs ("\t.globl\t", FILE); assemble_name (FILE, NAME); \
- fputc ('\n', FILE); \
- fputs ("\t.weak\t", FILE); assemble_name (FILE, NAME); \
- fputc ('\n', FILE); \
- } \
- while (0)
-
-
-/* The following macro defines the format used to output the second
- operand of the .type assembler directive. Different svr4 assemblers
- expect various different forms of this operand. The one given here
- is just a default. You may need to override it in your machine-
- specific tm.h file (depending on the particulars of your assembler). */
-
-#undef TYPE_OPERAND_FMT
-#define TYPE_OPERAND_FMT "@%s"
-
-
-/* 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 (and a.out on NetBSD).
- 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. */
-
-#undef ASM_DECLARE_FUNCTION_NAME
-#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_FUNCTION_LABEL (FILE, NAME, DECL); \
- } \
- 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. */
-
-#undef ASM_DECLARE_FUNCTION_SIZE
-#define ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL) \
- do \
- { \
- if (!flag_inhibit_size_directive) \
- ASM_OUTPUT_MEASURED_SIZE (FILE, FNAME); \
- } \
- while (0)
+++ /dev/null
-/* Definitions of target machine for GNU compiler,
- for PowerPC machines running GNU.
- Copyright (C) 2001, 2003, 2007 Free Software Foundation, Inc.
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
- <http://www.gnu.org/licenses/>. */
-
-#undef CPP_OS_DEFAULT_SPEC
-#define CPP_OS_DEFAULT_SPEC "%(cpp_os_gnu)"
-
-#undef STARTFILE_DEFAULT_SPEC
-#define STARTFILE_DEFAULT_SPEC "%(startfile_gnu)"
-
-#undef ENDFILE_DEFAULT_SPEC
-#define ENDFILE_DEFAULT_SPEC "%(endfile_gnu)"
-
-#undef LINK_START_DEFAULT_SPEC
-#define LINK_START_DEFAULT_SPEC "%(link_start_gnu)"
-
-#undef LINK_OS_DEFAULT_SPEC
-#define LINK_OS_DEFAULT_SPEC "%(link_os_gnu)"
-
-#undef TARGET_VERSION
-#define TARGET_VERSION fprintf (stderr, " (PowerPC GNU)");
#undef ASM_SPEC
#undef LINK_OS_LINUX_SPEC
-/* FIXME: This will quite possibly choose the wrong dynamic linker. */
-#undef LINK_OS_GNU_SPEC
-#define LINK_OS_GNU_SPEC LINK_OS_LINUX_SPEC
-
#ifndef RS6000_BI_ARCH
#define ASM_DEFAULT_SPEC "-mppc64"
#define ASM_SPEC "%(asm_spec64) %(asm_spec_common)"
%{mcall-freebsd: -mbig} \
%{mcall-i960-old: -mlittle} \
%{mcall-linux: -mbig} \
- %{mcall-gnu: -mbig} \
%{mcall-netbsd: -mbig} \
}}}}"
else \
rs6000_current_abi = ABI_V4; \
} \
- else if (!strcmp (rs6000_abi_name, "gnu")) \
- rs6000_current_abi = ABI_V4; \
else if (!strcmp (rs6000_abi_name, "netbsd")) \
rs6000_current_abi = ABI_V4; \
else if (!strcmp (rs6000_abi_name, "openbsd")) \
mcall-freebsd | \
mcall-netbsd | \
mcall-openbsd | \
- mcall-linux | \
- mcall-gnu :-mbig; \
+ mcall-linux :-mbig; \
mcall-i960-old :-mlittle}"
#define CC1_ENDIAN_BIG_SPEC ""
mcall-freebsd | \
mcall-netbsd | \
mcall-openbsd | \
- mcall-linux | \
- mcall-gnu : -mbig %(cc1_endian_big); \
+ mcall-linux : -mbig %(cc1_endian_big); \
mcall-i960-old : -mlittle %(cc1_endian_little); \
: %(cc1_endian_default)} \
%{meabi: %{!mcall-*: -mcall-sysv }} \
%{mcall-freebsd: -mno-eabi } \
%{mcall-i960-old: -meabi } \
%{mcall-linux: -mno-eabi } \
- %{mcall-gnu: -mno-eabi } \
%{mcall-netbsd: -mno-eabi } \
%{mcall-openbsd: -mno-eabi }}} \
%{msdata: -msdata=default} \
msim : %(link_start_sim) ; \
mcall-freebsd: %(link_start_freebsd) ; \
mcall-linux : %(link_start_linux) ; \
- mcall-gnu : %(link_start_gnu) ; \
mcall-netbsd : %(link_start_netbsd) ; \
mcall-openbsd: %(link_start_openbsd) ; \
: %(link_start_default) }"
msim : %(link_os_sim) ; \
mcall-freebsd: %(link_os_freebsd) ; \
mcall-linux : %(link_os_linux) ; \
- mcall-gnu : %(link_os_gnu) ; \
mcall-netbsd : %(link_os_netbsd) ; \
mcall-openbsd: %(link_os_openbsd) ; \
: %(link_os_default) }"
msim : %(cpp_os_sim) ; \
mcall-freebsd: %(cpp_os_freebsd) ; \
mcall-linux : %(cpp_os_linux) ; \
- mcall-gnu : %(cpp_os_gnu) ; \
mcall-netbsd : %(cpp_os_netbsd) ; \
mcall-openbsd: %(cpp_os_openbsd) ; \
: %(cpp_os_default) }"
msim : %(startfile_sim) ; \
mcall-freebsd: %(startfile_freebsd) ; \
mcall-linux : %(startfile_linux) ; \
- mcall-gnu : %(startfile_gnu) ; \
mcall-netbsd : %(startfile_netbsd) ; \
mcall-openbsd: %(startfile_openbsd) ; \
: %(startfile_default) }"
msim : %(lib_sim) ; \
mcall-freebsd: %(lib_freebsd) ; \
mcall-linux : %(lib_linux) ; \
- mcall-gnu : %(lib_gnu) ; \
mcall-netbsd : %(lib_netbsd) ; \
mcall-openbsd: %(lib_openbsd) ; \
: %(lib_default) }"
msim : %(endfile_sim) ; \
mcall-freebsd: %(endfile_freebsd) ; \
mcall-linux : %(endfile_linux) ; \
- mcall-gnu : %(endfile_gnu) ; \
mcall-netbsd : %(endfile_netbsd) ; \
mcall-openbsd: %(endfile_openbsd) ; \
: %(crtsavres_default) %(endfile_default) }"
%{std=gnu*:-Dunix -D__unix -Dlinux -D__linux}}} \
-Asystem=linux -Asystem=unix -Asystem=posix %{pthread:-D_REENTRANT}"
-/* GNU/Hurd support. */
-#define LIB_GNU_SPEC "%{mnewlib: --start-group -lgnu -lc --end-group } \
-%{!mnewlib: %{shared:-lc} %{!shared: %{pthread:-lpthread } \
-%{profile:-lc_p} %{!profile:-lc}}}"
-
-#define STARTFILE_GNU_SPEC "\
-%{!shared: %{!static: %{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} %{!p:crt1.o%s}}}} \
-%{static: %{pg:gcrt0.o%s} %{!pg:%{p:gcrt0.o%s} %{!p:crt0.o%s}}} \
-%{mnewlib: ecrti.o%s} %{!mnewlib: crti.o%s} \
-%{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}"
-
-#define ENDFILE_GNU_SPEC "%{!shared:crtend.o%s} %{shared:crtendS.o%s} \
-%{mnewlib: ecrtn.o%s} %{!mnewlib: crtn.o%s}"
-
-#define LINK_START_GNU_SPEC ""
-
-#define LINK_OS_GNU_SPEC "-m elf32ppclinux %{!shared: %{!static: \
- %{rdynamic:-export-dynamic} \
- -dynamic-linker /lib/ld.so.1}}"
-
-#define CPP_OS_GNU_SPEC "-D__unix__ -D__gnu_hurd__ -D__GNU__ \
-%{!undef: \
- %{!ansi: -Dunix -D__unix}} \
--Asystem=gnu -Asystem=unix -Asystem=posix %{pthread:-D_REENTRANT}"
-
/* NetBSD support. */
#define LIB_NETBSD_SPEC "\
-lc"
{ "lib_mvme", LIB_MVME_SPEC }, \
{ "lib_sim", LIB_SIM_SPEC }, \
{ "lib_freebsd", LIB_FREEBSD_SPEC }, \
- { "lib_gnu", LIB_GNU_SPEC }, \
{ "lib_linux", LIB_LINUX_SPEC }, \
{ "lib_netbsd", LIB_NETBSD_SPEC }, \
{ "lib_openbsd", LIB_OPENBSD_SPEC }, \
{ "startfile_mvme", STARTFILE_MVME_SPEC }, \
{ "startfile_sim", STARTFILE_SIM_SPEC }, \
{ "startfile_freebsd", STARTFILE_FREEBSD_SPEC }, \
- { "startfile_gnu", STARTFILE_GNU_SPEC }, \
{ "startfile_linux", STARTFILE_LINUX_SPEC }, \
{ "startfile_netbsd", STARTFILE_NETBSD_SPEC }, \
{ "startfile_openbsd", STARTFILE_OPENBSD_SPEC }, \
{ "endfile_mvme", ENDFILE_MVME_SPEC }, \
{ "endfile_sim", ENDFILE_SIM_SPEC }, \
{ "endfile_freebsd", ENDFILE_FREEBSD_SPEC }, \
- { "endfile_gnu", ENDFILE_GNU_SPEC }, \
{ "endfile_linux", ENDFILE_LINUX_SPEC }, \
{ "endfile_netbsd", ENDFILE_NETBSD_SPEC }, \
{ "endfile_openbsd", ENDFILE_OPENBSD_SPEC }, \
{ "link_start_mvme", LINK_START_MVME_SPEC }, \
{ "link_start_sim", LINK_START_SIM_SPEC }, \
{ "link_start_freebsd", LINK_START_FREEBSD_SPEC }, \
- { "link_start_gnu", LINK_START_GNU_SPEC }, \
{ "link_start_linux", LINK_START_LINUX_SPEC }, \
{ "link_start_netbsd", LINK_START_NETBSD_SPEC }, \
{ "link_start_openbsd", LINK_START_OPENBSD_SPEC }, \
{ "link_os_sim", LINK_OS_SIM_SPEC }, \
{ "link_os_freebsd", LINK_OS_FREEBSD_SPEC }, \
{ "link_os_linux", LINK_OS_LINUX_SPEC }, \
- { "link_os_gnu", LINK_OS_GNU_SPEC }, \
{ "link_os_netbsd", LINK_OS_NETBSD_SPEC }, \
{ "link_os_openbsd", LINK_OS_OPENBSD_SPEC }, \
{ "link_os_default", LINK_OS_DEFAULT_SPEC }, \
{ "cpp_os_mvme", CPP_OS_MVME_SPEC }, \
{ "cpp_os_sim", CPP_OS_SIM_SPEC }, \
{ "cpp_os_freebsd", CPP_OS_FREEBSD_SPEC }, \
- { "cpp_os_gnu", CPP_OS_GNU_SPEC }, \
{ "cpp_os_linux", CPP_OS_LINUX_SPEC }, \
{ "cpp_os_netbsd", CPP_OS_NETBSD_SPEC }, \
{ "cpp_os_openbsd", CPP_OS_OPENBSD_SPEC }, \
/* Definitions of target machine for GNU compiler for Renesas / SuperH SH.
Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2003,
- 2004, 2005, 2006, 2007, 2008, 2009, 2010
+ 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
Free Software Foundation, Inc.
Contributed by Steve Chamberlain (sac@cygnus.com).
Improved by Jim Wilson (wilson@cygnus.com).
extern void sh_fix_range (const char *);
extern bool sh_hard_regno_mode_ok (unsigned int, enum machine_mode);
#endif /* ! GCC_SH_PROTOS_H */
-
-#ifdef SYMBIAN
-extern const char * sh_symbian_strip_name_encoding (const char *);
-extern bool sh_symbian_is_dllexported_name (const char *);
-#ifdef TREE_CODE
-extern bool sh_symbian_is_dllexported (tree);
-extern int sh_symbian_import_export_class (tree, int);
-extern tree sh_symbian_handle_dll_attribute (tree *, tree, tree, int, bool *);
-#ifdef RTX_CODE
-extern void sh_symbian_encode_section_info (tree, rtx, int);
-#endif
-#endif
-#endif /* SYMBIAN */
-
+++ /dev/null
-/* header file for GCC for a Symbian OS targeted SH backend.
- Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc.
- Contributed by RedHat.
- Most of this code is stolen from i386/winnt.c.
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
- <http://www.gnu.org/licenses/>. */
-
-/* A unique character to encode declspec encoded objects. */
-#define SH_SYMBIAN_FLAG_CHAR "$"
-
-/* Unique strings to prefix exported and imported objects. */
-#define DLL_IMPORT_PREFIX SH_SYMBIAN_FLAG_CHAR "i."
-#define DLL_EXPORT_PREFIX SH_SYMBIAN_FLAG_CHAR "e."
-
-/* Select the level of debugging information to display.
- 0 for no debugging.
- 1 for informative messages about decisions to add attributes
- 2 for verbose information about what is being done. */
-#define SYMBIAN_DEBUG 0
-/* #define SYMBIAN_DEBUG 1 */
-/* #define SYMBIAN_DEBUG 2 */
-
-/* Functions exported from symbian-base.c. */
-extern tree sh_symbian_associated_type (tree);
-
-/* Functions exported from symbian-[c|c++].c. */
-extern bool sh_symbian_is_dllimported (tree);
-
sh_handle_resbank_handler_attribute, false },
{ "function_vector", 1, 1, true, false, false,
sh2a_handle_function_vector_handler_attribute, false },
-#ifdef SYMBIAN
- /* Symbian support adds three new attributes:
- dllexport - for exporting a function/variable that will live in a dll
- dllimport - for importing a function/variable from a dll
-
- Microsoft allows multiple declspecs in one __declspec, separating
- them with spaces. We do NOT support this. Instead, use __declspec
- multiple times. */
- { "dllimport", 0, 0, true, false, false,
- sh_symbian_handle_dll_attribute, false },
- { "dllexport", 0, 0, true, false, false,
- sh_symbian_handle_dll_attribute, false },
-#endif
{ NULL, 0, 0, false, false, false, NULL, false }
};
#undef TARGET_ENCODE_SECTION_INFO
#define TARGET_ENCODE_SECTION_INFO sh_encode_section_info
-#ifdef SYMBIAN
-
-#undef TARGET_ENCODE_SECTION_INFO
-#define TARGET_ENCODE_SECTION_INFO sh_symbian_encode_section_info
-#undef TARGET_STRIP_NAME_ENCODING
-#define TARGET_STRIP_NAME_ENCODING sh_symbian_strip_name_encoding
-#undef TARGET_CXX_IMPORT_EXPORT_CLASS
-#define TARGET_CXX_IMPORT_EXPORT_CLASS sh_symbian_import_export_class
-
-#endif /* SYMBIAN */
-
#undef TARGET_SECONDARY_RELOAD
#define TARGET_SECONDARY_RELOAD sh_secondary_reload
{
default_file_start ();
-#ifdef SYMBIAN
- /* Declare the .directive section before it is used. */
- fputs ("\t.section .directive, \"SM\", @progbits, 1\n", asm_out_file);
- fputs ("\t.asciz \"#<SYMEDIT>#\\n\"\n", asm_out_file);
-#endif
-
if (TARGET_ELF)
/* We need to show the text section with the proper
attributes as in TEXT_SECTION_ASM_OP, before dwarf2out
+++ /dev/null
-/* Routines for GCC for a Symbian OS targeted SH backend, shared by
- both the C and C++ compilers.
- Copyright (C) 2004, 2005, 2007, 2009, 2010 Free Software Foundation, Inc.
- Contributed by RedHat.
- Most of this code is stolen from i386/winnt.c.
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
- <http://www.gnu.org/licenses/>. */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "tm.h"
-#include "rtl.h"
-#include "output.h"
-#include "flags.h"
-#include "tree.h"
-#include "expr.h"
-#include "tm_p.h"
-#include "diagnostic-core.h"
-#include "sh-symbian.h"
-
-/* Return nonzero if SYMBOL is marked as being dllexport'd. */
-
-bool
-sh_symbian_is_dllexported_name (const char *symbol)
-{
- return strncmp (DLL_EXPORT_PREFIX, symbol,
- strlen (DLL_EXPORT_PREFIX)) == 0;
-}
-
-/* Return nonzero if SYMBOL is marked as being dllimport'd. */
-
-static bool
-sh_symbian_is_dllimported_name (const char *symbol)
-{
- return strncmp (DLL_IMPORT_PREFIX, symbol,
- strlen (DLL_IMPORT_PREFIX)) == 0;
-}
-
-/* Return nonzero if DECL is a dllexport'd object. */
-
-bool
-sh_symbian_is_dllexported (tree decl)
-{
- tree exp;
-
- if ( TREE_CODE (decl) != VAR_DECL
- && TREE_CODE (decl) != FUNCTION_DECL)
- return false;
-
- exp = lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl));
-
- /* Class members get the dllexport status of their class. */
- if (exp == NULL)
- {
- tree class = sh_symbian_associated_type (decl);
-
- if (class)
- exp = lookup_attribute ("dllexport", TYPE_ATTRIBUTES (class));
- }
-#if SYMBIAN_DEBUG
- if (exp)
- {
- print_node_brief (stderr, "dllexport:", decl, 0);
- fprintf (stderr, "\n");
- }
- else
-#if SYMBIAN_DEBUG < 2
- if (TREE_CODE (decl) != FUNCTION_DECL)
-#endif
- {
- print_node_brief (stderr, "no dllexport:", decl, 0);
- fprintf (stderr, "\n");
- }
-#endif
- return exp ? true : false;
-}
-
-/* Mark a DECL as being dllimport'd. */
-
-static void
-sh_symbian_mark_dllimport (tree decl)
-{
- const char *oldname;
- char *newname;
- tree idp;
- rtx rtlname;
- rtx newrtl;
-
- rtlname = XEXP (DECL_RTL (decl), 0);
- if (MEM_P (rtlname))
- rtlname = XEXP (rtlname, 0);
- gcc_assert (GET_CODE (rtlname) == SYMBOL_REF);
- oldname = XSTR (rtlname, 0);
-
- if (sh_symbian_is_dllexported_name (oldname))
- {
- error ("%qE declared as both exported to and imported from a DLL",
- DECL_NAME (decl));
- }
- else if (sh_symbian_is_dllimported_name (oldname))
- {
- /* Already done, but do a sanity check to prevent assembler errors. */
- if (!DECL_EXTERNAL (decl) || !TREE_PUBLIC (decl))
- error ("failure in redeclaration of %q+D: dllimport%'d symbol lacks external linkage",
- decl);
- }
- else
- {
- newname = (char *) alloca (strlen (DLL_IMPORT_PREFIX) + strlen (oldname) + 1);
- sprintf (newname, "%s%s", DLL_IMPORT_PREFIX, oldname);
-
- /* We pass newname through get_identifier to ensure it has a unique
- address. RTL processing can sometimes peek inside the symbol ref
- and compare the string's addresses to see if two symbols are
- identical. */
- idp = get_identifier (newname);
- newrtl = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
- XEXP (DECL_RTL (decl), 0) = newrtl;
- }
-}
-
-/* Mark a DECL as being dllexport'd.
- Note that we override the previous setting (e.g.: dllimport). */
-
-static void
-sh_symbian_mark_dllexport (tree decl)
-{
- const char *oldname;
- char *newname;
- rtx rtlname;
- tree idp;
-
- rtlname = XEXP (DECL_RTL (decl), 0);
- if (MEM_P (rtlname))
- rtlname = XEXP (rtlname, 0);
- gcc_assert (GET_CODE (rtlname) == SYMBOL_REF);
- oldname = XSTR (rtlname, 0);
-
- if (sh_symbian_is_dllimported_name (oldname))
- {
- /* Remove DLL_IMPORT_PREFIX.
- Note - we do not issue a warning here. In Symbian's environment it
- is legitimate for a prototype to be marked as dllimport and the
- corresponding definition to be marked as dllexport. The prototypes
- are in headers used everywhere and the definition is in a translation
- unit which has included the header in order to ensure argument
- correctness. */
- oldname += strlen (DLL_IMPORT_PREFIX);
- DECL_DLLIMPORT_P (decl) = 0;
- }
- else if (sh_symbian_is_dllexported_name (oldname))
- return; /* Already done. */
-
- newname = (char *) alloca (strlen (DLL_EXPORT_PREFIX) + strlen (oldname) + 1);
- sprintf (newname, "%s%s", DLL_EXPORT_PREFIX, oldname);
-
- /* We pass newname through get_identifier to ensure it has a unique
- address. RTL processing can sometimes peek inside the symbol ref
- and compare the string's addresses to see if two symbols are
- identical. */
- idp = get_identifier (newname);
-
- XEXP (DECL_RTL (decl), 0) =
- gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
-}
-
-void
-sh_symbian_encode_section_info (tree decl, rtx rtl, int first)
-{
- default_encode_section_info (decl, rtl, first);
-
- /* Mark the decl so we can tell from the rtl whether
- the object is dllexport'd or dllimport'd. */
- if (sh_symbian_is_dllexported (decl))
- sh_symbian_mark_dllexport (decl);
- else if (sh_symbian_is_dllimported (decl))
- sh_symbian_mark_dllimport (decl);
- /* It might be that DECL has already been marked as dllimport, but a
- subsequent definition nullified that. The attribute is gone but
- DECL_RTL still has (DLL_IMPORT_PREFIX) prefixed. We need to remove
- that. Ditto for the DECL_DLLIMPORT_P flag. */
- else if ( (TREE_CODE (decl) == FUNCTION_DECL
- || TREE_CODE (decl) == VAR_DECL)
- && DECL_RTL (decl) != NULL_RTX
- && MEM_P (DECL_RTL (decl))
- && MEM_P (XEXP (DECL_RTL (decl), 0))
- && GET_CODE (XEXP (XEXP (DECL_RTL (decl), 0), 0)) == SYMBOL_REF
- && sh_symbian_is_dllimported_name (XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0)))
- {
- const char * oldname = XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0);
- /* Remove DLL_IMPORT_PREFIX. */
- tree idp = get_identifier (oldname + strlen (DLL_IMPORT_PREFIX));
- rtx newrtl = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
-
- warning (0, "%s %q+D %s after being referenced with dllimport linkage",
- TREE_CODE (decl) == VAR_DECL ? "variable" : "function",
- decl, (DECL_INITIAL (decl) || !DECL_EXTERNAL (decl))
- ? "defined locally" : "redeclared without dllimport attribute");
-
- XEXP (DECL_RTL (decl), 0) = newrtl;
-
- DECL_DLLIMPORT_P (decl) = 0;
- }
-}
-
-/* Return the length of a function name prefix
- that starts with the character 'c'. */
-
-static int
-sh_symbian_get_strip_length (int c)
-{
- /* XXX Assumes strlen (DLL_EXPORT_PREFIX) == strlen (DLL_IMPORT_PREFIX). */
- return (c == SH_SYMBIAN_FLAG_CHAR[0]) ? strlen (DLL_EXPORT_PREFIX) : 0;
-}
-
-/* Return a pointer to a function's name with any
- and all prefix encodings stripped from it. */
-
-const char *
-sh_symbian_strip_name_encoding (const char *name)
-{
- int skip;
-
- while ((skip = sh_symbian_get_strip_length (*name)))
- name += skip;
-
- return name;
-}
-
+++ /dev/null
-/* Routines for C compiler part of GCC for a Symbian OS targeted SH backend.
- Copyright (C) 2004, 2005, 2007, 2009, 2010 Free Software Foundation, Inc.
- Contributed by RedHat.
- Most of this code is stolen from i386/winnt.c.
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
- <http://www.gnu.org/licenses/>. */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "tm.h"
-#include "rtl.h"
-#include "output.h"
-#include "flags.h"
-#include "tree.h"
-#include "expr.h"
-#include "tm_p.h"
-#include "diagnostic-core.h"
-#include "sh-symbian.h"
-
-\f
-/* Return the type that we should use to determine if DECL is
- imported or exported. */
-
-tree
-sh_symbian_associated_type (tree decl)
-{
- tree t = NULL_TREE;
-
- /* We can just take the DECL_CONTEXT as normal. */
- if (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl)))
- t = DECL_CONTEXT (decl);
-
- return t;
-}
-
-/* Return nonzero if DECL is a dllimport'd object. */
-
-bool
-sh_symbian_is_dllimported (tree decl)
-{
- tree imp;
-
- if ( TREE_CODE (decl) != VAR_DECL
- && TREE_CODE (decl) != FUNCTION_DECL)
- return false;
-
- imp = lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl));
- if (imp)
- return true;
-
- /* Class members get the dllimport status of their class. */
- imp = sh_symbian_associated_type (decl);
- if (! imp)
- return false;
-
- imp = lookup_attribute ("dllimport", TYPE_ATTRIBUTES (imp));
- if (!imp)
- return false;
-
- /* Don't mark defined functions as dllimport. If the definition itself
- was marked with dllimport, then sh_symbian_handle_dll_attribute reports
- an error. This handles the case when the definition overrides an
- earlier declaration. */
- if (TREE_CODE (decl) == FUNCTION_DECL
- && DECL_INITIAL (decl)
- && ! DECL_DECLARED_INLINE_P (decl))
- {
- warning (OPT_Wattributes, "function %q+D is defined after prior "
- "declaration as dllimport: attribute ignored",
- decl);
- return false;
- }
-
- /* Don't allow definitions of static data members in dllimport
- class. Just ignore the attribute for vtable data. */
- else if (TREE_CODE (decl) == VAR_DECL
- && TREE_STATIC (decl)
- && TREE_PUBLIC (decl)
- && !DECL_EXTERNAL (decl))
- {
- error ("definition of static data member %q+D of dllimport%'d class",
- decl);
- return false;
- }
-
- return true;
-}
-
-/* Handle a "dllimport" or "dllexport" attribute;
- arguments as in struct attribute_spec.handler. */
-
-tree
-sh_symbian_handle_dll_attribute (tree *pnode, tree name, tree args,
- int flags, bool *no_add_attrs)
-{
- tree node = *pnode;
- const char *attr = IDENTIFIER_POINTER (name);
-
- /* These attributes may apply to structure and union types being
- created, but otherwise should pass to the declaration involved. */
- if (!DECL_P (node))
- {
- if (flags & ((int) ATTR_FLAG_DECL_NEXT
- | (int) ATTR_FLAG_FUNCTION_NEXT
- | (int) ATTR_FLAG_ARRAY_NEXT))
- {
- warning (OPT_Wattributes, "%qs attribute ignored", attr);
- *no_add_attrs = true;
- return tree_cons (name, args, NULL_TREE);
- }
-
- if (TREE_CODE (node) != RECORD_TYPE && TREE_CODE (node) != UNION_TYPE)
- {
- warning (OPT_Wattributes, "%qs attribute ignored", attr);
- *no_add_attrs = true;
- }
-
- return NULL_TREE;
- }
-
- /* Report error on dllimport ambiguities
- seen now before they cause any damage. */
- else if (is_attribute_p ("dllimport", name))
- {
- if (TREE_CODE (node) == VAR_DECL)
- {
- if (DECL_INITIAL (node))
- {
- error ("variable %q+D definition is marked dllimport",
- node);
- *no_add_attrs = true;
- }
-
- /* `extern' needn't be specified with dllimport.
- Specify `extern' now and hope for the best. Sigh. */
- DECL_EXTERNAL (node) = 1;
- /* Also, implicitly give dllimport'd variables declared within
- a function global scope, unless declared static. */
- if (current_function_decl != NULL_TREE && ! TREE_STATIC (node))
- TREE_PUBLIC (node) = 1;
- }
- }
-
- /* Report error if symbol is not accessible at global scope. */
- if (!TREE_PUBLIC (node)
- && ( TREE_CODE (node) == VAR_DECL
- || TREE_CODE (node) == FUNCTION_DECL))
- {
- error ("external linkage required for symbol %q+D because of %qE attribute",
- node, name);
- *no_add_attrs = true;
- }
-
-#if SYMBIAN_DEBUG
- print_node_brief (stderr, "mark node", node, 0);
- fprintf (stderr, " as %s\n", attr);
-#endif
-
- return NULL_TREE;
-}
-
-int
-sh_symbian_import_export_class (tree ctype ATTRIBUTE_UNUSED, int import_export)
-{
- return import_export;
-}
+++ /dev/null
-/* Routines for C++ support for GCC for a Symbian OS targeted SH backend.
- Copyright (C) 2004, 2005, 2007, 2009, 2010 Free Software Foundation, Inc.
- Contributed by RedHat.
- Most of this code is stolen from i386/winnt.c.
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
- <http://www.gnu.org/licenses/>. */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "tm.h"
-#include "rtl.h"
-#include "output.h"
-#include "flags.h"
-#include "tree.h"
-#include "expr.h"
-#include "tm_p.h"
-#include "cp/cp-tree.h" /* We need access to the OVL_... macros. */
-#include "diagnostic-core.h"
-#include "sh-symbian.h"
-
-\f
-/* Return the type that we should use to determine if DECL is
- imported or exported. */
-
-tree
-sh_symbian_associated_type (tree decl)
-{
- tree t = NULL_TREE;
-
- if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
- /* Methods now inherit their dllimport/dllexport attributes correctly
- so there is no need to check their class. In fact it is wrong to
- check their class since a method can remain unexported from an
- exported class. */
- return t;
-
- /* Otherwise we can just take the DECL_CONTEXT as normal. */
- if (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl)))
- t = DECL_CONTEXT (decl);
-
- return t;
-}
-
-\f
-/* Return nonzero if DECL is a dllimport'd object. */
-
-bool
-sh_symbian_is_dllimported (tree decl)
-{
- tree imp;
-
- if ( TREE_CODE (decl) != VAR_DECL
- && TREE_CODE (decl) != FUNCTION_DECL)
- return false;
-
- imp = lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl));
- if (imp)
- return true;
-
- /* Class members get the dllimport status of their class. */
- imp = sh_symbian_associated_type (decl);
- if (! imp)
- return false;
-
- imp = lookup_attribute ("dllimport", TYPE_ATTRIBUTES (imp));
- if (!imp)
- return false;
-
- /* Don't mark defined functions as dllimport. If the definition itself
- was marked with dllimport, then sh_symbian_handle_dll_attribute reports
- an error. This handles the case when the definition overrides an
- earlier declaration. */
- if (TREE_CODE (decl) == FUNCTION_DECL
- && DECL_INITIAL (decl)
- && ! DECL_DECLARED_INLINE_P (decl))
- {
- /* Don't warn about artificial methods. */
- if (!DECL_ARTIFICIAL (decl))
- warning (OPT_Wattributes, "function %q+D is defined after prior "
- "declaration as dllimport: attribute ignored",
- decl);
- return false;
- }
-
- /* We ignore the dllimport attribute for inline member functions.
- This differs from MSVC behavior which treats it like GNUC
- 'extern inline' extension. */
- else if (TREE_CODE (decl) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl))
- {
- if (extra_warnings)
- warning (OPT_Wattributes, "inline function %q+D is declared as "
- "dllimport: attribute ignored",
- decl);
- return false;
- }
-
- /* Don't allow definitions of static data members in dllimport
- class. Just ignore the attribute for vtable data. */
- else if (TREE_CODE (decl) == VAR_DECL
- && TREE_STATIC (decl)
- && TREE_PUBLIC (decl)
- && !DECL_EXTERNAL (decl))
- {
- if (!DECL_VIRTUAL_P (decl))
- error ("definition of static data member %q+D of dllimport%'d class",
- decl);
- return false;
- }
-
- /* Since we can't treat a pointer to a dllimport'd symbol as a
- constant address, we turn off the attribute on C++ virtual
- methods to allow creation of vtables using thunks. Don't mark
- artificial methods either (in sh_symbian_associated_type, only
- COMDAT artificial method get import status from class context). */
- else if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE
- && (DECL_VIRTUAL_P (decl) || DECL_ARTIFICIAL (decl)))
- return false;
-
- return true;
-}
-
-\f
-/* This code implements a specification for exporting the vtable and rtti of
- classes that have members with the dllexport or dllexport attributes.
- This specification is defined here:
-
- http://www.armdevzone.com/EABI/exported_class.txt
-
- Basically it says that a class's vtable and rtti should be exported if
- the following rules apply:
-
- - If it has any non-inline non-pure virtual functions,
- at least one of these need to be declared dllimport
- OR any of the constructors is declared dllimport.
-
- AND
-
- - The class has an inline constructor/destructor and
- a key-function (placement of vtable uniquely defined) that
- is defined in this translation unit.
-
- The specification also says that for classes which will have their
- vtables and rtti exported that their base class(es) might also need a
- similar exporting if:
-
- - Every base class needs to have its vtable & rtti exported
- as well, if the following the conditions hold true:
- + The base class has a non-inline declared non-pure virtual function
- + The base class is polymorphic (has or inherits any virtual functions)
- or the base class has any virtual base classes. */
-
-/* Decide if a base class of a class should
- also have its vtable and rtti exported. */
-
-static void
-sh_symbian_possibly_export_base_class (tree base_class)
-{
- VEC(tree,gc) *method_vec;
- int len;
-
- if (! (TYPE_CONTAINS_VPTR_P (base_class)))
- return;
-
- method_vec = CLASSTYPE_METHOD_VEC (base_class);
- len = method_vec ? VEC_length (tree, method_vec) : 0;
-
- for (;len --;)
- {
- tree member = VEC_index (tree, method_vec, len);
-
- if (! member)
- continue;
-
- for (member = OVL_CURRENT (member); member; member = OVL_NEXT (member))
- {
- if (TREE_CODE (member) != FUNCTION_DECL)
- continue;
-
- if (DECL_CONSTRUCTOR_P (member) || DECL_DESTRUCTOR_P (member))
- continue;
-
- if (! DECL_VIRTUAL_P (member))
- continue;
-
- if (DECL_PURE_VIRTUAL_P (member))
- continue;
-
- if (DECL_DECLARED_INLINE_P (member))
- continue;
-
- break;
- }
-
- if (member)
- break;
- }
-
- if (len < 0)
- return;
-
- /* FIXME: According to the spec this base class should be exported, but
- a) how do we do this ? and
- b) it does not appear to be necessary for compliance with the Symbian
- OS which so far is the only consumer of this code. */
-#if SYMBIAN_DEBUG
- print_node_brief (stderr, "", base_class, 0);
- fprintf (stderr, " EXPORTed [base class of exported class]\n");
-#endif
-}
-
-/* Add the named attribute to the given node. Copes with both DECLs and
- TYPEs. Will only add the attribute if it is not already present. */
-
-static void
-sh_symbian_add_attribute (tree node, const char *attr_name)
-{
- tree attrs;
- tree attr;
-
- attrs = DECL_P (node) ? DECL_ATTRIBUTES (node) : TYPE_ATTRIBUTES (node);
-
- if (lookup_attribute (attr_name, attrs) != NULL_TREE)
- return;
-
- attr = get_identifier (attr_name);
-
- if (DECL_P (node))
- DECL_ATTRIBUTES (node) = tree_cons (attr, NULL_TREE, attrs);
- else
- TYPE_ATTRIBUTES (node) = tree_cons (attr, NULL_TREE, attrs);
-
-#if SYMBIAN_DEBUG
- fprintf (stderr, "propagate %s attribute", attr_name);
- print_node_brief (stderr, " to", node, 0);
- fprintf (stderr, "\n");
-#endif
-}
-
-/* Add the named attribute to a class and its vtable and rtti. */
-
-static void
-sh_symbian_add_attribute_to_class_vtable_and_rtti (tree ctype, const char *attr_name)
-{
- sh_symbian_add_attribute (ctype, attr_name);
-
- /* If the vtable exists then they need annotating as well. */
- if (CLASSTYPE_VTABLES (ctype))
- /* XXX - Do we need to annotate any vtables other than the primary ? */
- sh_symbian_add_attribute (CLASSTYPE_VTABLES (ctype), attr_name);
-
- /* If the rtti exists then it needs annotating as well. */
- if (TYPE_MAIN_VARIANT (ctype)
- && CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (ctype)))
- sh_symbian_add_attribute (CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (ctype)),
- attr_name);
-}
-
-/* Decide if a class needs to have an attribute because
- one of its member functions has the attribute. */
-
-static bool
-sh_symbian_class_needs_attribute (tree ctype, const char *attribute_name)
-{
- VEC(tree,gc) *method_vec;
-
- method_vec = CLASSTYPE_METHOD_VEC (ctype);
-
- /* If the key function has the attribute then the class needs it too. */
- if (TYPE_POLYMORPHIC_P (ctype)
- && method_vec
- && tree_contains_struct [TREE_CODE (ctype), TS_DECL_COMMON] == 1
- && lookup_attribute (attribute_name,
- DECL_ATTRIBUTES (VEC_index (tree, method_vec, 0))))
- return true;
-
- /* Check the class's member functions. */
- if (TREE_CODE (ctype) == RECORD_TYPE)
- {
- unsigned int len;
-
- len = method_vec ? VEC_length (tree, method_vec) : 0;
-
- for (;len --;)
- {
- tree member = VEC_index (tree, method_vec, len);
-
- if (! member)
- continue;
-
- for (member = OVL_CURRENT (member);
- member;
- member = OVL_NEXT (member))
- {
- if (TREE_CODE (member) != FUNCTION_DECL)
- continue;
-
- if (DECL_PURE_VIRTUAL_P (member))
- continue;
-
- if (! DECL_VIRTUAL_P (member))
- continue;
-
- if (lookup_attribute (attribute_name, DECL_ATTRIBUTES (member)))
- {
-#if SYMBIAN_DEBUG
- print_node_brief (stderr, "", ctype, 0);
- fprintf (stderr, " inherits %s because", attribute_name);
- print_node_brief (stderr, "", member, 0);
- fprintf (stderr, " has it.\n");
-#endif
- return true;
- }
- }
- }
- }
-
-#if SYMBIAN_DEBUG
- print_node_brief (stderr, "", ctype, 0);
- fprintf (stderr, " does not inherit %s\n", attribute_name);
-#endif
- return false;
-}
-
-/* Decide if a class needs its vtable and rtti exporting. */
-
-static bool
-symbian_export_vtable_and_rtti_p (tree ctype)
-{
- bool inline_ctor_dtor;
- bool dllimport_ctor_dtor;
- bool dllimport_member;
- tree binfo, base_binfo;
- VEC(tree,gc) *method_vec;
- tree key;
- int i;
- int len;
-
- /* Make sure that we are examining a class... */
- if (TREE_CODE (ctype) != RECORD_TYPE)
- {
-#if SYMBIAN_DEBUG
- print_node_brief (stderr, "", ctype, 0);
- fprintf (stderr, " does NOT need to be EXPORTed [not a class]\n");
-#endif
- return false;
- }
-
- /* If the class does not have a key function it
- does not need to have its vtable exported. */
- if ((key = CLASSTYPE_KEY_METHOD (ctype)) == NULL_TREE)
- {
-#if SYMBIAN_DEBUG
- print_node_brief (stderr, "", ctype, 0);
- fprintf (stderr, " does NOT need to be EXPORTed [no key function]\n");
-#endif
- return false;
- }
-
- /* If the key fn has not been defined
- then the class should not be exported. */
- if (! TREE_ASM_WRITTEN (key))
- {
-#if SYMBIAN_DEBUG
- print_node_brief (stderr, "", ctype, 0);
- fprintf (stderr, " does NOT need to be EXPORTed [key function not defined]\n");
-#endif
- return false;
- }
-
- /* Check the class's member functions. */
- inline_ctor_dtor = false;
- dllimport_ctor_dtor = false;
- dllimport_member = false;
-
- method_vec = CLASSTYPE_METHOD_VEC (ctype);
- len = method_vec ? VEC_length (tree, method_vec) : 0;
-
- for (;len --;)
- {
- tree member = VEC_index (tree, method_vec, len);
-
- if (! member)
- continue;
-
- for (member = OVL_CURRENT (member); member; member = OVL_NEXT (member))
- {
- if (TREE_CODE (member) != FUNCTION_DECL)
- continue;
-
- if (DECL_CONSTRUCTOR_P (member) || DECL_DESTRUCTOR_P (member))
- {
- if (DECL_DECLARED_INLINE_P (member)
- /* Ignore C++ backend created inline ctors/dtors. */
- && ( DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (member)
- || DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (member)))
- inline_ctor_dtor = true;
-
- if (lookup_attribute ("dllimport", DECL_ATTRIBUTES (member)))
- dllimport_ctor_dtor = true;
- }
- else
- {
- if (DECL_PURE_VIRTUAL_P (member))
- continue;
-
- if (! DECL_VIRTUAL_P (member))
- continue;
-
- if (DECL_DECLARED_INLINE_P (member))
- continue;
-
- if (lookup_attribute ("dllimport", DECL_ATTRIBUTES (member)))
- dllimport_member = true;
- }
- }
- }
-
- if (! dllimport_member && ! dllimport_ctor_dtor)
- {
-#if SYMBIAN_DEBUG
- print_node_brief (stderr, "", ctype, 0);
- fprintf (stderr,
- " does NOT need to be EXPORTed [no non-pure virtuals or ctors/dtors with dllimport]\n");
-#endif
- return false;
- }
-
- if (! inline_ctor_dtor)
- {
-#if SYMBIAN_DEBUG
- print_node_brief (stderr, "", ctype, 0);
- fprintf (stderr,
- " does NOT need to be EXPORTed [no inline ctor/dtor]\n");
-#endif
- return false;
- }
-
-#if SYMBIAN_DEBUG
- print_node_brief (stderr, "", ctype, 0);
- fprintf (stderr, " DOES need to be EXPORTed\n");
-#endif
-
- /* Now we must check and possibly export the base classes. */
- for (i = 0, binfo = TYPE_BINFO (ctype);
- BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
- sh_symbian_possibly_export_base_class (BINFO_TYPE (base_binfo));
-
- return true;
-}
-
-/* Possibly override the decision to export class TYPE. Upon entry
- IMPORT_EXPORT will contain 1 if the class is going to be exported,
- -1 if it is going to be imported and 0 otherwise. This function
- should return the modified value and perform any other actions
- necessary to support the backend's targeted operating system. */
-
-int
-sh_symbian_import_export_class (tree ctype, int import_export)
-{
- const char *attr_name = NULL;
-
- /* If we are exporting the class but it does not have the dllexport
- attribute then we may need to add it. Similarly imported classes
- may need the dllimport attribute. */
- switch (import_export)
- {
- case 1: attr_name = "dllexport"; break;
- case -1: attr_name = "dllimport"; break;
- default: break;
- }
-
- if (attr_name
- && ! lookup_attribute (attr_name, TYPE_ATTRIBUTES (ctype)))
- {
- if (sh_symbian_class_needs_attribute (ctype, attr_name))
- sh_symbian_add_attribute_to_class_vtable_and_rtti (ctype, attr_name);
-
- /* Classes can be forced to export their
- vtable and rtti under certain conditions. */
- if (symbian_export_vtable_and_rtti_p (ctype))
- {
- sh_symbian_add_attribute_to_class_vtable_and_rtti (ctype, "dllexport");
-
- /* Make sure that the class and its vtable are exported. */
- import_export = 1;
-
- if (CLASSTYPE_VTABLES (ctype))
- DECL_EXTERNAL (CLASSTYPE_VTABLES (ctype)) = 1;
-
- /* Check to make sure that if the class has a key method that
- it is now on the list of keyed classes. That way its vtable
- will be emitted. */
- if (CLASSTYPE_KEY_METHOD (ctype))
- {
- tree class;
-
- for (class = keyed_classes; class; class = TREE_CHAIN (class))
- if (class == ctype)
- break;
-
- if (class == NULL_TREE)
- {
-#if SYMBIAN_DEBUG
- print_node_brief (stderr, "Add node", ctype, 0);
- fprintf (stderr, " to the keyed classes list\n");
-#endif
- keyed_classes = tree_cons (NULL_TREE, ctype, keyed_classes);
- }
- }
-
- /* Make sure that the typeinfo will be emitted as well. */
- if (CLASS_TYPE_P (ctype))
- TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (ctype)))) = 1;
- }
- }
-
- return import_export;
-}
-
-/* Handle a "dllimport" or "dllexport" attribute;
- arguments as in struct attribute_spec.handler. */
-
-tree
-sh_symbian_handle_dll_attribute (tree *pnode, tree name, tree args,
- int flags, bool *no_add_attrs)
-{
- tree thunk;
- tree node = *pnode;
- const char *attr = IDENTIFIER_POINTER (name);
-
- /* These attributes may apply to structure and union types being
- created, but otherwise should pass to the declaration involved. */
- if (!DECL_P (node))
- {
- if (flags & ((int) ATTR_FLAG_DECL_NEXT
- | (int) ATTR_FLAG_FUNCTION_NEXT
- | (int) ATTR_FLAG_ARRAY_NEXT))
- {
- warning (OPT_Wattributes, "%qs attribute ignored", attr);
- *no_add_attrs = true;
- return tree_cons (name, args, NULL_TREE);
- }
-
- if (TREE_CODE (node) != RECORD_TYPE && TREE_CODE (node) != UNION_TYPE)
- {
- warning (OPT_Wattributes, "%qs attribute ignored", attr);
- *no_add_attrs = true;
- }
-
- return NULL_TREE;
- }
-
- /* Report error on dllimport ambiguities
- seen now before they cause any damage. */
- else if (is_attribute_p ("dllimport", name))
- {
- if (TREE_CODE (node) == VAR_DECL)
- {
- if (DECL_INITIAL (node))
- {
- error ("variable %q+D definition is marked dllimport",
- node);
- *no_add_attrs = true;
- }
-
- /* `extern' needn't be specified with dllimport.
- Specify `extern' now and hope for the best. Sigh. */
- DECL_EXTERNAL (node) = 1;
- /* Also, implicitly give dllimport'd variables declared within
- a function global scope, unless declared static. */
- if (current_function_decl != NULL_TREE && ! TREE_STATIC (node))
- TREE_PUBLIC (node) = 1;
- }
- }
-
- /* If the node is an overloaded constructor or destructor, then we must
- make sure that the attribute is propagated along the overload chain,
- as it is these overloaded functions which will be emitted, rather than
- the user declared constructor itself. */
- if (TREE_CODE (TREE_TYPE (node)) == METHOD_TYPE
- && (DECL_CONSTRUCTOR_P (node) || DECL_DESTRUCTOR_P (node)))
- {
- tree overload;
-
- for (overload = OVL_CHAIN (node); overload; overload = OVL_CHAIN (overload))
- {
- tree node_args;
- tree func_args;
- tree function = OVL_CURRENT (overload);
-
- if (! function
- || ! DECL_P (function)
- || (DECL_CONSTRUCTOR_P (node) && ! DECL_CONSTRUCTOR_P (function))
- || (DECL_DESTRUCTOR_P (node) && ! DECL_DESTRUCTOR_P (function)))
- continue;
-
- /* The arguments must match as well. */
- for (node_args = DECL_ARGUMENTS (node), func_args = DECL_ARGUMENTS (function);
- node_args && func_args;
- node_args = TREE_CHAIN (node_args), func_args = TREE_CHAIN (func_args))
- if (TREE_TYPE (node_args) != TREE_TYPE (func_args))
- break;
-
- if (node_args || func_args)
- {
- /* We can ignore an extraneous __in_chrg arguments in the node.
- GCC generated destructors, for example, will have this. */
- if ((node_args == NULL_TREE
- || func_args != NULL_TREE)
- && strcmp (IDENTIFIER_POINTER (DECL_NAME (node)), "__in_chrg") != 0)
- continue;
- }
-
- sh_symbian_add_attribute (function, attr);
-
- /* Propagate the attribute to any function thunks as well. */
- for (thunk = DECL_THUNKS (function); thunk; thunk = DECL_CHAIN (thunk))
- if (TREE_CODE (thunk) == FUNCTION_DECL)
- sh_symbian_add_attribute (thunk, attr);
- }
- }
-
- if (TREE_CODE (node) == FUNCTION_DECL && DECL_VIRTUAL_P (node))
- {
- /* Propagate the attribute to any thunks of this function. */
- for (thunk = DECL_THUNKS (node); thunk; thunk = DECL_CHAIN (thunk))
- if (TREE_CODE (thunk) == FUNCTION_DECL)
- sh_symbian_add_attribute (thunk, attr);
- }
-
- /* Report error if symbol is not accessible at global scope. */
- if (!TREE_PUBLIC (node)
- && ( TREE_CODE (node) == VAR_DECL
- || TREE_CODE (node) == FUNCTION_DECL))
- {
- error ("external linkage required for symbol %q+D because of %qE attribute",
- node, name);
- *no_add_attrs = true;
- }
-
-#if SYMBIAN_DEBUG
- print_node_brief (stderr, "mark node", node, 0);
- fprintf (stderr, " as %s\n", attr);
-#endif
-
- return NULL_TREE;
-}
+++ /dev/null
-/* Definitions for the Symbian OS running on an SH part.
- This file is included after all the other target specific headers.
-
- Copyright (C) 2004, 2007 Free Software Foundation, Inc.
- Contributed by Red Hat.
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
- <http://www.gnu.org/licenses/>. */
-
-#undef TARGET_VERSION
-#define TARGET_VERSION \
- fputs (" (Renesas SH for Symbian OS)", stderr);
-
-#undef LINK_EMUL_PREFIX
-#define LINK_EMUL_PREFIX "shlsymbian"
-
-
-#define SYMBIAN_EXPORT_NAME(NAME,FILE,DECL) \
- do \
- { \
- if ((DECL && sh_symbian_is_dllexported (DECL)) \
- || sh_symbian_is_dllexported_name (NAME)) \
- { \
- fprintf ((FILE), "\t.pushsection .directive\n"); \
- fprintf ((FILE), "\t.asciz \"EXPORT %s\\n\"\n", \
- sh_symbian_strip_name_encoding (NAME)); \
- fprintf ((FILE), "\t.popsection\n"); \
- } \
- } \
- while (0)
-
-/* Output a function definition label. */
-#undef ASM_DECLARE_FUNCTION_NAME
-#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
- do \
- { \
- SYMBIAN_EXPORT_NAME ((NAME), (FILE), (DECL)); \
- ASM_OUTPUT_TYPE_DIRECTIVE ((FILE), (NAME), "function"); \
- ASM_DECLARE_RESULT ((FILE), DECL_RESULT (DECL)); \
- ASM_OUTPUT_LABEL ((FILE), (NAME)); \
- } \
- while (0)
-
-/* Output the label for an initialized variable. */
-#undef ASM_DECLARE_OBJECT_NAME
-#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL) \
- do \
- { \
- HOST_WIDE_INT size; \
- \
- SYMBIAN_EXPORT_NAME ((NAME), (FILE), (DECL)); \
- 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)
-
-#undef ASM_OUTPUT_LABELREF
-#define ASM_OUTPUT_LABELREF(FILE, NAME) \
- do \
- { \
- asm_fprintf ((FILE), "%U%s", \
- sh_symbian_strip_name_encoding (NAME)); \
- } \
- while (0)
+++ /dev/null
-/* Definitions for the Symbian OS running on an SH part.
- This file is included before any other target specific headers.
-
- Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc.
- Contributed by Red Hat.
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
- <http://www.gnu.org/licenses/>. */
-
-/* Enable Symbian specific code. */
-#define SYMBIAN 1
-
-/* Default to using the Renesas ABI. */
-#define TARGET_ABI_DEFAULT MASK_HITACHI
-
-#define SUBTARGET_CPP_SPEC ""
-
-/* Get tree.c to declare merge_dllimport_decl_attributes(). */
-#define TARGET_DLLIMPORT_DECL_ATTRIBUTES 1
-
-/* The Symbian OS currently does not support exception handling. */
-#define SUBTARGET_CC1PLUS_SPEC "-fno-exceptions"
-
-/* Create constructor/destructor sections without the writable flag.
- Symbian puts them into the text segment and munges them later on. */
-#define CTORS_SECTION_ASM_OP "\t.section\t.ctors,\"ax\",@progbits"
-#define DTORS_SECTION_ASM_OP "\t.section\t.dtors,\"ax\",@progbits"
+++ /dev/null
-# Copyright (C) 2004, 2006, 2008, 2009 Free Software Foundation, Inc.
-#
-# This file is part of GCC.
-#
-# GCC is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3, or (at your option)
-# any later version.
-#
-# GCC is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with GCC; see the file COPYING3. If not see
-# <http://www.gnu.org/licenses/>.
-
-sh-c.o: $(srcdir)/config/sh/sh-c.c \
- $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(TM_H) $(TM_P_H) coretypes.h
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
- $(srcdir)/config/sh/sh-c.c
-
-symbian-cxx.o: \
- $(srcdir)/config/sh/symbian-cxx.c \
- $(srcdir)/config/sh/sh-symbian.h \
- $(CONFIG_H) $(SYSTEM_H) $(TM_H) $(TREE_H) $(RTL_H) \
- toplev.h output.h coretypes.h flags.h expr.h
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
-
-symbian-c.o: \
- $(srcdir)/config/sh/symbian-c.c \
- $(srcdir)/config/sh/sh-symbian.h \
- $(CONFIG_H) $(SYSTEM_H) $(TM_H) $(TREE_H) $(RTL_H) \
- toplev.h output.h coretypes.h flags.h expr.h
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
-
-symbian-base.o: \
- $(srcdir)/config/sh/symbian-base.c \
- $(srcdir)/config/sh/sh-symbian.h \
- $(CONFIG_H) $(SYSTEM_H) $(TM_H) $(TREE_H) $(RTL_H) \
- toplev.h output.h coretypes.h flags.h expr.h
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
-
-
-LIB1ASMSRC = sh/lib1funcs.asm
-LIB1ASMFUNCS = _ashiftrt _ashiftrt_n _ashiftlt _lshiftrt _movstr \
- _movstr_i4 _mulsi3 _sdivsi3 _sdivsi3_i4 _udivsi3 _udivsi3_i4 _set_fpscr \
- $(LIB1ASMFUNCS_CACHE)
-
-# 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
- cat $(srcdir)/config/fp-bit.c >> dp-bit.c
-
-fp-bit.c: $(srcdir)/config/fp-bit.c
- echo '#define FLOAT' > fp-bit.c
- cat $(srcdir)/config/fp-bit.c >> fp-bit.c
-
-$(T)crt1.o: $(srcdir)/config/sh/crt1.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -c -o $(T)crt1.o -x assembler-with-cpp $(srcdir)/config/sh/crt1.asm
-$(T)crti.o: $(srcdir)/config/sh/crti.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/sh/crti.asm
-$(T)crtn.o: $(srcdir)/config/sh/crtn.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/sh/crtn.asm
-
-$(out_object_file): gt-sh.h
-gt-sh.h : s-gtype ; @true
-
-symbian.o: $(srcdir)/config/sh/symbian.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(RTL_H) output.h flags.h $(TREE_H) expr.h toplev.h $(TM_P_H)
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
- $(srcdir)/config/sh/symbian.c
-
-
-# Local Variables:
-# mode: Makefile
-# End:
+++ /dev/null
-/* Operating system specific defines to be used when targeting GCC for
- generic System V Release 3 system.
- Copyright (C) 1991, 1996, 2000, 2002, 2004, 2007, 2010
- Free Software Foundation, Inc.
- Contributed by Ron Guilmette (rfg@monkeys.com).
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-/* Define a symbol indicating that we are using svr3.h. */
-#define USING_SVR3_H
-
-/* Define a symbol so that libgcc* can know what sort of operating
- environment and assembler syntax we are targeting for. */
-#define SVR3_target
-
-/* Assembler, linker, library, and startfile spec's. */
-
-/* The .file command should always begin the output. */
-#define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
-
-/* This says how to output an assembler line
- to define a global common symbol. */
-/* We don't use ROUNDED because the standard compiler doesn't,
- and the linker gives error messages if a common symbol
- has more than one length value. */
-
-#undef ASM_OUTPUT_COMMON
-#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
-( fputs (".comm ", (FILE)), \
- assemble_name ((FILE), (NAME)), \
- fprintf ((FILE), ",%lu\n", (unsigned long)(SIZE)))
-
-/* This says how to output an assembler line
- to define a local common symbol. */
-
-/* Note that using bss_section here caused errors
- in building shared libraries on system V.3. */
-#undef ASM_OUTPUT_LOCAL
-#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
- do { \
- int align = exact_log2 (ROUNDED); \
- if (align > 2) align = 2; \
- switch_to_section (data_section); \
- ASM_OUTPUT_ALIGN ((FILE), align == -1 ? 2 : align); \
- ASM_OUTPUT_LABEL ((FILE), (NAME)); \
- fprintf ((FILE), "\t.set .,.+%u\n", (int)(ROUNDED)); \
- } while (0)
-
-/* Output #ident as a .ident. */
-
-#undef ASM_OUTPUT_IDENT
-#define ASM_OUTPUT_IDENT(FILE, NAME) \
- fprintf (FILE, "\t.ident \"%s\"\n", NAME);
-
-/* Use periods rather than dollar signs in special g++ assembler names. */
-
-#define NO_DOLLAR_IN_LABEL
-
-/* System V Release 3 uses COFF debugging info. */
-
-#define SDB_DEBUGGING_INFO 1
-
-/* We don't want to output DBX debugging information. */
-
-#undef DBX_DEBUGGING_INFO
-
-/* The prefix to add to user-visible assembler symbols.
-
- For System V Release 3 the convention is to prepend a leading
- underscore onto user-level symbol names. */
-
-#undef USER_LABEL_PREFIX
-#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'.
-
- For most svr3 systems, the convention is that any symbol which begins
- with a period is not put into the linker symbol table by the assembler. */
-
-#undef ASM_GENERATE_INTERNAL_LABEL
-#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
- sprintf (LABEL, "*%s%s%ld", LOCAL_LABEL_PREFIX, PREFIX, (long)(NUM))
-
-/* We want local labels to start with period if made with asm_fprintf. */
-#undef LOCAL_LABEL_PREFIX
-#define LOCAL_LABEL_PREFIX "."
-
-/* Support const sections and the ctors and dtors sections for g++. */
-
-/* Define a few machine-specific details of the implementation of
- constructors.
-
- The __CTORS_LIST__ goes in the .init section. Define CTOR_LIST_BEGIN
- and CTOR_LIST_END to contribute to the .init section an instruction to
- push a word containing 0 (or some equivalent of that).
-
- Define TARGET_ASM_CONSTRUCTOR to push the address of the constructor. */
-
-#define INIT_SECTION_ASM_OP "\t.section\t.init"
-#define FINI_SECTION_ASM_OP "\t.section .fini,\"x\""
-#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. */
-
-#ifndef STACK_GROWS_DOWNWARD
-
-/* 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)
-
-#else
-
-/* Constructor list on stack is in correct order. Just call them. */
-#define DO_GLOBAL_CTORS_BODY \
-do { \
- func_ptr *p, *beg = alloca (0); \
- for (p = beg; *p; ) \
- (*p++) (); \
-} while (0)
-
-#endif /* STACK_GROWS_DOWNWARD */
+++ /dev/null
-/* Definitions of target machine for GNU compiler.
- NetBSD/vax a.out version.
- Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2007
- Free Software Foundation, Inc.
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-
-#define TARGET_OS_CPP_BUILTINS() \
- do \
- { \
- NETBSD_OS_CPP_BUILTINS_AOUT(); \
- } \
- while (0)
-
-#undef CPP_SPEC
-#define CPP_SPEC NETBSD_CPP_SPEC
-
-/* Make gcc agree with <machine/ansi.h> */
-
-#undef SIZE_TYPE
-#define SIZE_TYPE "unsigned int"
-
-#undef PTRDIFF_TYPE
-#define PTRDIFF_TYPE "int"
-
-/* Until they use ELF or something that handles dwarf2 unwinds
- and initialization stuff better. Use sjlj exceptions. */
-#undef DWARF2_UNWIND_INFO
-
-/* We use gas, not the UNIX assembler. */
-#undef TARGET_DEFAULT
-#define TARGET_DEFAULT 0
# and later they can use TFmode.
case "$target" in
powerpc*-*-linux* | \
- powerpc*-*-gnu* | \
sparc*-*-linux* | \
s390*-*-linux* | \
alpha*-*-linux*)
# and later they can use TFmode.
case "$target" in
powerpc*-*-linux* | \
- powerpc*-*-gnu* | \
sparc*-*-linux* | \
s390*-*-linux* | \
alpha*-*-linux*)
@item interrupt
@cindex interrupt handler functions
-Use this attribute on the ARM, AVR, CRX, M32C, M32R/D, m68k, MeP, MIPS,
+Use this attribute on the ARM, AVR, M32C, M32R/D, m68k, MeP, MIPS,
RX and Xstormy16 ports to indicate that the specified function is an
interrupt handler. The compiler will generate function entry and exit
sequences suitable for use in an interrupt handler when this attribute
-@c Copyright (C) 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+@c Copyright (C) 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+@c 1999, 2000, 2001, 2002, 2003, 2011 Free Software Foundation, Inc.
@c This is part of the GCC manual.
@c For copying conditions, see the file install.texi.
@c gmicro, fx80, spur and tahoe omitted since they don't work.
1750a, a29k, alpha, arm, avr, c@var{n}, clipper, dsp16xx, elxsi, fr30, h8300,
hppa1.0, hppa1.1, i370, i386, i486, i586, i686, i786, i860, i960, ip2k, m32r,
-m68000, m68k, m6811, m6812, m88k, mcore, mips, mipsel, mips64, mips64el,
+m68000, m68k, m88k, mcore, mips, mipsel, mips64, mips64el,
mn10200, mn10300, ns32k, pdp11, powerpc, powerpcle, romp, rs6000, sh, sparc,
sparclite, sparc64, v850, vax, we32k.
@end quotation
Some targets provide finer-grained control over which multilibs are built
(e.g., @option{--disable-softfloat}):
@table @code
-@item arc-*-elf*
-biendian.
-
@item arm-*-*
fpu, 26bit, underscore, interwork, biendian, nofmult.
@item
@uref{#alpha-dec-osf51,,alpha*-dec-osf5.1}
@item
-@uref{#arc-x-elf,,arc-*-elf}
-@item
@uref{#arm-x-elf,,arm-*-elf}
@item
@uref{#avr,,avr}
@item
@uref{#m32r-x-elf,,m32r-*-elf}
@item
-@uref{#m6811-elf,,m6811-elf}
-@item
-@uref{#m6812-elf,,m6812-elf}
-@item
@uref{#m68k-x-x,,m68k-*-*}
@item
@uref{#m68k-uclinux,,m68k-uclinux}
@c FIXME: still applicable?
-@html
-<hr />
-@end html
-@heading @anchor{arc-x-elf}arc-*-elf
-Argonaut ARC processor.
-This configuration is intended for embedded systems.
-
@html
<hr />
@end html
information about this platform is available at
@uref{http://developer.axis.com/}.
-@html
-<hr />
-@end html
-@heading @anchor{crx}CRX
-
-The CRX CompactRISC architecture is a low-power 32-bit architecture with
-fast context switching and architectural extensibility features.
-
-@ifnothtml
-@xref{CRX Options,, CRX Options, gcc, Using and Porting the GNU Compiler
-Collection (GCC)},
-@end ifnothtml
-
-@ifhtml
-See ``CRX Options'' in the main manual for a list of CRX-specific options.
-@end ifhtml
-
-Use @samp{configure --target=crx-elf --enable-languages=c,c++} to configure
-GCC@ for building a CRX cross-compiler. The option @samp{--target=crx-elf}
-is also used to build the @samp{newlib} C library for CRX.
-
-It is also possible to build libstdc++-v3 for the CRX architecture. This
-needs to be done in a separate step with the following configure settings:
-
-@smallexample
-gcc/libstdc++-v3/configure --host=crx-elf --with-newlib \
- --enable-sjlj-exceptions --enable-cxx-flags='-fexceptions -frtti'
-@end smallexample
-
@html
<hr />
@end html
Renesas M32R processor.
This configuration is intended for embedded systems.
-@html
-<hr />
-@end html
-@heading @anchor{m6811-elf}m6811-elf
-Motorola 68HC11 family micro controllers. These are used in embedded
-applications. There are no standard Unix configurations.
-
-@html
-<hr />
-@end html
-@heading @anchor{m6812-elf}m6812-elf
-Motorola 68HC12 family micro controllers. These are used in embedded
-applications. There are no standard Unix configurations.
-
@html
<hr />
@end html
GCC 4.3 changed the uClinux configuration so that it uses the
@samp{m68k-linux-gnu} ABI rather than the @samp{m68k-elf} ABI.
It also added improved support for C++ and flat shared libraries,
-both of which were ABI changes. However, you can still use the
-original ABI by configuring for @samp{m68k-uclinuxoldabi} or
-@samp{m68k-@var{vendor}-uclinuxoldabi}.
+both of which were ABI changes.
@html
@c Try and put the significant identifier (CPU or system) first,
@c so users have a clue at guessing where the ones they want will be.
-@emph{ARC Options}
-@gccoptlist{-EB -EL @gol
--mmangle-cpu -mcpu=@var{cpu} -mtext=@var{text-section} @gol
--mdata=@var{data-section} -mrodata=@var{readonly-data-section}}
-
@emph{ARM Options}
@gccoptlist{-mapcs-frame -mno-apcs-frame @gol
-mabi=@var{name} @gol
-melf -maout -melinux -mlinux -sim -sim2 @gol
-mmul-bug-workaround -mno-mul-bug-workaround}
-@emph{CRX Options}
-@gccoptlist{-mmac -mpush-args}
-
@emph{Darwin Options}
@gccoptlist{-all_load -allowable_client -arch -arch_errors_fatal @gol
-arch_only -bind_at_load -bundle -bundle_loader @gol
-mshared-library-id=n -mid-shared-library -mno-id-shared-library @gol
-mxgot -mno-xgot}
-@emph{M68hc1x Options}
-@gccoptlist{-m6811 -m6812 -m68hc11 -m68hc12 -m68hcs12 @gol
--mauto-incdec -minmax -mlong-calls -mshort @gol
--msoft-reg-count=@var{count}}
-
@emph{MCore Options}
@gccoptlist{-mhardlit -mno-hardlit -mdiv -mno-div -mrelax-immediates @gol
-mno-relax-immediates -mwide-bitfields -mno-wide-bitfields @gol
@c in Machine Dependent Options
@menu
-* ARC Options::
* ARM Options::
* AVR Options::
* Blackfin Options::
* CRIS Options::
-* CRX Options::
* Darwin Options::
* DEC Alpha Options::
* DEC Alpha/VMS Options::
* M32C Options::
* M32R/D Options::
* M680x0 Options::
-* M68hc1x Options::
* MCore Options::
* MeP Options::
* MicroBlaze Options::
* zSeries Options::
@end menu
-@node ARC Options
-@subsection ARC Options
-@cindex ARC Options
-
-These options are defined for ARC implementations:
-
-@table @gcctabopt
-@item -EL
-@opindex EL
-Compile code for little endian mode. This is the default.
-
-@item -EB
-@opindex EB
-Compile code for big endian mode.
-
-@item -mmangle-cpu
-@opindex mmangle-cpu
-Prepend the name of the CPU to all public symbol names.
-In multiple-processor systems, there are many ARC variants with different
-instruction and register set characteristics. This flag prevents code
-compiled for one CPU to be linked with code compiled for another.
-No facility exists for handling variants that are ``almost identical''.
-This is an all or nothing option.
-
-@item -mcpu=@var{cpu}
-@opindex mcpu
-Compile code for ARC variant @var{cpu}.
-Which variants are supported depend on the configuration.
-All variants support @option{-mcpu=base}, this is the default.
-
-@item -mtext=@var{text-section}
-@itemx -mdata=@var{data-section}
-@itemx -mrodata=@var{readonly-data-section}
-@opindex mtext
-@opindex mdata
-@opindex mrodata
-Put functions, data, and readonly data in @var{text-section},
-@var{data-section}, and @var{readonly-data-section} respectively
-by default. This can be overridden with the @code{section} attribute.
-@xref{Variable Attributes}.
-
-@end table
-
@node ARM Options
@subsection ARM Options
@cindex ARM options
0x40000000 and zero-initialized data at 0x80000000.
@end table
-@node CRX Options
-@subsection CRX Options
-@cindex CRX Options
-
-These options are defined specifically for the CRX ports.
-
-@table @gcctabopt
-
-@item -mmac
-@opindex mmac
-Enable the use of multiply-accumulate instructions. Disabled by default.
-
-@item -mpush-args
-@opindex mpush-args
-Push instructions will be used to pass outgoing arguments when functions
-are called. Enabled by default.
-@end table
-
@node Darwin Options
@subsection Darwin Options
@cindex Darwin options
@end table
-@node M68hc1x Options
-@subsection M68hc1x Options
-@cindex M68hc1x options
-
-These are the @samp{-m} options defined for the 68hc11 and 68hc12
-microcontrollers. The default values for these options depends on
-which style of microcontroller was selected when the compiler was configured;
-the defaults for the most common choices are given below.
-
-@table @gcctabopt
-@item -m6811
-@itemx -m68hc11
-@opindex m6811
-@opindex m68hc11
-Generate output for a 68HC11. This is the default
-when the compiler is configured for 68HC11-based systems.
-
-@item -m6812
-@itemx -m68hc12
-@opindex m6812
-@opindex m68hc12
-Generate output for a 68HC12. This is the default
-when the compiler is configured for 68HC12-based systems.
-
-@item -m68S12
-@itemx -m68hcs12
-@opindex m68S12
-@opindex m68hcs12
-Generate output for a 68HCS12.
-
-@item -mauto-incdec
-@opindex mauto-incdec
-Enable the use of 68HC12 pre and post auto-increment and auto-decrement
-addressing modes.
-
-@item -minmax
-@itemx -mnominmax
-@opindex minmax
-@opindex mnominmax
-Enable the use of 68HC12 min and max instructions.
-
-@item -mlong-calls
-@itemx -mno-long-calls
-@opindex mlong-calls
-@opindex mno-long-calls
-Treat all calls as being far away (near). If calls are assumed to be
-far away, the compiler will use the @code{call} instruction to
-call a function and the @code{rtc} instruction for returning.
-
-@item -mshort
-@opindex mshort
-Consider type @code{int} to be 16 bits wide, like @code{short int}.
-
-@item -msoft-reg-count=@var{count}
-@opindex msoft-reg-count
-Specify the number of pseudo-soft registers which are used for the
-code generation. The maximum number is 32. Using more pseudo-soft
-register may or may not result in better code depending on the program.
-The default is 4 for 68HC11 and 2 for 68HC12.
-
-@end table
-
@node MCore Options
@subsection MCore Options
@cindex MCore options
On System V.4 and embedded PowerPC systems compile code for the
Linux-based GNU system.
-@item -mcall-gnu
-@opindex mcall-gnu
-On System V.4 and embedded PowerPC systems compile code for the
-Hurd-based GNU system.
-
@item -mcall-freebsd
@opindex mcall-freebsd
On System V.4 and embedded PowerPC systems compile code for the
@opindex mhitachi
Comply with the calling conventions defined for GCC before the Renesas
conventions were available. This option is the default for all
-targets of the SH toolchain except for @samp{sh-symbianelf}.
+targets of the SH toolchain.
@item -mnomacsave
@opindex mnomacsave
A memory address based on Y or Z pointer with displacement.
@end table
-@item CRX Architecture---@file{config/crx/crx.h}
-@table @code
-
-@item b
-Registers from r0 to r14 (registers without stack pointer)
-
-@item l
-Register r16 (64-bit accumulator lo register)
-
-@item h
-Register r17 (64-bit accumulator hi register)
-
-@item k
-Register pair r16-r17. (64-bit accumulator lo-hi pair)
-
-@item I
-Constant that fits in 3 bits
-
-@item J
-Constant that fits in 4 bits
-
-@item K
-Constant that fits in 5 bits
-
-@item L
-Constant that is one of @minus{}1, 4, @minus{}4, 7, 8, 12, 16, 20, 32, 48
-
-@item G
-Floating point constant that is legal for store immediate
-@end table
-
@item Hewlett-Packard PA-RISC---@file{config/pa/pa.h}
@table @code
@item a
@end table
-@item Motorola 68HC11 & 68HC12 families---@file{config/m68hc11/m68hc11.h}
-@table @code
-@item a
-Register `a'
-
-@item b
-Register `b'
-
-@item d
-Register `d'
-
-@item q
-An 8-bit register
-
-@item t
-Temporary soft register _.tmp
-
-@item u
-A soft register _.d1 to _.d31
-
-@item w
-Stack pointer register
-
-@item x
-Register `x'
-
-@item y
-Register `y'
-
-@item z
-Pseudo register `z' (replaced by `x' or `y' at the end)
-
-@item A
-An address register: x, y or z
-
-@item B
-An address register: x or y
-
-@item D
-Register pair (x:d) to form a 32-bit value
-
-@item L
-Constants in the range @minus{}65536 to 65535
-
-@item M
-Constants whose 16-bit low part is zero
-
-@item N
-Constant integer 1 or @minus{}1
-
-@item O
-Constant integer 16
-
-@item P
-Constants in the range @minus{}8 to 2
-
-@end table
-
@item Moxie---@file{config/moxie/constraints.md}
@table @code
@item A
+2011-03-22 Joseph Myers <joseph@codesourcery.com>
+
+ * gcc.c-torture/execute/920501-8.x: Remove.
+ * gcc.c-torture/execute/930513-1.x: Remove.
+ * gcc.c-torture/execute/960312-1.x: Remove.
+ * gcc.c-torture/compile/20000804-1.c,
+ gcc.c-torture/compile/20001205-1.c,
+ gcc.c-torture/compile/20001226-1.c,
+ gcc.c-torture/compile/20010518-2.c,
+ gcc.c-torture/compile/20020312-1.c,
+ gcc.c-torture/compile/20020604-1.c,
+ gcc.c-torture/compile/920501-12.c,
+ gcc.c-torture/compile/920501-4.c,
+ gcc.c-torture/compile/920520-1.c,
+ gcc.c-torture/compile/980506-1.c,
+ gcc.c-torture/execute/980709-1.x,
+ gcc.c-torture/execute/990826-0.x: Don't XFAIL or use special
+ options for m68hc11.
+ * gcc.dg/cpp/assert4.c: Don't handle ARC.
+ * gcc.dg/sibcall-3.c, gcc.dg/sibcall-4.c: Don't XFAIL for arc or
+ m68hc11.
+
2011-03-22 Nick Clifton <nickc@redhat.com>
* lib/target-supports.exp (check_profiling_available): Add MN10300
-/* This does not work on m68hc11 or h8300 due to the use of an asm
+/* This does not work on h8300 due to the use of an asm
statement to force a 'long long' (64-bits) to go in a register. */
/* { dg-do assemble } */
/* { dg-skip-if "" { { i?86-*-* x86_64-*-* } && { ilp32 && { ! nonpic } } } { "*" } { "" } } */
/* { dg-skip-if "No 64-bit registers" { m32c-*-* } { "*" } { "" } } */
/* { dg-skip-if "Not enough 64-bit registers" { pdp11-*-* } { "-O0" } { "" } } */
-/* { dg-xfail-if "" { m6811-*-* m6812-*-* h8300-*-* } { "*" } { "" } } */
+/* { dg-xfail-if "" { h8300-*-* } { "*" } { "" } } */
/* Copyright (C) 2000, 2003 Free Software Foundation */
__complex__ long long f ()
-/* This does not work on m68hc11 due to the asm statement which forces
- two 'long' (32-bits) variables to go in registers. */
/* { dg-do assemble } */
-/* { dg-xfail-if "" { m6811-*-* m6812-*-* } { "*" } { "" } } */
static inline unsigned long rdfpcr(void)
{
-/* This does not assemble on m68hc11 because the function is larger
- than 64K. */
/* { dg-do assemble } */
-/* { dg-xfail-if "function larger than 64K" { m6811-*-* } { "*" } { "" } } */
/* { dg-skip-if "too much code for avr" { "avr-*-*" } { "*" } { "" } } */
/* { dg-skip-if "too much code for pdp11" { "pdp11-*-*" } { "*" } { "" } } */
/* { dg-xfail-if "jump beyond 128K not supported" { xtensa*-*-* } { "-O0" } { "" } } */
/* { dg-do compile } */
-/* This test fails on HC11/HC12 when it is compiled without -mshort because
- the array is too large (INT_MAX/2 > 64K). Force to use 16-bit ints
- for it. */
-/* { dg-options "-w -mshort" { target m6811-*-* m6812-*-* } } */
-
/* Large static storage. */
#include <limits.h>
-/* This does not compile on HC11/HC12 due to the asm which requires
- two 32-bit registers. */
/* { dg-do assemble } */
-/* { dg-xfail-if "" { m6811-*-* m6812-*-* } { "*" } { "" } } */
/* { dg-skip-if "" { pdp11-*-* } { "-O0" } { "" } } */
/* PR optimization/5892 */
/* { dg-do assemble } */
-/* { dg-xfail-if "The array is too big" { "m6811-*-* m6812-*-*" } { "*" } { "" } } */
/* { dg-skip-if "The array is too big" { "avr-*-*" "pdp11-*-*" } { "*" } { "" } } */
/* { dg-xfail-if "The array too big" { "h8300-*-*" } { "-mno-h" "-mn" } { "" } } */
/* { dg-skip-if "" { m32c-*-* } { } { } } */
-/* This test fails on HC11/HC12 when it is compiled without -mshort because
- the stack arrays are too large. Force to use 16-bit ints for it. */
/* { dg-do assemble } */
-/* { dg-xfail-if "" { m6811-*-* m6812-*-* } { "*" } { "-mshort" } } */
x(x){ return 3 + x;}
a(x){int y[994]; return 3 + x;}
-/* This test fails on HC11/HC12 when it is compiled without -mshort because
- the 'r0' array is too large. Force to use 16-bit ints for it. */
/* { dg-do assemble } */
-/* { dg-xfail-if "" { m6811-*-* m6812-*-* } { "*" } { "-mshort" } } */
foo ()
{
/* { dg-do compile } */
-/* { dg-xfail-if "" { m6811-*-* m6812-*-* } { "*" } { "" } } */
/* { dg-skip-if "" { pdp11-*-* } { "*" } { "" } } */
f(){asm("%0"::"r"(1.5F));}g(){asm("%0"::"r"(1.5));}
/* The arrays are too large for the xstormy16 - won't fit in 16 bits. */
/* { dg-do assemble } */
/* { dg-require-effective-target size32plus } */
-/* { dg-xfail-if "The array too big" { m6811-*-* m6812-*-* } { "*" } { "" } } /*
/* { dg-skip-if "Array too big" { "avr-*-*" } { "*" } { "" } } */
/* { dg-xfail-if "The array too big" { h8300-*-* } { "-mno-h" "-mn" } { "" } } */
+++ /dev/null
-# sprintf() does not support %f on m6811/m6812 target.
-if { [istarget "m6811-*-*"] || [istarget "m6812-*-*"]} {
- return 1
-}
-return 0
+++ /dev/null
-# sprintf() does not support %f on m6811/m6812 target.
-if { [istarget "m6811-*-*"] || [istarget "m6812-*-*"]} {
- return 1
-}
-return 0
+++ /dev/null
-# This test fails on HC11/HC12 when it is compiled without -mshort because
-# is uses an asm that requires two 32-bit registers (int). It passes
-# when using -mshort because there are enough registers; force -mshort.
-if { [istarget "m6811-*-*"] || [istarget "m6812-*-*"] } {
- set options "-mshort"
-}
-return 0
-# pow() is not available on m6811/m6812 target, this test will not link.
-if { [istarget "m6811-*-*"] || [istarget "m6812-*-*"]} {
- return 1
-}
# XFAIL this test for AIX using -msoft-float.
# This test calls the system libm.a function pow.
# A false failure is reported if -msoft-float is used.
-# floor() is not available on m6811/m6812 target, this test will not link.
-if { [istarget "m6811-*-*"] || [istarget "m6812-*-*"]} {
- return 1
-}
# XFAIL this test for AIX using -msoft-float.
# This test calls the system libm.a function floor.
# A false failure is reported if -msoft-float is used.
/* Check for #cpu and #machine assertions. */
-#if defined __arc__
-# if !#cpu(arc) || !#machine(arc)
-# error
-# endif
-#elif #cpu(arc) || #machine(arc)
-# error
-#endif
-
#if defined __alpha__
# if !#cpu(alpha) || !#machine(alpha) \
|| (defined __alpha_cix__ && !#cpu(cix)) \
Copyright (C) 2002 Free Software Foundation Inc.
Contributed by Hans-Peter Nilsson <hp@bitrange.com> */
-/* { dg-do run { xfail { { arc-*-* avr-*-* cris-*-* crisv32-*-* h8300-*-* hppa*64*-*-* m32r-*-* m68hc1?-*-* mcore-*-* mn10300-*-* xstormy16-*-* v850*-*-* vax-*-* xtensa*-*-* } || { arm*-*-* && { ! arm32 } } } } } */
+/* { dg-do run { xfail { { avr-*-* cris-*-* crisv32-*-* h8300-*-* hppa*64*-*-* m32r-*-* mcore-*-* mn10300-*-* xstormy16-*-* v850*-*-* vax-*-* xtensa*-*-* } || { arm*-*-* && { ! arm32 } } } } } */
/* -mlongcall disables sibcall patterns. */
/* { dg-skip-if "" { powerpc*-*-* } { "-mlongcall" } { "" } } */
/* { dg-options "-O2 -foptimize-sibling-calls" } */
Copyright (C) 2002 Free Software Foundation Inc.
Contributed by Hans-Peter Nilsson <hp@bitrange.com> */
-/* { dg-do run { xfail { { arc-*-* avr-*-* cris-*-* crisv32-*-* h8300-*-* hppa*64*-*-* m32r-*-* m68hc1?-*-* mcore-*-* mn10300-*-* xstormy16-*-* v850*-*-* vax-*-* xtensa*-*-* } || { arm*-*-* && { ! arm32 } } } } } */
+/* { dg-do run { xfail { { avr-*-* cris-*-* crisv32-*-* h8300-*-* hppa*64*-*-* m32r-*-* mcore-*-* mn10300-*-* xstormy16-*-* v850*-*-* vax-*-* xtensa*-*-* } || { arm*-*-* && { ! arm32 } } } } } */
/* -mlongcall disables sibcall patterns. */
/* { dg-skip-if "" { powerpc*-*-* } { "-mlongcall" } { "" } } */
/* { dg-options "-O2 -foptimize-sibling-calls" } */
+2011-03-22 Joseph Myers <joseph@codesourcery.com>
+
+ * config.host (alpha*-*-gnu*, arc-*-elf*, arm*-*-netbsd*,
+ arm-*-pe*, crx-*-elf, i[34567]86-*-netbsd*, i[34567]86-*-pe,
+ m68hc11-*-*|m6811-*-*, m68hc12-*-*|m6812-*-*, mcore-*-pe*,
+ powerpc64-*-gnu*, powerpc-*-gnu-gnualtivec*, powerpc-*-gnu*,
+ sh-*-symbianelf* | sh[12346l]*-*-symbianelf*, vax-*-netbsd*):
+ Remove cases.
+
2011-03-14 Andreas Tobler <andreast@fgznet.ch>
* config.host (cpu_type): Add FreeBSD PowerPC specific parts.
then tmake_file=${cpu_type}/t-$rest
fi
;;
-alpha*-*-linux* | alpha*-*-gnu*)
+alpha*-*-linux*)
tmake_file="${tmake_file} alpha/t-crtfm"
extra_parts="$extra_parts crtfastmath.o"
;;
alpha*-dec-*vms*)
tmake_file="vms/t-vms alpha/t-vms"
;;
-arc-*-elf*)
- ;;
arm-wrs-vxworks)
;;
arm*-*-freebsd*)
;;
arm*-*-netbsdelf*)
;;
-arm*-*-netbsd*)
- ;;
arm*-*-linux*) # ARM GNU/Linux with ELF
;;
arm*-*-uclinux*) # ARM ucLinux
;;
arm*-wince-pe*)
;;
-arm-*-pe*)
- ;;
avr-*-rtems*)
;;
avr-*-*)
;;
cris-*-linux* | crisv32-*-linux*)
;;
-crx-*-elf)
- ;;
fido-*-elf)
;;
fr30-*-elf)
;;
i[34567]86-*-netbsdelf*)
;;
-i[34567]86-*-netbsd*)
- ;;
x86_64-*-netbsd*)
;;
i[34567]86-*-openbsd2.*|i[34567]86-*openbsd3.[0123])
;;
i[4567]86-wrs-vxworks|i[4567]86-wrs-vxworksae)
;;
-i[34567]86-*-pe)
- ;;
i[34567]86-*-cygwin* | i[34567]86-*-mingw*)
extra_parts="crtbegin.o crtend.o crtfastmath.o"
tmake_file="i386/t-cygming i386/t-crtfm"
;;
m32rle-*-linux*)
;;
-m68hc11-*-*|m6811-*-*)
- ;;
-m68hc12-*-*|m6812-*-*)
- ;;
m68k-*-elf*)
;;
m68k*-*-netbsdelf*)
;;
mcore-*-elf)
;;
-mcore-*-pe*)
- ;;
microblaze*-*-*)
tmake_file="microblaze/t-microblaze"
;;
powerpc-*-linux* | powerpc64-*-linux*)
tmake_file="${tmake_file} rs6000/t-ppccomm rs6000/t-ldbl128 t-softfp"
;;
-powerpc64-*-gnu*)
- tmake_file="${tmake_file} rs6000/t-ldbl128 t-softfp"
- ;;
-powerpc-*-gnu-gnualtivec*)
- tmake_file="${tmake_file} rs6000/t-ldbl128"
- ;;
-powerpc-*-gnu*)
- tmake_file="${tmake_file} rs6000/t-ldbl128"
- ;;
powerpc-wrs-vxworks|powerpc-wrs-vxworksae)
;;
powerpc-*-lynxos*)
score-*-elf)
;;
sh-*-elf* | sh[12346l]*-*-elf* | \
-sh-*-symbianelf* | sh[12346l]*-*-symbianelf* | \
sh-*-linux* | sh[2346lbe]*-*-linux* | \
sh-*-netbsdelf* | shl*-*-netbsdelf* | sh5-*-netbsd* | sh5l*-*-netbsd* | \
sh64-*-netbsd* | sh64l*-*-netbsd*)
;;
vax-*-netbsdelf*)
;;
-vax-*-netbsd*)
- ;;
vax-*-openbsd*)
;;
xstormy16-*-elf)
+2011-03-22 Joseph Myers <joseph@codesourcery.com>
+
+ * configure.ac: Don't handle powerpc*-*-gnu*.
+ * configure: Regenerate.
+
2011-03-22 Paolo Carlini <paolo.carlini@oracle.com>
* testsuite/21_strings/basic_string/cons/char/moveable2.cc: Tweak
ac_ldbl_compat=no
case "$target" in
powerpc*-*-linux* | \
- powerpc*-*-gnu* | \
sparc*-*-linux* | \
s390*-*-linux* | \
alpha*-*-linux*)
ac_ldbl_compat=no
case "$target" in
powerpc*-*-linux* | \
- powerpc*-*-gnu* | \
sparc*-*-linux* | \
s390*-*-linux* | \
alpha*-*-linux*)