aboutsummaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config')
-rw-r--r--gcc/config/1750a/1750a.h2
-rw-r--r--gcc/config/a29k/a29k.c1
-rw-r--r--gcc/config/a29k/xm-a29k.h5
-rw-r--r--gcc/config/a29k/xm-unix.h4
-rw-r--r--gcc/config/alpha/alpha-protos.h1
-rw-r--r--gcc/config/alpha/alpha.c91
-rw-r--r--gcc/config/alpha/alpha.h43
-rw-r--r--gcc/config/alpha/alpha.md65
-rw-r--r--gcc/config/alpha/elf.h35
-rw-r--r--gcc/config/alpha/freebsd.h4
-rw-r--r--gcc/config/alpha/linux.h60
-rw-r--r--gcc/config/alpha/osf.h65
-rw-r--r--gcc/config/alpha/osf5.h34
-rw-r--r--gcc/config/alpha/t-interix5
-rw-r--r--gcc/config/alpha/t-osf410
-rw-r--r--gcc/config/alpha/xm-alpha.h5
-rw-r--r--gcc/config/arc/arc.c1
-rw-r--r--gcc/config/arc/arc.h9
-rw-r--r--gcc/config/arc/initfini.c2
-rw-r--r--gcc/config/arc/xm-arc.h4
-rw-r--r--gcc/config/arm/aof.h2
-rw-r--r--gcc/config/arm/arm.c17
-rw-r--r--gcc/config/arm/arm.h12
-rw-r--r--gcc/config/arm/arm.md12
-rw-r--r--gcc/config/arm/coff.h7
-rw-r--r--gcc/config/arm/conix-elf.h17
-rw-r--r--gcc/config/arm/elf.h13
-rw-r--r--gcc/config/arm/linux-elf.h50
-rw-r--r--gcc/config/arm/rtems-elf.h2
-rw-r--r--gcc/config/arm/unknown-elf.h17
-rw-r--r--gcc/config/arm/xm-arm.h6
-rw-r--r--gcc/config/avr/avr.c18
-rw-r--r--gcc/config/avr/avr.h9
-rw-r--r--gcc/config/avr/avr.md9
-rw-r--r--gcc/config/avr/libgcc.S5
-rw-r--r--gcc/config/c4x/c4x.c2
-rw-r--r--gcc/config/c4x/c4x.h30
-rw-r--r--gcc/config/c4x/xm-c4x.h5
-rw-r--r--gcc/config/clipper/clipper.c1
-rw-r--r--gcc/config/clipper/xm-clix.h4
-rw-r--r--gcc/config/convex/convex.c1
-rw-r--r--gcc/config/convex/xm-convex.h4
-rw-r--r--gcc/config/d30v/d30v.c1
-rw-r--r--gcc/config/d30v/d30v.h22
-rw-r--r--gcc/config/d30v/xm-d30v.h4
-rw-r--r--gcc/config/dbxelf.h22
-rw-r--r--gcc/config/dsp16xx/dsp16xx.c1
-rw-r--r--gcc/config/dsp16xx/dsp16xx.h3
-rw-r--r--gcc/config/dsp16xx/xm-dsp16xx.h4
-rw-r--r--gcc/config/elfos.h15
-rw-r--r--gcc/config/elxsi/xm-elxsi.h5
-rw-r--r--gcc/config/fr30/fr30.c1
-rw-r--r--gcc/config/fr30/xm-fr30.h4
-rw-r--r--gcc/config/freebsd-nthr.h (renamed from gcc/config/arm/linux-elf26.h)12
-rw-r--r--gcc/config/freebsd.h92
-rw-r--r--gcc/config/freebsd3.h (renamed from gcc/config/arm/linux-oldld.h)15
-rw-r--r--gcc/config/freebsd4.h22
-rw-r--r--gcc/config/freebsd5.h22
-rw-r--r--gcc/config/freebsd6.h22
-rw-r--r--gcc/config/h8300/h8300.c5
-rw-r--r--gcc/config/h8300/h8300.h11
-rw-r--r--gcc/config/h8300/h8300.md56
-rw-r--r--gcc/config/h8300/t-h83003
-rw-r--r--gcc/config/h8300/xm-h8300.h5
-rw-r--r--gcc/config/i370/i370.c1
-rw-r--r--gcc/config/i370/i370.h1
-rw-r--r--gcc/config/i370/i370.md4
-rw-r--r--gcc/config/i370/xm-i370.h5
-rw-r--r--gcc/config/i370/xm-linux.h4
-rw-r--r--gcc/config/i370/xm-mvs.h5
-rw-r--r--gcc/config/i370/xm-oe.h3
-rw-r--r--gcc/config/i386/att.h7
-rw-r--r--gcc/config/i386/beos-elf.h12
-rw-r--r--gcc/config/i386/bsd.h5
-rw-r--r--gcc/config/i386/cygwin.h144
-rw-r--r--gcc/config/i386/dgux.c4
-rw-r--r--gcc/config/i386/djgpp.h41
-rw-r--r--gcc/config/i386/freebsd-aout.h12
-rw-r--r--gcc/config/i386/freebsd.h4
-rw-r--r--gcc/config/i386/gas.h1
-rw-r--r--gcc/config/i386/gnu.h3
-rw-r--r--gcc/config/i386/i386-aout.h2
-rw-r--r--gcc/config/i386/i386-coff.h2
-rw-r--r--gcc/config/i386/i386-interix.h2
-rw-r--r--gcc/config/i386/i386-protos.h6
-rw-r--r--gcc/config/i386/i386.c448
-rw-r--r--gcc/config/i386/i386.h79
-rw-r--r--gcc/config/i386/i386.md257
-rw-r--r--gcc/config/i386/i386afe.h37
-rw-r--r--gcc/config/i386/i386elf.h34
-rw-r--r--gcc/config/i386/linux.h123
-rw-r--r--gcc/config/i386/netbsd.h5
-rw-r--r--gcc/config/i386/openbsd.h7
-rw-r--r--gcc/config/i386/osf1elf.h15
-rw-r--r--gcc/config/i386/osfrose.h112
-rw-r--r--gcc/config/i386/ptx4-i.h34
-rw-r--r--gcc/config/i386/sco5.h65
-rw-r--r--gcc/config/i386/sol2.h21
-rw-r--r--gcc/config/i386/sun386.h5
-rw-r--r--gcc/config/i386/svr3gas.h4
-rw-r--r--gcc/config/i386/sysv4.h57
-rw-r--r--gcc/config/i386/t-beos3
-rw-r--r--gcc/config/i386/t-cygwin2
-rw-r--r--gcc/config/i386/t-interix3
-rw-r--r--gcc/config/i386/t-openbsd6
-rw-r--r--gcc/config/i386/vsta.h4
-rw-r--r--gcc/config/i386/win-nt.h4
-rw-r--r--gcc/config/i386/win32.h4
-rw-r--r--gcc/config/i386/winnt.c39
-rw-r--r--gcc/config/i386/xm-aix.h2
-rw-r--r--gcc/config/i386/xm-cygwin.h25
-rw-r--r--gcc/config/i386/xm-i386.h4
-rw-r--r--gcc/config/i386/xm-osf.h2
-rw-r--r--gcc/config/i860/i860.c1
-rw-r--r--gcc/config/i860/varargs.asm201
-rw-r--r--gcc/config/i860/xm-i860.h4
-rw-r--r--gcc/config/i960/i960.c4
-rw-r--r--gcc/config/i960/i960.h1
-rw-r--r--gcc/config/i960/xm-i960.h4
-rw-r--r--gcc/config/ia64/crtbegin.asm45
-rw-r--r--gcc/config/ia64/crtend.asm14
-rw-r--r--gcc/config/ia64/fde-glibc.c160
-rw-r--r--gcc/config/ia64/frame-ia64.c1272
-rw-r--r--gcc/config/ia64/hpux.h92
-rw-r--r--gcc/config/ia64/ia64.c498
-rw-r--r--gcc/config/ia64/ia64.h124
-rw-r--r--gcc/config/ia64/ia64.md109
-rw-r--r--gcc/config/ia64/lib1funcs.asm11
-rw-r--r--gcc/config/ia64/libgcc-ia64.ver1
-rw-r--r--gcc/config/ia64/linux.h4
-rw-r--r--gcc/config/ia64/sysv4.h7
-rw-r--r--gcc/config/ia64/t-hpux6
-rw-r--r--gcc/config/ia64/t-ia643
-rw-r--r--gcc/config/ia64/unwind-ia64.c2015
-rw-r--r--gcc/config/ia64/unwind-ia64.h (renamed from gcc/config/ia64/frame-ia64.h)23
-rw-r--r--gcc/config/ia64/xm-ia64.h4
-rw-r--r--gcc/config/linux.h13
-rw-r--r--gcc/config/m32r/m32r.c1
-rw-r--r--gcc/config/m32r/xm-m32r.h4
-rw-r--r--gcc/config/m68hc11/larith.asm255
-rw-r--r--gcc/config/m68hc11/m68hc11-protos.h11
-rw-r--r--gcc/config/m68hc11/m68hc11.c663
-rw-r--r--gcc/config/m68hc11/m68hc11.h210
-rw-r--r--gcc/config/m68hc11/m68hc11.md1166
-rw-r--r--gcc/config/m68hc11/m68hc12.h5
-rw-r--r--gcc/config/m68hc11/t-m68hc11-gas6
-rw-r--r--gcc/config/m68k/3b1.h4
-rw-r--r--gcc/config/m68k/auxgas.h8
-rw-r--r--gcc/config/m68k/crds.h4
-rw-r--r--gcc/config/m68k/hp320.h4
-rw-r--r--gcc/config/m68k/linux-aout.h3
-rw-r--r--gcc/config/m68k/linux.h3
-rw-r--r--gcc/config/m68k/m68k.c7
-rw-r--r--gcc/config/m68k/m68k.h136
-rw-r--r--gcc/config/m68k/m68k.md606
-rw-r--r--gcc/config/m68k/m68kv4.h18
-rw-r--r--gcc/config/m68k/mot3300.h8
-rw-r--r--gcc/config/m68k/news.h5
-rw-r--r--gcc/config/m68k/sgs.h7
-rw-r--r--gcc/config/m68k/t-openbsd5
-rw-r--r--gcc/config/m68k/tower-as.h5
-rw-r--r--gcc/config/m68k/xm-m68k.h5
-rw-r--r--gcc/config/m88k/m88k.c6
-rw-r--r--gcc/config/m88k/xm-m88k.h5
-rw-r--r--gcc/config/mcore/mcore-elf.h14
-rw-r--r--gcc/config/mcore/mcore.c11
-rw-r--r--gcc/config/mcore/t-mcore3
-rw-r--r--gcc/config/mcore/t-mcore-pe3
-rw-r--r--gcc/config/mcore/xm-mcore.h5
-rw-r--r--gcc/config/mips/abi64.h17
-rw-r--r--gcc/config/mips/ecoff.h1
-rw-r--r--gcc/config/mips/elf.h6
-rw-r--r--gcc/config/mips/elf64.h6
-rw-r--r--gcc/config/mips/gnu.h18
-rw-r--r--gcc/config/mips/iris4.h25
-rw-r--r--gcc/config/mips/iris5.h36
-rw-r--r--gcc/config/mips/iris6.h67
-rw-r--r--gcc/config/mips/irix6-libc-compat.c140
-rw-r--r--gcc/config/mips/linux.h107
-rw-r--r--gcc/config/mips/mips.c57
-rw-r--r--gcc/config/mips/mips.h67
-rw-r--r--gcc/config/mips/mips.md110
-rw-r--r--gcc/config/mips/osfrose.h29
-rw-r--r--gcc/config/mips/sni-svr4.h9
-rw-r--r--gcc/config/mips/t-iris614
-rw-r--r--gcc/config/mips/xm-mips.h5
-rw-r--r--gcc/config/mn10200/mn10200.c1
-rw-r--r--gcc/config/mn10200/t-mn102004
-rw-r--r--gcc/config/mn10200/xm-mn10200.h4
-rw-r--r--gcc/config/mn10300/mn10300.c1
-rw-r--r--gcc/config/mn10300/mn10300.h11
-rw-r--r--gcc/config/mn10300/xm-mn10300.h4
-rw-r--r--gcc/config/nextstep.h5
-rw-r--r--gcc/config/ns32k/ns32k.c1
-rw-r--r--gcc/config/ns32k/xm-ns32k.h4
-rw-r--r--gcc/config/openbsd.h11
-rw-r--r--gcc/config/pa/lib2funcs.asm1
-rw-r--r--gcc/config/pa/long_double.h3
-rw-r--r--gcc/config/pa/pa-hpux10.h5
-rw-r--r--gcc/config/pa/pa.c295
-rw-r--r--gcc/config/pa/pa.h41
-rw-r--r--gcc/config/pa/pa.md109
-rw-r--r--gcc/config/pa/pa32-regs.h2
-rw-r--r--gcc/config/pa/quadlib.c9
-rw-r--r--gcc/config/pa/som.h57
-rw-r--r--gcc/config/pa/xm-linux.h4
-rw-r--r--gcc/config/pa/xm-pa.h4
-rw-r--r--gcc/config/pa/xm-pa64hpux.h5
-rw-r--r--gcc/config/pa/xm-pahpux.h6
-rw-r--r--gcc/config/pa/xm-papro.h4
-rw-r--r--gcc/config/pdp11/pdp11.c1
-rw-r--r--gcc/config/pdp11/pdp11.h4
-rw-r--r--gcc/config/pj/lib1funcs.S18
-rw-r--r--gcc/config/pj/pj.c1
-rw-r--r--gcc/config/pj/pj.h12
-rw-r--r--gcc/config/pj/xm-pj.h4
-rw-r--r--gcc/config/psos.h12
-rw-r--r--gcc/config/ptx4.h15
-rw-r--r--gcc/config/romp/romp.c1
-rw-r--r--gcc/config/romp/xm-romp.h5
-rw-r--r--gcc/config/rs6000/aix.h50
-rw-r--r--gcc/config/rs6000/aix43.h4
-rw-r--r--gcc/config/rs6000/aix51.h30
-rw-r--r--gcc/config/rs6000/linux.h66
-rw-r--r--gcc/config/rs6000/rs6000-protos.h7
-rw-r--r--gcc/config/rs6000/rs6000.c486
-rw-r--r--gcc/config/rs6000/rs6000.h156
-rw-r--r--gcc/config/rs6000/rs6000.md566
-rw-r--r--gcc/config/rs6000/rtems.h8
-rw-r--r--gcc/config/rs6000/sysv4.h30
-rw-r--r--gcc/config/rs6000/t-ppccomm5
-rw-r--r--gcc/config/rs6000/xm-beos.h7
-rw-r--r--gcc/config/rs6000/xm-rs6000.h5
-rw-r--r--gcc/config/rs6000/xm-sysv4.h5
-rw-r--r--gcc/config/s390/fixdfdi.h301
-rw-r--r--gcc/config/s390/linux.h381
-rw-r--r--gcc/config/s390/linux64.h80
-rw-r--r--gcc/config/s390/s390-protos.h85
-rw-r--r--gcc/config/s390/s390.c3118
-rw-r--r--gcc/config/s390/s390.h1881
-rw-r--r--gcc/config/s390/s390.md5882
-rw-r--r--gcc/config/s390/t-linux6
-rw-r--r--gcc/config/s390/xm-s390.h41
-rw-r--r--gcc/config/s390/xm-s390x.h41
-rw-r--r--gcc/config/sh/crti.asm6
-rw-r--r--gcc/config/sh/crtn.asm6
-rw-r--r--gcc/config/sh/lib1funcs.asm17
-rw-r--r--gcc/config/sh/sh.c218
-rw-r--r--gcc/config/sh/sh.h20
-rw-r--r--gcc/config/sh/sh.md94
-rw-r--r--gcc/config/sh/xm-sh.h4
-rw-r--r--gcc/config/sparc/linux-aout.h6
-rw-r--r--gcc/config/sparc/linux.h9
-rw-r--r--gcc/config/sparc/linux64.h9
-rw-r--r--gcc/config/sparc/openbsd.h3
-rw-r--r--gcc/config/sparc/rtems.h2
-rw-r--r--gcc/config/sparc/rtemself.h4
-rw-r--r--gcc/config/sparc/sol2-sld-64.h26
-rw-r--r--gcc/config/sparc/sol2.h19
-rw-r--r--gcc/config/sparc/sp64-elf.h38
-rw-r--r--gcc/config/sparc/sparc.c41
-rw-r--r--gcc/config/sparc/sparc.h6
-rw-r--r--gcc/config/sparc/sparc.md115
-rw-r--r--gcc/config/sparc/t-openbsd5
-rw-r--r--gcc/config/sparc/xm-sparc.h5
-rw-r--r--gcc/config/sparc/xm-sysv4.h5
-rw-r--r--gcc/config/t-freebsd6
-rw-r--r--gcc/config/t-freebsd-thread2
-rw-r--r--gcc/config/t-libgcc-pic2
-rw-r--r--gcc/config/t-linux22
-rw-r--r--gcc/config/t-linux-aout3
-rw-r--r--gcc/config/t-netbsd3
-rw-r--r--gcc/config/t-openbsd2
-rw-r--r--gcc/config/t-rtems3
-rw-r--r--gcc/config/t-slibgcc-elf-ver (renamed from gcc/config/sparc/t-slibgcc)13
-rw-r--r--gcc/config/t-slibgcc-sld (renamed from gcc/config/sparc/t-slibgcc-sld)10
-rw-r--r--gcc/config/v850/v850.c4
-rw-r--r--gcc/config/v850/xm-v850.h4
-rw-r--r--gcc/config/vax/vax.c1
-rw-r--r--gcc/config/vax/vax.h53
-rw-r--r--gcc/config/vax/xm-vax.h5
-rw-r--r--gcc/config/vax/xm-vms.h4
-rw-r--r--gcc/config/we32k/xm-we32k.h5
-rw-r--r--gcc/config/x-linux3
-rw-r--r--gcc/config/xm-lynx.h4
-rw-r--r--gcc/config/xm-std32.h4
286 files changed, 20382 insertions, 5565 deletions
diff --git a/gcc/config/1750a/1750a.h b/gcc/config/1750a/1750a.h
index 94f4262ef0f..ea2e8bb5eee 100644
--- a/gcc/config/1750a/1750a.h
+++ b/gcc/config/1750a/1750a.h
@@ -1048,8 +1048,6 @@ enum reg_class { NO_REGS, R2, R0_1, INDEX_REGS, BASE_REGS, ALL_REGS, LIM_REG_CLA
/****************** Assembler output formatting **********************/
-#define ASM_IDENTIFY_GCC(FILE) fputs ("; gcc2_compiled:\n", FILE)
-
#define ASM_COMMENT_START ";"
#define ASM_OUTPUT_FUNNAM(FILE,NAME) \
diff --git a/gcc/config/a29k/a29k.c b/gcc/config/a29k/a29k.c
index 5a87e940e06..5621e0c726e 100644
--- a/gcc/config/a29k/a29k.c
+++ b/gcc/config/a29k/a29k.c
@@ -29,7 +29,6 @@ Boston, MA 02111-1307, USA. */
#include "real.h"
#include "insn-config.h"
#include "conditions.h"
-#include "insn-flags.h"
#include "output.h"
#include "insn-attr.h"
#include "flags.h"
diff --git a/gcc/config/a29k/xm-a29k.h b/gcc/config/a29k/xm-a29k.h
index 774e34b38a8..fbf6c2f7ca9 100644
--- a/gcc/config/a29k/xm-a29k.h
+++ b/gcc/config/a29k/xm-a29k.h
@@ -18,11 +18,6 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-
-/* #defines that need visibility everywhere. */
-#define FALSE 0
-#define TRUE 1
-
/* This describes the machine the compiler is hosted on. */
#define HOST_BITS_PER_CHAR 8
#define HOST_BITS_PER_SHORT 16
diff --git a/gcc/config/a29k/xm-unix.h b/gcc/config/a29k/xm-unix.h
index 206d8fdc41d..b8a19421a41 100644
--- a/gcc/config/a29k/xm-unix.h
+++ b/gcc/config/a29k/xm-unix.h
@@ -18,10 +18,6 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* #defines that need visibility everywhere. */
-#define FALSE 0
-#define TRUE 1
-
/* This describes the machine the compiler is hosted on. */
#define HOST_BITS_PER_CHAR 8
#define HOST_BITS_PER_SHORT 16
diff --git a/gcc/config/alpha/alpha-protos.h b/gcc/config/alpha/alpha-protos.h
index c12b92d9c79..06ecfa3848b 100644
--- a/gcc/config/alpha/alpha-protos.h
+++ b/gcc/config/alpha/alpha-protos.h
@@ -100,6 +100,7 @@ extern int alpha_expand_block_move PARAMS ((rtx []));
extern int alpha_expand_block_clear PARAMS ((rtx []));
extern int alpha_adjust_cost PARAMS ((rtx, rtx, rtx, int));
extern rtx alpha_return_addr PARAMS ((int, rtx));
+extern rtx alpha_gp_save_rtx PARAMS ((void));
extern void print_operand PARAMS ((FILE *, rtx, int));
extern void print_operand_address PARAMS ((FILE *, rtx));
extern void alpha_initialize_trampoline PARAMS ((rtx, rtx, rtx, int, int, int));
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index 25d7d3b503f..3f7d98db6c3 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -1,6 +1,6 @@
/* Subroutines used for code generation on the DEC Alpha.
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000 Free Software Foundation, Inc.
+ 2000, 2001 Free Software Foundation, Inc.
Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
This file is part of GNU CC.
@@ -29,7 +29,6 @@ Boston, MA 02111-1307, USA. */
#include "real.h"
#include "insn-config.h"
#include "conditions.h"
-#include "insn-flags.h"
#include "output.h"
#include "insn-attr.h"
#include "flags.h"
@@ -343,6 +342,19 @@ override_options ()
if (!g_switch_set)
g_switch_value = 8;
+ /* Align labels and loops for optimal branching. */
+ /* ??? Kludge these by not doing anything if we don't optimize and also if
+ we are writing ECOFF symbols to work around a bug in DEC's assembler. */
+ if (optimize > 0 && write_symbols != SDB_DEBUG)
+ {
+ if (align_loops <= 0)
+ align_loops = 16;
+ if (align_jumps <= 0)
+ align_jumps = 16;
+ }
+ if (align_functions <= 0)
+ align_functions = 16;
+
/* Acquire a unique set number for our register saves and restores. */
alpha_sr_alias_set = new_alias_set ();
@@ -2324,10 +2336,10 @@ alpha_emit_xfloating_compare (code, op0, op1)
operands[1] = op1;
out = gen_reg_rtx (DImode);
- /* ??? Strange equiv cause what's actually returned is -1,0,1, not a
- proper boolean value. */
- alpha_emit_xfloating_libcall (func, out, operands, 2,
- gen_rtx_COMPARE (TFmode, op0, op1));
+ /* ??? Strange mode for equiv because what's actually returned
+ is -1,0,1, not a proper boolean value. */
+ alpha_emit_xfloating_libcall (func, out, operands, 2,
+ gen_rtx_fmt_ee (code, CCmode, op0, op1));
return out;
}
@@ -3665,8 +3677,8 @@ alpha_mark_machine_status (p)
if (machine)
{
- ggc_mark_rtx (machine->eh_epilogue_sp_ofs);
ggc_mark_rtx (machine->ra_rtx);
+ ggc_mark_rtx (machine->gp_save_rtx);
}
}
@@ -3708,6 +3720,29 @@ alpha_return_addr (count, frame)
return reg;
}
+/* Return or create a pseudo containing the gp value for the current
+ function. Needed only if TARGET_LD_BUGGY_LDGP. */
+
+rtx
+alpha_gp_save_rtx ()
+{
+ rtx init, reg;
+
+ reg = cfun->machine->gp_save_rtx;
+ if (reg == NULL)
+ {
+ reg = gen_reg_rtx (DImode);
+ cfun->machine->gp_save_rtx = reg;
+ init = gen_rtx_SET (VOIDmode, reg, gen_rtx_REG (DImode, 29));
+
+ push_topmost_sequence ();
+ emit_insn_after (init, get_insns ());
+ pop_topmost_sequence ();
+ }
+
+ return reg;
+}
+
static int
alpha_ra_ever_killed ()
{
@@ -4317,6 +4352,7 @@ alpha_va_arg (valist, type)
tree t;
tree offset_field, base_field, addr_tree, addend;
tree wide_type, wide_ofs;
+ int indirect = 0;
if (TARGET_OPEN_VMS)
return std_expand_builtin_va_arg (valist, type);
@@ -4335,7 +4371,13 @@ alpha_va_arg (valist, type)
wide_ofs = save_expr (build1 (CONVERT_EXPR, wide_type, offset_field));
addend = wide_ofs;
- if (FLOAT_TYPE_P (type))
+
+ if (TYPE_MODE (type) == TFmode || TYPE_MODE (type) == TCmode)
+ {
+ indirect = 1;
+ tsize = UNITS_PER_WORD;
+ }
+ else if (FLOAT_TYPE_P (type))
{
tree fpaddend, cond;
@@ -4361,6 +4403,12 @@ alpha_va_arg (valist, type)
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+ if (indirect)
+ {
+ addr = force_reg (Pmode, addr);
+ addr = gen_rtx_MEM (Pmode, addr);
+ }
+
return addr;
}
@@ -4417,6 +4465,18 @@ alpha_sa_mask (imaskP, fmaskP)
fmask |= (1L << (i - 32));
}
+ /* We need to restore these for the handler. */
+ if (current_function_calls_eh_return)
+ {
+ for (i = 0; ; ++i)
+ {
+ unsigned regno = EH_RETURN_DATA_REGNO (i);
+ if (regno == INVALID_REGNUM)
+ break;
+ imask |= 1L << regno;
+ }
+ }
+
if (imask || fmask || alpha_ra_ever_killed ())
imask |= (1L << REG_RA);
}
@@ -5113,7 +5173,11 @@ alpha_expand_epilogue ()
fp_offset = 0;
sa_reg = stack_pointer_rtx;
- eh_ofs = cfun->machine->eh_epilogue_sp_ofs;
+ if (current_function_calls_eh_return)
+ eh_ofs = EH_RETURN_STACKADJ_RTX;
+ else
+ eh_ofs = NULL_RTX;
+
if (sa_size)
{
/* If we have a frame pointer, restore SP from it. */
@@ -5141,12 +5205,11 @@ alpha_expand_epilogue ()
/* Restore registers in order, excepting a true frame pointer. */
+ mem = gen_rtx_MEM (DImode, plus_constant (sa_reg, reg_offset));
if (! eh_ofs)
- {
- mem = gen_rtx_MEM (DImode, plus_constant(sa_reg, reg_offset));
- MEM_ALIAS_SET (mem) = alpha_sr_alias_set;
- FRP (emit_move_insn (gen_rtx_REG (DImode, REG_RA), mem));
- }
+ MEM_ALIAS_SET (mem) = alpha_sr_alias_set;
+ FRP (emit_move_insn (gen_rtx_REG (DImode, REG_RA), mem));
+
reg_offset += 8;
imask &= ~(1L << REG_RA);
diff --git a/gcc/config/alpha/alpha.h b/gcc/config/alpha/alpha.h
index dc2a1ec4439..ce644f1747c 100644
--- a/gcc/config/alpha/alpha.h
+++ b/gcc/config/alpha/alpha.h
@@ -186,6 +186,9 @@ extern enum alpha_fp_trap_mode alpha_fptm;
#ifndef TARGET_PROFILING_NEEDS_GP
#define TARGET_PROFILING_NEEDS_GP 0
#endif
+#ifndef TARGET_LD_BUGGY_LDGP
+#define TARGET_LD_BUGGY_LDGP 0
+#endif
/* Macro to define tables used to set the flags.
This is a list in braces of pairs in braces,
@@ -494,7 +497,7 @@ extern const char *alpha_mlat_string; /* For -mmemory-latency= */
#define STACK_BOUNDARY 64
/* Allocation boundary (in *bits*) for the code of a function. */
-#define FUNCTION_BOUNDARY 128
+#define FUNCTION_BOUNDARY 32
/* Alignment of field after `int : 0' in a structure. */
#define EMPTY_FIELD_BOUNDARY 64
@@ -505,22 +508,6 @@ extern const char *alpha_mlat_string; /* For -mmemory-latency= */
/* A bitfield declared as `int' forces `int' alignment for the struct. */
#define PCC_BITFIELD_TYPE_MATTERS 1
-/* Align loop starts for optimal branching.
-
- ??? Kludge this and the next macro for the moment by not doing anything if
- we don't optimize and also if we are writing ECOFF symbols to work around
- a bug in DEC's assembler. */
-
-#define LOOP_ALIGN(LABEL) \
- (optimize > 0 && write_symbols != SDB_DEBUG ? 4 : 0)
-
-/* This is how to align an instruction for optimal branching. On
- Alpha we'll get better performance by aligning on an octaword
- boundary. */
-
-#define LABEL_ALIGN_AFTER_BARRIER(FILE) \
- (optimize > 0 && write_symbols != SDB_DEBUG ? 4 : 0)
-
/* No data type wants to be aligned rounder than this. */
#define BIGGEST_ALIGNMENT 128
@@ -1213,11 +1200,11 @@ extern struct alpha_compare alpha_compare;
struct machine_function
{
- /* An offset to apply to the stack pointer when unwinding from EH. */
- struct rtx_def *eh_epilogue_sp_ofs;
-
/* If non-null, this rtx holds the return address for the function. */
struct rtx_def *ra_rtx;
+
+ /* If non-null, this rtx holds a saved copy of the GP for the function. */
+ struct rtx_def *gp_save_rtx;
};
/* Make (or fake) .linkage entry for function call.
@@ -1342,6 +1329,13 @@ do { \
/* Before the prologue, RA lives in $26. */
#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (Pmode, 26)
#define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGNUM (26)
+
+/* Describe how we implement __builtin_eh_return. */
+#define EH_RETURN_DATA_REGNO(N) ((N) < 4 ? (N) + 16 : INVALID_REGNUM)
+#define EH_RETURN_STACKADJ_RTX gen_rtx_REG (Pmode, 28)
+#define EH_RETURN_HANDLER_RTX \
+ gen_rtx_MEM (Pmode, plus_constant (stack_pointer_rtx, \
+ current_function_outgoing_args_size))
/* Addressing modes, and classification of registers for them. */
@@ -1926,15 +1920,6 @@ do { \
/* Control the assembler format that we output. */
-/* We don't emit these labels, so as to avoid getting linker errors about
- missing exception handling info. If we emit a gcc_compiled. label into
- text, and the file has no code, then the DEC assembler gives us a zero
- sized text section with no associated exception handling info. The
- DEC linker sees this text section, and gives a warning saying that
- the exception handling info is missing. */
-#define ASM_IDENTIFY_GCC(x)
-#define ASM_IDENTIFY_LANGUAGE(x)
-
/* Output to assembler file text saying following lines
may contain character constants, extra white space, comments, etc. */
diff --git a/gcc/config/alpha/alpha.md b/gcc/config/alpha/alpha.md
index 9961617a3dc..cafee4453e7 100644
--- a/gcc/config/alpha/alpha.md
+++ b/gcc/config/alpha/alpha.md
@@ -4276,6 +4276,20 @@
}
}")
+(define_insn "*call_osf_1_noreturn"
+ [(call (mem:DI (match_operand:DI 0 "call_operand" "c,R,i"))
+ (match_operand 1 "" ""))
+ (clobber (reg:DI 27))
+ (clobber (reg:DI 26))]
+ "! TARGET_WINDOWS_NT && ! TARGET_OPEN_VMS
+ && find_reg_note (insn, REG_NORETURN, NULL_RTX)"
+ "@
+ jsr $26,($27),0
+ bsr $26,$%0..ng
+ jsr $26,%0"
+ [(set_attr "type" "jsr")
+ (set_attr "length" "*,*,8")])
+
(define_insn "*call_osf_1"
[(call (mem:DI (match_operand:DI 0 "call_operand" "c,R,i"))
(match_operand 1 "" ""))
@@ -4659,7 +4673,7 @@
"
{
alpha_split_tfmode_pair (operands);
- if (rtx_equal_p (operands[0], operands[3]))
+ if (reg_overlap_mentioned_p (operands[0], operands[3]))
{
rtx tmp;
tmp = operands[0], operands[0] = operands[1], operands[1] = tmp;
@@ -4717,7 +4731,7 @@
st%, %R1,%0"
[(set_attr "type" "ilog,iadd,iadd,ild,ist,fcpys,fld,fst")])
-(define_insn "*movsf_fix"
+(define_insn "*movsi_fix"
[(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,m,*f,*f,m,r,*f")
(match_operand:SI 1 "input_operand" "rJ,K,L,m,rJ,*fJ,m,*f,*f,r"))]
"! TARGET_WINDOWS_NT && ! TARGET_OPEN_VMS && TARGET_FIX
@@ -5886,22 +5900,6 @@
DONE;
}")
-(define_expand "eh_epilogue"
- [(use (match_operand:DI 0 "register_operand" "r"))
- (use (match_operand:DI 1 "register_operand" "r"))
- (use (match_operand:DI 2 "register_operand" "r"))]
- "! TARGET_OPEN_VMS"
- "
-{
- cfun->machine->eh_epilogue_sp_ofs = operands[1];
- if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 26)
- {
- rtx ra = gen_rtx_REG (Pmode, 26);
- emit_move_insn (ra, operands[2]);
- operands[2] = ra;
- }
-}")
-
;; In creating a large stack frame, NT _must_ use ldah+lda to load
;; the frame size into a register. We use this pattern to ensure
;; we get lda instead of addq.
@@ -5961,13 +5959,36 @@
[(set_attr "length" "12")
(set_attr "type" "multi")])
-(define_insn "exception_receiver"
- [(unspec_volatile [(const_int 0)] 7)]
+(define_expand "exception_receiver"
+ [(unspec_volatile [(match_dup 0)] 7)]
"! TARGET_OPEN_VMS && ! TARGET_WINDOWS_NT"
- "br $29,$LSJ%=\\n$LSJ%=:\;ldgp $29,0($29)"
- [(set_attr "length" "12")
+ "
+{
+ if (TARGET_LD_BUGGY_LDGP)
+ operands[0] = alpha_gp_save_rtx ();
+ else
+ operands[0] = const0_rtx;
+}")
+
+(define_insn "*exception_receiver_1"
+ [(unspec_volatile [(const_int 0)] 7)]
+ "! TARGET_LD_BUGGY_LDGP"
+ "ldgp $29,0($26)"
+ [(set_attr "length" "8")
(set_attr "type" "multi")])
+;; ??? We don't represent the usage of $29 properly in address loads
+;; and function calls. This leads to the following move being deleted
+;; as dead code unless it is represented as a volatile unspec.
+
+(define_insn "*exception_receiver_2"
+ [(unspec_volatile [(match_operand:DI 0 "nonimmediate_operand" "r,m")] 7)]
+ "TARGET_LD_BUGGY_LDGP"
+ "@
+ mov %0,$29
+ ldq $29,%0"
+ [(set_attr "type" "ilog,ild")])
+
(define_expand "nonlocal_goto_receiver"
[(unspec_volatile [(const_int 0)] 1)
(set (reg:DI 27) (mem:DI (reg:DI 29)))
diff --git a/gcc/config/alpha/elf.h b/gcc/config/alpha/elf.h
index 9224a393d47..a77a64328d9 100644
--- a/gcc/config/alpha/elf.h
+++ b/gcc/config/alpha/elf.h
@@ -66,31 +66,9 @@ do { \
} \
} while (0)
-/* Attach a special .ident directive to the end of the file to identify
- the version of GCC which compiled this code. The format of the
- .ident string is patterned after the ones produced by native svr4
- C compilers. */
-
#undef IDENT_ASM_OP
#define IDENT_ASM_OP "\t.ident\t"
-#ifdef IDENTIFY_WITH_IDENT
-#undef ASM_IDENTIFY_GCC
-#define ASM_IDENTIFY_GCC(FILE) /* nothing */
-#undef ASM_IDENTIFY_LANGUAGE
-#define ASM_IDENTIFY_LANGUAGE(FILE) \
- fprintf(FILE, "%s\"GCC (%s) %s\"\n", IDENT_ASM_OP, \
- lang_identify(), version_string)
-#else
-#undef ASM_FILE_END
-#define ASM_FILE_END(FILE) \
-do { \
- if (!flag_no_ident) \
- fprintf ((FILE), "%s\"GCC: (GNU) %s\"\n", \
- IDENT_ASM_OP, version_string); \
- } while (0)
-#endif
-
/* Allow #sccs in preprocessor. */
#define SCCS_DIRECTIVE
@@ -480,6 +458,8 @@ void FN () \
} \
while (0)
+#define MAKE_DECL_ONE_ONLY(DECL) (DECL_WEAK (DECL) = 1)
+
#define UNIQUE_SECTION_P(DECL) (DECL_ONE_ONLY (DECL))
#undef UNIQUE_SECTION
@@ -707,3 +687,14 @@ void FN () \
#undef UNALIGNED_SHORT_ASM_OP
#undef UNALIGNED_INT_ASM_OP
#undef UNALIGNED_DOUBLE_INT_ASM_OP
+
+/* Select a format to encode pointers in exception handling data. CODE
+ is 0 for data, 1 for code labels, 2 for function pointers. GLOBAL is
+ true if the symbol may be affected by dynamic relocations.
+
+ Since application size is already constrained to <2GB by the form of
+ the ldgp relocation, we can use a 32-bit pc-relative relocation to
+ static data. Dynamic data is accessed indirectly to allow for read
+ only EH sections. */
+#define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL) \
+ (((GLOBAL) ? DW_EH_PE_indirect : 0) | DW_EH_PE_pcrel | DW_EH_PE_sdata4)
diff --git a/gcc/config/alpha/freebsd.h b/gcc/config/alpha/freebsd.h
index f7c76b2a876..494fdab7a98 100644
--- a/gcc/config/alpha/freebsd.h
+++ b/gcc/config/alpha/freebsd.h
@@ -19,10 +19,6 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES \
- "-D__ELF__ -Dunix -D__FreeBSD__ -Asystem(unix) -Asystem(bsd) -Asystem(FreeBSD)"
-
/* Provide a CPP_SPEC appropriate for FreeBSD/alpha. Besides the dealing with
the GCC option `-posix', and PIC issues as on all FreeBSD platforms, we must
deal with the Alpha's FP issues. */
diff --git a/gcc/config/alpha/linux.h b/gcc/config/alpha/linux.h
index c8f649a7582..e2a6e6004d7 100644
--- a/gcc/config/alpha/linux.h
+++ b/gcc/config/alpha/linux.h
@@ -28,8 +28,15 @@ Boston, MA 02111-1307, USA. */
"-Dlinux -Dunix -Asystem=linux -D_LONGLONG -D__alpha__ " \
SUB_CPP_PREDEFINES
+/* The GNU C++ standard library requires that these macros be defined. */
+#undef CPLUSPLUS_CPP_SPEC
+#define CPLUSPLUS_CPP_SPEC "-D_GNU_SOURCE %(cpp)"
+
#undef LIB_SPEC
-#define LIB_SPEC "%{pg:-lgmon} %{pg:-lc_p} %{!pg:-lc}"
+#define LIB_SPEC \
+ "%{shared: -lc} \
+ %{!shared: %{pthread:-lpthread} \
+ %{profile:-lc_p} %{!profile: -lc}}"
/* Show that we need a GP when profiling. */
#undef TARGET_PROFILING_NEEDS_GP
@@ -44,3 +51,54 @@ SUB_CPP_PREDEFINES
/* Define this so that all GNU/Linux targets handle the same pragmas. */
#define HANDLE_PRAGMA_PACK_PUSH_POP
+
+/* Do code reading to identify a signal frame, and set the frame
+ state data appropriately. See unwind-dw2.c for the structs. */
+
+#ifdef IN_LIBGCC2
+#include <signal.h>
+#include <sys/ucontext.h>
+#endif
+
+#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \
+ do { \
+ unsigned int *pc_ = (CONTEXT)->ra; \
+ struct sigcontext *sc_; \
+ long new_cfa_, i_; \
+ \
+ if (pc_[0] != 0x47fe0410 /* mov $30,$16 */ \
+ || pc_[2] != 0x00000083 /* callsys */) \
+ break; \
+ if (pc_[1] == 0x201f0067) /* lda $0,NR_sigreturn */ \
+ sc_ = (CONTEXT)->cfa; \
+ else if (pc_[1] == 0x201f015f) /* lda $0,NR_rt_sigreturn */ \
+ { \
+ struct rt_sigframe { \
+ struct siginfo info; \
+ struct ucontext uc; \
+ } *rt_ = (CONTEXT)->cfa; \
+ sc_ = &rt_->uc.uc_mcontext; \
+ } \
+ else \
+ break; \
+ new_cfa_ = sc_->sc_regs[30]; \
+ (FS)->cfa_how = CFA_REG_OFFSET; \
+ (FS)->cfa_reg = 30; \
+ (FS)->cfa_offset = new_cfa_ - (long) (CONTEXT)->cfa; \
+ for (i_ = 0; i_ < 30; ++i_) \
+ { \
+ (FS)->regs.reg[i_].how = REG_SAVED_OFFSET; \
+ (FS)->regs.reg[i_].loc.offset \
+ = (long)&sc_->sc_regs[i_] - new_cfa_; \
+ } \
+ for (i_ = 0; i_ < 31; ++i_) \
+ { \
+ (FS)->regs.reg[i_+32].how = REG_SAVED_OFFSET; \
+ (FS)->regs.reg[i_+32].loc.offset \
+ = (long)&sc_->sc_fpregs[i_] - new_cfa_; \
+ } \
+ (FS)->regs.reg[31].how = REG_SAVED_OFFSET; \
+ (FS)->regs.reg[31].loc.offset = (long)&sc_->sc_pc - new_cfa_; \
+ (FS)->retaddr_column = 31; \
+ goto SUCCESS; \
+ } while (0)
diff --git a/gcc/config/alpha/osf.h b/gcc/config/alpha/osf.h
index 1d1109b3c2f..6552edbbf13 100644
--- a/gcc/config/alpha/osf.h
+++ b/gcc/config/alpha/osf.h
@@ -36,13 +36,18 @@ Boston, MA 02111-1307, USA. */
-Dunix -D__osf__ -D_LONGLONG -DSYSTYPE_BSD \
-D_SYSTYPE_BSD -Asystem=unix -Asystem=xpg4"
+/* Tru64 UNIX V5 requires additional definitions for 16 byte long double
+ support. Empty by default. */
+
+#define CPP_XFLOAT_SPEC ""
+
/* Accept DEC C flags for multithreaded programs. We use _PTHREAD_USE_D4
instead of PTHREAD_USE_D4 since both have the same effect and the former
doesn't invade the users' namespace. */
#undef CPP_SUBTARGET_SPEC
#define CPP_SUBTARGET_SPEC \
-"%{pthread|threads:-D_REENTRANT} %{threads:-D_PTHREAD_USE_D4}"
+"%{pthread|threads:-D_REENTRANT} %{threads:-D_PTHREAD_USE_D4} %(cpp_xfloat)"
/* Under OSF4, -p and -pg require -lprof1, and -lprof1 requires -lpdf. */
@@ -52,11 +57,13 @@ Boston, MA 02111-1307, USA. */
/* Pass "-G 8" to ld because Alpha's CC does. Pass -O3 if we are
optimizing, -O1 if we are not. Pass -shared, -non_shared or
- -call_shared as appropriate. Also pass -pg. */
+ -call_shared as appropriate. Pass -hidden_symbol so that our
+ constructor and call-frame data structures are not accidentally
+ overridden. */
#define LINK_SPEC \
"-G 8 %{O*:-O3} %{!O*:-O1} %{static:-non_shared} \
- %{!static:%{shared:-shared} %{!shared:-call_shared}} %{pg} %{taso} \
- %{rpath*}"
+ %{!static:%{shared:-shared -hidden_symbol _GLOBAL_*} \
+ %{!shared:-call_shared}} %{pg} %{taso} %{rpath*}"
#define STARTFILE_SPEC \
"%{!shared:%{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}}"
@@ -79,10 +86,14 @@ Boston, MA 02111-1307, USA. */
ASM_OUTPUT_SOURCE_FILENAME (FILE, main_input_filename); \
}
+/* Tru64 UNIX V5.1 requires a special as flag. Empty by default. */
+
+#define ASM_OLDAS_SPEC ""
+
/* No point in running CPP on our assembler output. */
#if ((TARGET_DEFAULT | TARGET_CPU_DEFAULT) & MASK_GAS) != 0
/* Don't pass -g to GNU as, because some versions don't accept this option. */
-#define ASM_SPEC "%{malpha-as:-g} -nocpp %{pg}"
+#define ASM_SPEC "%{malpha-as:-g %(asm_oldas)} -nocpp %{pg}"
#else
/* In OSF/1 v3.2c, the assembler by default does not output file names which
causes mips-tfile to fail. Passing -g to the assembler fixes this problem.
@@ -91,7 +102,7 @@ Boston, MA 02111-1307, USA. */
if the user does not specify -g. If we don't pass -g, then mips-tfile
will need to be fixed to work in this case. Pass -O0 since some
optimization are broken and don't help us anyway. */
-#define ASM_SPEC "%{!mgas:-g} -nocpp %{pg} -O0"
+#define ASM_SPEC "%{!mgas:-g %(asm_oldas)} -nocpp %{pg} -O0"
#endif
/* Specify to run a post-processor, mips-tfile after the assembler
@@ -120,6 +131,11 @@ Boston, MA 02111-1307, USA. */
#endif
+#undef SUBTARGET_EXTRA_SPECS
+#define SUBTARGET_EXTRA_SPECS \
+ { "cpp_xfloat", CPP_XFLOAT_SPEC }, \
+ { "asm_oldas", ASM_OLDAS_SPEC }
+
/* Indicate that we have a stamp.h to use. */
#ifndef CROSS_COMPILE
#define HAVE_STAMP_H 1
@@ -153,3 +169,40 @@ __enable_execute_stack (addr) \
#define HAS_INIT_SECTION
#define LD_INIT_SWITCH "-init"
#define LD_FINI_SWITCH "-fini"
+
+/* Select a format to encode pointers in exception handling data. CODE
+ is 0 for data, 1 for code labels, 2 for function pointers. GLOBAL is
+ true if the symbol may be affected by dynamic relocations.
+
+ We really ought to be using the SREL32 relocations that ECOFF has,
+ but no version of the native assembler supports creating such things,
+ and Compaq has no plans to rectify this. Worse, the dynamic loader
+ cannot handle unaligned relocations, so we have to make sure that
+ things get padded appropriately. */
+#define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL) \
+ (TARGET_GAS \
+ ? (((GLOBAL) ? DW_EH_PE_indirect : 0) | DW_EH_PE_pcrel | DW_EH_PE_sdata4) \
+ : DW_EH_PE_aligned)
+
+/* This is how we tell the assembler that a symbol is weak. */
+
+#define ASM_OUTPUT_WEAK_ALIAS(FILE, NAME, VALUE) \
+ do \
+ { \
+ ASM_GLOBALIZE_LABEL (FILE, NAME); \
+ fputs ("\t.weakext\t", FILE); \
+ assemble_name (FILE, NAME); \
+ if (VALUE) \
+ { \
+ fputc (' ', FILE); \
+ assemble_name (FILE, VALUE); \
+ } \
+ fputc ('\n', FILE); \
+ } \
+ while (0)
+
+#define ASM_WEAKEN_LABEL(FILE, NAME) ASM_OUTPUT_WEAK_ALIAS(FILE, NAME, 0)
+
+/* Handle #pragma weak and #pragma pack. */
+#undef HANDLE_SYSV_PRAGMA
+#define HANDLE_SYSV_PRAGMA 1
diff --git a/gcc/config/alpha/osf5.h b/gcc/config/alpha/osf5.h
index 1c336bd0670..c832c574188 100644
--- a/gcc/config/alpha/osf5.h
+++ b/gcc/config/alpha/osf5.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler, for DEC Alpha on Tru64 5.
- Copyright (C) 2000 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2001 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -20,3 +20,35 @@
#undef LONG_DOUBLE_TYPE_SIZE
#define LONG_DOUBLE_TYPE_SIZE 128
+
+/* Tru64 UNIX V5 has a 16 byte long double type and requires __X_FLOAT to be
+ defined to get the appropriate prototypes for the long double functions
+ in <math.h>. */
+
+#undef CPP_XFLOAT_SPEC
+#define CPP_XFLOAT_SPEC "-D__X_FLOAT"
+
+/* In Tru64 UNIX V5.1, Compaq introduced a new assembler
+ (/usr/lib/cmplrs/cc/adu) which currently (versions between 3.04.29 and
+ 3.04.32) breaks mips-tfile. Passing the undocumented -oldas flag reverts
+ to using the old assembler (/usr/lib/cmplrs/cc/as[01]).
+
+ The V5.0 and V5.0A assemblers silently ignore -oldas, so it can be
+ specified here.
+
+ It is clearly not desirable to depend on this undocumented flag, and
+ Compaq wants -oldas to go away soon, but until they have released a
+ new adu that works with mips-tfile, this is the only option.
+
+ In some versions of the DTK, the assembler driver invokes ld after
+ assembly. This has been fixed in current versions, but adding -c
+ works as expected for all versions. */
+
+#undef ASM_OLDAS_SPEC
+#define ASM_OLDAS_SPEC "-oldas -c"
+
+/* The linker appears to perform invalid code optimizations that result
+ in the ldgp emitted for the exception_receiver pattern being incorrectly
+ linked. */
+#undef TARGET_LD_BUGGY_LDGP
+#define TARGET_LD_BUGGY_LDGP 1
diff --git a/gcc/config/alpha/t-interix b/gcc/config/alpha/t-interix
index d6d80e9c085..85474359320 100644
--- a/gcc/config/alpha/t-interix
+++ b/gcc/config/alpha/t-interix
@@ -4,11 +4,6 @@
# Even LANG_EXTRA_HEADERS may be temporary.
USER_H=$(LANG_EXTRA_HEADERS)
-# We don't want this one either.
-INSTALL_ASSERT_H=
-
-
-
CROSS_LIBGCC1 = libgcc1-asm.a
LIBGCC1 = libgcc1-asm.a
diff --git a/gcc/config/alpha/t-osf4 b/gcc/config/alpha/t-osf4
index 5c7bd8afe65..af1a67dfcbb 100644
--- a/gcc/config/alpha/t-osf4
+++ b/gcc/config/alpha/t-osf4
@@ -7,12 +7,12 @@ TARGET_LIBGCC2_CFLAGS = -fPIC
# Build a shared libgcc library.
SHLIB_EXT = .so
SHLIB_LINK = $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) -shared -nodefaultlibs \
- -Wl,-msym -Wl,-set_version,gcc.0 -Wl,-soname,@shlib_base_name@.so.0 \
+ -Wl,-msym -Wl,-set_version,gcc.1 -Wl,-soname,@shlib_base_name@.so.1 \
-o @shlib_base_name@.so @multilib_flags@ @shlib_objs@ -lc && \
- rm -f @shlib_base_name@.so.0 && \
- $(LN_S) @shlib_base_name@.so @shlib_base_name@.so.0
+ rm -f @shlib_base_name@.so.1 && \
+ $(LN_S) @shlib_base_name@.so @shlib_base_name@.so.1
# $(slibdir) double quoted to protect it from expansion while building
# libgcc.mk. We want this delayed until actual install time.
-SHLIB_INSTALL = $(INSTALL_DATA) @shlib_base_name@.so $$(slibdir)/@shlib_base_name@.so.0; \
+SHLIB_INSTALL = $(INSTALL_DATA) @shlib_base_name@.so $$(slibdir)/@shlib_base_name@.so.1; \
rm -f $$(slibdir)/@shlib_base_name@.so; \
- $(LN_S) @shlib_base_name@.so.0 $$(slibdir)/@shlib_base_name@.so
+ $(LN_S) @shlib_base_name@.so.1 $$(slibdir)/@shlib_base_name@.so
diff --git a/gcc/config/alpha/xm-alpha.h b/gcc/config/alpha/xm-alpha.h
index 57ebeb11469..036975c98ef 100644
--- a/gcc/config/alpha/xm-alpha.h
+++ b/gcc/config/alpha/xm-alpha.h
@@ -20,11 +20,6 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-
-/* #defines that need visibility everywhere. */
-#define FALSE 0
-#define TRUE 1
-
/* This describes the machine the compiler is hosted on. */
#define HOST_BITS_PER_CHAR 8
#define HOST_BITS_PER_SHORT 16
diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
index e0ad002a4ff..5c9acc603ca 100644
--- a/gcc/config/arc/arc.c
+++ b/gcc/config/arc/arc.c
@@ -30,7 +30,6 @@ Boston, MA 02111-1307, USA. */
#include "real.h"
#include "insn-config.h"
#include "conditions.h"
-#include "insn-flags.h"
#include "output.h"
#include "insn-attr.h"
#include "flags.h"
diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
index 520266b6d88..04121fdc707 100644
--- a/gcc/config/arc/arc.h
+++ b/gcc/config/arc/arc.h
@@ -1260,15 +1260,6 @@ do { \
#undef ASM_FILE_START
#define ASM_FILE_START(FILE) arc_asm_file_start (FILE)
-/* A C statement to output assembler commands which will identify the
- object file as having been compiled with GNU CC (or another GNU
- compiler). */
-#undef ASM_IDENTIFY_GCC
-#define ASM_IDENTIFY_GCC(FILE) /* nothing */
-
-/* Needed because we define ASM_IDENTIFY_GCC. */
-#define ASM_IDENTIFY_LANGUAGE(FILE) output_lang_identify (FILE)
-
/* A C string constant describing how to begin a comment in the target
assembler language. The compiler assumes that the comment will
end at the end of the line. */
diff --git a/gcc/config/arc/initfini.c b/gcc/config/arc/initfini.c
index 9d4952b8721..dd52be98ffd 100644
--- a/gcc/config/arc/initfini.c
+++ b/gcc/config/arc/initfini.c
@@ -141,7 +141,7 @@ __do_global_ctors ()
asm ("\n\
.section .init\n\
- bl.nd __do_global_ctors\
+ bl.nd __do_global_ctors\n\
ld blink,[fp,4]\n\
j.d blink\n\
ld.a fp,[sp,16]\n\
diff --git a/gcc/config/arc/xm-arc.h b/gcc/config/arc/xm-arc.h
index ba011e94be6..3c059d3a59d 100644
--- a/gcc/config/arc/xm-arc.h
+++ b/gcc/config/arc/xm-arc.h
@@ -18,10 +18,6 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* #defines that need visibility everywhere. */
-#define FALSE 0
-#define TRUE 1
-
/* This describes the machine the compiler is hosted on. */
#define HOST_BITS_PER_CHAR 8
#define HOST_BITS_PER_SHORT 16
diff --git a/gcc/config/arm/aof.h b/gcc/config/arm/aof.h
index 60d736a79dd..f10b7c45cb2 100644
--- a/gcc/config/arm/aof.h
+++ b/gcc/config/arm/aof.h
@@ -220,8 +220,6 @@ do \
fputs ("\tEND\n", (STREAM)); \
} while (0);
-#define ASM_IDENTIFY_GCC(STREAM) fputs ("|gcc2_compiled.|\n", (STREAM))
-
#define ASM_COMMENT_START ";"
#define ASM_APP_ON ""
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index d906b14c514..b67ff3905e6 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -32,7 +32,6 @@ Boston, MA 02111-1307, USA. */
#include "real.h"
#include "insn-config.h"
#include "conditions.h"
-#include "insn-flags.h"
#include "output.h"
#include "insn-attr.h"
#include "flags.h"
@@ -4823,7 +4822,13 @@ arm_reload_in_hi (operands)
}
}
- scratch = gen_rtx_REG (SImode, REGNO (operands[2]));
+ /* If the scratch overlaps the output, use the top half of the DImode
+ register we allocated. */
+ if (REGNO (operands[2]) == REGNO (operands[0]))
+ scratch = gen_rtx_REG (SImode, REGNO (operands[2]) + 1);
+ else
+ scratch = gen_rtx_REG (SImode, REGNO (operands[2]));
+
emit_insn (gen_zero_extendqisi2 (scratch,
gen_rtx_MEM (QImode,
plus_constant (base,
@@ -5455,7 +5460,11 @@ add_minipool_backward_ref (fix)
than the one we are trying to add. */
Mnode * min_mp = NULL;
/* This can be negative, since it is only a constraint. */
- HOST_WIDE_INT min_address = fix->address - fix->backwards;
+ /* If the object to be inserted into the pool is larger than
+ a single word, we need to take into account that all words
+ must be reachable. */
+ HOST_WIDE_INT min_address = fix->address - fix->backwards
+ + (fix->fix_size - 4);
Mnode * mp;
/* If we can't reach the current pool from this insn, or if we can't
@@ -7046,6 +7055,8 @@ output_return_instruction (operand, really_return, reverse)
load a single register. On other architectures, the cost is the same.
In 26 bit mode we have to use LDM in order to be able to restore the CPSR. */
if ((live_regs_mask == (1 << LR_REGNUM))
+ && ! TARGET_INTERWORK
+ && ! IS_INTERRUPT (func_type)
&& (! really_return || TARGET_APCS_32))
{
if (! really_return)
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index 3332c220a67..81440e5c396 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -425,9 +425,9 @@ Unrecognized value in TARGET_CPU_DEFAULT.
{"no-poke-function-name", -ARM_FLAG_POKE, "" }, \
{"fpe", ARM_FLAG_FPE, "" }, \
{"apcs-32", ARM_FLAG_APCS_32, \
- N_("Use the 32bit version of the APCS") }, \
+ N_("Use the 32-bit version of the APCS") }, \
{"apcs-26", -ARM_FLAG_APCS_32, \
- N_("Use the 26bit version of the APCS") }, \
+ N_("Use the 26-bit version of the APCS") }, \
{"apcs-stack-check", ARM_FLAG_APCS_STACK, "" }, \
{"no-apcs-stack-check", -ARM_FLAG_APCS_STACK, "" }, \
{"apcs-float", ARM_FLAG_APCS_FLOAT, \
@@ -454,14 +454,14 @@ Unrecognized value in TARGET_CPU_DEFAULT.
{"words-little-endian", ARM_FLAG_LITTLE_WORDS, \
N_("Assume big endian bytes, little endian words") }, \
{"thumb-interwork", ARM_FLAG_INTERWORK, \
- N_("Support calls between THUMB and ARM instructions sets") }, \
+ N_("Support calls between Thumb and ARM instruction sets") }, \
{"no-thumb-interwork", -ARM_FLAG_INTERWORK, "" }, \
{"abort-on-noreturn", ARM_FLAG_ABORT_NORETURN, \
N_("Generate a call to abort if a noreturn function returns")}, \
{"no-abort-on-noreturn", -ARM_FLAG_ABORT_NORETURN, "" }, \
- {"sched-prolog", -ARM_FLAG_NO_SCHED_PRO, \
+ {"no-sched-prolog", ARM_FLAG_NO_SCHED_PRO, \
N_("Do not move instructions into a function's prologue") }, \
- {"no-sched-prolog", ARM_FLAG_NO_SCHED_PRO, "" }, \
+ {"sched-prolog", -ARM_FLAG_NO_SCHED_PRO, "" }, \
{"single-pic-base", ARM_FLAG_SINGLE_PIC_BASE, \
N_("Do not load the PIC register in function prologues") }, \
{"no-single-pic-base", -ARM_FLAG_SINGLE_PIC_BASE, "" }, \
@@ -1929,7 +1929,7 @@ typedef struct
`assemble_name' uses this. */
#undef ASM_OUTPUT_LABELREF
#define ASM_OUTPUT_LABELREF(FILE, NAME) \
- fprintf (FILE, "%s%s", USER_LABEL_PREFIX, arm_strip_name_encoding (NAME))
+ asm_fprintf (FILE, "%U%s", arm_strip_name_encoding (NAME))
/* If we are referencing a function that is weak then encode a long call
flag in the function name, otherwise if the function is static or
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index f69e0fee170..17c40b0b9dd 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -5239,7 +5239,7 @@
(define_insn "*ldmsi_postinc4"
[(match_parallel 0 "load_multiple_operation"
- [(set (match_operand:SI 1 "s_register_operand" "+r")
+ [(set (match_operand:SI 1 "s_register_operand" "=r")
(plus:SI (match_operand:SI 2 "s_register_operand" "1")
(const_int 16)))
(set (match_operand:SI 3 "arm_hard_register_operand" "")
@@ -5258,7 +5258,7 @@
(define_insn "*ldmsi_postinc3"
[(match_parallel 0 "load_multiple_operation"
- [(set (match_operand:SI 1 "s_register_operand" "+r")
+ [(set (match_operand:SI 1 "s_register_operand" "=r")
(plus:SI (match_operand:SI 2 "s_register_operand" "1")
(const_int 12)))
(set (match_operand:SI 3 "arm_hard_register_operand" "")
@@ -5275,7 +5275,7 @@
(define_insn "*ldmsi_postinc2"
[(match_parallel 0 "load_multiple_operation"
- [(set (match_operand:SI 1 "s_register_operand" "+r")
+ [(set (match_operand:SI 1 "s_register_operand" "=r")
(plus:SI (match_operand:SI 2 "s_register_operand" "1")
(const_int 8)))
(set (match_operand:SI 3 "arm_hard_register_operand" "")
@@ -5361,7 +5361,7 @@
(define_insn "*stmsi_postinc4"
[(match_parallel 0 "store_multiple_operation"
- [(set (match_operand:SI 1 "s_register_operand" "+r")
+ [(set (match_operand:SI 1 "s_register_operand" "=r")
(plus:SI (match_operand:SI 2 "s_register_operand" "1")
(const_int 16)))
(set (mem:SI (match_dup 2))
@@ -5380,7 +5380,7 @@
(define_insn "*stmsi_postinc3"
[(match_parallel 0 "store_multiple_operation"
- [(set (match_operand:SI 1 "s_register_operand" "+r")
+ [(set (match_operand:SI 1 "s_register_operand" "=r")
(plus:SI (match_operand:SI 2 "s_register_operand" "1")
(const_int 12)))
(set (mem:SI (match_dup 2))
@@ -5397,7 +5397,7 @@
(define_insn "*stmsi_postinc2"
[(match_parallel 0 "store_multiple_operation"
- [(set (match_operand:SI 1 "s_register_operand" "+r")
+ [(set (match_operand:SI 1 "s_register_operand" "=r")
(plus:SI (match_operand:SI 2 "s_register_operand" "1")
(const_int 8)))
(set (mem:SI (match_dup 2))
diff --git a/gcc/config/arm/coff.h b/gcc/config/arm/coff.h
index 94999d4b4aa..6265691e352 100644
--- a/gcc/config/arm/coff.h
+++ b/gcc/config/arm/coff.h
@@ -57,13 +57,6 @@ Boston, MA 02111-1307, USA. */
/* A C statement to output assembler commands which will identify the
object file as having been compiled with GNU CC (or another GNU
compiler). */
-/* Define this to NULL so we don't get anything.
- We have ASM_IDENTIFY_LANGUAGE.
- Also, when using stabs, gcc2_compiled must be a stabs entry, not an
- ordinary symbol, or gdb won't see it. The stabs entry must be
- before the N_SO in order for gdb to find it. */
-#define ASM_IDENTIFY_GCC(STREAM) \
- fprintf (STREAM, "%sgcc2_compiled.:\n", LOCAL_LABEL_PREFIX )
/* This outputs a lot of .req's to define alias for various registers.
Let's try to avoid this. */
diff --git a/gcc/config/arm/conix-elf.h b/gcc/config/arm/conix-elf.h
index 2d447a5f602..a626af88fd8 100644
--- a/gcc/config/arm/conix-elf.h
+++ b/gcc/config/arm/conix-elf.h
@@ -99,23 +99,6 @@ func_ptr __DTOR_END__[1] = { (func_ptr) 0 };
} \
while (0)
-/* Don't know how to order these. UNALIGNED_WORD_ASM_OP is in
- dwarf2.out. */
-#define UNALIGNED_WORD_ASM_OP "\t.4byte\t"
-
-#define ASM_OUTPUT_DWARF2_ADDR_CONST(FILE,ADDR) \
- fprintf ((FILE), "%s%s", UNALIGNED_WORD_ASM_OP, ADDR)
-
-#define ASM_OUTPUT_DWARF_ADDR_CONST(FILE,RTX) \
- do \
- { \
- fprintf ((FILE), "%s", UNALIGNED_WORD_ASM_OP); \
- output_addr_const ((FILE), (RTX)); \
- fputc ('\n', (FILE)); \
- } \
- while (0)
-
-
/* The ARM development system defines __main. */
#define NAME__MAIN "__gccmain"
#define SYMBOL__MAIN __gccmain
diff --git a/gcc/config/arm/elf.h b/gcc/config/arm/elf.h
index 32770443494..bb7be334c1a 100644
--- a/gcc/config/arm/elf.h
+++ b/gcc/config/arm/elf.h
@@ -198,19 +198,6 @@ Boston, MA 02111-1307, USA. */
arm_valid_machine_decl_attribute (DECL, IDENTIFIER, ARGS)
-/* A C statement to output assembler commands which will identify the
- object file as having been compiled with GNU CC (or another GNU
- compiler). */
-/* Define this to NULL so we don't get anything.
- We have ASM_IDENTIFY_LANGUAGE.
- Also, when using stabs, gcc2_compiled must be a stabs entry, not an
- ordinary symbol, or gdb won't see it. The stabs entry must be
- before the N_SO in order for gdb to find it. */
-#ifndef ASM_IDENTIFY_GCC
-#define ASM_IDENTIFY_GCC(STREAM) \
- fprintf (STREAM, "%sgcc2_compiled.:\n", LOCAL_LABEL_PREFIX )
-#endif
-
/* This outputs a lot of .req's to define alias for various registers.
Let's try to avoid this. */
#ifndef ASM_FILE_START
diff --git a/gcc/config/arm/linux-elf.h b/gcc/config/arm/linux-elf.h
index cd1befed8b5..acaa71d6c9f 100644
--- a/gcc/config/arm/linux-elf.h
+++ b/gcc/config/arm/linux-elf.h
@@ -1,5 +1,6 @@
/* Definitions for ARM running Linux-based GNU systems using ELF
- Copyright (C) 1993, 1994, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1994, 1997, 1998, 1999, 2000, 2001
+ Free Software Foundation, Inc.
Contributed by Philip Blundell <philb@gnu.org>
This file is part of GNU CC.
@@ -25,35 +26,12 @@ Boston, MA 02111-1307, USA. */
/* Do not assume anything about header files. */
#define NO_IMPLICIT_EXTERN_C
-#ifndef SUBTARGET_DEFAULT_APCS26
/* Default is to use APCS-32 mode. */
-# define TARGET_DEFAULT (ARM_FLAG_APCS_32 | ARM_FLAG_MMU_TRAPS)
-# ifdef SUBTARGET_OLD_LINKER
-# define SUBTARGET_EXTRA_LINK_SPEC \
- " %{mapcs-26:-m elf32arm26} %{!mapcs-26:-m elf32arm}"
-# else /* new linker */
-# define SUBTARGET_EXTRA_LINK_SPEC \
- " %{mapcs-26:-m armelf_linux26} %{!mapcs-26:-m armelf_linux} -p"
-# endif
-# define SUBTARGET_EXTRA_ASM_SPEC \
- " %{mapcs-26:-mapcs-26} %{!mapcs-26:-mapcs-32}"
-# define MULTILIB_DEFAULTS \
+#define TARGET_DEFAULT (ARM_FLAG_APCS_32 | ARM_FLAG_MMU_TRAPS)
+#define SUBTARGET_EXTRA_LINK_SPEC " -m armelf_linux -p"
+#define MULTILIB_DEFAULTS \
{ "marm", "mlittle-endian", "mhard-float", "mapcs-32", "mno-thumb-interwork" }
-# define CPP_APCS_PC_DEFAULT_SPEC "-D__APCS_32__"
-#else /* default is APCS-26 */
-# define TARGET_DEFAULT (ARM_FLAG_MMU_TRAPS)
-# ifdef SUBTARGET_OLD_LINKER
-# define SUBTARGET_EXTRA_LINK_SPEC \
- " %{mapcs-32:-m elf32arm} %{!mapcs-32:-m elf32arm26}"
-# else /* new linker */
-# define SUBTARGET_EXTRA_LINK_SPEC \
- " %{mapcs-32:-m armelf_linux} %{!mapcs-32:-m armelf_linux26} -p"
-# endif
-# define SUBTARGET_EXTRA_ASM_SPEC \
- " %{mapcs-32:-mapcs-32} %{!mapcs-32:-mapcs-26}"
-# define MULTILIB_DEFAULTS \
- { "marm", "mlittle-endian", "mhard-float", "mapcs-26", "mno-thumb-interwork" }
-#endif
+#define CPP_APCS_PC_DEFAULT_SPEC "-D__APCS_32__"
/* This was defined in linux.h. Define it here also. */
#undef DEFAULT_VTABLE_THUNKS
@@ -114,27 +92,11 @@ Boston, MA 02111-1307, USA. */
#define USER_LABEL_PREFIX "" /* For ELF the default is no underscores */
#define LOCAL_LABEL_PREFIX "."
-/* Attach a special .ident directive to the end of the file to identify
- the version of GCC which compiled this code. */
#define IDENT_ASM_OP "\t.ident\t"
/* Output #ident as a .ident. */
#define ASM_OUTPUT_IDENT(FILE, NAME) \
fprintf (FILE, "%s\"%s\"\n", IDENT_ASM_OP, NAME);
-
-#ifdef IDENTIFY_WITH_IDENT
-#define ASM_IDENTIFY_GCC(FILE) /* nothing */
-#define ASM_IDENTIFY_LANGUAGE(FILE) \
- fprintf (FILE, "%s\"GCC (%s) %s\"\n", IDENT_ASM_OP, \
- lang_identify (), version_string)
-#else
-#define ASM_FILE_END(FILE) \
-do { \
- if (!flag_no_ident) \
- fprintf ((FILE), "%s\"GCC: (GNU) %s\"\n", \
- IDENT_ASM_OP, version_string); \
- } while (0)
-#endif
/* Support const sections and the ctors and dtors sections for g++.
Note that there appears to be two different ways to support const
diff --git a/gcc/config/arm/rtems-elf.h b/gcc/config/arm/rtems-elf.h
index 23a1a3201db..03036b3cd78 100644
--- a/gcc/config/arm/rtems-elf.h
+++ b/gcc/config/arm/rtems-elf.h
@@ -26,7 +26,7 @@ Boston, MA 02111-1307, USA. */
#include "unknown-elf.h"
#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-Darm -Darm_elf -Drtems -D__rtems__ -D__ELF__ \
+#define CPP_PREDEFINES "-Drtems -D__rtems__ -D__ELF__ \
-Asystem(rtems) -Acpu(arm) -Amachine(arm)"
/*#undef INVOKE_main*/
diff --git a/gcc/config/arm/unknown-elf.h b/gcc/config/arm/unknown-elf.h
index 315baff6920..fab8155f1ef 100644
--- a/gcc/config/arm/unknown-elf.h
+++ b/gcc/config/arm/unknown-elf.h
@@ -103,23 +103,6 @@ rdata_section () \
} \
while (0)
-/* Don't know how to order these. UNALIGNED_WORD_ASM_OP is in
- dwarf2.out. */
-#define UNALIGNED_WORD_ASM_OP "\t.4byte\t"
-
-#define ASM_OUTPUT_DWARF2_ADDR_CONST(FILE,ADDR) \
- fprintf ((FILE), "%s%s", UNALIGNED_WORD_ASM_OP, ADDR)
-
-#define ASM_OUTPUT_DWARF_ADDR_CONST(FILE,RTX) \
- do \
- { \
- fprintf ((FILE), "%s", UNALIGNED_WORD_ASM_OP); \
- output_addr_const ((FILE), (RTX)); \
- fputc ('\n', (FILE)); \
- } \
- while (0)
-
-
/* The ARM development system defines __main. */
#define NAME__MAIN "__gccmain"
#define SYMBOL__MAIN __gccmain
diff --git a/gcc/config/arm/xm-arm.h b/gcc/config/arm/xm-arm.h
index 0899e9f74e5..3996bafd366 100644
--- a/gcc/config/arm/xm-arm.h
+++ b/gcc/config/arm/xm-arm.h
@@ -21,10 +21,6 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* #defines that need visibility everywhere. */
-#define FALSE 0
-#define TRUE 1
-
/* This describes the machine the compiler is hosted on. */
#define HOST_BITS_PER_CHAR 8
#define HOST_BITS_PER_SHORT 16
@@ -65,5 +61,3 @@ Boston, MA 02111-1307, USA. */
#endif
/* EOF xm-arm.h */
-
-
diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c
index b01f9519859..b1e44bf8071 100644
--- a/gcc/config/avr/avr.c
+++ b/gcc/config/avr/avr.c
@@ -27,7 +27,6 @@
#include "real.h"
#include "insn-config.h"
#include "conditions.h"
-#include "insn-flags.h"
#include "output.h"
#include "insn-attr.h"
#include "flags.h"
@@ -803,7 +802,8 @@ legitimate_address_p (mode, x, strict)
rtx x;
int strict;
{
- int r = 0;
+ enum reg_class r = NO_REGS;
+
if (TARGET_ALL_DEBUG)
{
fprintf (stderr, "mode: (%s) %s %s %s %s:",
@@ -825,9 +825,9 @@ legitimate_address_p (mode, x, strict)
}
if (REG_P (x) && (strict ? REG_OK_FOR_BASE_STRICT_P (x)
: REG_OK_FOR_BASE_NOSTRICT_P (x)))
- r = 'R';
+ r = POINTER_REGS;
else if (CONSTANT_ADDRESS_P (x))
- r = 'S';
+ r = ALL_REGS;
else if (GET_CODE (x) == PLUS
&& REG_P (XEXP (x, 0))
&& GET_CODE (XEXP (x, 1)) == CONST_INT
@@ -839,26 +839,26 @@ legitimate_address_p (mode, x, strict)
if (! strict
|| REGNO (XEXP (x,0)) == REG_Y
|| REGNO (XEXP (x,0)) == REG_Z)
- r = 'Q';
+ r = BASE_POINTER_REGS;
if (XEXP (x,0) == frame_pointer_rtx
|| XEXP (x,0) == arg_pointer_rtx)
- r = 'Q';
+ r = BASE_POINTER_REGS;
}
else if (frame_pointer_needed && XEXP (x,0) == frame_pointer_rtx)
- r = 'U';
+ r = POINTER_Y_REGS;
}
else if ((GET_CODE (x) == PRE_DEC || GET_CODE (x) == POST_INC)
&& REG_P (XEXP (x, 0))
&& (strict ? REG_OK_FOR_BASE_STRICT_P (XEXP (x, 0))
: REG_OK_FOR_BASE_NOSTRICT_P (XEXP (x, 0))))
{
- r = 'T';
+ r = POINTER_REGS;
}
if (TARGET_ALL_DEBUG)
{
fprintf (stderr, " ret = %c\n", r);
}
- return r;
+ return r == NO_REGS ? 0 : (int)r;
}
/* Attempts to replace X with a valid
diff --git a/gcc/config/avr/avr.h b/gcc/config/avr/avr.h
index 34566b62e50..96f2872669e 100644
--- a/gcc/config/avr/avr.h
+++ b/gcc/config/avr/avr.h
@@ -3256,12 +3256,3 @@ extern struct rtx_def *ldi_reg_rtx;
/* Get the standard ELF stabs definitions. */
#include "dbxelf.h"
-
-#undef ASM_IDENTIFY_GCC
-#define ASM_IDENTIFY_GCC(FILE) \
-do \
- { \
- if (write_symbols != DBX_DEBUG) \
- fputs ("gcc2_compiled.:\n", FILE); \
- } \
-while (0)
diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index cd72f1014dc..de7b6100657 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -475,11 +475,10 @@
(set_attr "cc" "clobber,clobber")])
(define_expand "strlenhi"
- [(parallel
- [(set (match_dup 4)
- (unspec:HI [(match_operand:BLK 1 "memory_operand" "")
- (match_operand:QI 2 "const_int_operand" "")
- (match_operand:HI 3 "immediate_operand" "")] 0))])
+ [(set (match_dup 4)
+ (unspec:HI [(match_operand:BLK 1 "memory_operand" "")
+ (match_operand:QI 2 "const_int_operand" "")
+ (match_operand:HI 3 "immediate_operand" "")] 0))
(set (match_dup 4) (plus:HI (match_dup 4)
(const_int -1)))
(set (match_operand:HI 0 "register_operand" "")
diff --git a/gcc/config/avr/libgcc.S b/gcc/config/avr/libgcc.S
index cdf2c3f4ee1..d324a2166a6 100644
--- a/gcc/config/avr/libgcc.S
+++ b/gcc/config/avr/libgcc.S
@@ -137,12 +137,13 @@ __mulhi3_skip1:
add r_arg2L,r_arg2L ; shift multiplicand
adc r_arg2H,r_arg2H
- cpc r_arg2L,__zero_reg__
+ cp r_arg2L,__zero_reg__
+ cpc r_arg2H,__zero_reg__
breq __mulhi3_exit ; while multiplicand != 0
lsr r_arg1H ; gets LSB of multiplier
ror r_arg1L
- cpc r_arg1H,__zero_reg__
+ sbiw r_arg1L,0
brne __mulhi3_loop ; exit if multiplier = 0
__mulhi3_exit:
mov r_arg1H,r_resH ; result to return register
diff --git a/gcc/config/c4x/c4x.c b/gcc/config/c4x/c4x.c
index 48f4451ad69..e468babc2a0 100644
--- a/gcc/config/c4x/c4x.c
+++ b/gcc/config/c4x/c4x.c
@@ -33,9 +33,7 @@ Boston, MA 02111-1307, USA. */
#include "real.h"
#include "insn-config.h"
#include "insn-attr.h"
-#include "insn-codes.h"
#include "conditions.h"
-#include "insn-flags.h"
#include "output.h"
#include "tree.h"
#include "function.h"
diff --git a/gcc/config/c4x/c4x.h b/gcc/config/c4x/c4x.h
index 72ffb37c0ae..e6fee5dafa9 100644
--- a/gcc/config/c4x/c4x.h
+++ b/gcc/config/c4x/c4x.h
@@ -370,7 +370,8 @@ extern const char *c4x_rpts_cycles_string, *c4x_cpu_version_string;
/* If a structure has a floating point field then force structure
to have BLKMODE. */
-#define STRUCT_FORCE_BLK(FIELD) (TREE_CODE (TREE_TYPE (FIELD)) == REAL_TYPE)
+#define MEMBER_TYPE_FORCES_BLK(FIELD) \
+ (TREE_CODE (TREE_TYPE (FIELD)) == REAL_TYPE)
/* Number of bits in the high and low parts of a two stage
load of an immediate constant. */
@@ -629,12 +630,16 @@ extern const char *c4x_rpts_cycles_string, *c4x_cpu_version_string;
#define CLASS_LIKELY_SPILLED_P(CLASS) ((CLASS) == INDEX_REGS)
-/* CCmode is wrongly defined in machmode.def It should have a size
- of UNITS_PER_WORD. */
+/* CCmode is wrongly defined in machmode.def. It should have a size
+ of UNITS_PER_WORD. HFmode is 40-bits and thus fits within a single
+ extended precision register. Similarly, HCmode fits within two
+ extended precision registers. */
#define HARD_REGNO_NREGS(REGNO, MODE) \
-(((MODE) == CCmode || (MODE) == CC_NOOVmode) ? 1 : ((MODE) == HFmode) ? 1 : \
-((GET_MODE_SIZE(MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
+(((MODE) == CCmode || (MODE) == CC_NOOVmode) ? 1 : \
+ ((MODE) == HFmode) ? 1 : \
+ ((MODE) == HCmode) ? 2 : \
+ ((GET_MODE_SIZE(MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
/* A C expression that is nonzero if the hard register REGNO is preserved
@@ -2162,6 +2167,10 @@ dtors_section () \
/* Overall Framework of an Assembler File. */
+/* We need to have a data section we can identify so that we can set
+ the DP register back to a data pointer in the small memory model.
+ This is only required for ISRs if we are paranoid that someone
+ may have quietly changed this register on the sly. */
#define ASM_FILE_START(FILE) \
{ \
@@ -2184,18 +2193,9 @@ dtors_section () \
} \
else \
output_quoted_string (FILE, main_input_filename); \
- fprintf (FILE, "\n"); \
+ fputs ("\n\t.data\ndata_sec:\n", FILE); \
}
-/* We need to have a data section we can identify so that we can set
- the DP register back to a data pointer in the small memory model.
- This is only required for ISRs if we are paranoid that someone
- may have quietly changed this register on the sly. */
-
-#define ASM_IDENTIFY_GCC(FILE) \
- if (! TARGET_TI) fputs ("gcc2_compiled.:\n", FILE); \
- fputs ("\t.data\ndata_sec:\n", FILE);
-
#define ASM_COMMENT_START ";"
#define ASM_APP_ON ""
diff --git a/gcc/config/c4x/xm-c4x.h b/gcc/config/c4x/xm-c4x.h
index dc329ebc9ba..491032477d1 100644
--- a/gcc/config/c4x/xm-c4x.h
+++ b/gcc/config/c4x/xm-c4x.h
@@ -1,7 +1,3 @@
-/* #defines that need visibility everywhere. */
-#define FALSE 0
-#define TRUE 1
-
/* This describes the machine the compiler is hosted on. */
#define HOST_BITS_PER_CHAR 32
#define HOST_BITS_PER_SHORT 32
@@ -18,4 +14,3 @@
/* Arguments to use with `exit'. */
#define SUCCESS_EXIT_CODE 0
#define FATAL_EXIT_CODE 33
-
diff --git a/gcc/config/clipper/clipper.c b/gcc/config/clipper/clipper.c
index 9e743eb0294..0c3f379569c 100644
--- a/gcc/config/clipper/clipper.c
+++ b/gcc/config/clipper/clipper.c
@@ -28,7 +28,6 @@ Boston, MA 02111-1307, USA. */
#include "real.h"
#include "insn-config.h"
#include "conditions.h"
-#include "insn-flags.h"
#include "output.h"
#include "insn-attr.h"
#include "tree.h"
diff --git a/gcc/config/clipper/xm-clix.h b/gcc/config/clipper/xm-clix.h
index 726660df46a..7e671f6d27e 100644
--- a/gcc/config/clipper/xm-clix.h
+++ b/gcc/config/clipper/xm-clix.h
@@ -1,10 +1,6 @@
/* Config file for Clipper running Clix, system V. 3.2 clone */
-/* #defines that need visibility everywhere. */
-#define FALSE 0
-#define TRUE 1
-
/* target machine dependencies.
tm.h is a symbolic link to the actual target specific file. */
diff --git a/gcc/config/convex/convex.c b/gcc/config/convex/convex.c
index 1b41db35dc7..947a715fccd 100644
--- a/gcc/config/convex/convex.c
+++ b/gcc/config/convex/convex.c
@@ -28,7 +28,6 @@ Boston, MA 02111-1307, USA. */
#include "real.h"
#include "insn-config.h"
#include "conditions.h"
-#include "insn-flags.h"
#include "insn-attr.h"
#include "output.h"
#include "function.h"
diff --git a/gcc/config/convex/xm-convex.h b/gcc/config/convex/xm-convex.h
index aaaa3b1464c..aab0b90946e 100644
--- a/gcc/config/convex/xm-convex.h
+++ b/gcc/config/convex/xm-convex.h
@@ -18,10 +18,6 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* #defines that need visibility everywhere. */
-#define FALSE 0
-#define TRUE 1
-
/* target machine dependencies.
tm.h is a symbolic link to the actual target specific file. */
#include "tm.h"
diff --git a/gcc/config/d30v/d30v.c b/gcc/config/d30v/d30v.c
index c103e81b36b..a4f5e8d8473 100644
--- a/gcc/config/d30v/d30v.c
+++ b/gcc/config/d30v/d30v.c
@@ -28,7 +28,6 @@
#include "real.h"
#include "insn-config.h"
#include "conditions.h"
-#include "insn-flags.h"
#include "output.h"
#include "insn-attr.h"
#include "flags.h"
diff --git a/gcc/config/d30v/d30v.h b/gcc/config/d30v/d30v.h
index 890639a0376..48322136340 100644
--- a/gcc/config/d30v/d30v.h
+++ b/gcc/config/d30v/d30v.h
@@ -4077,28 +4077,6 @@ extern const char *d30v_branch_cost_string;
Defined in svr4.h. */
/* #define ASM_FILE_END(STREAM) */
-/* A C statement to output assembler commands which will identify the object
- file as having been compiled with GNU CC (or another GNU compiler).
-
- If you don't define this macro, the string `gcc_compiled.:' is output. This
- string is calculated to define a symbol which, on BSD systems, will never be
- defined for any other reason. GDB checks for the presence of this symbol
- when reading the symbol table of an executable.
-
- On non-BSD systems, you must arrange communication with GDB in some other
- fashion. If GDB is not used on your system, you can define this macro with
- an empty body.
-
- Defined in svr4.h. */
-/* #define ASM_IDENTIFY_GCC(FILE) */
-
-/* Like ASM_IDENTIFY_GCC, but used when dbx debugging is selected to emit
- a stab the debugger uses to identify gcc as the compiler that is emitted
- after the stabs for the filename, which makes it easier for GDB to parse.
-
- Defined in svr4.h. */
-/* #define ASM_IDENTIFY_GCC_AFTER_SOURCE(FILE) */
-
/* A C string constant describing how to begin a comment in the target
assembler language. The compiler assumes that the comment will end at the
end of the line. */
diff --git a/gcc/config/d30v/xm-d30v.h b/gcc/config/d30v/xm-d30v.h
index 4d3396ec584..024032a9422 100644
--- a/gcc/config/d30v/xm-d30v.h
+++ b/gcc/config/d30v/xm-d30v.h
@@ -19,10 +19,6 @@
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* #defines that need visibility everywhere. */
-#define FALSE 0
-#define TRUE 1
-
/* Define this macro if the host system is System V. */
/* #define USG */
diff --git a/gcc/config/dbxelf.h b/gcc/config/dbxelf.h
index 57d97a6af43..8a2c266a82f 100644
--- a/gcc/config/dbxelf.h
+++ b/gcc/config/dbxelf.h
@@ -54,28 +54,6 @@ Boston, MA 02111-1307, USA. */
#define DBX_CONTIN_LENGTH 0
#endif
-/* When using stabs, gcc2_compiled must be a stabs entry, not an
- ordinary symbol, or gdb won't see it. Furthermore, since gdb reads
- the input piecemeal, starting with each N_SO, it's a lot easier if
- the gcc2 flag symbol is *after* the N_SO rather than before it. So
- we emit an N_OPT stab there. */
-
-#define ASM_IDENTIFY_GCC(FILE) \
-do \
- { \
- if (write_symbols != DBX_DEBUG) \
- fputs ("gcc2_compiled.:\n", FILE); \
- } \
-while (0)
-
-#define ASM_IDENTIFY_GCC_AFTER_SOURCE(FILE) \
-do \
- { \
- if (write_symbols == DBX_DEBUG) \
- fputs ("\t.stabs\t\"gcc2_compiled.\", 0x3c, 0, 0, 0\n", FILE); \
- } \
-while (0)
-
/* Like block addresses, stabs line numbers are relative to the
current function. */
diff --git a/gcc/config/dsp16xx/dsp16xx.c b/gcc/config/dsp16xx/dsp16xx.c
index c74ac388411..fbc28c0d505 100644
--- a/gcc/config/dsp16xx/dsp16xx.c
+++ b/gcc/config/dsp16xx/dsp16xx.c
@@ -28,7 +28,6 @@ Boston, MA 02111-1307, USA. */
#include "real.h"
#include "insn-config.h"
#include "conditions.h"
-#include "insn-flags.h"
#include "output.h"
#include "insn-attr.h"
#include "tree.h"
diff --git a/gcc/config/dsp16xx/dsp16xx.h b/gcc/config/dsp16xx/dsp16xx.h
index 86ff76f6312..8aa0556800b 100644
--- a/gcc/config/dsp16xx/dsp16xx.h
+++ b/gcc/config/dsp16xx/dsp16xx.h
@@ -1599,9 +1599,6 @@ const_section () \
/* Output at beginning of assembler file. */
#define ASM_FILE_START(FILE) dsp16xx_file_start ()
-/* Prevent output of .gcc_compiled */
-#define ASM_IDENTIFY_GCC(FILE)
-
/* A C string constant describing how to begin a comment in the target
assembler language. */
/* define ASM_COMMENT_START */
diff --git a/gcc/config/dsp16xx/xm-dsp16xx.h b/gcc/config/dsp16xx/xm-dsp16xx.h
index 11e1fe912d7..752eb82264d 100644
--- a/gcc/config/dsp16xx/xm-dsp16xx.h
+++ b/gcc/config/dsp16xx/xm-dsp16xx.h
@@ -19,10 +19,6 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* #defines that need visibility everywhere. */
-#define FALSE 0
-#define TRUE 1
-
/* This describes the machine the compiler is hosted on. */
#define HOST_BITS_PER_CHAR 8
#define HOST_BITS_PER_SHORT 16
diff --git a/gcc/config/elfos.h b/gcc/config/elfos.h
index 7d9ac7640a5..5d6a0241db8 100644
--- a/gcc/config/elfos.h
+++ b/gcc/config/elfos.h
@@ -94,23 +94,8 @@ Boston, MA 02111-1307, USA. */
#define ASM_OUTPUT_IDENT(FILE, NAME) \
fprintf (FILE, "%s\"%s\"\n", IDENT_ASM_OP, NAME);
-/* Attach a special .ident directive to the end of the file to identify
- the version of GCC which compiled this code. The format of the
- .ident string is patterned after the ones produced by native svr4
- C compilers. */
-
#define IDENT_ASM_OP "\t.ident\t"
-#undef ASM_FILE_END
-#define ASM_FILE_END(FILE) \
- do \
- { \
- if (!flag_no_ident) \
- fprintf ((FILE), "%s\"GCC: (GNU) %s\"\n", \
- IDENT_ASM_OP, version_string); \
- } \
- while (0)
-
#undef ASM_BYTE_OP
#define ASM_BYTE_OP "\t.byte\t"
diff --git a/gcc/config/elxsi/xm-elxsi.h b/gcc/config/elxsi/xm-elxsi.h
index 8264becd898..84f02cb4aa1 100644
--- a/gcc/config/elxsi/xm-elxsi.h
+++ b/gcc/config/elxsi/xm-elxsi.h
@@ -18,10 +18,6 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* #defines that need visibility everywhere. */
-#define FALSE 0
-#define TRUE 1
-
/* target machine dependencies.
tm.h is a symbolic link to the actual target specific file. */
#include "tm.h"
@@ -35,4 +31,3 @@ Boston, MA 02111-1307, USA. */
/* Arguments to use with `exit'. */
#define SUCCESS_EXIT_CODE 0
#define FATAL_EXIT_CODE 33
-
diff --git a/gcc/config/fr30/fr30.c b/gcc/config/fr30/fr30.c
index c2ee0055b82..f1f63e1c324 100644
--- a/gcc/config/fr30/fr30.c
+++ b/gcc/config/fr30/fr30.c
@@ -32,7 +32,6 @@ Boston, MA 02111-1307, USA. */
#include "real.h"
#include "insn-config.h"
#include "conditions.h"
-#include "insn-flags.h"
#include "output.h"
#include "insn-attr.h"
#include "flags.h"
diff --git a/gcc/config/fr30/xm-fr30.h b/gcc/config/fr30/xm-fr30.h
index a43a3324c37..04abdf8b77d 100644
--- a/gcc/config/fr30/xm-fr30.h
+++ b/gcc/config/fr30/xm-fr30.h
@@ -19,10 +19,6 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* #defines that need visibility everywhere. */
-#define FALSE 0
-#define TRUE 1
-
/* A C expression for the status code to be returned when the compiler exits
after serious errors. */
#define FATAL_EXIT_CODE 33
diff --git a/gcc/config/arm/linux-elf26.h b/gcc/config/freebsd-nthr.h
index ce26f1fef9d..2f1d65f4b24 100644
--- a/gcc/config/arm/linux-elf26.h
+++ b/gcc/config/freebsd-nthr.h
@@ -1,7 +1,6 @@
-/* Definitions for ARM running Linux-based GNU systems
- using ELF and 26-bit APCS.
- Copyright (C) 1999 Free Software Foundation, Inc.
- Contributed by Philip Blundell <Philip.Blundell@pobox.com>
+/* FreeBSD configuration setting for FreeBSD systems.
+ Copyright (C) 2001 Free Software Foundation, Inc.
+ Contributed by Loren J. Rittle <ljrittle@acm.org>
This file is part of GNU CC.
@@ -16,9 +15,8 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with this program; see the file COPYING. If not, write to
+along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* Tell linux-elf.h to default to 26-bit mode. */
-#define SUBTARGET_DEFAULT_APCS26
+#define FBSD_NO_THREADS
diff --git a/gcc/config/freebsd.h b/gcc/config/freebsd.h
index 98a5c9e41b2..88e0226ec71 100644
--- a/gcc/config/freebsd.h
+++ b/gcc/config/freebsd.h
@@ -1,5 +1,5 @@
/* Base configuration file for all FreeBSD targets.
- Copyright (C) 1999, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -22,7 +22,9 @@ Boston, MA 02111-1307, USA. */
All FreeBSD architectures should include this file, which will specify
their commonalities.
Adapted from gcc/config/i386/freebsd-elf.h by
- David O'Brien <obrien@FreeBSD.org>. */
+ David O'Brien <obrien@FreeBSD.org>.
+ Further work by David O'Brien <obrien@FreeBSD.org> and
+ Loren J. Rittle <ljrittle@acm.org>. */
/* This defines which switch letters take arguments. On FreeBSD, most of
@@ -48,6 +50,34 @@ Boston, MA 02111-1307, USA. */
#undef WORD_SWITCH_TAKES_ARG
#define WORD_SWITCH_TAKES_ARG(STR) (FBSD_WORD_SWITCH_TAKES_ARG(STR))
+#if FBSD_MAJOR == 6
+#define FBSD_CPP_PREDEFINES \
+ "-D__FreeBSD__=6 -Dunix -D__ELF__ -Asystem=unix -Asystem=bsd -Asystem=FreeBSD"
+#endif
+
+#if FBSD_MAJOR == 5
+#define FBSD_CPP_PREDEFINES \
+ "-D__FreeBSD__=5 -Dunix -D__ELF__ -Asystem=unix -Asystem=bsd -Asystem=FreeBSD"
+#endif
+
+#if FBSD_MAJOR == 4
+#define FBSD_CPP_PREDEFINES \
+ "-D__FreeBSD__=4 -Dunix -D__ELF__ -Asystem=unix -Asystem=bsd -Asystem=FreeBSD"
+#endif
+
+#if FBSD_MAJOR == 3
+#define FBSD_CPP_PREDEFINES \
+ "-D__FreeBSD__=3 -Dunix -D__ELF__ -Asystem=unix -Asystem=bsd -Asystem=FreeBSD"
+#endif
+
+#ifndef FBSD_CPP_PREDEFINES
+#define FBSD_CPP_PREDEFINES \
+ "-D__FreeBSD__ -Dunix -D__ELF__ -Asystem=unix -Asystem=bsd -Asystem=FreeBSD"
+#endif
+
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES FBSD_CPP_PREDEFINES
+
/* Provide a CPP_SPEC appropriate for FreeBSD. We just deal with the GCC
option `-posix', and PIC issues. */
@@ -56,11 +86,37 @@ Boston, MA 02111-1307, USA. */
%{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} \
%{posix:-D_POSIX_SOURCE}"
-/* Provide a LIB_SPEC appropriate for FreeBSD. Just select the appropriate
- libc, depending on whether we're doing profiling or need threads support.
- (simular to the default, except no -lg, and no -p). */
+/* Provide a LIB_SPEC appropriate for FreeBSD as configured and as
+ required by the user-land thread model. Before __FreeBSD_version
+ 500016, select the appropriate libc, depending on whether we're
+ doing profiling or need threads support. At __FreeBSD_version
+ 500016 and later, when threads support is requested include both
+ -lc and -lc_r instead of only -lc_r. To make matters interesting,
+ we can't actually use __FreeBSD_version provided by <osreldate.h>
+ directly since it breaks cross-compiling. As a final twist, make
+ it a hard error if -pthread is provided on the command line and gcc
+ was configured with --disable-threads (this will help avoid bug
+ reports from users complaining about threading when they
+ misconfigured the gcc bootstrap but are later consulting FreeBSD
+ manual pages that refer to the mythical -pthread option). */
#undef LIB_SPEC
+#ifdef FBSD_NO_THREADS
+#define LIB_SPEC " \
+ %{pthread: %eThe -pthread option is only supported on FreeBSD when gcc \
+is built with the --enable-threads configure-time option.} \
+ %{!shared: \
+ %{!pg: -lc} \
+ %{pg: -lc_p} \
+ }"
+#else
+#if FBSD_MAJOR >= 5
+#define LIB_SPEC " \
+ %{!shared: \
+ %{!pg: %{pthread:-lc_r} -lc} \
+ %{pg: %{pthread:-lc_r_p} -lc_p} \
+ }"
+#else
#define LIB_SPEC " \
%{!shared: \
%{!pg: \
@@ -70,7 +126,8 @@ Boston, MA 02111-1307, USA. */
%{!pthread:-lc_p} \
%{pthread:-lc_r_p}} \
}"
-
+#endif
+#endif
/* Code generation parameters. */
@@ -97,13 +154,12 @@ Boston, MA 02111-1307, USA. */
#undef DEFAULT_VTABLE_THUNKS
#define DEFAULT_VTABLE_THUNKS 1
-/* This is BSD, so use stabs instead of DWARF debug format. */
+/* The GNU tools operate better with dwarf2 than stabs. Since we
+ don't have any native tools to be compatible with, default to
+ dwarf2. */
#undef PREFERRED_DEBUGGING_TYPE
-#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
+#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
-/* Attach a special .ident directive to the end of the file to identify
- the version of GCC which compiled this code. The format of the .ident
- string is patterned after the ones produced by native SVR4 C compilers. */
#undef IDENT_ASM_OP
#define IDENT_ASM_OP "\t.ident\t"
@@ -112,20 +168,6 @@ Boston, MA 02111-1307, USA. */
#define ASM_OUTPUT_IDENT(FILE, NAME) \
fprintf ((FILE), "%s\"%s\"\n", IDENT_ASM_OP, (NAME));
-#undef ASM_IDENTIFY_LANGUAGE
-#define ASM_IDENTIFY_LANGUAGE(FILE) \
- fprintf ((FILE), "%s\"GCC (%s) %s\"\n", IDENT_ASM_OP, \
- lang_identify (), version_string)
-
-#undef ASM_FILE_END
-#define ASM_FILE_END(FILE) \
-do { \
- if (!flag_no_ident) \
- fprintf ((FILE), "%s\"GCC: (GNU) %s\"\n", \
- IDENT_ASM_OP, version_string); \
- } while (0)
-
-
/* Miscellaneous parameters. */
/* Don't assume anything about the header files. */
diff --git a/gcc/config/arm/linux-oldld.h b/gcc/config/freebsd3.h
index 8b2af015efe..7b5426f9336 100644
--- a/gcc/config/arm/linux-oldld.h
+++ b/gcc/config/freebsd3.h
@@ -1,7 +1,6 @@
-/* Definitions for ARM running Linux-based GNU systems
- using ELF with old binutils.
- Copyright (C) 1999 Free Software Foundation, Inc.
- Contributed by Philip Blundell <Philip.Blundell@pobox.com>
+/* FreeBSD version number setting for FreeBSD 3.x systems.
+ Copyright (C) 2001 Free Software Foundation, Inc.
+ Contributed by David E. O'Brien <obrien@FreeBSD.org> and BSDi.
This file is part of GNU CC.
@@ -16,12 +15,8 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with this program; see the file COPYING. If not, write to
+along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* Unfortunately, owing to various historical accidents, version 2.9.4
- and newer of GNU binutils are not quite compatible with the old
- (2.9.1-based) toolset. This tells linux-elf.h to generate specs
- appropriate for the older versions. */
-#define SUBTARGET_OLD_LINKER
+#define FBSD_MAJOR 3
diff --git a/gcc/config/freebsd4.h b/gcc/config/freebsd4.h
new file mode 100644
index 00000000000..ec2ae4752bb
--- /dev/null
+++ b/gcc/config/freebsd4.h
@@ -0,0 +1,22 @@
+/* FreeBSD version number setting for FreeBSD 4.x systems.
+ Copyright (C) 2001 Free Software Foundation, Inc.
+ Contributed by David E. O'Brien <obrien@FreeBSD.org> and BSDi.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#define FBSD_MAJOR 4
diff --git a/gcc/config/freebsd5.h b/gcc/config/freebsd5.h
new file mode 100644
index 00000000000..3c276d50d7a
--- /dev/null
+++ b/gcc/config/freebsd5.h
@@ -0,0 +1,22 @@
+/* FreeBSD version number setting for FreeBSD 5.x systems.
+ Copyright (C) 2001 Free Software Foundation, Inc.
+ Contributed by David E. O'Brien <obrien@FreeBSD.org> and BSDi.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#define FBSD_MAJOR 5
diff --git a/gcc/config/freebsd6.h b/gcc/config/freebsd6.h
new file mode 100644
index 00000000000..38bc0cdbb23
--- /dev/null
+++ b/gcc/config/freebsd6.h
@@ -0,0 +1,22 @@
+/* FreeBSD version number setting for FreeBSD 6.x systems.
+ Copyright (C) 2001 Free Software Foundation, Inc.
+ Contributed by David E. O'Brien <obrien@FreeBSD.org> and BSDi.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#define FBSD_MAJOR 6
diff --git a/gcc/config/h8300/h8300.c b/gcc/config/h8300/h8300.c
index a52120c9dca..2a43e52439c 100644
--- a/gcc/config/h8300/h8300.c
+++ b/gcc/config/h8300/h8300.c
@@ -30,7 +30,6 @@ Boston, MA 02111-1307, USA. */
#include "real.h"
#include "insn-config.h"
#include "conditions.h"
-#include "insn-flags.h"
#include "output.h"
#include "insn-attr.h"
#include "flags.h"
@@ -509,7 +508,7 @@ ok_for_bclr (value)
return small_power_of_two ((~value) & 0xff);
}
-/* Return true is OP is a valid source operand for an integer move
+/* Return true if OP is a valid source operand for an integer move
instruction. */
int
@@ -2239,7 +2238,7 @@ get_shift_alg (shift_type, shift_mode, count, info)
{
if (count == 15 && shift_type == SHIFT_ASHIFTRT)
{
- info->special = "shll\t%t0,%t0\n\tsubx\t%t0,%t0\n\tmov.b\t%t0,%s0";
+ info->special = "shll\t%t0\n\tsubx\t%t0,%t0\n\tmov.b\t%t0,%s0";
info->cc_valid_p = 0;
return SHIFT_SPECIAL;
}
diff --git a/gcc/config/h8300/h8300.h b/gcc/config/h8300/h8300.h
index a0862c5ec8a..b360c796183 100644
--- a/gcc/config/h8300/h8300.h
+++ b/gcc/config/h8300/h8300.h
@@ -846,12 +846,6 @@ struct cum_arg
/* Extra constraints. */
-/* 'T' if valid for dec.[wl] on H8/300H and H8/S. Note that, for
- inc.[wl], we can use 'K', which has already been defined. */
-#define OK_FOR_T(OP) \
- (GET_CODE (OP) == CONST_INT \
- && (INTVAL (OP) == -1 || INTVAL (OP) == -2))
-
/* Nonzero if X is a constant address suitable as an 8-bit absolute on
the H8/300H, which is a special case of the 'R' operand. */
@@ -881,8 +875,7 @@ struct cum_arg
&& GET_CODE (XEXP (OP, 0)) == CONST_INT))
#define EXTRA_CONSTRAINT(OP, C) \
- ((C) == 'T' ? OK_FOR_T (OP) : \
- (C) == 'U' ? OK_FOR_U (OP) : \
+ ((C) == 'U' ? OK_FOR_U (OP) : \
0)
/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
@@ -1068,8 +1061,6 @@ h8300_valid_machine_decl_attribute (DECL, ATTRIBUTES, IDENTIFIER, ARGS)
/* Control the assembler format that we output. */
-#define ASM_IDENTIFY_GCC(FILE) /* nothing */
-
/* Output at beginning/end of assembler file. */
#define ASM_FILE_START(FILE) asm_file_start(FILE)
diff --git a/gcc/config/h8300/h8300.md b/gcc/config/h8300/h8300.md
index 661f5a8aaa5..51fb4ee2f98 100644
--- a/gcc/config/h8300/h8300.md
+++ b/gcc/config/h8300/h8300.md
@@ -1,6 +1,6 @@
;; GCC machine description for Hitachi H8/300
-;; Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000
-;; Free Software Foundation, Inc.
+;; Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+;; 2001 Free Software Foundation, Inc.
;; Contributed by Steve Chamberlain (sac@cygnus.com),
;; Jim Wilson (wilson@cygnus.com), and Doug Evans (dje@cygnus.com).
@@ -399,8 +399,8 @@
(set_attr "cc" "clobber")])
(define_insn "movsi_h8300hs"
- [(set (match_operand:SI 0 "general_operand_dst" "=r,r,r,m,<,r,*a,*a,r")
- (match_operand:SI 1 "general_operand_src" "I,r,im,r,r,>,I,r,*a"))]
+ [(set (match_operand:SI 0 "general_operand_dst" "=r,r,r,r,m,<,r,*a,*a,r")
+ (match_operand:SI 1 "general_operand_src" "I,r,i,m,r,r,>,I,r,*a"))]
"(TARGET_H8300S || TARGET_H8300H)
&& (register_operand (operands[0], SImode)
|| register_operand (operands[1], SImode))"
@@ -410,11 +410,11 @@
{
case 0:
return \"sub.l %S0,%S0\";
- case 6:
- return \"clrmac\";
case 7:
- return \"clrmac\;ldmac %1,macl\";
+ return \"clrmac\";
case 8:
+ return \"clrmac\;ldmac %1,macl\";
+ case 9:
return \"stmac macl,%0\";
default:
if (GET_CODE (operands[1]) == CONST_INT)
@@ -446,8 +446,8 @@
}
return \"mov.l %S1,%S0\";
}"
- [(set_attr "length" "2,2,10,10,4,4,2,6,4")
- (set_attr "cc" "set_zn,set_znv,set_znv,set_znv,set_znv,set_znv,none_0hit,none_0hit,set_znv")])
+ [(set_attr "length" "2,2,10,10,10,4,4,2,6,4")
+ (set_attr "cc" "set_zn,set_znv,clobber,set_znv,set_znv,set_znv,set_znv,none_0hit,none_0hit,set_znv")])
(define_insn "movsf_h8300h"
[(set (match_operand:SF 0 "general_operand_dst" "=r,r,r,m,<,r")
@@ -628,19 +628,17 @@
(set_attr "cc" "none_0hit,none_0hit,clobber,set_zn,set_zn")])
(define_insn ""
- [(set (match_operand:HI 0 "register_operand" "=r,r,r,r,r,r")
- (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0,0,0,0")
- (match_operand:HI 2 "nonmemory_operand" "K,T,L,N,n,r")))]
+ [(set (match_operand:HI 0 "register_operand" "=r,r,r,r")
+ (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0,0")
+ (match_operand:HI 2 "nonmemory_operand" "L,N,n,r")))]
"TARGET_H8300H || TARGET_H8300S"
"@
- inc.w %2,%T0
- dec.w %G2,%T0
adds %2,%A0
subs %G2,%A0
add.w %T2,%T0
add.w %T2,%T0"
- [(set_attr "length" "2,2,2,2,4,2")
- (set_attr "cc" "set_znv,set_znv,none_0hit,none_0hit,set_zn,set_zn")])
+ [(set_attr "length" "2,2,4,2")
+ (set_attr "cc" "none_0hit,none_0hit,set_zn,set_zn")])
(define_split
[(set (match_operand:HI 0 "register_operand" "")
@@ -670,19 +668,17 @@
(set_attr "cc" "clobber")])
(define_insn "addsi_h8300h"
- [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
- (plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")
- (match_operand:SI 2 "nonmemory_operand" "K,T,L,N,i,r")))]
+ [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
+ (plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0")
+ (match_operand:SI 2 "nonmemory_operand" "L,N,i,r")))]
"TARGET_H8300H || TARGET_H8300S"
"@
- inc.l %2,%S0
- dec.l %G2,%S0
adds %2,%A0
subs %G2,%A0
add.l %S2,%S0
add.l %S2,%S0"
- [(set_attr "length" "2,2,2,2,6,2")
- (set_attr "cc" "set_znv,set_znv,none_0hit,none_0hit,set_zn,set_zn")])
+ [(set_attr "length" "2,2,6,2")
+ (set_attr "cc" "none_0hit,none_0hit,set_zn,set_zn")])
(define_split
[(set (match_operand:SI 0 "register_operand" "")
@@ -898,7 +894,7 @@
(match_operand:HI 1 "general_operand" "0")
(zero_extend:HI (match_operand:QI 2 "register_operand" "r")))))]
""
- "divxu %X2,%T0\;mov %t0,%s0"
+ "divxu %X2,%T0\;mov %t0,%s0"
[(set_attr "length" "4")
(set_attr "cc" "clobber")])
@@ -909,7 +905,7 @@
(match_operand:HI 1 "general_operand" "0")
(sign_extend:HI (match_operand:QI 2 "register_operand" "r")))))]
"TARGET_H8300H || TARGET_H8300S"
- "divxs.b %X2,%T0\;mov %t0,%s0"
+ "divxs.b %X2,%T0\;mov %t0,%s0"
[(set_attr "length" "6")
(set_attr "cc" "clobber")])
@@ -920,7 +916,7 @@
(match_operand:SI 1 "general_operand" "0")
(zero_extend:SI (match_operand:HI 2 "register_operand" "r")))))]
"TARGET_H8300H || TARGET_H8300S"
- "divxu.w %T2,%S0\;mov %e0,%f0"
+ "divxu.w %T2,%S0\;mov %e0,%f0"
[(set_attr "length" "4")
(set_attr "cc" "clobber")])
@@ -931,7 +927,7 @@
(match_operand:SI 1 "general_operand" "0")
(sign_extend:SI (match_operand:HI 2 "register_operand" "r")))))]
"TARGET_H8300H || TARGET_H8300S"
- "divxs.w %T2,%S0\;mov %e0,%f0"
+ "divxs.w %T2,%S0\;mov %e0,%f0"
[(set_attr "length" "6")
(set_attr "cc" "clobber")])
@@ -1034,7 +1030,7 @@
}
if (TARGET_H8300H || TARGET_H8300S)
return \"and.l %S2,%S0\";
- return \"and %w2,%w0\;and %x2,%x0\;and %y2,%y0\;and %z2,%z0\;\";
+ return \"and %w2,%w0\;and %x2,%x0\;and %y2,%y0\;and %z2,%z0\";
}"
[(set_attr "length" "8")
(set_attr "cc" "clobber")])
@@ -1122,7 +1118,7 @@
}
if (TARGET_H8300H || TARGET_H8300S)
return \"or.l %S2,%S0\";
- return \"or %w2,%w0\;or %x2,%x0\;or %y2,%y0\;or %z2,%z0\;\";
+ return \"or %w2,%w0\;or %x2,%x0\;or %y2,%y0\;or %z2,%z0\";
}"
[(set_attr "length" "2,8")
(set_attr "cc" "clobber,clobber")])
@@ -1209,7 +1205,7 @@
}
if (TARGET_H8300H || TARGET_H8300S)
return \"xor.l %S2,%S0\";
- return \"xor %w2,%w0\;xor %x2,%x0\;xor %y2,%y0\;xor %z2,%z0\;\";
+ return \"xor %w2,%w0\;xor %x2,%x0\;xor %y2,%y0\;xor %z2,%z0\";
}"
[(set_attr "length" "2,8")
(set_attr "cc" "clobber,clobber")])
diff --git a/gcc/config/h8300/t-h8300 b/gcc/config/h8300/t-h8300
index fbc4d731440..4bca0e04a5e 100644
--- a/gcc/config/h8300/t-h8300
+++ b/gcc/config/h8300/t-h8300
@@ -1,6 +1,7 @@
CROSS_LIBGCC1 = libgcc1-asm.a
LIB1ASMSRC = h8300/lib1funcs.asm
-LIB1ASMFUNCS = _cmpsi2 _ucmpsi2 _divhi3 _divsi3 _mulhi3 _mulsi3
+LIB1ASMFUNCS = _cmpsi2 _ucmpsi2 _divhi3 _divsi3 _mulhi3 _mulsi3 \
+ _floatdisf _fixsfdi
# We do not have DF or DI types, so fake out the libgcc2 compilation.
TARGET_LIBGCC2_CFLAGS = -DDF=SF -DDI=SI
diff --git a/gcc/config/h8300/xm-h8300.h b/gcc/config/h8300/xm-h8300.h
index 7fde9e6cd87..8b5b3f3d797 100644
--- a/gcc/config/h8300/xm-h8300.h
+++ b/gcc/config/h8300/xm-h8300.h
@@ -18,10 +18,6 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* #defines that need visibility everywhere. */
-#define FALSE 0
-#define TRUE 1
-
/* This describes the machine the compiler is hosted on. */
#define HOST_BITS_PER_CHAR 8
#define HOST_BITS_PER_SHORT 16
@@ -43,4 +39,3 @@ Boston, MA 02111-1307, USA. */
/* target machine dependencies.
tm.h is a symbolic link to the actual target specific file. */
#include "tm.h"
-
diff --git a/gcc/config/i370/i370.c b/gcc/config/i370/i370.c
index 2db1a01b9fc..778930e5808 100644
--- a/gcc/config/i370/i370.c
+++ b/gcc/config/i370/i370.c
@@ -31,7 +31,6 @@ Boston, MA 02111-1307, USA. */
#include "real.h"
#include "insn-config.h"
#include "conditions.h"
-#include "insn-flags.h"
#include "output.h"
#include "insn-attr.h"
#include "function.h"
diff --git a/gcc/config/i370/i370.h b/gcc/config/i370/i370.h
index 8967d0b6de6..6bb638b95a5 100644
--- a/gcc/config/i370/i370.h
+++ b/gcc/config/i370/i370.h
@@ -1091,7 +1091,6 @@ enum reg_class
fputs ("\tCSECT\n", FILE); }
#define ASM_FILE_END(FILE) fputs ("\tEND\n", FILE);
-#define ASM_IDENTIFY_GCC(FILE)
#define ASM_COMMENT_START "*"
#define ASM_APP_OFF ""
#define ASM_APP_ON ""
diff --git a/gcc/config/i370/i370.md b/gcc/config/i370/i370.md
index 614e3d6fb6b..4ee3e14f835 100644
--- a/gcc/config/i370/i370.md
+++ b/gcc/config/i370/i370.md
@@ -4702,8 +4702,8 @@ check_label_emit ();
;; Call subroutine returning any type.
;; This instruction pattern appears to be used only by the
;; expand_builtin_apply definition for __builtin_apply. It is needed
-;; since call_value might return an in in r15 or a float in fpr0 (r16)
-;; and the builtin code calla abort since the reg is ambiguous. Well,
+;; since call_value might return an int in r15 or a float in fpr0 (r16)
+;; and the builtin code calls abort since the reg is ambiguous. Well,
;; the below is probably broken anyway, we just want to go for now.
;;
(define_expand "untyped_call"
diff --git a/gcc/config/i370/xm-i370.h b/gcc/config/i370/xm-i370.h
index b80efb9917d..8e5161fd326 100644
--- a/gcc/config/i370/xm-i370.h
+++ b/gcc/config/i370/xm-i370.h
@@ -20,11 +20,6 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* #defines that need visibility everywhere. */
-
-#define FALSE 0
-#define TRUE 1
-
/* This describes the machine the compiler is hosted on. */
#define HOST_BITS_PER_CHAR 8
diff --git a/gcc/config/i370/xm-linux.h b/gcc/config/i370/xm-linux.h
index e0ab373c54d..69298b71dcd 100644
--- a/gcc/config/i370/xm-linux.h
+++ b/gcc/config/i370/xm-linux.h
@@ -23,9 +23,6 @@ Boston, MA 02111-1307, USA. */
/* #defines that need visibility everywhere. */
-#define FALSE 0
-#define TRUE 1
-
#define USE_STDARGS 1
#define USE_PROTOTYPES 1
@@ -59,7 +56,6 @@ extern char *alloca ();
#include "tm.h"
/* Arguments to use with `exit'. */
-
#define SUCCESS_EXIT_CODE 0
#define FATAL_EXIT_CODE 12
diff --git a/gcc/config/i370/xm-mvs.h b/gcc/config/i370/xm-mvs.h
index f43a8408ce2..e10bdae7cc0 100644
--- a/gcc/config/i370/xm-mvs.h
+++ b/gcc/config/i370/xm-mvs.h
@@ -20,11 +20,6 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* #defines that need visibility everywhere. */
-
-#define FALSE 0
-#define TRUE 1
-
/* This describes the machine the compiler is hosted on. */
#define HOST_BITS_PER_CHAR 8
diff --git a/gcc/config/i370/xm-oe.h b/gcc/config/i370/xm-oe.h
index a930a2bae61..19a46f6428b 100644
--- a/gcc/config/i370/xm-oe.h
+++ b/gcc/config/i370/xm-oe.h
@@ -22,9 +22,6 @@ Boston, MA 02111-1307, USA. */
/* #defines that need visibility everywhere. */
-#define FALSE 0
-#define TRUE 1
-
#define USE_STDARGS 1
#define USE_PROTOTYPES 1
diff --git a/gcc/config/i386/att.h b/gcc/config/i386/att.h
index e04b035b473..b41218e387f 100644
--- a/gcc/config/i386/att.h
+++ b/gcc/config/i386/att.h
@@ -30,10 +30,8 @@ Boston, MA 02111-1307, USA. */
/* Assembler pseudos to introduce constants of various size. */
-/* #define ASM_BYTE_OP "\t.byte" Now in svr3.h or svr4.h. */
-#define ASM_SHORT "\t.value"
-#define ASM_LONG "\t.long"
-#define ASM_DOUBLE "\t.double"
+#define ASM_SHORT "\t.value\t"
+#define ASM_LONG "\t.long\t"
/* How to output an ASCII string constant. */
@@ -56,7 +54,6 @@ do \
output_file_directive (FILE, main_input_filename); \
if (target_flags & MASK_INTEL_SYNTAX) \
fputs ("\t.intel_syntax\n", FILE); \
- fprintf (FILE, "\t.version\t\"01.01\"\n"); \
} while (0)
/* Do use .optim by default on this machine. */
diff --git a/gcc/config/i386/beos-elf.h b/gcc/config/i386/beos-elf.h
index 0ac148b2458..bbd809617a8 100644
--- a/gcc/config/i386/beos-elf.h
+++ b/gcc/config/i386/beos-elf.h
@@ -264,15 +264,3 @@ Boston, MA 02111-1307, USA. */
without user intervention. For instance, under Microsoft Windows
symbols must be explicitly imported from shared libraries (DLLs). */
#define MULTIPLE_SYMBOL_SPACES
-
-/* A C statement to output assembler commands which will identify the object
- file as having been compiled with GNU CC. This isn't needed for BeOS
- because we use DWARF and DWARF has an DW_AT_producer tag that does the
- same thing. BeOS debuggers, like bdb, that don't know about this hack
- can get confused when they find two symbols with the same address, and
- print the wrong one (gcc2_compiled) in things like backtraces. The most
- likely ill effect of disabling this is that a BeOS port of gdb would not
- be able to tell that an executable was compiled with gcc if there was no
- DWARF info. */
-#undef ASM_IDENTIFY_GCC
-#define ASM_IDENTIFY_GCC(FILE)
diff --git a/gcc/config/i386/bsd.h b/gcc/config/i386/bsd.h
index 1666696cbfc..82b141130f9 100644
--- a/gcc/config/i386/bsd.h
+++ b/gcc/config/i386/bsd.h
@@ -41,9 +41,8 @@ Boston, MA 02111-1307, USA. */
/* Assembler pseudos to introduce constants of various size. */
#define ASM_BYTE_OP "\t.byte\t"
-#define ASM_SHORT "\t.word"
-#define ASM_LONG "\t.long"
-#define ASM_DOUBLE "\t.double"
+#define ASM_SHORT "\t.word\t"
+#define ASM_LONG "\t.long\t"
/* Output at beginning of assembler file.
??? I am skeptical of this -- RMS. */
diff --git a/gcc/config/i386/cygwin.h b/gcc/config/i386/cygwin.h
index 46b93aea113..0c05a406e41 100644
--- a/gcc/config/i386/cygwin.h
+++ b/gcc/config/i386/cygwin.h
@@ -1,8 +1,6 @@
/* Operating system specific defines to be used when targeting GCC for
- hosting on Windows NT 3.x, using a Unix style C library and tools,
- as distinct from winnt.h, which is used to build GCC for use with a
- windows style library and tool set and uses the Microsoft tools.
- Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000
+ hosting on Windows32, using a Unix style C library and tools.
+ Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001
Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -28,6 +26,7 @@ Boston, MA 02111-1307, USA. */
#define SDB_DEBUGGING_INFO
#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
+#include <stdio.h> /* Required for FILE use below */
#include "i386/gas.h"
#include "dbxcoff.h"
@@ -61,44 +60,37 @@ Boston, MA 02111-1307, USA. */
{ "no-nop-fun-dllimport", -MASK_NOP_FUN_DLLIMPORT, "" }, \
{ "threads", 0, N_("Use Mingw-specific thread support") },
-
-/* Support the __declspec keyword by turning them into attributes.
- We currently only support: dllimport and dllexport.
- Note that the current way we do this may result in a collision with
- predefined attributes later on. This can be solved by using one attribute,
- say __declspec__, and passing args to it. The problem with that approach
- is that args are not accumulated: each new appearance would clobber any
- existing args. */
-
#undef CPP_PREDEFINES
#define CPP_PREDEFINES "-D_X86_=1 -Asystem=winnt"
-/* Normally, -lgcc is not needed since everything in it is in the DLL, but we
- want to allow things to be added to it when installing new versions of
- GCC without making a new CYGWIN.DLL, so we leave it. Profiling is handled
- by calling the init function from the prologue. */
-
-#undef LIBGCC_SPEC
-#define LIBGCC_SPEC "%{mno-cygwin: %{mthreads:-lmingwthrd} -lmingw32} -lgcc %{mno-cygwin:-lmoldname -lmsvcrt}"
-
#ifdef CROSS_COMPILE
#define CYGWIN_INCLUDES "-idirafter " CYGWIN_CROSS_DIR "/include"
-#define CYGWIN_W32API "-I" CYGWIN_CROSS_DIR "/include/w32api"
+#define W32API_INC "-idirafter " CYGWIN_CROSS_DIR "/include/w32api"
+#define W32API_LIB "-L" CYGWIN_CROSS_DIR "/lib/w32api/"
#define CYGWIN_LIB CYGWIN_CROSS_DIR "/lib"
#define MINGW_LIBS "-L" CYGWIN_CROSS_DIR "/lib/mingw"
-#define MINGW_INCLUDES "-I" CYGWIN_CROSS_DIR "/include/mingw"
+#define MINGW_INCLUDES "-isystem " CYGWIN_CROSS_DIR "/include/mingw/g++-3 "\
+ "-isystem " CYGWIN_CROSS_DIR "/include/mingw/g++ "\
+ "-idirafter " CYGWIN_CROSS_DIR "/include/mingw"
#else
#define CYGWIN_INCLUDES "-isystem /usr/local/include -idirafter /usr/include"
-#define CYGWIN_W32API "-I/usr/include/w32api"
+#define W32API_INC "-idirafter /usr/include/w32api"
+#define W32API_LIB "-L/usr/lib/w32api/"
#define CYGWIN_LIB "/usr/lib"
#define MINGW_LIBS "-L/usr/local/lib/mingw -L/usr/lib/mingw"
-#define MINGW_INCLUDES "-isystem /usr/local/include/mingw -idirafter /usr/include/mingw"
+#define MINGW_INCLUDES "-isystem /usr/include/mingw/g++-3 "\
+ "-isystem /usr/include/mingw/g++ "\
+ "-isystem /usr/local/include/mingw" \
+ "-idirafter /usr/include/mingw"
#endif
-#undef STARTFILE_SPEC
-#define STARTFILE_SPEC "%{shared|mdll: %{mno-cygwin:dllcrt2%O%s}} \
- %{!shared: %{!mdll: %{!mno-cygwin:crt0%O%s} %{mno-cygwin:" MINGW_LIBS " mingw/crt2%O%s} \
- %{pg:gcrt0%O%s}}}"
+/* Support the __declspec keyword by turning them into attributes.
+ We currently only support: dllimport and dllexport.
+ Note that the current way we do this may result in a collision with
+ predefined attributes later on. This can be solved by using one attribute,
+ say __declspec__, and passing args to it. The problem with that approach
+ is that args are not accumulated: each new appearance would clobber any
+ existing args. */
#undef CPP_SPEC
#define CPP_SPEC "%(cpp_cpu) %{posix:-D_POSIX_SOURCE} \
@@ -108,16 +100,29 @@ Boston, MA 02111-1307, USA. */
-D_cdecl=__attribute__((__cdecl__))} \
-D__declspec(x)=__attribute__((x)) \
-D__i386__ -D__i386 \
- %{!mno-cygwin:-D__CYGWIN32__ -D__CYGWIN__ -Dunix -D__unix__ -D__unix \
- " CYGWIN_INCLUDES "} \
- %{mno-win32: %{mno-cygwin: %emno-cygwin and mno-win32 are not compatible}} \
- %{mno-cygwin:-DWIN32 -D_WIN32 -D__WIN32 -D__WIN32__ -DWINNT -D__MSVCRT__ \
- -D__MINGW32__=0.3 %{mthreads:-D_MT} " MINGW_INCLUDES CYGWIN_W32API "\
- -iwithprefixbefore ../../../../mingw/include/g++-3 \
- -iwithprefixbefore ../../../../mingw/include \
- -iwithprefixbefore ../../../../mingw32/include/g++-3 \
- -iwithprefixbefore ../../../../mingw32/include } \
- %{!mno-win32:-DWIN32 -D_WIN32 -D__WIN32 -D__WIN32__ -DWINNT " CYGWIN_W32API "}"
+ %{mno-win32:%{mno-cygwin: %emno-cygwin and mno-win32 are not compatible}} \
+ %{mno-cygwin:-D__MSVCRT__ -D__MINGW32__ %{mthreads:-D_MT} "\
+ MINGW_INCLUDES "} \
+ %{!mno-cygwin:-D__CYGWIN32__ -D__CYGWIN__ -Dunix -D__unix__ -D__unix "\
+ CYGWIN_INCLUDES "}\
+ %{mwin32|mno-cygwin:-DWIN32 -D_WIN32 -D__WIN32 -D__WIN32__ -DWINNT}\
+ %{!mno-win32:" W32API_INC "}\
+"
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC "\
+ %{shared|mdll: %{mno-cygwin:" MINGW_LIBS " mingw/dllcrt2%O%s}}\
+ %{!shared: %{!mdll: %{!mno-cygwin:crt0%O%s} %{mno-cygwin:" MINGW_LIBS " mingw/crt2%O%s}\
+ %{pg:gcrt0%O%s}}}\
+"
+
+/* Normally, -lgcc is not needed since everything in it is in the DLL, but we
+ want to allow things to be added to it when installing new versions of
+ GCC without making a new CYGWIN.DLL, so we leave it. Profiling is handled
+ by calling the init function from the prologue. */
+
+#undef LIBGCC_SPEC
+#define LIBGCC_SPEC "%{mno-cygwin: %{mthreads:-lmingwthrd} -lmingw32} -lgcc %{mno-cygwin:-lmoldname -lmsvcrt}"
/* This macro defines names of additional specifications to put in the specs
that can be used in various specifications like CC1_SPEC. Its definition
@@ -140,20 +145,23 @@ Boston, MA 02111-1307, USA. */
ld, but that doesn't work just yet. */
#undef LIB_SPEC
-#define LIB_SPEC "%{pg:-lgmon} \
+#define LIB_SPEC "\
+ %{pg:-lgmon} \
%{!mno-cygwin:-lcygwin} \
%{mno-cygwin:%{mthreads:-lmingwthrd} -lmingw32} \
%{mwindows:-lgdi32 -lcomdlg32} \
-luser32 -lkernel32 -ladvapi32 -lshell32"
-#define LINK_SPEC "%{mwindows:--subsystem windows} \
+#define LINK_SPEC W32API_LIB "\
+ %{mwindows:--subsystem windows} \
%{mconsole:--subsystem console} \
%{shared: %{mdll: %eshared and mdll are not compatible}} \
%{shared: --shared} %{mdll:--dll} \
%{static:-Bstatic} %{!static:-Bdynamic} \
%{shared|mdll: -e \
%{mno-cygwin:_DllMainCRTStartup@12} \
- %{!mno-cygwin:__cygwin_dll_entry@12}}"
+ %{!mno-cygwin:__cygwin_dll_entry@12}}\
+ --dll-search-prefix=cyg"
#undef MATH_LIBRARY
#define MATH_LIBRARY ""
@@ -227,6 +235,7 @@ ctor_section () \
in_section = in_ctor; \
} \
}
+void ctor_section PARAMS ((void));
#define DTOR_SECTION_FUNCTION \
void \
@@ -238,6 +247,7 @@ dtor_section () \
in_section = in_dtor; \
} \
}
+void dtor_section PARAMS ((void));
#define DRECTVE_SECTION_FUNCTION \
void \
@@ -249,6 +259,7 @@ drectve_section () \
in_section = in_drectve; \
} \
}
+void drectve_section PARAMS ((void));
/* Switch to SECTION (an `enum in_section').
@@ -257,6 +268,7 @@ drectve_section () \
ASM_DECLARE_OBJECT_NAME and then switch back to the original section
afterwards. */
#define SWITCH_TO_SECTION_FUNCTION \
+void switch_to_section PARAMS ((enum in_section, tree)); \
void \
switch_to_section (section, decl) \
enum in_section section; \
@@ -277,7 +289,7 @@ switch_to_section (section, decl) \
#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \
do { \
ctor_section (); \
- fprintf (FILE, "%s\t", ASM_LONG); \
+ fputs (ASM_LONG, FILE); \
assemble_name (FILE, NAME); \
fprintf (FILE, "\n"); \
} while (0)
@@ -285,7 +297,7 @@ switch_to_section (section, decl) \
#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \
do { \
dtor_section (); \
- fprintf (FILE, "%s\t", ASM_LONG); \
+ fputs (ASM_LONG, FILE); \
assemble_name (FILE, NAME); \
fprintf (FILE, "\n"); \
} while (0)
@@ -359,7 +371,7 @@ do { \
#undef ASM_OUTPUT_LABELREF
#define ASM_OUTPUT_LABELREF(STREAM, NAME) \
fprintf (STREAM, "%s%s", USER_LABEL_PREFIX, \
- I386_PE_STRIP_ENCODING (NAME)) \
+ I386_PE_STRIP_ENCODING (NAME)) \
/* Output a common block. */
#undef ASM_OUTPUT_COMMON
@@ -446,11 +458,11 @@ do { \
else \
{ \
type = SECT_RW; \
- if (TREE_CODE (DECL) == VAR_DECL \
- && lookup_attribute ("shared", DECL_MACHINE_ATTRIBUTES (DECL))) \
- mode = "ws"; \
+ if (DECL && TREE_CODE (DECL) == VAR_DECL \
+ && lookup_attribute ("shared", DECL_MACHINE_ATTRIBUTES (DECL))) \
+ mode = "ws"; \
else \
- mode = "w"; \
+ mode = "w"; \
} \
\
if (s == 0) \
@@ -463,12 +475,12 @@ do { \
sections = s; \
fprintf (STREAM, ".section\t%s,\"%s\"\n", NAME, mode); \
/* Functions may have been compiled at various levels of \
- optimization so we can't use `same_size' here. Instead, \
- have the linker pick one. */ \
+ optimization so we can't use `same_size' here. Instead, \
+ have the linker pick one. */ \
if ((DECL) && DECL_ONE_ONLY (DECL)) \
- fprintf (STREAM, "\t.linkonce %s\n", \
- TREE_CODE (DECL) == FUNCTION_DECL \
- ? "discard" : "same_size"); \
+ fprintf (STREAM, "\t.linkonce %s\n", \
+ TREE_CODE (DECL) == FUNCTION_DECL \
+ ? "discard" : "same_size"); \
} \
else \
{ \
@@ -529,25 +541,19 @@ do { \
&& MAIN_NAME_P (DECL_NAME (current_function_decl))) \
{ \
emit_call_insn (gen_rtx (CALL, VOIDmode, \
- gen_rtx_MEM (FUNCTION_MODE, \
+ gen_rtx_MEM (FUNCTION_MODE, \
gen_rtx_SYMBOL_REF (Pmode, "_monstartup")), \
const0_rtx)); \
}
/* External function declarations. */
-#ifndef PARAMS
-#if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
-#define PARAMS(ARGS) ARGS
-#else
-#define PARAMS(ARGS) ()
-#endif
-#endif
-
-extern void i386_pe_record_external_function PARAMS ((char *));
-/* extern void i386_pe_declare_function_type PARAMS ((FILE *, char *, int)); */
-extern void i386_pe_record_exported_symbol PARAMS ((char *, int));
-/* extern void i386_pe_asm_file_end PARAMS ((FILE *)); */
+extern void i386_pe_record_external_function PARAMS ((const char *));
+extern void i386_pe_declare_function_type PARAMS ((FILE *, const char *, int));
+extern void i386_pe_record_exported_symbol PARAMS ((const char *, int));
+extern void i386_pe_asm_file_end PARAMS ((FILE *));
+extern int i386_pe_dllexport_name_p PARAMS ((const char *));
+extern int i386_pe_dllimport_name_p PARAMS ((const char *));
/* For Win32 ABI compatibility */
#undef DEFAULT_PCC_STRUCT_RETURN
@@ -568,10 +574,6 @@ extern void i386_pe_record_exported_symbol PARAMS ((char *, int));
#define SET_ASM_OP "\t.set\t"
#endif
-#ifndef INT_ASM_OP
-#define INT_ASM_OP "\t.long\t"
-#endif
-
#undef MD_STARTFILE_PREFIX
#define MD_STARTFILE_PREFIX "/usr/lib/"
diff --git a/gcc/config/i386/dgux.c b/gcc/config/i386/dgux.c
index 60e36b44dd6..e9d2b51c3b7 100644
--- a/gcc/config/i386/dgux.c
+++ b/gcc/config/i386/dgux.c
@@ -120,8 +120,8 @@ output_file_start (file, f_options, f_len, W_options, W_len)
output_file_directive (file, main_input_filename);
fprintf (file, "\t.version\t\"01.01\"\n"); \
- /* Switch to the data section so that the coffsem symbol and the
- gcc2_compiled. symbol aren't in the text section. */
+ /* Switch to the data section so that the coffsem symbol
+ isn't in the text section. */
data_section ();
pos = fprintf (file, "\n// cc1 (%s) arguments:", VERSION_STRING);
diff --git a/gcc/config/i386/djgpp.h b/gcc/config/i386/djgpp.h
index 91940b570ef..e116a8b94f5 100644
--- a/gcc/config/i386/djgpp.h
+++ b/gcc/config/i386/djgpp.h
@@ -112,11 +112,12 @@ Boston, MA 02111-1307, USA. */
(((NAME)[0] >= 'A') && ((NAME)[0] <= 'z') && ((NAME)[1] == ':')))
#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-D__MSDOS__ -Asystem=msdos"
+#define CPP_PREDEFINES "-D__MSDOS__ -D__GO32__ -Asystem=msdos"
/* Include <sys/version.h> so __DJGPP__ and __DJGPP_MINOR__ are defined. */
#undef CPP_SPEC
#define CPP_SPEC "-remap %(cpp_cpu) %{posix:-D_POSIX_SOURCE} \
+ %{!ansi:%{!std=c*:%{!std=i*:-DMSDOS}}} %{!ansi:%{!std=c*:%{!std=i*:-DGO32}}} \
-imacros %s../include/sys/version.h"
/* We need to override link_command_spec in gcc.c so support -Tdjgpp.djl.
@@ -150,6 +151,11 @@ Boston, MA 02111-1307, USA. */
unless user explicitly requests it. */
#undef LOCAL_INCLUDE_DIR
+/* Do not make only .exe if no executable file suffix was specified. */
+/* Let the linker handle that. */
+#undef NO_AUTO_EXE_SUFFIX
+#define NO_AUTO_EXE_SUFFIX
+
#undef EXTRA_SECTIONS
#define EXTRA_SECTIONS in_ctor, in_dtor
@@ -183,7 +189,7 @@ dtor_section () \
#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \
do { \
ctor_section (); \
- fprintf (FILE, "%s\t", ASM_LONG); \
+ fputs (ASM_LONG, FILE); \
assemble_name (FILE, NAME); \
fprintf (FILE, "\n"); \
} while (0)
@@ -200,7 +206,7 @@ dtor_section () \
#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \
do { \
dtor_section (); \
- fprintf (FILE, "%s\t", ASM_LONG); \
+ fputs (ASM_LONG, FILE); \
assemble_name (FILE, NAME); \
fprintf (FILE, "\n"); \
} while (0)
@@ -260,22 +266,27 @@ dtor_section () \
/* Used to be defined in xm-djgpp.h, but moved here for cross-compilers. */
#define LIBSTDCXX "-lstdcxx"
-/* Add command line option -mbnu210 to indicate we can use binutil 2.10's features. */
+/* -mbnu210 is now ignored and obsolete. It was used to enable support for
+ weak symbols, and .gnu.linkonce support. */
#undef MASK_BNU210
#define MASK_BNU210 (0x40000000)
#undef SUBTARGET_SWITCHES
-#define SUBTARGET_SWITCHES \
- { "bnu210", -MASK_BNU210, "Enable weak symbol and enhanced C++ template support. Binutils 2.10 or higher required." }, \
- { "no-bnu210", MASK_BNU210, "Disable weak symbol and enhanced C++ template support." },
-
-/* Weak symbols and .gnu.linkonce are only in Binutils-2.10 and later.
- Default to using Binutils 2.10 features. */
-#undef SUPPORTS_WEAK
-#define SUPPORTS_WEAK ((target_flags & MASK_BNU210) == 0)
-
-#undef SUPPORTS_ONE_ONLY
-#define SUPPORTS_ONE_ONLY ((target_flags & MASK_BNU210) == 0)
+#define SUBTARGET_SWITCHES \
+ { "no-bnu210", -MASK_BNU210, "Ignored (obsolete)." }, \
+ { "bnu210", MASK_BNU210, "Ignored (obsolete)." },
+
+/* Warn that -mbnu210 is now obsolete. */
+#undef SUBTARGET_OVERRIDE_OPTIONS
+#define SUBTARGET_OVERRIDE_OPTIONS \
+do \
+ { \
+ if (target_flags & MASK_BNU210) \
+ { \
+ warning ("-mbnu210 is ignored (option is obsolete)."); \
+ } \
+ } \
+while (0)
/* Support for C++ templates. */
#undef MAKE_DECL_ONE_ONLY
diff --git a/gcc/config/i386/freebsd-aout.h b/gcc/config/i386/freebsd-aout.h
index ef63b1c9b2d..fdd37133fa4 100644
--- a/gcc/config/i386/freebsd-aout.h
+++ b/gcc/config/i386/freebsd-aout.h
@@ -34,6 +34,13 @@ Boston, MA 02111-1307, USA. */
#define TARGET_DEFAULT \
(MASK_80387 | MASK_IEEE_FP | MASK_FLOAT_RETURNS | MASK_NO_FANCY_MATH_387)
+/* The macro defined in i386.h doesn't work with the old gas of
+ FreeBSD 2.x. The definition in sco.h and sol2.h appears to work,
+ but it turns out that, even though the assembler doesn't complain,
+ we get incorrect results. Fortunately, the definition in
+ defaults.h works. */
+#undef ASM_PREFERRED_EH_DATA_FORMAT
+
#undef CPP_PREDEFINES
#define CPP_PREDEFINES "-Dunix -D__FreeBSD__\
-Asystem=unix -Asystem=bsd -Asystem=FreeBSD"
@@ -245,8 +252,3 @@ do { \
/* Define this so we can compile MS code for use with WINE. */
#define HANDLE_PRAGMA_PACK_PUSH_POP
-
-/* This is the pseudo-op used to generate a 32-bit word of data with a
- specific value in some section. */
-
-#define INT_ASM_OP "\t.long\t"
diff --git a/gcc/config/i386/freebsd.h b/gcc/config/i386/freebsd.h
index ebd337a5911..68af02bf28d 100644
--- a/gcc/config/i386/freebsd.h
+++ b/gcc/config/i386/freebsd.h
@@ -77,10 +77,6 @@ Boston, MA 02111-1307, USA. */
#undef WCHAR_TYPE_SIZE
#define WCHAR_TYPE_SIZE BITS_PER_WORD
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-Dunix -D__ELF__ -D__FreeBSD__\
- -Asystem=unix -Asystem=bsd -Asystem=FreeBSD"
-
/* Provide a STARTFILE_SPEC appropriate for FreeBSD. Here we add
the magical crtbegin.o file (see crtstuff.c) which provides part
of the support for getting C++ file-scope static object constructed
diff --git a/gcc/config/i386/gas.h b/gcc/config/i386/gas.h
index cef43857b07..6c28bf9a0ee 100644
--- a/gcc/config/i386/gas.h
+++ b/gcc/config/i386/gas.h
@@ -169,5 +169,4 @@ Boston, MA 02111-1307, USA. */
if (target_flags & MASK_INTEL_SYNTAX) \
fputs ("\t.intel_syntax\n", FILE); \
output_file_directive (FILE, main_input_filename); \
- fputs ("\t.version\t\"01.01\"\n", FILE); \
} while (0)
diff --git a/gcc/config/i386/gnu.h b/gcc/config/i386/gnu.h
index 1c776096484..205d5767991 100644
--- a/gcc/config/i386/gnu.h
+++ b/gcc/config/i386/gnu.h
@@ -30,3 +30,6 @@
%{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} %{!p:crt1.o%s}}} \
%{static:crt0.o%s}} \
crti.o%s %{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}"
+
+/* FIXME: Is a Hurd-specific fallback mechanism necessary? */
+#undef MD_FALLBACK_FRAME_STATE_FOR
diff --git a/gcc/config/i386/i386-aout.h b/gcc/config/i386/i386-aout.h
index 68393c77ac9..7385bec6d7c 100644
--- a/gcc/config/i386/i386-aout.h
+++ b/gcc/config/i386/i386-aout.h
@@ -31,6 +31,4 @@ Boston, MA 02111-1307, USA. */
#undef CPP_PREDEFINES
#define CPP_PREDEFINES ""
-#define INT_ASM_OP "\t.long\t"
-
/* end of i386-aout.h */
diff --git a/gcc/config/i386/i386-coff.h b/gcc/config/i386/i386-coff.h
index e2e5ed700ef..69839e17276 100644
--- a/gcc/config/i386/i386-coff.h
+++ b/gcc/config/i386/i386-coff.h
@@ -77,8 +77,6 @@ dtors_section () \
} \
}
-#define INT_ASM_OP "\t.long\t"
-
/* A C statement (sans semicolon) to output an element in the table of
global constructors. */
#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \
diff --git a/gcc/config/i386/i386-interix.h b/gcc/config/i386/i386-interix.h
index f5e9ea58ec2..d2debcbef5d 100644
--- a/gcc/config/i386/i386-interix.h
+++ b/gcc/config/i386/i386-interix.h
@@ -361,8 +361,6 @@ dtors_section () \
(DECL) && TREE_READONLY (DECL) ? "a" : "aw")
#endif
-#define INT_ASM_OP "\t.long\t"
-
/* The MS compilers take alignment as a number of bytes, so we do as well */
#undef ASM_OUTPUT_ALIGN
#define ASM_OUTPUT_ALIGN(FILE,LOG) \
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index 03fa84f3795..fbf8ca2832f 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler for IA-32.
- Copyright (C) 1988, 1992, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000
- Free Software Foundation, Inc.
+ Copyright (C) 1988, 1992, 1994, 1995, 1996, 1996, 1997, 1998, 1999,
+ 2000, 2001 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -140,6 +140,8 @@ extern void function_arg_advance PARAMS ((CUMULATIVE_ARGS *, enum machine_mode,
extern void ix86_init_builtins PARAMS ((void));
extern rtx ix86_expand_builtin PARAMS ((tree, rtx, rtx, enum machine_mode, int));
#endif
+extern void ix86_set_move_mem_attrs PARAMS ((rtx, rtx, rtx, rtx, rtx));
+
#endif
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 2737b6bccd4..ca24e2f4733 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -30,7 +30,6 @@ Boston, MA 02111-1307, USA. */
#include "real.h"
#include "insn-config.h"
#include "conditions.h"
-#include "insn-flags.h"
#include "output.h"
#include "insn-attr.h"
#include "flags.h"
@@ -196,7 +195,8 @@ const int x86_cmove = m_PPRO | m_ATHLON;
const int x86_deep_branch = m_PPRO | m_K6 | m_ATHLON;
const int x86_use_sahf = m_PPRO | m_K6;
const int x86_partial_reg_stall = m_PPRO;
-const int x86_use_loop = m_K6;
+const int x86_use_loop = 0; /* Should be set to K6 and i386, but is broken
+ and temporarily disabled for 3.0.x. */
const int x86_use_fiop = ~(m_PPRO | m_ATHLON | m_PENT);
const int x86_use_mov0 = m_K6;
const int x86_use_cltd = ~(m_PENT | m_K6);
@@ -336,6 +336,40 @@ struct machine_function
#define ix86_stack_locals (cfun->machine->stack_locals)
+/* Structure describing stack frame layout.
+ Stack grows downward:
+
+ [arguments]
+ <- ARG_POINTER
+ saved pc
+
+ saved frame pointer if frame_pointer_needed
+ <- HARD_FRAME_POINTER
+ [saved regs]
+
+ [padding1] \
+ )
+ [va_arg registers] (
+ > to_allocate <- FRAME_POINTER
+ [frame] (
+ )
+ [padding2] /
+ */
+struct ix86_frame
+{
+ int nregs;
+ int padding1;
+ HOST_WIDE_INT frame;
+ int padding2;
+ int outgoing_arguments_size;
+
+ HOST_WIDE_INT to_allocate;
+ /* The offsets relative to ARG_POINTER. */
+ HOST_WIDE_INT frame_pointer_offset;
+ HOST_WIDE_INT hard_frame_pointer_offset;
+ HOST_WIDE_INT stack_pointer_offset;
+};
+
/* which cpu are we scheduling for */
enum processor_type ix86_cpu;
@@ -407,12 +441,11 @@ static void ix86_mark_machine_status PARAMS ((struct function *));
static void ix86_free_machine_status PARAMS ((struct function *));
static int ix86_split_to_parts PARAMS ((rtx, rtx *, enum machine_mode));
static int ix86_safe_length_prefix PARAMS ((rtx));
-static HOST_WIDE_INT ix86_compute_frame_size PARAMS((HOST_WIDE_INT,
- int *, int *, int *));
static int ix86_nsaved_regs PARAMS((void));
static void ix86_emit_save_regs PARAMS((void));
-static void ix86_emit_restore_regs_using_mov PARAMS ((rtx, int));
+static void ix86_emit_restore_regs_using_mov PARAMS ((rtx, int, int));
static void ix86_emit_epilogue_esp_adjustment PARAMS((int));
+static void ix86_set_move_mem_attrs_1 PARAMS ((rtx, rtx, rtx, rtx, rtx));
static void ix86_sched_reorder_pentium PARAMS((rtx *, rtx *));
static void ix86_sched_reorder_ppro PARAMS((rtx *, rtx *));
static HOST_WIDE_INT ix86_GOT_alias_set PARAMS ((void));
@@ -446,6 +479,8 @@ static int ix86_fp_comparison_arithmetics_cost PARAMS ((enum rtx_code code));
static int ix86_fp_comparison_fcomi_cost PARAMS ((enum rtx_code code));
static int ix86_fp_comparison_sahf_cost PARAMS ((enum rtx_code code));
static int ix86_fp_comparison_cost PARAMS ((enum rtx_code code));
+static int ix86_save_reg PARAMS ((int, int));
+static void ix86_compute_frame_layout PARAMS ((struct ix86_frame *));
/* Sometimes certain combinations of command options do not make
sense on a particular target machine. You can define a macro
@@ -1234,6 +1269,10 @@ general_no_elim_operand (op, mode)
|| t == virtual_incoming_args_rtx || t == virtual_stack_vars_rtx
|| t == virtual_stack_dynamic_rtx)
return 0;
+ if (REG_P (t)
+ && REGNO (t) >= FIRST_VIRTUAL_REGISTER
+ && REGNO (t) <= LAST_VIRTUAL_REGISTER)
+ return 0;
return general_operand (op, mode);
}
@@ -1677,8 +1716,7 @@ symbolic_reference_mentioned_p (op)
int
ix86_can_use_return_insn_p ()
{
- HOST_WIDE_INT tsize;
- int nregs;
+ struct ix86_frame frame;
#ifdef NON_SAVING_SETJMP
if (NON_SAVING_SETJMP && current_function_calls_setjmp)
@@ -1698,8 +1736,8 @@ ix86_can_use_return_insn_p ()
&& current_function_args_size >= 32768)
return 0;
- tsize = ix86_compute_frame_size (get_frame_size (), &nregs, NULL, NULL);
- return tsize == 0 && nregs == 0;
+ ix86_compute_frame_layout (&frame);
+ return frame.to_allocate == 0 && frame.nregs == 0;
}
/* Value should be nonzero if functions must have frame pointers.
@@ -1827,24 +1865,49 @@ gen_push (arg)
arg);
}
+/* Return 1 if we need to save REGNO. */
+static int
+ix86_save_reg (regno, maybe_eh_return)
+ int regno;
+ int maybe_eh_return;
+{
+ if (flag_pic
+ && regno == PIC_OFFSET_TABLE_REGNUM
+ && (current_function_uses_pic_offset_table
+ || current_function_uses_const_pool
+ || current_function_calls_eh_return))
+ return 1;
+
+ if (current_function_calls_eh_return && maybe_eh_return)
+ {
+ unsigned i;
+ for (i = 0; ; i++)
+ {
+ unsigned test = EH_RETURN_DATA_REGNO(i);
+ if (test == INVALID_REGNUM)
+ break;
+ if (test == (unsigned) regno)
+ return 1;
+ }
+ }
+
+ return (regs_ever_live[regno]
+ && !call_used_regs[regno]
+ && !fixed_regs[regno]
+ && (regno != HARD_FRAME_POINTER_REGNUM || !frame_pointer_needed));
+}
+
/* Return number of registers to be saved on the stack. */
static int
ix86_nsaved_regs ()
{
int nregs = 0;
- int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table
- || current_function_uses_const_pool);
- int limit = (frame_pointer_needed
- ? HARD_FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM);
int regno;
- for (regno = limit - 1; regno >= 0; regno--)
- if ((regs_ever_live[regno] && ! call_used_regs[regno])
- || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used))
- {
- nregs ++;
- }
+ for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--)
+ if (ix86_save_reg (regno, true))
+ nregs++;
return nregs;
}
@@ -1856,82 +1919,46 @@ ix86_initial_elimination_offset (from, to)
int from;
int to;
{
- int padding1;
- int nregs;
-
- /* Stack grows downward:
-
- [arguments]
- <- ARG_POINTER
- saved pc
-
- saved frame pointer if frame_pointer_needed
- <- HARD_FRAME_POINTER
- [saved regs]
-
- [padding1] \
- | <- FRAME_POINTER
- [frame] > tsize
- |
- [padding2] /
- */
+ struct ix86_frame frame;
+ ix86_compute_frame_layout (&frame);
if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
- /* Skip saved PC and previous frame pointer.
- Executed only when frame_pointer_needed. */
- return 8;
+ return frame.hard_frame_pointer_offset;
else if (from == FRAME_POINTER_REGNUM
&& to == HARD_FRAME_POINTER_REGNUM)
- {
- ix86_compute_frame_size (get_frame_size (), &nregs, &padding1, (int *) 0);
- padding1 += nregs * UNITS_PER_WORD;
- return -padding1;
- }
+ return frame.hard_frame_pointer_offset - frame.frame_pointer_offset;
else
{
- /* ARG_POINTER or FRAME_POINTER to STACK_POINTER elimination. */
- int frame_size = frame_pointer_needed ? 8 : 4;
- HOST_WIDE_INT tsize = ix86_compute_frame_size (get_frame_size (),
- &nregs, &padding1, (int *) 0);
-
if (to != STACK_POINTER_REGNUM)
abort ();
else if (from == ARG_POINTER_REGNUM)
- return tsize + nregs * UNITS_PER_WORD + frame_size;
+ return frame.stack_pointer_offset;
else if (from != FRAME_POINTER_REGNUM)
abort ();
else
- return tsize - padding1;
+ return frame.stack_pointer_offset - frame.frame_pointer_offset;
}
}
-/* Compute the size of local storage taking into consideration the
- desired stack alignment which is to be maintained. Also determine
- the number of registers saved below the local storage.
+/* Fill structure ix86_frame about frame of currently computed function. */
- PADDING1 returns padding before stack frame and PADDING2 returns
- padding after stack frame;
- */
-
-static HOST_WIDE_INT
-ix86_compute_frame_size (size, nregs_on_stack, rpadding1, rpadding2)
- HOST_WIDE_INT size;
- int *nregs_on_stack;
- int *rpadding1;
- int *rpadding2;
+static void
+ix86_compute_frame_layout (frame)
+ struct ix86_frame *frame;
{
- int nregs;
- int padding1 = 0;
- int padding2 = 0;
HOST_WIDE_INT total_size;
int stack_alignment_needed = cfun->stack_alignment_needed / BITS_PER_UNIT;
int offset;
int preferred_alignment = cfun->preferred_stack_boundary / BITS_PER_UNIT;
+ HOST_WIDE_INT size = get_frame_size ();
- nregs = ix86_nsaved_regs ();
+ frame->nregs = ix86_nsaved_regs ();
total_size = size;
- offset = frame_pointer_needed ? 8 : 4;
+ /* Skip return value and save base pointer. */
+ offset = frame_pointer_needed ? UNITS_PER_WORD * 2 : UNITS_PER_WORD;
+
+ frame->hard_frame_pointer_offset = offset;
/* Do some sanity checking of stack_alignment_needed and
preferred_alignment, since i386 port is the only using those features
@@ -1946,36 +1973,58 @@ ix86_compute_frame_size (size, nregs_on_stack, rpadding1, rpadding2)
if (stack_alignment_needed > PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT)
abort ();
- if (stack_alignment_needed < 4)
- stack_alignment_needed = 4;
+ if (stack_alignment_needed < STACK_BOUNDARY / BITS_PER_UNIT)
+ stack_alignment_needed = STACK_BOUNDARY / BITS_PER_UNIT;
- offset += nregs * UNITS_PER_WORD;
+ /* Register save area */
+ offset += frame->nregs * UNITS_PER_WORD;
- if (ACCUMULATE_OUTGOING_ARGS)
- total_size += current_function_outgoing_args_size;
+ /* Align start of frame for local function. */
+ frame->padding1 = ((offset + stack_alignment_needed - 1)
+ & -stack_alignment_needed) - offset;
- total_size += offset;
+ offset += frame->padding1;
- /* Align start of frame for local function. */
- padding1 = ((offset + stack_alignment_needed - 1)
- & -stack_alignment_needed) - offset;
- total_size += padding1;
+ /* Frame pointer points here. */
+ frame->frame_pointer_offset = offset;
- /* Align stack boundary. */
- padding2 = ((total_size + preferred_alignment - 1)
- & -preferred_alignment) - total_size;
+ offset += size;
+ /* Add outgoing arguments area. */
if (ACCUMULATE_OUTGOING_ARGS)
- padding2 += current_function_outgoing_args_size;
-
- if (nregs_on_stack)
- *nregs_on_stack = nregs;
- if (rpadding1)
- *rpadding1 = padding1;
- if (rpadding2)
- *rpadding2 = padding2;
+ {
+ offset += current_function_outgoing_args_size;
+ frame->outgoing_arguments_size = current_function_outgoing_args_size;
+ }
+ else
+ frame->outgoing_arguments_size = 0;
- return size + padding1 + padding2;
+ /* Align stack boundary. */
+ frame->padding2 = ((offset + preferred_alignment - 1)
+ & -preferred_alignment) - offset;
+
+ offset += frame->padding2;
+
+ /* We've reached end of stack frame. */
+ frame->stack_pointer_offset = offset;
+
+ /* Size prologue needs to allocate. */
+ frame->to_allocate =
+ (size + frame->padding1 + frame->padding2
+ + frame->outgoing_arguments_size);
+
+#if 0
+ fprintf (stderr, "nregs: %i\n", frame->nregs);
+ fprintf (stderr, "size: %i\n", size);
+ fprintf (stderr, "alignment1: %i\n", stack_alignment_needed);
+ fprintf (stderr, "padding1: %i\n", frame->padding1);
+ fprintf (stderr, "padding2: %i\n", frame->padding2);
+ fprintf (stderr, "to_allocate: %i\n", frame->to_allocate);
+ fprintf (stderr, "frame_pointer_offset: %i\n", frame->frame_pointer_offset);
+ fprintf (stderr, "hard_frame_pointer_offset: %i\n",
+ frame->hard_frame_pointer_offset);
+ fprintf (stderr, "stack_pointer_offset: %i\n", frame->stack_pointer_offset);
+#endif
}
/* Emit code to save registers in the prologue. */
@@ -1984,16 +2033,10 @@ static void
ix86_emit_save_regs ()
{
register int regno;
- int limit;
rtx insn;
- int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table
- || current_function_uses_const_pool);
- limit = (frame_pointer_needed
- ? HARD_FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM);
- for (regno = limit - 1; regno >= 0; regno--)
- if ((regs_ever_live[regno] && !call_used_regs[regno])
- || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used))
+ for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--)
+ if (ix86_save_reg (regno, true))
{
insn = emit_insn (gen_push (gen_rtx_REG (SImode, regno)));
RTX_FRAME_RELATED_P (insn) = 1;
@@ -2005,11 +2048,12 @@ ix86_emit_save_regs ()
void
ix86_expand_prologue ()
{
- HOST_WIDE_INT tsize = ix86_compute_frame_size (get_frame_size (), (int *) 0,
- (int *) 0, (int *) 0);
rtx insn;
int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table
|| current_function_uses_const_pool);
+ struct ix86_frame frame;
+
+ ix86_compute_frame_layout (&frame);
/* Note: AT&T enter does NOT have reversed args. Enter is probably
slower on all targets. Also sdb doesn't like it. */
@@ -2025,17 +2069,13 @@ ix86_expand_prologue ()
ix86_emit_save_regs ();
- if (tsize == 0)
+ if (frame.to_allocate == 0)
;
- else if (! TARGET_STACK_PROBE || tsize < CHECK_STACK_LIMIT)
+ else if (! TARGET_STACK_PROBE || frame.to_allocate < CHECK_STACK_LIMIT)
{
- if (frame_pointer_needed)
- insn = emit_insn (gen_pro_epilogue_adjust_stack
- (stack_pointer_rtx, stack_pointer_rtx,
- GEN_INT (-tsize), hard_frame_pointer_rtx));
- else
- insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
- GEN_INT (-tsize)));
+ insn = emit_insn (gen_pro_epilogue_adjust_stack
+ (stack_pointer_rtx, stack_pointer_rtx,
+ GEN_INT (-frame.to_allocate)));
RTX_FRAME_RELATED_P (insn) = 1;
}
else
@@ -2045,7 +2085,7 @@ ix86_expand_prologue ()
rtx arg0, sym;
arg0 = gen_rtx_REG (SImode, 0);
- emit_move_insn (arg0, GEN_INT (tsize));
+ emit_move_insn (arg0, GEN_INT (frame.to_allocate));
sym = gen_rtx_MEM (FUNCTION_MODE,
gen_rtx_SYMBOL_REF (Pmode, "_alloca"));
@@ -2077,34 +2117,23 @@ static void
ix86_emit_epilogue_esp_adjustment (tsize)
int tsize;
{
- /* If a frame pointer is present, we must be sure to tie the sp
- to the fp so that we don't mis-schedule. */
- if (frame_pointer_needed)
- emit_insn (gen_pro_epilogue_adjust_stack (stack_pointer_rtx,
- stack_pointer_rtx,
- GEN_INT (tsize),
- hard_frame_pointer_rtx));
- else
- emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
- GEN_INT (tsize)));
+ emit_insn (gen_pro_epilogue_adjust_stack (stack_pointer_rtx,
+ stack_pointer_rtx,
+ GEN_INT (tsize)));
}
/* Emit code to restore saved registers using MOV insns. First register
is restored from POINTER + OFFSET. */
static void
-ix86_emit_restore_regs_using_mov (pointer, offset)
- rtx pointer;
- int offset;
+ix86_emit_restore_regs_using_mov (pointer, offset, maybe_eh_return)
+ rtx pointer;
+ int offset;
+ int maybe_eh_return;
{
int regno;
- int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table
- || current_function_uses_const_pool);
- int limit = (frame_pointer_needed
- ? HARD_FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM);
- for (regno = 0; regno < limit; regno++)
- if ((regs_ever_live[regno] && !call_used_regs[regno])
- || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used))
+ for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+ if (ix86_save_reg (regno, maybe_eh_return))
{
emit_move_insn (gen_rtx_REG (SImode, regno),
adj_offsettable_operand (gen_rtx_MEM (SImode,
@@ -2117,21 +2146,24 @@ ix86_emit_restore_regs_using_mov (pointer, offset)
/* Restore function stack, frame, and registers. */
void
-ix86_expand_epilogue (emit_return)
- int emit_return;
+ix86_expand_epilogue (style)
+ int style;
{
- int nregs;
int regno;
-
- int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table
- || current_function_uses_const_pool);
int sp_valid = !frame_pointer_needed || current_function_sp_is_unchanging;
+ struct ix86_frame frame;
HOST_WIDE_INT offset;
- HOST_WIDE_INT tsize = ix86_compute_frame_size (get_frame_size (), &nregs,
- (int *) 0, (int *) 0);
- /* Calculate start of saved registers relative to ebp. */
- offset = -nregs * UNITS_PER_WORD;
+ ix86_compute_frame_layout (&frame);
+
+ /* Calculate start of saved registers relative to ebp. Special care
+ must be taken for the normal return case of a function using
+ eh_return: the eax and edx registers are marked as saved, but not
+ restored along this path. */
+ offset = frame.nregs;
+ if (current_function_calls_eh_return && style != 2)
+ offset -= 2;
+ offset *= -UNITS_PER_WORD;
#ifdef FUNCTION_BLOCK_PROFILER_EXIT
if (profile_block_flag == 2)
@@ -2150,10 +2182,11 @@ ix86_expand_epilogue (emit_return)
are no registers to restore. We also use this code when TARGET_USE_LEAVE
and there is exactly one register to pop. This heruistic may need some
tuning in future. */
- if ((!sp_valid && nregs <= 1)
- || (frame_pointer_needed && !nregs && tsize)
+ if ((!sp_valid && frame.nregs <= 1)
+ || (frame_pointer_needed && !frame.nregs && frame.to_allocate)
|| (frame_pointer_needed && TARGET_USE_LEAVE && !optimize_size
- && nregs == 1))
+ && frame.nregs == 1)
+ || style == 2)
{
/* Restore registers. We can use ebp or esp to address the memory
locations. If both are available, default to ebp, since offsets
@@ -2161,13 +2194,41 @@ ix86_expand_epilogue (emit_return)
end of block of saved registers, where we may simplify addressing
mode. */
- if (!frame_pointer_needed || (sp_valid && !tsize))
- ix86_emit_restore_regs_using_mov (stack_pointer_rtx, tsize);
+ if (!frame_pointer_needed || (sp_valid && !frame.to_allocate))
+ ix86_emit_restore_regs_using_mov (stack_pointer_rtx,
+ frame.to_allocate, style == 2);
else
- ix86_emit_restore_regs_using_mov (hard_frame_pointer_rtx, offset);
+ ix86_emit_restore_regs_using_mov (hard_frame_pointer_rtx,
+ offset, style == 2);
+
+ /* eh_return epilogues need %ecx added to the stack pointer. */
+ if (style == 2)
+ {
+ rtx tmp, sa = EH_RETURN_STACKADJ_RTX;
+
+ if (frame_pointer_needed)
+ {
+ tmp = gen_rtx_PLUS (Pmode, hard_frame_pointer_rtx, sa);
+ tmp = plus_constant (tmp, UNITS_PER_WORD);
+ emit_insn (gen_rtx_SET (VOIDmode, sa, tmp));
+
+ tmp = gen_rtx_MEM (Pmode, hard_frame_pointer_rtx);
+ emit_move_insn (hard_frame_pointer_rtx, tmp);
- if (!frame_pointer_needed)
- ix86_emit_epilogue_esp_adjustment (tsize + nregs * UNITS_PER_WORD);
+ emit_insn (gen_pro_epilogue_adjust_stack
+ (stack_pointer_rtx, sa, const0_rtx));
+ }
+ else
+ {
+ tmp = gen_rtx_PLUS (Pmode, stack_pointer_rtx, sa);
+ tmp = plus_constant (tmp, (frame.to_allocate
+ + frame.nregs * UNITS_PER_WORD));
+ emit_insn (gen_rtx_SET (VOIDmode, stack_pointer_rtx, tmp));
+ }
+ }
+ else if (!frame_pointer_needed)
+ ix86_emit_epilogue_esp_adjustment (frame.to_allocate
+ + frame.nregs * UNITS_PER_WORD);
/* If not an i386, mov & pop is faster than "leave". */
else if (TARGET_USE_LEAVE || optimize_size)
emit_insn (gen_leave ());
@@ -2175,8 +2236,7 @@ ix86_expand_epilogue (emit_return)
{
emit_insn (gen_pro_epilogue_adjust_stack (stack_pointer_rtx,
hard_frame_pointer_rtx,
- const0_rtx,
- hard_frame_pointer_rtx));
+ const0_rtx));
emit_insn (gen_popsi1 (hard_frame_pointer_rtx));
}
}
@@ -2190,20 +2250,20 @@ ix86_expand_epilogue (emit_return)
abort ();
emit_insn (gen_pro_epilogue_adjust_stack (stack_pointer_rtx,
hard_frame_pointer_rtx,
- GEN_INT (offset),
- hard_frame_pointer_rtx));
+ GEN_INT (offset)));
}
- else if (tsize)
- ix86_emit_epilogue_esp_adjustment (tsize);
+ else if (frame.to_allocate)
+ ix86_emit_epilogue_esp_adjustment (frame.to_allocate);
- for (regno = 0; regno < STACK_POINTER_REGNUM; regno++)
- if ((regs_ever_live[regno] && !call_used_regs[regno])
- || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used))
+ for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+ if (ix86_save_reg (regno, false))
emit_insn (gen_popsi1 (gen_rtx_REG (SImode, regno)));
+ if (frame_pointer_needed)
+ emit_insn (gen_popsi1 (hard_frame_pointer_rtx));
}
/* Sibcall epilogues don't want a return instruction. */
- if (! emit_return)
+ if (style == 0)
return;
if (current_function_pops_args && current_function_args_size)
@@ -5478,9 +5538,12 @@ ix86_expand_setcc (code, dest)
emit subreg setcc, zero extend.
2 -- destination is in QImode:
emit setcc only.
- */
- type = 0;
+ We don't use mode 0 early in compilation because it confuses CSE.
+ There are peepholes to turn mode 1 into mode 0 if things work out
+ nicely after reload. */
+
+ type = cse_not_expected ? 0 : 1;
if (GET_MODE (dest) == QImode)
type = 2;
@@ -5628,7 +5691,7 @@ ix86_expand_int_movcc (operands)
* Size 5 - 8.
*/
if (ct)
- emit_insn (gen_addsi3 (out, out, GEN_INT (ct)));
+ emit_insn (gen_addsi3 (tmp, tmp, GEN_INT (ct)));
}
else if (cf == -1)
{
@@ -5639,7 +5702,7 @@ ix86_expand_int_movcc (operands)
*
* Size 8.
*/
- emit_insn (gen_iorsi3 (out, out, GEN_INT (ct)));
+ emit_insn (gen_iorsi3 (tmp, tmp, GEN_INT (ct)));
}
else if (diff == -1 && ct)
{
@@ -5653,7 +5716,7 @@ ix86_expand_int_movcc (operands)
*/
emit_insn (gen_one_cmplsi2 (tmp, tmp));
if (cf)
- emit_insn (gen_addsi3 (out, out, GEN_INT (cf)));
+ emit_insn (gen_addsi3 (tmp, tmp, GEN_INT (cf)));
}
else
{
@@ -5665,9 +5728,9 @@ ix86_expand_int_movcc (operands)
*
* Size 8 - 11.
*/
- emit_insn (gen_andsi3 (out, out, GEN_INT (cf - ct)));
+ emit_insn (gen_andsi3 (tmp, tmp, GEN_INT (cf - ct)));
if (ct)
- emit_insn (gen_addsi3 (out, out, GEN_INT (ct)));
+ emit_insn (gen_addsi3 (tmp, tmp, GEN_INT (ct)));
}
if (tmp != out)
@@ -5895,6 +5958,9 @@ ix86_expand_int_movcc (operands)
emit_move_insn (tmp, operands[2]);
operands[2] = tmp;
}
+ if (! register_operand (operands[2], VOIDmode)
+ && ! register_operand (operands[3], VOIDmode))
+ operands[2] = force_reg (GET_MODE (operands[0]), operands[2]);
emit_insn (compare_seq);
emit_insn (gen_rtx_SET (VOIDmode, operands[0],
@@ -7327,6 +7393,52 @@ ix86_variable_issue (dump, sched_verbose, insn, can_issue_more)
}
}
+/* Walk through INSNS and look for MEM references whose address is DSTREG or
+ SRCREG and set the memory attribute to those of DSTREF and SRCREF, as
+ appropriate. */
+
+void
+ix86_set_move_mem_attrs (insns, dstref, srcref, dstreg, srcreg)
+ rtx insns;
+ rtx dstref, srcref, dstreg, srcreg;
+{
+ rtx insn;
+
+ for (insn = insns; insn != 0 ; insn = NEXT_INSN (insn))
+ if (INSN_P (insn))
+ ix86_set_move_mem_attrs_1 (PATTERN (insn), dstref, srcref,
+ dstreg, srcreg);
+}
+
+/* Subroutine of above to actually do the updating by recursively walking
+ the rtx. */
+
+static void
+ix86_set_move_mem_attrs_1 (x, dstref, srcref, dstreg, srcreg)
+ rtx x;
+ rtx dstref, srcref, dstreg, srcreg;
+{
+ enum rtx_code code = GET_CODE (x);
+ const char *format_ptr = GET_RTX_FORMAT (code);
+ int i, j;
+
+ if (code == MEM && XEXP (x, 0) == dstreg)
+ MEM_COPY_ATTRIBUTES (x, dstref);
+ else if (code == MEM && XEXP (x, 0) == srcreg)
+ MEM_COPY_ATTRIBUTES (x, srcref);
+
+ for (i = 0; i < GET_RTX_LENGTH (code); i++, format_ptr++)
+ {
+ if (*format_ptr == 'e')
+ ix86_set_move_mem_attrs_1 (XEXP (x, i), dstref, srcref,
+ dstreg, srcreg);
+ else if (*format_ptr == 'E')
+ for (j = XVECLEN (x, i) - 1; j >= 0; j--)
+ ix86_set_move_mem_attrs_1 (XVECEXP (x, i, j), dstref, srcref,
+ dstreg, srcreg);
+ }
+}
+
/* Compute the alignment given to a constant that is being placed in memory.
EXP is the constant and ALIGN is the alignment that the object would
ordinarily have.
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 48008724198..7471560fd09 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -294,13 +294,6 @@ extern const int x86_partial_reg_dependency, x86_memory_mismatch_stall;
N_("Use push instructions to save outgoing arguments") }, \
{ "no-accumulate-outgoing-args",-MASK_ACCUMULATE_OUTGOING_ARGS, \
N_("Do not use push instructions to save outgoing arguments") }, \
- { "mmx", MASK_MMX, N_("Support MMX builtins") }, \
- { "no-mmx", -MASK_MMX, \
- N_("Do not support MMX builtins") }, \
- { "sse", MASK_SSE, \
- N_("Support MMX and SSE builtins") }, \
- { "no-sse", -MASK_SSE, \
- N_("Do not support MMX and SSE builtins") }, \
{ "128bit-long-double", MASK_128BIT_LONG_DOUBLE, \
N_("sizeof(long double) is 16.") }, \
{ "96bit-long-double", -MASK_128BIT_LONG_DOUBLE, \
@@ -381,10 +374,14 @@ extern int ix86_arch;
#ifndef CC1_CPU_SPEC
#define CC1_CPU_SPEC "\
%{!mcpu*: \
-%{m386:-mcpu=i386} \
-%{m486:-mcpu=i486} \
-%{mpentium:-mcpu=pentium} \
-%{mpentiumpro:-mcpu=pentiumpro}}"
+%{m386:-mcpu=i386 \
+%n`-m386' is deprecated. Use `-march=i386' or `-mcpu=i386' instead.\n} \
+%{m486:-mcpu=i486 \
+%n`-m486' is deprecated. Use `-march=i486' or `-mcpu=i486' instead.\n} \
+%{mpentium:-mcpu=pentium \
+%n`-mpentium' is deprecated. Use `-march=pentium' or `-mcpu=pentium' instead.\n} \
+%{mpentiumpro:-mcpu=pentiumpro \
+%n`-mpentiumpro' is deprecated. Use `-march=pentiumpro' or `-mcpu=pentiumpro' instead.\n}}"
#endif
#ifndef CPP_CPU_DEFAULT_SPEC
@@ -514,6 +511,13 @@ extern int ix86_arch;
aligned; the compiler cannot rely on having this alignment. */
#define PREFERRED_STACK_BOUNDARY ix86_preferred_stack_boundary
+/* As of July 2001, many runtimes to not align the stack properly when
+ entering main. This causes expand_main_function to forcably align
+ the stack, which results in aligned frames for functions called from
+ main, though it does nothing for the alignment of main itself. */
+#define FORCE_PREFERRED_STACK_BOUNDARY_IN_MAIN \
+ (ix86_preferred_stack_boundary > STACK_BOUNDARY)
+
/* Allocation boundary for the code of a function. */
#define FUNCTION_BOUNDARY \
(1 << ((ix86_align_funcs >= 0 ? ix86_align_funcs : -ix86_align_funcs) + 3))
@@ -899,11 +903,11 @@ extern int ix86_arch;
should always be returned in memory. You should instead use
`DEFAULT_PCC_STRUCT_RETURN' to indicate this. */
-#define RETURN_IN_MEMORY(TYPE) \
- ((TYPE_MODE (TYPE) == BLKmode) \
- || (VECTOR_MODE_P (TYPE_MODE (TYPE)) && int_size_in_bytes (TYPE) == 8) \
- || (int_size_in_bytes (TYPE) > 12 && TYPE_MODE (TYPE) != TImode \
- && ! VECTOR_MODE_P (TYPE_MODE (TYPE))))
+#define RETURN_IN_MEMORY(TYPE) \
+ ((TYPE_MODE (TYPE) == BLKmode) \
+ || (VECTOR_MODE_P (TYPE_MODE (TYPE)) && int_size_in_bytes (TYPE) == 8)\
+ || (int_size_in_bytes (TYPE) > 12 && TYPE_MODE (TYPE) != TImode \
+ && TYPE_MODE (TYPE) != TFmode && ! VECTOR_MODE_P (TYPE_MODE (TYPE))))
/* Define the classes of registers for register constraints in the
@@ -2633,6 +2637,22 @@ extern int const svr4_dbx_register_map[FIRST_PSEUDO_REGISTER];
/* Before the prologue, the top of the frame is at 4(%esp). */
#define INCOMING_FRAME_SP_OFFSET 4
+/* Describe how we implement __builtin_eh_return. */
+#define EH_RETURN_DATA_REGNO(N) ((N) < 2 ? (N) : INVALID_REGNUM)
+#define EH_RETURN_STACKADJ_RTX gen_rtx_REG (Pmode, 2)
+
+/* Select a format to encode pointers in exception handling data. CODE
+ is 0 for data, 1 for code labels, 2 for function pointers. GLOBAL is
+ true if the symbol may be affected by dynamic relocations.
+
+ ??? All x86 object file formats are capable of representing this.
+ After all, the relocation needed is the same as for the call insn.
+ Whether or not a particular assembler allows us to enter such, I
+ guess we'll have to see. */
+#define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL) \
+ (flag_pic ? (GLOBAL ? DW_EH_PE_indirect : 0) | DW_EH_PE_pcrel \
+ : DW_EH_PE_absptr)
+
/* This is how to output the definition of a user-level label named NAME,
such as the label on a static function or variable NAME. */
@@ -2644,7 +2664,7 @@ extern int const svr4_dbx_register_map[FIRST_PSEUDO_REGISTER];
#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
do { long l[2]; \
REAL_VALUE_TO_TARGET_DOUBLE (VALUE, l); \
- fprintf (FILE, "%s\t0x%lx,0x%lx\n", ASM_LONG, l[0], l[1]); \
+ fprintf (FILE, "%s0x%lx,0x%lx\n", ASM_LONG, l[0], l[1]); \
} while (0)
/* This is how to output a `long double' extended real constant. */
@@ -2654,9 +2674,9 @@ do { long l[2]; \
do { long l[4]; \
REAL_VALUE_TO_TARGET_LONG_DOUBLE (VALUE, l); \
if (TARGET_128BIT_LONG_DOUBLE) \
- fprintf (FILE, "%s\t0x%lx,0x%lx,0x%lx,0x0\n", ASM_LONG, l[0], l[1], l[2]); \
+ fprintf (FILE, "%s0x%lx,0x%lx,0x%lx,0x0\n", ASM_LONG, l[0], l[1], l[2]); \
else \
- fprintf (FILE, "%s\t0x%lx,0x%lx,0x%lx\n", ASM_LONG, l[0], l[1], l[2]); \
+ fprintf (FILE, "%s0x%lx,0x%lx,0x%lx\n", ASM_LONG, l[0], l[1], l[2]); \
} while (0)
/* This is how to output an assembler line defining a `float' constant. */
@@ -2664,7 +2684,7 @@ do { long l[4]; \
#define ASM_OUTPUT_FLOAT(FILE,VALUE) \
do { long l; \
REAL_VALUE_TO_TARGET_SINGLE (VALUE, l); \
- fprintf ((FILE), "%s\t0x%lx\n", ASM_LONG, l); \
+ fprintf ((FILE), "%s0x%lx\n", ASM_LONG, l); \
} while (0)
/* Store in OUTPUT a string (made with alloca) containing
@@ -2678,23 +2698,30 @@ do { long l; \
/* This is how to output an assembler line defining an `int' constant. */
#define ASM_OUTPUT_INT(FILE,VALUE) \
-( fprintf (FILE, "%s\t", ASM_LONG), \
+( fputs (ASM_LONG, FILE), \
output_addr_const (FILE,(VALUE)), \
putc('\n',FILE))
/* Likewise for `char' and `short' constants. */
-/* is this supposed to do align too?? */
#define ASM_OUTPUT_SHORT(FILE,VALUE) \
-( fprintf (FILE, "%s\t", ASM_SHORT), \
+( fputs (ASM_SHORT, FILE), \
output_addr_const (FILE,(VALUE)), \
putc('\n',FILE))
#define ASM_OUTPUT_CHAR(FILE,VALUE) \
-( fprintf (FILE, "%s", ASM_BYTE_OP), \
+( fputs (ASM_BYTE_OP, FILE), \
output_addr_const (FILE, (VALUE)), \
putc ('\n', FILE))
+/* Given that x86 natively supports unaligned data, it's reasonable to
+ assume that all x86 assemblers don't auto-align data. Thus the
+ unaligned output macros required by dwarf2 frame unwind information
+ degenerate to the macros used above. */
+#define UNALIGNED_SHORT_ASM_OP ASM_SHORT
+#define UNALIGNED_INT_ASM_OP ASM_LONG
+#define INT_ASM_OP ASM_LONG
+
/* This is how to output an assembler line for a numeric constant byte. */
#define ASM_OUTPUT_BYTE(FILE,VALUE) \
@@ -2716,7 +2743,7 @@ do { long l; \
*/
#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
- fprintf (FILE, "%s %s%d\n", ASM_LONG, LPREFIX, VALUE)
+ fprintf (FILE, "%s%s%d\n", ASM_LONG, LPREFIX, VALUE)
/* This is how to output an element of a case-vector that is relative.
We don't use these on the 386 yet, because the ATT assembler can't do
@@ -2724,7 +2751,7 @@ do { long l; \
*/
#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
- fprintf (FILE, "\t%s\t%s%d-%s%d\n",ASM_LONG, LPREFIX, VALUE, LPREFIX, REL)
+ fprintf (FILE, "%s%s%d-%s%d\n",ASM_LONG, LPREFIX, VALUE, LPREFIX, REL)
/* A C statement that outputs an address constant appropriate to
for DWARF debugging. */
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index df16d5b608d..f9eacbca3bb 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -1,5 +1,5 @@
;; GCC machine description for IA-32.
-;; Copyright (C) 1988, 1994, 1995, 1996, 1997, 1998, 1999, 2000
+;; Copyright (C) 1988, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
;; Free Software Foundation, Inc.
;; Mostly by William Schelter.
;;
@@ -72,6 +72,7 @@
;; 10 This is a `sahf' operation.
;; 11 This is a `fstcw' operation
;; 12 This is behaviour of add when setting carry flag.
+;; 13 This is a `eh_return' placeholder.
;; For SSE/MMX support:
;; 30 This is `fix', guaranteed to be truncating.
@@ -1553,7 +1554,7 @@
(define_insn "*pushsi2_prologue"
[(set (match_operand:SI 0 "push_operand" "=<")
(match_operand:SI 1 "general_no_elim_operand" "ri*m"))
- (set (reg:SI 6) (reg:SI 6))]
+ (clobber (mem:BLK (scratch)))]
""
"push{l}\\t%1"
[(set_attr "type" "push")
@@ -1564,7 +1565,7 @@
(mem:SI (reg:SI 7)))
(set (reg:SI 7)
(plus:SI (reg:SI 7) (const_int 4)))
- (set (reg:SI 6) (reg:SI 6))]
+ (clobber (mem:BLK (scratch)))]
""
"pop{l}\\t%0"
[(set_attr "type" "pop")
@@ -3671,7 +3672,7 @@
(set_attr "mode" "SF")])
(define_insn "*truncxfsf2_2"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=m")
+ [(set (match_operand:SF 0 "memory_operand" "=m")
(float_truncate:SF
(match_operand:TF 1 "register_operand" "f")))]
"TARGET_80387"
@@ -9593,6 +9594,25 @@
(match_dup 0)
(pc)))]
"")
+
+;; Convert setcc + movzbl to xor + setcc if operands don't overlap.
+
+(define_peephole2
+ [(set (reg 17) (match_operand 0 "" ""))
+ (set (match_operand:QI 1 "register_operand" "")
+ (match_operator:QI 2 "ix86_comparison_operator"
+ [(reg 17) (const_int 0)]))
+ (set (match_operand 3 "q_regs_operand" "")
+ (zero_extend (match_dup 1)))]
+ "peep2_reg_dead_p (3, operands[1])
+ && ! reg_overlap_mentioned_p (operands[3], operands[0])"
+ [(parallel [(set (match_dup 3) (const_int 0))
+ (clobber (reg:CC 17))])
+ (set (match_dup 4) (match_dup 0))
+ (set (strict_low_part (match_dup 5))
+ (match_dup 2))]
+ "operands[4] = gen_rtx_REG (GET_MODE (operands[0]), 17);
+ operands[5] = gen_rtx_REG (QImode, REGNO (operands[3]));")
;; Call instructions.
@@ -9914,9 +9934,39 @@
""
"ix86_expand_epilogue (0); DONE;")
+(define_expand "eh_return"
+ [(use (match_operand 0 "register_operand" ""))
+ (use (match_operand 1 "register_operand" ""))]
+ ""
+ "
+{
+ rtx tmp, sa = operands[0], ra = operands[1];
+
+ /* Tricky bit: we write the address of the handler to which we will
+ be returning into someone else's stack frame, one word below the
+ stack address we wish to restore. */
+ tmp = gen_rtx_PLUS (Pmode, arg_pointer_rtx, sa);
+ tmp = plus_constant (tmp, -UNITS_PER_WORD);
+ tmp = gen_rtx_MEM (Pmode, tmp);
+ emit_move_insn (tmp, ra);
+
+ emit_insn (gen_eh_return_1 (sa));
+ emit_barrier ();
+ DONE;
+}")
+
+(define_insn_and_split "eh_return_1"
+ [(unspec_volatile [(match_operand 0 "register_operand" "c")] 13)]
+ ""
+ "#"
+ "reload_completed"
+ [(const_int 1)]
+ "ix86_expand_epilogue (2); DONE;")
+
(define_insn "leave"
[(set (reg:SI 7) (reg:SI 6))
- (set (reg:SI 6) (mem:SI (pre_dec:SI (reg:SI 7))))]
+ (set (reg:SI 6) (mem:SI (pre_dec:SI (reg:SI 7))))
+ (clobber (mem:BLK (scratch)))]
""
"leave"
[(set_attr "length_immediate" "0")
@@ -10703,6 +10753,9 @@
rtx srcreg, destreg, countreg;
int align = 0;
int count = -1;
+ rtx insns;
+
+ start_sequence ();
if (GET_CODE (operands[3]) == CONST_INT)
align = INTVAL (operands[3]);
@@ -10717,7 +10770,7 @@
destreg = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
srcreg = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
- emit_insn (gen_cld());
+ emit_insn (gen_cld ());
/* When optimizing for size emit simple rep ; movsb instruction for
counts not divisible by 4. */
@@ -10766,10 +10819,13 @@
library version, since it is usually equally fast and result in
shorter code. */
if (!TARGET_INLINE_ALL_STRINGOPS && align < 4)
- FAIL;
+ {
+ end_sequence ();
+ FAIL;
+ }
if (TARGET_SINGLE_STRINGOP)
- emit_insn (gen_cld());
+ emit_insn (gen_cld ());
countreg2 = gen_reg_rtx (SImode);
countreg = copy_to_mode_reg (SImode, operands[2]);
@@ -10869,6 +10925,12 @@
LABEL_NUSES (label) = 1;
}
}
+
+ insns = get_insns ();
+ end_sequence ();
+
+ ix86_set_move_mem_attrs (insns, operands[0], operands[1], destreg, srcreg);
+ emit_insns (insns);
DONE;
}")
@@ -11039,6 +11101,9 @@
rtx destreg, zeroreg, countreg;
int align = 0;
int count = -1;
+ rtx insns;
+
+ start_sequence ();
if (GET_CODE (operands[2]) == CONST_INT)
align = INTVAL (operands[2]);
@@ -11052,7 +11117,7 @@
destreg = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
- emit_insn (gen_cld());
+ emit_insn (gen_cld ());
/* When optimizing for size emit simple rep ; movsb instruction for
counts not divisible by 4. */
@@ -11095,10 +11160,13 @@
library version, since it is usually equally fast and result in
shorter code. */
if (!TARGET_INLINE_ALL_STRINGOPS && align < 4)
- FAIL;
+ {
+ end_sequence ();
+ FAIL;
+ }
if (TARGET_SINGLE_STRINGOP)
- emit_insn (gen_cld());
+ emit_insn (gen_cld ());
countreg2 = gen_reg_rtx (SImode);
countreg = copy_to_mode_reg (SImode, operands[1]);
@@ -11192,6 +11260,13 @@
LABEL_NUSES (label) = 1;
}
}
+
+ insns = get_insns ();
+ end_sequence ();
+
+ ix86_set_move_mem_attrs (insns, operands[0], operands[0], destreg, destreg);
+ emit_insns (insns);
+
DONE;
}")
@@ -11504,6 +11579,91 @@
[(set_attr "type" "str")
(set_attr "mode" "QI")
(set_attr "prefix_rep" "1")])
+
+;; Peephole optimizations to clean up after cmpstr*. This should be
+;; handled in combine, but it is not currently up to the task.
+;; When used for their truth value, the cmpstr* expanders generate
+;; code like this:
+;;
+;; repz cmpsb
+;; seta %al
+;; setb %dl
+;; cmpb %al, %dl
+;; jcc label
+;;
+;; The intermediate three instructions are unnecessary.
+
+;; This one handles cmpstr*_nz_1...
+(define_peephole2
+ [(parallel[
+ (set (reg:CC 17)
+ (compare:CC (mem:BLK (match_operand 4 "register_operand" ""))
+ (mem:BLK (match_operand 5 "register_operand" ""))))
+ (use (match_operand 6 "register_operand" ""))
+ (use (match_operand:SI 3 "immediate_operand" ""))
+ (use (reg:SI 19))
+ (clobber (match_operand 0 "register_operand" ""))
+ (clobber (match_operand 1 "register_operand" ""))
+ (clobber (match_operand 2 "register_operand" ""))])
+ (set (match_operand:QI 7 "register_operand" "")
+ (gtu:QI (reg:CC 17) (const_int 0)))
+ (set (match_operand:QI 8 "register_operand" "")
+ (ltu:QI (reg:CC 17) (const_int 0)))
+ (set (reg 17)
+ (compare (match_dup 7) (match_dup 8)))
+ ]
+ "peep2_reg_dead_p (4, operands[7]) && peep2_reg_dead_p (4, operands[8])"
+ [(parallel[
+ (set (reg:CC 17)
+ (compare:CC (mem:BLK (match_dup 4))
+ (mem:BLK (match_dup 5))))
+ (use (match_dup 6))
+ (use (match_dup 3))
+ (use (reg:SI 19))
+ (clobber (match_dup 0))
+ (clobber (match_dup 1))
+ (clobber (match_dup 2))])]
+ "")
+
+;; ...and this one handles cmpstr*_1.
+(define_peephole2
+ [(parallel[
+ (set (reg:CC 17)
+ (if_then_else:CC (ne (match_operand 6 "register_operand" "")
+ (const_int 0))
+ (compare:CC (mem:BLK (match_operand 4 "register_operand" ""))
+ (mem:BLK (match_operand 5 "register_operand" "")))
+ (const_int 0)))
+ (use (match_operand:SI 3 "immediate_operand" ""))
+ (use (reg:CC 17))
+ (use (reg:SI 19))
+ (clobber (match_operand 0 "register_operand" ""))
+ (clobber (match_operand 1 "register_operand" ""))
+ (clobber (match_operand 2 "register_operand" ""))])
+ (set (match_operand:QI 7 "register_operand" "")
+ (gtu:QI (reg:CC 17) (const_int 0)))
+ (set (match_operand:QI 8 "register_operand" "")
+ (ltu:QI (reg:CC 17) (const_int 0)))
+ (set (reg 17)
+ (compare (match_dup 7) (match_dup 8)))
+ ]
+ "peep2_reg_dead_p (4, operands[7]) && peep2_reg_dead_p (4, operands[8])"
+ [(parallel[
+ (set (reg:CC 17)
+ (if_then_else:CC (ne (match_dup 6)
+ (const_int 0))
+ (compare:CC (mem:BLK (match_dup 4))
+ (mem:BLK (match_dup 5)))
+ (const_int 0)))
+ (use (match_dup 3))
+ (use (reg:CC 17))
+ (use (reg:SI 19))
+ (clobber (match_dup 0))
+ (clobber (match_dup 1))
+ (clobber (match_dup 2))])]
+ "")
+
+
;; Conditional move instructions.
@@ -11671,9 +11831,8 @@
[(set (match_operand:SI 0 "register_operand" "=r,r")
(plus:SI (match_operand:SI 1 "register_operand" "0,r")
(match_operand:SI 2 "immediate_operand" "i,i")))
- (set (match_operand:SI 3 "register_operand" "+r,r")
- (match_dup 3))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC 17))
+ (clobber (mem:BLK (scratch)))]
""
"*
{
@@ -11745,15 +11904,6 @@
DONE;
}")
-(define_expand "exception_receiver"
- [(const_int 0)]
- "flag_pic"
- "
-{
- load_pic_register ();
- DONE;
-}")
-
(define_expand "builtin_setjmp_receiver"
[(label_ref (match_operand 0 "" ""))]
"flag_pic"
@@ -11784,7 +11934,7 @@
operands[1] = gen_lowpart (SImode, operands[1]);
if (GET_CODE (operands[3]) != ASHIFT)
operands[2] = gen_lowpart (SImode, operands[2]);
- GET_MODE (operands[3]) = SImode;")
+ PUT_MODE (operands[3], SImode);")
(define_split
[(set (reg 17)
@@ -12272,23 +12422,23 @@
(define_peephole2
[(match_scratch:SI 0 "r")
(parallel [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -4)))
- (set (reg:SI 6) (reg:SI 6))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC 17))
+ (clobber (mem:BLK (scratch)))])]
"optimize_size || !TARGET_SUB_ESP_4"
[(clobber (match_dup 0))
(parallel [(set (mem:SI (pre_dec:SI (reg:SI 7))) (match_dup 0))
- (set (reg:SI 6) (reg:SI 6))])])
+ (clobber (mem:BLK (scratch)))])])
(define_peephole2
[(match_scratch:SI 0 "r")
(parallel [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -8)))
- (set (reg:SI 6) (reg:SI 6))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC 17))
+ (clobber (mem:BLK (scratch)))])]
"optimize_size || !TARGET_SUB_ESP_8"
[(clobber (match_dup 0))
(set (mem:SI (pre_dec:SI (reg:SI 7))) (match_dup 0))
(parallel [(set (mem:SI (pre_dec:SI (reg:SI 7))) (match_dup 0))
- (set (reg:SI 6) (reg:SI 6))])])
+ (clobber (mem:BLK (scratch)))])])
;; Convert esp substractions to push.
(define_peephole2
@@ -12312,12 +12462,12 @@
(define_peephole2
[(match_scratch:SI 0 "r")
(parallel [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 4)))
- (set (reg:SI 6) (reg:SI 6))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC 17))
+ (clobber (mem:BLK (scratch)))])]
"optimize_size || !TARGET_ADD_ESP_4"
[(parallel [(set (match_dup 0) (mem:SI (reg:SI 7)))
(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 4)))
- (set (reg:SI 6) (reg:SI 6))])]
+ (clobber (mem:BLK (scratch)))])]
"")
;; Two pops case is tricky, since pop causes dependency on destination register.
@@ -12326,12 +12476,12 @@
[(match_scratch:SI 0 "r")
(match_scratch:SI 1 "r")
(parallel [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 8)))
- (set (reg:SI 6) (reg:SI 6))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC 17))
+ (clobber (mem:BLK (scratch)))])]
"optimize_size || !TARGET_ADD_ESP_8"
[(parallel [(set (match_dup 0) (mem:SI (reg:SI 7)))
(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 4)))
- (set (reg:SI 6) (reg:SI 6))])
+ (clobber (mem:BLK (scratch)))])
(parallel [(set (match_dup 1) (mem:SI (reg:SI 7)))
(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 4)))])]
"")
@@ -12339,12 +12489,12 @@
(define_peephole2
[(match_scratch:SI 0 "r")
(parallel [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 8)))
- (set (reg:SI 6) (reg:SI 6))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC 17))
+ (clobber (mem:BLK (scratch)))])]
"optimize_size"
[(parallel [(set (match_dup 0) (mem:SI (reg:SI 7)))
(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 4)))
- (set (reg:SI 6) (reg:SI 6))])
+ (clobber (mem:BLK (scratch)))])
(parallel [(set (match_dup 0) (mem:SI (reg:SI 7)))
(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 4)))])]
"")
@@ -12446,6 +12596,25 @@
(const_int 128)))
(clobber (match_dup 0))])]
"")
+
+;; Convert setcc + movzbl to xor + setcc if operands don't overlap.
+
+(define_peephole2
+ [(set (reg 17) (match_operand 0 "" ""))
+ (set (match_operand:QI 1 "register_operand" "")
+ (match_operator:QI 2 "ix86_comparison_operator"
+ [(reg 17) (const_int 0)]))
+ (set (match_operand 3 "q_regs_operand" "")
+ (zero_extend (match_dup 1)))]
+ "peep2_reg_dead_p (3, operands[1])
+ && ! reg_overlap_mentioned_p (operands[3], operands[0])"
+ [(parallel [(set (match_dup 3) (const_int 0))
+ (clobber (reg:CC 17))])
+ (set (match_dup 4) (match_dup 0))
+ (set (strict_low_part (match_dup 5))
+ (match_dup 2))]
+ "operands[4] = gen_rtx_REG (GET_MODE (operands[0]), 17);
+ operands[5] = gen_rtx_REG (QImode, REGNO (operands[3]));")
;; Call-value patterns last so that the wildcard operand does not
;; disrupt insn-recog's switch tables.
@@ -13892,8 +14061,9 @@
;; See logical MMX insns.
(define_insn "mmx_lshrdi3"
[(set (match_operand:DI 0 "register_operand" "=y")
- (lshiftrt:DI (match_operand:DI 1 "register_operand" "0")
- (match_operand:DI 2 "nonmemory_operand" "yi")))]
+ (unspec:DI
+ [(lshiftrt:DI (match_operand:DI 1 "register_operand" "0")
+ (match_operand:DI 2 "nonmemory_operand" "yi"))] 45))]
"TARGET_MMX"
"psrlq\\t{%2, %0|%0, %2}"
[(set_attr "type" "mmx")])
@@ -13917,8 +14087,9 @@
;; See logical MMX insns.
(define_insn "mmx_ashldi3"
[(set (match_operand:DI 0 "register_operand" "=y")
- (ashift:DI (match_operand:DI 1 "register_operand" "0")
- (match_operand:DI 2 "nonmemory_operand" "yi")))]
+ (unspec:DI
+ [(ashift:DI (match_operand:DI 1 "register_operand" "0")
+ (match_operand:DI 2 "nonmemory_operand" "yi"))] 45))]
"TARGET_MMX"
"psllq\\t{%2, %0|%0, %2}"
[(set_attr "type" "mmx")])
diff --git a/gcc/config/i386/i386afe.h b/gcc/config/i386/i386afe.h
deleted file mode 100644
index b40be840af6..00000000000
--- a/gcc/config/i386/i386afe.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* Copyright (C) 2001 Free Software Foundation, Inc.
-
-This file is part of GNU CC.
-
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* Irritatingly, config/elfos.h defines its own version of ASM_FILE_END,
- conflicting with a definition which we wish to have in i386/i386.h.
- We _really_ need to clean up the hodge-podge of random macro placement
- in the configury... */
-
-/* This macro is invoked at the end of compilation. It is used here to
- output code for -fpic that will load the return address into %ebx. */
-
-#undef ASM_FILE_END
-#define ASM_FILE_END(FILE) \
- do \
- { \
- ix86_asm_file_end (FILE); \
- if (!flag_no_ident) \
- fprintf ((FILE), "%s\"GCC: (GNU) %s\"\n", \
- IDENT_ASM_OP, version_string); \
- } \
- while (0)
diff --git a/gcc/config/i386/i386elf.h b/gcc/config/i386/i386elf.h
index d333551f2b8..64c1bae9f3f 100644
--- a/gcc/config/i386/i386elf.h
+++ b/gcc/config/i386/i386elf.h
@@ -56,9 +56,9 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
do { long value; \
REAL_VALUE_TO_TARGET_SINGLE ((VALUE), value); \
if (sizeof (int) == sizeof (long)) \
- fprintf((FILE), "%s\t0x%x\n", ASM_LONG, value); \
+ fprintf((FILE), "%s0x%x\n", ASM_LONG, value); \
else \
- fprintf((FILE), "%s\t0x%lx\n", ASM_LONG, value); \
+ fprintf((FILE), "%s0x%lx\n", ASM_LONG, value); \
} while (0)
/* This is how to output assembly code to define a `double' constant.
@@ -72,13 +72,13 @@ do { long value[2]; \
REAL_VALUE_TO_TARGET_DOUBLE ((VALUE), value); \
if (sizeof (int) == sizeof (long)) \
{ \
- fprintf((FILE), "%s\t0x%x\n", ASM_LONG, value[0]); \
- fprintf((FILE), "%s\t0x%x\n", ASM_LONG, value[1]); \
+ fprintf((FILE), "%s0x%x\n", ASM_LONG, value[0]); \
+ fprintf((FILE), "%s0x%x\n", ASM_LONG, value[1]); \
} \
else \
{ \
- fprintf((FILE), "%s\t0x%lx\n", ASM_LONG, value[0]); \
- fprintf((FILE), "%s\t0x%lx\n", ASM_LONG, value[1]); \
+ fprintf((FILE), "%s0x%lx\n", ASM_LONG, value[0]); \
+ fprintf((FILE), "%s0x%lx\n", ASM_LONG, value[1]); \
} \
} while (0)
@@ -89,28 +89,18 @@ do { long value[3]; \
REAL_VALUE_TO_TARGET_LONG_DOUBLE ((VALUE), value); \
if (sizeof (int) == sizeof (long)) \
{ \
- fprintf((FILE), "%s\t0x%x\n", ASM_LONG, value[0]); \
- fprintf((FILE), "%s\t0x%x\n", ASM_LONG, value[1]); \
- fprintf((FILE), "%s\t0x%x\n", ASM_LONG, value[2]); \
+ fprintf((FILE), "%s0x%x\n", ASM_LONG, value[0]); \
+ fprintf((FILE), "%s0x%x\n", ASM_LONG, value[1]); \
+ fprintf((FILE), "%s0x%x\n", ASM_LONG, value[2]); \
} \
else \
{ \
- fprintf((FILE), "%s\t0x%lx\n", ASM_LONG, value[0]); \
- fprintf((FILE), "%s\t0x%lx\n", ASM_LONG, value[1]); \
- fprintf((FILE), "%s\t0x%lx\n", ASM_LONG, value[2]); \
+ fprintf((FILE), "%s0x%lx\n", ASM_LONG, value[0]); \
+ fprintf((FILE), "%s0x%lx\n", ASM_LONG, value[1]); \
+ fprintf((FILE), "%s0x%lx\n", ASM_LONG, value[2]); \
} \
} while (0)
-/* Output at beginning of assembler file. */
-/* The .file command should always begin the output. */
-
-#undef ASM_FILE_START
-#define ASM_FILE_START(FILE) \
- do { \
- output_file_directive (FILE, main_input_filename); \
- fprintf (FILE, "\t.version\t\"01.01\"\n"); \
- } while (0)
-
#undef DBX_REGISTER_NUMBER
#define DBX_REGISTER_NUMBER(n) svr4_dbx_register_map[n]
diff --git a/gcc/config/i386/linux.h b/gcc/config/i386/linux.h
index 0ad1c3ac0cb..aacf7eb718d 100644
--- a/gcc/config/i386/linux.h
+++ b/gcc/config/i386/linux.h
@@ -30,7 +30,6 @@ Boston, MA 02111-1307, USA. */
output_file_directive (FILE, main_input_filename); \
if (target_flags & MASK_INTEL_SYNTAX) \
fputs ("\t.intel_syntax\n", FILE); \
- fprintf (FILE, "\t.version\t\"01.01\"\n"); \
} while (0)
#undef TARGET_VERSION
@@ -73,6 +72,15 @@ Boston, MA 02111-1307, USA. */
fprintf (FILE, "\tcall\tmcount\n"); \
}
+/* True if it is possible to profile code that does not have a frame
+ pointer.
+
+ The GLIBC version of mcount for the x86 assumes that there is a
+ frame, so we cannot allow profiling without a frame pointer. */
+
+#undef TARGET_ALLOWS_PROFILING_WITHOUT_FRAME_POINTER
+#define TARGET_ALLOWS_PROFILING_WITHOUT_FRAME_POINTER false
+
#undef SIZE_TYPE
#define SIZE_TYPE "unsigned int"
@@ -169,3 +177,116 @@ Boston, MA 02111-1307, USA. */
} \
} while (0)
#endif
+
+#if defined(__PIC__) && defined (USE_GNULIBC_1)
+/* This is a kludge. The i386 GNU/Linux dynamic linker needs ___brk_addr,
+ __environ and atexit (). We have to make sure they are in the .dynsym
+ section. We accomplish it by making a dummy call here. This
+ code is never reached. */
+
+#define CRT_END_INIT_DUMMY \
+ do \
+ { \
+ extern void *___brk_addr; \
+ extern char **__environ; \
+ \
+ ___brk_addr = __environ; \
+ atexit (0); \
+ } \
+ while (0)
+#endif
+
+/* Handle special EH pointer encodings. Absolute, pc-relative, and
+ indirect are handled automatically. */
+#define ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX(FILE, ENCODING, SIZE, ADDR, DONE) \
+ do { \
+ if ((SIZE) == 4 && ((ENCODING) & 0x70) == DW_EH_PE_datarel) \
+ { \
+ fputs (UNALIGNED_INT_ASM_OP, FILE); \
+ assemble_name (FILE, XSTR (ADDR, 0)); \
+ fputs (((ENCODING) & DW_EH_PE_indirect ? "@GOT" : "@GOTOFF"), FILE); \
+ goto DONE; \
+ } \
+ } while (0)
+
+/* Used by crtstuff.c to initialize the base of data-relative relocations.
+ These are GOT relative on x86, so return the pic register. */
+#ifdef __PIC__
+#define CRT_GET_RFIB_DATA(BASE) \
+ { \
+ register void *ebx_ __asm__("ebx"); \
+ BASE = ebx_; \
+ }
+#else
+#define CRT_GET_RFIB_DATA(BASE) \
+ __asm__ ("call\t.LPR%=\n" \
+ ".LPR%=:\n\t" \
+ "popl\t%0\n\t" \
+ /* Due to a GAS bug, this cannot use EAX. That encodes \
+ smaller than the traditional EBX, which results in the \
+ offset being off by one. */ \
+ "addl\t$_GLOBAL_OFFSET_TABLE_+[.-.LPR%=],%0" \
+ : "=d"(BASE))
+#endif
+
+/* Do code reading to identify a signal frame, and set the frame
+ state data appropriately. See unwind-dw2.c for the structs. */
+
+#ifdef IN_LIBGCC2
+#include <signal.h>
+#include <sys/ucontext.h>
+#endif
+
+#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \
+ do { \
+ unsigned char *pc_ = (CONTEXT)->ra; \
+ struct sigcontext *sc_; \
+ long new_cfa_; \
+ \
+ /* popl %eax ; movl $__NR_sigreturn,%eax ; int $0x80 */ \
+ if (*(unsigned short *)(pc_+0) == 0xb858 \
+ && *(unsigned int *)(pc_+2) == 119 \
+ && *(unsigned short *)(pc_+6) == 0x80cd) \
+ sc_ = (CONTEXT)->cfa + 4; \
+ /* movl $__NR_rt_sigreturn,%eax ; int $0x80 */ \
+ else if (*(unsigned char *)(pc_+0) == 0xb8 \
+ && *(unsigned int *)(pc_+1) == 173 \
+ && *(unsigned short *)(pc_+5) == 0x80cd) \
+ { \
+ struct rt_sigframe { \
+ int sig; \
+ struct siginfo *pinfo; \
+ void *puc; \
+ struct siginfo info; \
+ struct ucontext uc; \
+ } *rt_ = (CONTEXT)->cfa; \
+ sc_ = (struct sigcontext *) &rt_->uc.uc_mcontext; \
+ } \
+ else \
+ break; \
+ \
+ new_cfa_ = sc_->esp; \
+ (FS)->cfa_how = CFA_REG_OFFSET; \
+ (FS)->cfa_reg = 4; \
+ (FS)->cfa_offset = new_cfa_ - (long) (CONTEXT)->cfa; \
+ \
+ /* The SVR4 register numbering macros aren't usable in libgcc. */ \
+ (FS)->regs.reg[0].how = REG_SAVED_OFFSET; \
+ (FS)->regs.reg[0].loc.offset = (long)&sc_->eax - new_cfa_; \
+ (FS)->regs.reg[3].how = REG_SAVED_OFFSET; \
+ (FS)->regs.reg[3].loc.offset = (long)&sc_->ebx - new_cfa_; \
+ (FS)->regs.reg[1].how = REG_SAVED_OFFSET; \
+ (FS)->regs.reg[1].loc.offset = (long)&sc_->ecx - new_cfa_; \
+ (FS)->regs.reg[2].how = REG_SAVED_OFFSET; \
+ (FS)->regs.reg[2].loc.offset = (long)&sc_->edx - new_cfa_; \
+ (FS)->regs.reg[6].how = REG_SAVED_OFFSET; \
+ (FS)->regs.reg[6].loc.offset = (long)&sc_->esi - new_cfa_; \
+ (FS)->regs.reg[7].how = REG_SAVED_OFFSET; \
+ (FS)->regs.reg[7].loc.offset = (long)&sc_->edi - new_cfa_; \
+ (FS)->regs.reg[5].how = REG_SAVED_OFFSET; \
+ (FS)->regs.reg[5].loc.offset = (long)&sc_->ebp - new_cfa_; \
+ (FS)->regs.reg[8].how = REG_SAVED_OFFSET; \
+ (FS)->regs.reg[8].loc.offset = (long)&sc_->eip - new_cfa_; \
+ (FS)->retaddr_column = 8; \
+ goto SUCCESS; \
+ } while (0)
diff --git a/gcc/config/i386/netbsd.h b/gcc/config/i386/netbsd.h
index 51f65611956..25c9549e204 100644
--- a/gcc/config/i386/netbsd.h
+++ b/gcc/config/i386/netbsd.h
@@ -85,8 +85,3 @@
/* Until they use ELF or something that handles dwarf2 unwinds
and initialization stuff better. */
#define DWARF2_UNWIND_INFO 0
-
-/* This is the pseudo-op used to generate a 32-bit word of data with a
- specific value in some section. */
-
-#define INT_ASM_OP "\t.long\t"
diff --git a/gcc/config/i386/openbsd.h b/gcc/config/i386/openbsd.h
index c8d0a65e29d..9359fb99822 100644
--- a/gcc/config/i386/openbsd.h
+++ b/gcc/config/i386/openbsd.h
@@ -114,6 +114,8 @@ Boston, MA 02111-1307, USA. */
configuration files... */
#define DWARF2_UNWIND_INFO 0
+#undef ASM_PREFERRED_EH_DATA_FORMAT
+
/* Assembler format: alignment output. */
/* A C statement to output to the stdio stream FILE an assembler
@@ -134,7 +136,6 @@ Boston, MA 02111-1307, USA. */
/* Note that we pick up ASM_OUTPUT_MI_THUNK from unix.h. */
-/* This is the pseudo-op used to generate a 32-bit word of data with a
- specific value in some section. */
+#undef ASM_COMMENT_START
+#define ASM_COMMENT_START ";#"
-#define INT_ASM_OP "\t.long\t"
diff --git a/gcc/config/i386/osf1elf.h b/gcc/config/i386/osf1elf.h
index 8282953dc0a..5aee6fa1926 100644
--- a/gcc/config/i386/osf1elf.h
+++ b/gcc/config/i386/osf1elf.h
@@ -85,21 +85,6 @@
#undef LIBGCC_SPEC
#define LIBGCC_SPEC "%{!shared:%{!symbolic:libgcc.a%s}}"
-/* A C statement to output assembler commands which will identify the object
- file as having been compile with GNU CC. We don't need or want this for
- OSF1. */
-#undef ASM_IDENTIFY_GCC
-#define ASM_IDENTIFY_GCC(FILE)
-
-/* Identify the front-end which produced this file. To keep symbol
- space down, and not confuse kdb, only do this if the language is
- not C. */
-#define ASM_IDENTIFY_LANGUAGE(STREAM) \
-{ \
- if (strcmp (lang_identify (), "c") != 0) \
- output_lang_identify (STREAM); \
-}
-
/* Specify size_t, ptrdiff_t, and wchar_t types. */
#undef SIZE_TYPE
#undef PTRDIFF_TYPE
diff --git a/gcc/config/i386/osfrose.h b/gcc/config/i386/osfrose.h
index 1f86883599b..138ef67688b 100644
--- a/gcc/config/i386/osfrose.h
+++ b/gcc/config/i386/osfrose.h
@@ -740,11 +740,6 @@ do \
} \
while (0)
-/* Attach a special .ident directive to the end of the file to identify
- the version of GCC which compiled this code. The format of the
- .ident string is patterned after the ones produced by native svr4
- C compilers. */
-
#define IDENT_ASM_OP "\t.ident\t"
/* Allow #sccs in preprocessor. */
@@ -759,98 +754,6 @@ do \
if (HALF_PIC_P ()) \
HALF_PIC_FINISH (STREAM); \
ix86_asm_file_end (STREAM); \
- if (!flag_no_ident) \
- { \
- char *fstart = main_input_filename; \
- char *fname; \
- \
- if (!fstart) \
- fstart = "<no file>"; \
- \
- fname = fstart + strlen (fstart) - 1; \
- while (fname > fstart && *fname != '/') \
- fname--; \
- \
- if (*fname == '/') \
- fname++; \
- \
- fprintf ((STREAM), "%s\"GCC: (GNU) %s %s -O%d", \
- IDENT_ASM_OP, version_string, fname, optimize); \
- \
- if (write_symbols == PREFERRED_DEBUGGING_TYPE) \
- fprintf ((STREAM), " -g%d", (int)debug_info_level); \
- \
- else if (write_symbols == DBX_DEBUG) \
- fprintf ((STREAM), " -gstabs%d", (int)debug_info_level); \
- \
- else if (write_symbols == DWARF_DEBUG) \
- fprintf ((STREAM), " -gdwarf%d", (int)debug_info_level); \
- \
- else if (write_symbols != NO_DEBUG) \
- fprintf ((STREAM), " -g??%d", (int)debug_info_level); \
- \
- if (flag_omit_frame_pointer) \
- fprintf ((STREAM), " -fomit-frame-pointer"); \
- \
- if (flag_strength_reduce) \
- fprintf ((STREAM), " -fstrength-reduce"); \
- \
- if (flag_unroll_loops) \
- fprintf ((STREAM), " -funroll-loops"); \
- \
- if (flag_schedule_insns) \
- fprintf ((STREAM), " -fschedule-insns"); \
- \
- if (flag_schedule_insns_after_reload) \
- fprintf ((STREAM), " -fschedule-insns2"); \
- \
- if (flag_force_mem) \
- fprintf ((STREAM), " -fforce-mem"); \
- \
- if (flag_force_addr) \
- fprintf ((STREAM), " -fforce-addr"); \
- \
- if (flag_inline_functions) \
- fprintf ((STREAM), " -finline-functions"); \
- \
- if (flag_caller_saves) \
- fprintf ((STREAM), " -fcaller-saves"); \
- \
- if (flag_pic) \
- fprintf ((STREAM), (flag_pic > 1) ? " -fPIC" : " -fpic"); \
- \
- if (flag_inhibit_size_directive) \
- fprintf ((STREAM), " -finhibit-size-directive"); \
- \
- if (flag_gnu_linker) \
- fprintf ((STREAM), " -fgnu-linker"); \
- \
- if (profile_flag) \
- fprintf ((STREAM), " -p"); \
- \
- if (profile_block_flag) \
- fprintf ((STREAM), " -a"); \
- \
- if (TARGET_IEEE_FP) \
- fprintf ((STREAM), " -mieee-fp"); \
- \
- if (TARGET_HALF_PIC) \
- fprintf ((STREAM), " -mhalf-pic"); \
- \
- if (!TARGET_MOVE) \
- fprintf ((STREAM), " -mno-move"); \
- \
- if (TARGET_386) \
- fprintf ((STREAM), " -m386"); \
- \
- else if (TARGET_486) \
- fprintf ((STREAM), " -m486"); \
- \
- else \
- fprintf ((STREAM), " -munknown-machine"); \
- \
- fprintf ((STREAM), (TARGET_ELF) ? " -melf\"\n" : " -mrose\"\n"); \
- } \
} \
while (0)
@@ -866,21 +769,6 @@ while (0)
to do the search */
#define LINK_LIBGCC_SPECIAL
-/* A C statement to output assembler commands which will identify the object
- file as having been compile with GNU CC. We don't need or want this for
- OSF1. GDB doesn't need it and kdb doesn't like it */
-#define ASM_IDENTIFY_GCC(FILE)
-
-/* Identify the front-end which produced this file. To keep symbol
- space down, and not confuse kdb, only do this if the language is
- not C. */
-
-#define ASM_IDENTIFY_LANGUAGE(STREAM) \
-{ \
- if (strcmp (lang_identify (), "c") != 0) \
- output_lang_identify (STREAM); \
-}
-
/* Generate calls to memcpy, etc., not bcopy, etc. */
#define TARGET_MEM_FUNCTIONS
diff --git a/gcc/config/i386/ptx4-i.h b/gcc/config/i386/ptx4-i.h
index 0d4b33edf61..735408ebf8f 100644
--- a/gcc/config/i386/ptx4-i.h
+++ b/gcc/config/i386/ptx4-i.h
@@ -53,9 +53,9 @@ Boston, MA 02111-1307, USA. */
do { long value; \
REAL_VALUE_TO_TARGET_SINGLE ((VALUE), value); \
if (sizeof (int) == sizeof (long)) \
- fprintf((FILE), "%s\t0x%x\n", ASM_LONG, value); \
+ fprintf((FILE), "%s0x%x\n", ASM_LONG, value); \
else \
- fprintf((FILE), "%s\t0x%lx\n", ASM_LONG, value); \
+ fprintf((FILE), "%s0x%lx\n", ASM_LONG, value); \
} while (0)
/* This is how to output assembly code to define a `double' constant.
@@ -69,13 +69,13 @@ do { long value[2]; \
REAL_VALUE_TO_TARGET_DOUBLE ((VALUE), value); \
if (sizeof (int) == sizeof (long)) \
{ \
- fprintf((FILE), "%s\t0x%x\n", ASM_LONG, value[0]); \
- fprintf((FILE), "%s\t0x%x\n", ASM_LONG, value[1]); \
+ fprintf((FILE), "%s0x%x\n", ASM_LONG, value[0]); \
+ fprintf((FILE), "%s0x%x\n", ASM_LONG, value[1]); \
} \
else \
{ \
- fprintf((FILE), "%s\t0x%lx\n", ASM_LONG, value[0]); \
- fprintf((FILE), "%s\t0x%lx\n", ASM_LONG, value[1]); \
+ fprintf((FILE), "%s0x%lx\n", ASM_LONG, value[0]); \
+ fprintf((FILE), "%s0x%lx\n", ASM_LONG, value[1]); \
} \
} while (0)
@@ -86,28 +86,18 @@ do { long value[3]; \
REAL_VALUE_TO_TARGET_LONG_DOUBLE ((VALUE), value); \
if (sizeof (int) == sizeof (long)) \
{ \
- fprintf((FILE), "%s\t0x%x\n", ASM_LONG, value[0]); \
- fprintf((FILE), "%s\t0x%x\n", ASM_LONG, value[1]); \
- fprintf((FILE), "%s\t0x%x\n", ASM_LONG, value[2]); \
+ fprintf((FILE), "%s0x%x\n", ASM_LONG, value[0]); \
+ fprintf((FILE), "%s0x%x\n", ASM_LONG, value[1]); \
+ fprintf((FILE), "%s0x%x\n", ASM_LONG, value[2]); \
} \
else \
{ \
- fprintf((FILE), "%s\t0x%lx\n", ASM_LONG, value[0]); \
- fprintf((FILE), "%s\t0x%lx\n", ASM_LONG, value[1]); \
- fprintf((FILE), "%s\t0x%lx\n", ASM_LONG, value[2]); \
+ fprintf((FILE), "%s0x%lx\n", ASM_LONG, value[0]); \
+ fprintf((FILE), "%s0x%lx\n", ASM_LONG, value[1]); \
+ fprintf((FILE), "%s0x%lx\n", ASM_LONG, value[2]); \
} \
} while (0)
-/* Output at beginning of assembler file. */
-/* The .file command should always begin the output. */
-
-#undef ASM_FILE_START
-#define ASM_FILE_START(FILE) \
- do { \
- output_file_directive (FILE, main_input_filename); \
- fprintf (FILE, "\t.version\t\"01.01\"\n"); \
- } while (0)
-
#undef DBX_REGISTER_NUMBER
#define DBX_REGISTER_NUMBER(n) svr4_dbx_register_map[n]
diff --git a/gcc/config/i386/sco5.h b/gcc/config/i386/sco5.h
index ae832b91f5f..49031cf0c5d 100644
--- a/gcc/config/i386/sco5.h
+++ b/gcc/config/i386/sco5.h
@@ -54,13 +54,10 @@ Boston, MA 02111-1307, USA. */
#define INT_ASM_OP "\t.long\t"
#undef ASM_SHORT
-#define ASM_SHORT "\t.value"
+#define ASM_SHORT "\t.value\t"
#undef ASM_LONG
-#define ASM_LONG "\t.long"
-
-#undef ASM_DOUBLE
-#define ASM_DOUBLE "\t.double"
+#define ASM_LONG "\t.long\t"
#undef TYPE_ASM_OP
#define TYPE_ASM_OP "\t.type\t"
@@ -210,15 +207,6 @@ do { \
fprintf ((FILE), "\t.version\t\"01.01\"\n"); \
} while (0)
-#undef ASM_FILE_END
-#define ASM_FILE_END(FILE) \
-do { \
- ix86_asm_file_end (FILE); \
- if (!flag_no_ident) \
- fprintf ((FILE), "%s\"GCC: (GNU) %s\"\n", \
- IDENT_ASM_OP, version_string); \
-} while (0)
-
#undef ASM_FINISH_DECLARE_OBJECT
#define ASM_FINISH_DECLARE_OBJECT(FILE, DECL, TOP_LEVEL, AT_END) \
do { \
@@ -250,9 +238,9 @@ do { \
#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
do { \
if (TARGET_ELF) \
- fprintf (FILE, "%s _GLOBAL_OFFSET_TABLE_+[.-%s%d]\n", ASM_LONG, LPREFIX, VALUE); \
+ fprintf (FILE, "%s_GLOBAL_OFFSET_TABLE_+[.-%s%d]\n", ASM_LONG, LPREFIX, VALUE); \
else \
- fprintf (FILE, "\t.word %s%d-%s%d\n", LPREFIX,VALUE,LPREFIX,REL); \
+ fprintf (FILE, "%s%s%d-%s%d\n", ASM_LONG, LPREFIX,VALUE,LPREFIX,REL); \
} while (0)
#undef ASM_OUTPUT_ALIGNED_COMMON
@@ -428,7 +416,7 @@ do { \
fprintf (FILE, "\n"); \
} else { \
fini_section (); \
- fprintf (FILE, "%s\t ", ASM_LONG); \
+ fprintf (FILE, "%s", INT_ASM_OP); \
assemble_name (FILE, NAME); \
fprintf (FILE, "\n"); } \
} while (0)
@@ -548,11 +536,13 @@ do { \
#define DBX_REGISTER_NUMBER(n) \
((TARGET_ELF) ? svr4_dbx_register_map[n] : dbx_register_map[n])
+#undef DWARF2_DEBUGGING_INFO
#undef DWARF_DEBUGGING_INFO
#undef SDB_DEBUGGING_INFO
#undef DBX_DEBUGGING_INFO
#undef PREFERRED_DEBUGGING_TYPE
+#define DWARF2_DEBUGGING_INFO 1
#define DWARF_DEBUGGING_INFO 1
#define SDB_DEBUGGING_INFO 1
#define DBX_DEBUGGING_INFO 1
@@ -963,3 +953,44 @@ do { \
} while (0)
# endif /* ! _SCO_ELF */
#endif /* CRT_BEGIN !! CRT_END */
+
+/* Handle special EH pointer encodings. Absolute, pc-relative, and
+ indirect are handled automatically. */
+#define ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX(FILE, ENCODING, SIZE, ADDR, DONE) \
+ do { \
+ if ((SIZE) == 4 && ((ENCODING) & 0x70) == DW_EH_PE_datarel) \
+ { \
+ fputs (UNALIGNED_INT_ASM_OP, FILE); \
+ assemble_name (FILE, XSTR (ADDR, 0)); \
+ fputs (((ENCODING) & DW_EH_PE_indirect ? "@GOT" : "@GOTOFF"), FILE); \
+ goto DONE; \
+ } \
+ } while (0)
+
+/* Used by crtstuff.c to initialize the base of data-relative relocations.
+ These are GOT relative on x86, so return the pic register. */
+#ifdef __PIC__
+#define CRT_GET_RFIB_DATA(BASE) \
+ { \
+ register void *ebx_ __asm__("ebx"); \
+ BASE = ebx_; \
+ }
+#else
+#define CRT_GET_RFIB_DATA(BASE) \
+ __asm__ ("call\t.LPR%=\n" \
+ ".LPR%=:\n\t" \
+ "popl\t%0\n\t" \
+ /* Due to a GAS bug, this cannot use EAX. That encodes \
+ smaller than the traditional EBX, which results in the \
+ offset being off by one. */ \
+ "addl\t$_GLOBAL_OFFSET_TABLE_+[.-.LPR%=],%0" \
+ : "=d"(BASE))
+#endif
+
+/* Select a format to encode pointers in exception handling data. CODE
+ is 0 for data, 1 for code labels, 2 for function pointers. GLOBAL is
+ true if the symbol may be affected by dynamic relocations. */
+#undef ASM_PREFERRED_EH_DATA_FORMAT
+#define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL) \
+ (flag_pic ? (GLOBAL ? DW_EH_PE_indirect : 0) | DW_EH_PE_datarel \
+ : DW_EH_PE_absptr)
diff --git a/gcc/config/i386/sol2.h b/gcc/config/i386/sol2.h
index bd61ee99700..4a1883913ee 100644
--- a/gcc/config/i386/sol2.h
+++ b/gcc/config/i386/sol2.h
@@ -1,5 +1,5 @@
/* Target definitions for GNU compiler for Intel 80386 running Solaris 2
- Copyright (C) 1993, 1995, 1996, 1997, 1998, 1999
+ Copyright (C) 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001
Free Software Foundation, Inc.
Contributed by Fred Fish (fnf@cygnus.com).
@@ -61,16 +61,27 @@ Boston, MA 02111-1307, USA. */
#define FORCE_INIT_SECTION_ALIGN asm (ALIGN_ASM_OP ## "16")
#define FORCE_FINI_SECTION_ALIGN FORCE_INIT_SECTION_ALIGN
+/* Select a format to encode pointers in exception handling data. CODE
+ is 0 for data, 1 for code labels, 2 for function pointers. GLOBAL is
+ true if the symbol may be affected by dynamic relocations. */
+#undef ASM_PREFERRED_EH_DATA_FORMAT
+#define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL) \
+ (flag_pic ? (GLOBAL ? DW_EH_PE_indirect : 0) | DW_EH_PE_datarel \
+ : DW_EH_PE_absptr)
+
/* Add "sun" to the list of symbols defined for SVR4. */
#undef CPP_PREDEFINES
#define CPP_PREDEFINES \
"-Dunix -D__svr4__ -D__SVR4 -Dsun -Asystem=svr4"
+/* Solaris 2/Intel as chokes on #line directives. */
#undef CPP_SPEC
-#define CPP_SPEC "%(cpp_cpu) \
- %{pthreads:-D_REENTRANT -D_PTHREADS} \
- %{!pthreads:%{threads:-D_REENTRANT -D_SOLARIS_THREADS}} \
- %{compat-bsd:-iwithprefixbefore ucbinclude -I/usr/ucbinclude}"
+#define CPP_SPEC \
+ "%{.S:-P} \
+ %(cpp_cpu) \
+ %{pthreads:-D_REENTRANT -D_PTHREADS} \
+ %{!pthreads:%{threads:-D_REENTRANT -D_SOLARIS_THREADS}} \
+ %{compat-bsd:-iwithprefixbefore ucbinclude -I/usr/ucbinclude}"
#undef LIB_SPEC
#define LIB_SPEC \
diff --git a/gcc/config/i386/sun386.h b/gcc/config/i386/sun386.h
index 67349e19ac1..b28f20fd01a 100644
--- a/gcc/config/i386/sun386.h
+++ b/gcc/config/i386/sun386.h
@@ -34,9 +34,8 @@ Boston, MA 02111-1307, USA. */
/* Assembler pseudos to introduce constants of various size. */
#define ASM_BYTE_OP "\t.byte\t"
-#define ASM_SHORT "\t.value"
-#define ASM_LONG "\t.long"
-#define ASM_DOUBLE "\t.double"
+#define ASM_SHORT "\t.value\t"
+#define ASM_LONG "\t.long\t"
/* How to output an ASCII string constant. */
diff --git a/gcc/config/i386/svr3gas.h b/gcc/config/i386/svr3gas.h
index e5bf3db5b4b..db4be5da68f 100644
--- a/gcc/config/i386/svr3gas.h
+++ b/gcc/config/i386/svr3gas.h
@@ -220,8 +220,8 @@ dtors_section () \
global destructors. */
#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \
do { \
- fini_section (); \
- fprintf (FILE, "%s\t ", ASM_LONG); \
+ fini_section (); \
+ fputs (ASM_LONG, FILE); \
assemble_name (FILE, NAME); \
fprintf (FILE, "\n"); \
} while (0)
diff --git a/gcc/config/i386/sysv4.h b/gcc/config/i386/sysv4.h
index eb6c32c25b6..f56d58326c0 100644
--- a/gcc/config/i386/sysv4.h
+++ b/gcc/config/i386/sysv4.h
@@ -51,9 +51,9 @@ Boston, MA 02111-1307, USA. */
do { long value; \
REAL_VALUE_TO_TARGET_SINGLE ((VALUE), value); \
if (sizeof (int) == sizeof (long)) \
- fprintf((FILE), "%s\t0x%x\n", ASM_LONG, value); \
+ fprintf((FILE), "%s0x%x\n", ASM_LONG, value); \
else \
- fprintf((FILE), "%s\t0x%lx\n", ASM_LONG, value); \
+ fprintf((FILE), "%s0x%lx\n", ASM_LONG, value); \
} while (0)
/* This is how to output assembly code to define a `double' constant.
@@ -67,13 +67,13 @@ do { long value[2]; \
REAL_VALUE_TO_TARGET_DOUBLE ((VALUE), value); \
if (sizeof (int) == sizeof (long)) \
{ \
- fprintf((FILE), "%s\t0x%x\n", ASM_LONG, value[0]); \
- fprintf((FILE), "%s\t0x%x\n", ASM_LONG, value[1]); \
+ fprintf((FILE), "%s0x%x\n", ASM_LONG, value[0]); \
+ fprintf((FILE), "%s0x%x\n", ASM_LONG, value[1]); \
} \
else \
{ \
- fprintf((FILE), "%s\t0x%lx\n", ASM_LONG, value[0]); \
- fprintf((FILE), "%s\t0x%lx\n", ASM_LONG, value[1]); \
+ fprintf((FILE), "%s0x%lx\n", ASM_LONG, value[0]); \
+ fprintf((FILE), "%s0x%lx\n", ASM_LONG, value[1]); \
} \
} while (0)
@@ -84,15 +84,15 @@ do { long value[3]; \
REAL_VALUE_TO_TARGET_LONG_DOUBLE ((VALUE), value); \
if (sizeof (int) == sizeof (long)) \
{ \
- fprintf((FILE), "%s\t0x%x\n", ASM_LONG, value[0]); \
- fprintf((FILE), "%s\t0x%x\n", ASM_LONG, value[1]); \
- fprintf((FILE), "%s\t0x%x\n", ASM_LONG, value[2]); \
+ fprintf((FILE), "%s0x%x\n", ASM_LONG, value[0]); \
+ fprintf((FILE), "%s0x%x\n", ASM_LONG, value[1]); \
+ fprintf((FILE), "%s0x%x\n", ASM_LONG, value[2]); \
} \
else \
{ \
- fprintf((FILE), "%s\t0x%lx\n", ASM_LONG, value[0]); \
- fprintf((FILE), "%s\t0x%lx\n", ASM_LONG, value[1]); \
- fprintf((FILE), "%s\t0x%lx\n", ASM_LONG, value[2]); \
+ fprintf((FILE), "%s0x%lx\n", ASM_LONG, value[0]); \
+ fprintf((FILE), "%s0x%lx\n", ASM_LONG, value[1]); \
+ fprintf((FILE), "%s0x%lx\n", ASM_LONG, value[2]); \
} \
} while (0)
@@ -179,3 +179,36 @@ do { long value[3]; \
#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \
asm_output_aligned_bss (FILE, DECL, NAME, SIZE, ALIGN)
+
+/* Handle special EH pointer encodings. Absolute, pc-relative, and
+ indirect are handled automatically. */
+#define ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX(FILE, ENCODING, SIZE, ADDR, DONE) \
+ do { \
+ if ((SIZE) == 4 && ((ENCODING) & 0x70) == DW_EH_PE_datarel) \
+ { \
+ fputs (UNALIGNED_INT_ASM_OP, FILE); \
+ assemble_name (FILE, XSTR (ADDR, 0)); \
+ fputs (((ENCODING) & DW_EH_PE_indirect ? "@GOT" : "@GOTOFF"), FILE); \
+ goto DONE; \
+ } \
+ } while (0)
+
+/* Used by crtstuff.c to initialize the base of data-relative relocations.
+ These are GOT relative on x86, so return the pic register. */
+#ifdef __PIC__
+#define CRT_GET_RFIB_DATA(BASE) \
+ { \
+ register void *ebx_ __asm__("ebx"); \
+ BASE = ebx_; \
+ }
+#else
+#define CRT_GET_RFIB_DATA(BASE) \
+ __asm__ ("call\t.LPR%=\n" \
+ ".LPR%=:\n\t" \
+ "popl\t%0\n\t" \
+ /* Due to a GAS bug, this cannot use EAX. That encodes \
+ smaller than the traditional EBX, which results in the \
+ offset being off by one. */ \
+ "addl\t$_GLOBAL_OFFSET_TABLE_+[.-.LPR%=],%0" \
+ : "=d"(BASE))
+#endif
diff --git a/gcc/config/i386/t-beos b/gcc/config/i386/t-beos
index e8e8e50682f..f63e2d4e1b5 100644
--- a/gcc/config/i386/t-beos
+++ b/gcc/config/i386/t-beos
@@ -6,6 +6,3 @@ CROSS_LIBGCC1 =
# we are most likely to want to apply any fixes to.
SYSTEM_HEADER_DIR = /boot/develop/headers/posix
CROSS_SYSTEM_HEADER_DIR = $(tooldir)/sys-include/posix
-
-# Use the system assert.h
-INSTALL_ASSERT_H =
diff --git a/gcc/config/i386/t-cygwin b/gcc/config/i386/t-cygwin
index 1909f154308..fc009b85437 100644
--- a/gcc/config/i386/t-cygwin
+++ b/gcc/config/i386/t-cygwin
@@ -16,5 +16,5 @@ LIBGCC2_INCLUDES = -I$(srcdir)/../winsup/include \
-I$(srcdir)/../winsup/cygwin/include \
-I$(srcdir)/../winsup/w32api/include
-winnt.o: $(srcdir)/config/i386/winnt.c $(RTL_H) $(TREE_H)
+winnt.o: $(srcdir)/config/i386/winnt.c $(RTL_H) $(TREE_H) $(CONFIG_H)
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/i386/winnt.c
diff --git a/gcc/config/i386/t-interix b/gcc/config/i386/t-interix
index 4c6d84f1b39..c5fe1720bae 100644
--- a/gcc/config/i386/t-interix
+++ b/gcc/config/i386/t-interix
@@ -11,6 +11,3 @@ interix.o: $(srcdir)/config/i386/interix.c
# System headers will track gcc's needs.
# Even LANG_EXTRA_HEADERS may be temporary.
USER_H=$(LANG_EXTRA_HEADERS)
-
-# We don't want this one either.
-INSTALL_ASSERT_H=
diff --git a/gcc/config/i386/t-openbsd b/gcc/config/i386/t-openbsd
new file mode 100644
index 00000000000..18304634000
--- /dev/null
+++ b/gcc/config/i386/t-openbsd
@@ -0,0 +1,6 @@
+# gdb gets confused if pic code is linked with non pic
+# We cope by building variants of libgcc.
+MULTILIB_OPTIONS = fpic
+MULTILIB_MATCHES=fpic=fPIC
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
diff --git a/gcc/config/i386/vsta.h b/gcc/config/i386/vsta.h
index 6a41b4e1cf8..e9479ef103a 100644
--- a/gcc/config/i386/vsta.h
+++ b/gcc/config/i386/vsta.h
@@ -61,7 +61,7 @@ dtor_section () \
#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \
do { \
ctor_section (); \
- fprintf (FILE, "%s\t", ASM_LONG); \
+ fputs (ASM_LONG, FILE); \
assemble_name (FILE, NAME); \
fprintf (FILE, "\n"); \
} while (0)
@@ -69,7 +69,7 @@ dtor_section () \
#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \
do { \
dtor_section (); \
- fprintf (FILE, "%s\t", ASM_LONG); \
+ fputs (ASM_LONG, FILE); \
assemble_name (FILE, NAME); \
fprintf (FILE, "\n"); \
} while (0)
diff --git a/gcc/config/i386/win-nt.h b/gcc/config/i386/win-nt.h
index ce1e5bfb2be..aff89290f35 100644
--- a/gcc/config/i386/win-nt.h
+++ b/gcc/config/i386/win-nt.h
@@ -75,7 +75,7 @@ dtor_section () \
#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \
do { \
ctor_section (); \
- fprintf (FILE, "%s\t", ASM_LONG); \
+ fputs (ASM_LONG, FILE); \
assemble_name (FILE, NAME); \
fprintf (FILE, "\n"); \
} while (0)
@@ -83,7 +83,7 @@ dtor_section () \
#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \
do { \
dtor_section (); \
- fprintf (FILE, "%s\t", ASM_LONG); \
+ fputs (ASM_LONG, FILE); \
assemble_name (FILE, NAME); \
fprintf (FILE, "\n"); \
} while (0)
diff --git a/gcc/config/i386/win32.h b/gcc/config/i386/win32.h
index 519a1380cf7..2427bbd9d71 100644
--- a/gcc/config/i386/win32.h
+++ b/gcc/config/i386/win32.h
@@ -136,7 +136,7 @@ dtor_section () \
#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \
do { \
ctor_section (); \
- fprintf (FILE, "%s\t", ASM_LONG); \
+ fputs (ASM_LONG, FILE); \
assemble_name (FILE, NAME); \
fprintf (FILE, "\n"); \
} while (0)
@@ -144,7 +144,7 @@ dtor_section () \
#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \
do { \
dtor_section (); \
- fprintf (FILE, "%s\t", ASM_LONG); \
+ fputs (ASM_LONG, FILE); \
assemble_name (FILE, NAME); \
fprintf (FILE, "\n"); \
} while (0)
diff --git a/gcc/config/i386/winnt.c b/gcc/config/i386/winnt.c
index ae6b6253a8b..39074cc1c6c 100644
--- a/gcc/config/i386/winnt.c
+++ b/gcc/config/i386/winnt.c
@@ -27,6 +27,8 @@ Boston, MA 02111-1307, USA. */
#include "output.h"
#include "tree.h"
#include "flags.h"
+#include "tm_p.h"
+#include "toplev.h"
/* i386/PE specific attribute support.
@@ -39,6 +41,13 @@ Boston, MA 02111-1307, USA. */
multiple times.
*/
+static tree associated_type PARAMS ((tree));
+const char * gen_stdcall_suffix PARAMS ((tree));
+int i386_pe_dllexport_p PARAMS ((tree));
+int i386_pe_dllimport_p PARAMS ((tree));
+void i386_pe_mark_dllexport PARAMS ((tree));
+void i386_pe_mark_dllimport PARAMS ((tree));
+
/* Return nonzero if ATTR is a valid attribute for DECL.
ATTRIBUTES are any existing attributes and ARGS are the arguments
supplied with ATTR. */
@@ -226,7 +235,7 @@ i386_pe_dllimport_p (decl)
int
i386_pe_dllexport_name_p (symbol)
- char *symbol;
+ const char *symbol;
{
return symbol[0] == '@' && symbol[1] == 'e' && symbol[2] == '.';
}
@@ -235,7 +244,7 @@ i386_pe_dllexport_name_p (symbol)
int
i386_pe_dllimport_name_p (symbol)
- char *symbol;
+ const char *symbol;
{
return symbol[0] == '@' && symbol[1] == 'i' && symbol[2] == '.';
}
@@ -247,7 +256,8 @@ void
i386_pe_mark_dllexport (decl)
tree decl;
{
- char *oldname, *newname;
+ const char *oldname;
+ char *newname;
rtx rtlname;
tree idp;
@@ -283,7 +293,8 @@ void
i386_pe_mark_dllimport (decl)
tree decl;
{
- char *oldname, *newname;
+ const char *oldname;
+ char *newname;
tree idp;
rtx rtlname, newrtl;
@@ -370,14 +381,14 @@ i386_pe_mark_dllimport (decl)
suffix consisting of an atsign (@) followed by the number of bytes of
arguments */
-char *
+const char *
gen_stdcall_suffix (decl)
tree decl;
{
int total = 0;
/* ??? This probably should use XSTR (XEXP (DECL_RTL (decl), 0), 0) instead
of DECL_ASSEMBLER_NAME. */
- char *asmname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+ const char *asmname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
char *newsym;
if (TYPE_ARG_TYPES (TREE_TYPE (decl)))
@@ -444,7 +455,7 @@ i386_pe_encode_section_info (decl)
&& GET_CODE (XEXP (XEXP (DECL_RTL (decl), 0), 0)) == SYMBOL_REF
&& i386_pe_dllimport_name_p (XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0)))
{
- char *oldname = XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0);
+ const char *oldname = XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0);
tree idp = get_identifier (oldname + 9);
rtx newrtl = gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (idp));
@@ -465,8 +476,8 @@ i386_pe_unique_section (decl, reloc)
int reloc;
{
int len;
- const char *name;
- char *string,*prefix;
+ const char *name, *prefix;
+ char *string;
name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
/* Strip off any encoding in fnname. */
@@ -513,7 +524,7 @@ i386_pe_unique_section (decl, reloc)
void
i386_pe_declare_function_type (file, name, public)
FILE *file;
- char *name;
+ const char *name;
int public;
{
fprintf (file, "\t.def\t");
@@ -528,7 +539,7 @@ i386_pe_declare_function_type (file, name, public)
struct extern_list
{
struct extern_list *next;
- char *name;
+ const char *name;
};
static struct extern_list *extern_head;
@@ -541,7 +552,7 @@ static struct extern_list *extern_head;
void
i386_pe_record_external_function (name)
- char *name;
+ const char *name;
{
struct extern_list *p;
@@ -556,7 +567,7 @@ i386_pe_record_external_function (name)
struct export_list
{
struct export_list *next;
- char *name;
+ const char *name;
int is_data; /* used to type tag exported symbols. */
};
@@ -570,7 +581,7 @@ static struct export_list *export_head;
void
i386_pe_record_exported_symbol (name, is_data)
- char *name;
+ const char *name;
int is_data;
{
struct export_list *p;
diff --git a/gcc/config/i386/xm-aix.h b/gcc/config/i386/xm-aix.h
index 4cbd36ef518..e69de29bb2d 100644
--- a/gcc/config/i386/xm-aix.h
+++ b/gcc/config/i386/xm-aix.h
@@ -1,2 +0,0 @@
-#undef TRUE
-#undef FALSE
diff --git a/gcc/config/i386/xm-cygwin.h b/gcc/config/i386/xm-cygwin.h
index e7755bb54a4..7dd1f187598 100644
--- a/gcc/config/i386/xm-cygwin.h
+++ b/gcc/config/i386/xm-cygwin.h
@@ -1,6 +1,6 @@
/* Configuration for GNU C-compiler for hosting on Windows NT.
using a unix style C library.
- Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -31,30 +31,9 @@ Boston, MA 02111-1307, USA. */
backslashes as escape characters. Many Win32 programs use forward
slashes so using a forward slash shouldn't be problematic from the
perspective of wanting gcc to produce native Win32 paths. */
-#define DIR_SEPARATOR '/'
+#undef DIR_SEPARATOR_2
#define DIR_SEPARATOR_2 '\\'
-/* Convert win32 style path lists to POSIX style for consistency. */
-#undef GET_ENV_PATH_LIST
-#define GET_ENV_PATH_LIST(VAR,NAME) \
-do { \
- char *_epath; \
- char *_posixepath; \
- _epath = _posixepath = getenv (NAME); \
- /* if we have a posix path list, convert to posix path list */ \
- if (_epath != NULL && *_epath != 0 \
- && ! cygwin_posix_path_list_p (_epath)) \
- { \
- char *p; \
- _posixepath = (char *) xmalloc \
- (cygwin_win32_to_posix_path_list_buf_size (_epath)); \
- cygwin_win32_to_posix_path_list (_epath, _posixepath); \
- } \
- (VAR) = _posixepath; \
-} while (0)
-
-#define PATH_SEPARATOR ':'
-
/* This is needed so that protoize will compile. */
#ifndef POSIX
#define POSIX
diff --git a/gcc/config/i386/xm-i386.h b/gcc/config/i386/xm-i386.h
index d115e6eff0d..81e13f0b24e 100644
--- a/gcc/config/i386/xm-i386.h
+++ b/gcc/config/i386/xm-i386.h
@@ -22,10 +22,6 @@ Boston, MA 02111-1307, USA. */
#define __i386__ 1
#endif
-/* #defines that need visibility everywhere. */
-#define FALSE 0
-#define TRUE 1
-
/* This describes the machine the compiler is hosted on. */
#define HOST_BITS_PER_CHAR 8
#define HOST_BITS_PER_SHORT 16
diff --git a/gcc/config/i386/xm-osf.h b/gcc/config/i386/xm-osf.h
index 4cbd36ef518..e69de29bb2d 100644
--- a/gcc/config/i386/xm-osf.h
+++ b/gcc/config/i386/xm-osf.h
@@ -1,2 +0,0 @@
-#undef TRUE
-#undef FALSE
diff --git a/gcc/config/i860/i860.c b/gcc/config/i860/i860.c
index 912e4e62e4f..7cc9d51e22e 100644
--- a/gcc/config/i860/i860.c
+++ b/gcc/config/i860/i860.c
@@ -36,7 +36,6 @@ Boston, MA 02111-1307, USA. */
#include "real.h"
#include "insn-config.h"
#include "conditions.h"
-#include "insn-flags.h"
#include "output.h"
#include "recog.h"
#include "insn-attr.h"
diff --git a/gcc/config/i860/varargs.asm b/gcc/config/i860/varargs.asm
new file mode 100644
index 00000000000..8f870063c41
--- /dev/null
+++ b/gcc/config/i860/varargs.asm
@@ -0,0 +1,201 @@
+/* Special varargs support for i860.
+ Copyright (C) 2001 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+In addition to the permissions in the GNU General Public License, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file into combinations with other programs,
+and to distribute those combinations without any restriction coming
+from the use of this file. (The General Public License restrictions
+do apply in other respects; for example, they cover modification of
+the file, and distribution when not linked into a combine
+executable.)
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#if defined(__svr4__) || defined(__alliant__)
+ .text
+ .align 4
+
+/* The Alliant needs the added underscore. */
+ .globl __builtin_saveregs
+__builtin_saveregs:
+ .globl ___builtin_saveregs
+___builtin_saveregs:
+
+ andnot 0x0f,%sp,%sp /* round down to 16-byte boundary */
+ adds -96,%sp,%sp /* allocate stack space for reg save
+ area and also for a new va_list
+ structure */
+ /* Save all argument registers in the arg reg save area. The
+ arg reg save area must have the following layout (according
+ to the svr4 ABI):
+
+ struct {
+ union {
+ float freg[8];
+ double dreg[4];
+ } float_regs;
+ long ireg[12];
+ };
+ */
+
+ fst.q %f8, 0(%sp) /* save floating regs (f8-f15) */
+ fst.q %f12,16(%sp)
+
+ st.l %r16,32(%sp) /* save integer regs (r16-r27) */
+ st.l %r17,36(%sp)
+ st.l %r18,40(%sp)
+ st.l %r19,44(%sp)
+ st.l %r20,48(%sp)
+ st.l %r21,52(%sp)
+ st.l %r22,56(%sp)
+ st.l %r23,60(%sp)
+ st.l %r24,64(%sp)
+ st.l %r25,68(%sp)
+ st.l %r26,72(%sp)
+ st.l %r27,76(%sp)
+
+ adds 80,%sp,%r16 /* compute the address of the new
+ va_list structure. Put in into
+ r16 so that it will be returned
+ to the caller. */
+
+ /* Initialize all fields of the new va_list structure. This
+ structure looks like:
+
+ typedef struct {
+ unsigned long ireg_used;
+ unsigned long freg_used;
+ long *reg_base;
+ long *mem_ptr;
+ } va_list;
+ */
+
+ st.l %r0, 0(%r16) /* nfixed */
+ st.l %r0, 4(%r16) /* nfloating */
+ st.l %sp, 8(%r16) /* __va_ctl points to __va_struct. */
+ bri %r1 /* delayed return */
+ st.l %r28,12(%r16) /* pointer to overflow args */
+
+#else /* not __svr4__ */
+#if defined(__PARAGON__)
+ /*
+ * we'll use SVR4-ish varargs but need SVR3.2 assembler syntax,
+ * and we stand a better chance of hooking into libraries
+ * compiled by PGI. [andyp@ssd.intel.com]
+ */
+ .text
+ .align 4
+ .globl __builtin_saveregs
+__builtin_saveregs:
+ .globl ___builtin_saveregs
+___builtin_saveregs:
+
+ andnot 0x0f,sp,sp /* round down to 16-byte boundary */
+ adds -96,sp,sp /* allocate stack space for reg save
+ area and also for a new va_list
+ structure */
+ /* Save all argument registers in the arg reg save area. The
+ arg reg save area must have the following layout (according
+ to the svr4 ABI):
+
+ struct {
+ union {
+ float freg[8];
+ double dreg[4];
+ } float_regs;
+ long ireg[12];
+ };
+ */
+
+ fst.q f8, 0(sp)
+ fst.q f12,16(sp)
+ st.l r16,32(sp)
+ st.l r17,36(sp)
+ st.l r18,40(sp)
+ st.l r19,44(sp)
+ st.l r20,48(sp)
+ st.l r21,52(sp)
+ st.l r22,56(sp)
+ st.l r23,60(sp)
+ st.l r24,64(sp)
+ st.l r25,68(sp)
+ st.l r26,72(sp)
+ st.l r27,76(sp)
+
+ adds 80,sp,r16 /* compute the address of the new
+ va_list structure. Put in into
+ r16 so that it will be returned
+ to the caller. */
+
+ /* Initialize all fields of the new va_list structure. This
+ structure looks like:
+
+ typedef struct {
+ unsigned long ireg_used;
+ unsigned long freg_used;
+ long *reg_base;
+ long *mem_ptr;
+ } va_list;
+ */
+
+ st.l r0, 0(r16) /* nfixed */
+ st.l r0, 4(r16) /* nfloating */
+ st.l sp, 8(r16) /* __va_ctl points to __va_struct. */
+ bri r1 /* delayed return */
+ st.l r28,12(r16) /* pointer to overflow args */
+#else /* not __PARAGON__ */
+ .text
+ .align 4
+
+ .globl ___builtin_saveregs
+___builtin_saveregs:
+ mov sp,r30
+ andnot 0x0f,sp,sp
+ adds -96,sp,sp /* allocate sufficient space on the stack */
+
+/* Fill in the __va_struct. */
+ st.l r16, 0(sp) /* save integer regs (r16-r27) */
+ st.l r17, 4(sp) /* int fixed[12] */
+ st.l r18, 8(sp)
+ st.l r19,12(sp)
+ st.l r20,16(sp)
+ st.l r21,20(sp)
+ st.l r22,24(sp)
+ st.l r23,28(sp)
+ st.l r24,32(sp)
+ st.l r25,36(sp)
+ st.l r26,40(sp)
+ st.l r27,44(sp)
+
+ fst.q f8, 48(sp) /* save floating regs (f8-f15) */
+ fst.q f12,64(sp) /* int floating[8] */
+
+/* Fill in the __va_ctl. */
+ st.l sp, 80(sp) /* __va_ctl points to __va_struct. */
+ st.l r28,84(sp) /* pointer to more args */
+ st.l r0, 88(sp) /* nfixed */
+ st.l r0, 92(sp) /* nfloating */
+
+ adds 80,sp,r16 /* return address of the __va_ctl. */
+ bri r1
+ mov r30,sp
+ /* recover stack and pass address to start
+ of data. */
+#endif /* not __PARAGON__ */
+#endif /* not __svr4__ */
diff --git a/gcc/config/i860/xm-i860.h b/gcc/config/i860/xm-i860.h
index 4e8488f1f10..b833c47c7a3 100644
--- a/gcc/config/i860/xm-i860.h
+++ b/gcc/config/i860/xm-i860.h
@@ -22,10 +22,6 @@ Boston, MA 02111-1307, USA. */
#define i860
#endif
-/* #defines that need visibility everywhere. */
-#define FALSE 0
-#define TRUE 1
-
/* This describes the machine the compiler is hosted on. */
#define HOST_BITS_PER_CHAR 8
#define HOST_BITS_PER_SHORT 16
diff --git a/gcc/config/i960/i960.c b/gcc/config/i960/i960.c
index 21753a207b2..47b2b1de026 100644
--- a/gcc/config/i960/i960.c
+++ b/gcc/config/i960/i960.c
@@ -31,12 +31,10 @@ Boston, MA 02111-1307, USA. */
#include "real.h"
#include "insn-config.h"
#include "conditions.h"
-#include "insn-flags.h"
#include "output.h"
#include "insn-attr.h"
#include "flags.h"
#include "tree.h"
-#include "insn-codes.h"
#include "expr.h"
#include "except.h"
#include "function.h"
@@ -291,7 +289,7 @@ fp_arith_operand (op, mode)
return (register_operand (op, mode) || fp_literal (op, mode));
}
-/* Return true is OP is a register or a valid signed integer literal. */
+/* Return true if OP is a register or a valid signed integer literal. */
int
signed_arith_operand (op, mode)
diff --git a/gcc/config/i960/i960.h b/gcc/config/i960/i960.h
index 510793b307f..484bb81d6bd 100644
--- a/gcc/config/i960/i960.h
+++ b/gcc/config/i960/i960.h
@@ -39,6 +39,7 @@ Boston, MA 02111-1307, USA. */
%{mmc:-D__i960MC}\
%{mca:-D__i960CA}%{mcc:-D__i960CC}\
%{mcf:-D__i960CF}}\
+ %{msoft-float:-D_SOFT_FLOAT}\
%{mka:-D__i960KA__ -D__i960_KA__}\
%{mkb:-D__i960KB__ -D__i960_KB__}\
%{msa:-D__i960SA__ -D__i960_SA__}\
diff --git a/gcc/config/i960/xm-i960.h b/gcc/config/i960/xm-i960.h
index 09dcadff460..693661d6af0 100644
--- a/gcc/config/i960/xm-i960.h
+++ b/gcc/config/i960/xm-i960.h
@@ -18,10 +18,6 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* #defines that need visibility everywhere. */
-#define FALSE 0
-#define TRUE 1
-
/* This describes the machine the compiler is hosted on. */
#define HOST_BITS_PER_CHAR 8
#define HOST_BITS_PER_SHORT 16
diff --git a/gcc/config/ia64/crtbegin.asm b/gcc/config/ia64/crtbegin.asm
index 1b57a99316c..ac2f86bcc87 100644
--- a/gcc/config/ia64/crtbegin.asm
+++ b/gcc/config/ia64/crtbegin.asm
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 Free Software Foundation, Inc.
+/* Copyright (C) 2000, 2001 Free Software Foundation, Inc.
Contributed by Jes Sorensen, <Jes.Sorensen@cern.ch>
The GNU C Library is free software; you can redistribute it and/or
@@ -32,14 +32,6 @@ __DTOR_LIST__:
dtor_ptr:
data8 __DTOR_LIST__# + 8
-#ifndef SHARED
- .type __ia64_app_header#,@object
- .size __ia64_app_header#,8
- .global __ia64_app_header
-__ia64_app_header:
- data8 @segrel(.Lsegrel_ref#)
-#endif
-
/* A handle for __cxa_finalize to manage c++ local destructors. */
.global __dso_handle#
.type __dso_handle#,@object
@@ -71,42 +63,19 @@ __dso_handle:
*/
.section .fini,"ax","progbits"
{ .mlx
- movl r2 = @gprel(__do_global_dtors_aux#)
- ;;
+ movl r2 = @pcrel(__do_global_dtors_aux# - 16)
}
{ .mii
- nop.m 0
- add r2 = r2, gp
- ;;
- mov b6 = r2
- }
- { .bbb
- br.call.sptk.many b0 = b6
+ mov r3 = ip
;;
- }
-
-#ifndef SHARED
-/*
- * Fragment of the ELF _init routine that sets up __ia64_app_header
- */
-
-.section .init,"ax","progbits"
-.Lsegrel_ref:
- { .mmi
- addl r2 = @gprel(__ia64_app_header), gp
- mov r16 = ip
+ add r2 = r2, r3
;;
}
- { .mmi
- ld8 r3 = [r2]
- ;;
- sub r16 = r16, r3
+ { .mib
+ mov b6 = r2
+ br.call.sptk.many b0 = b6
;;
}
- { .mfb
- st8 [r2] = r16
- }
-#endif
.section .text
.align 16
diff --git a/gcc/config/ia64/crtend.asm b/gcc/config/ia64/crtend.asm
index 81f90198fb6..3a097d7622f 100644
--- a/gcc/config/ia64/crtend.asm
+++ b/gcc/config/ia64/crtend.asm
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 Free Software Foundation, Inc.
+/* Copyright (C) 2000, 2001 Free Software Foundation, Inc.
Contributed by Jes Sorensen, <Jes.Sorensen@cern.ch>
The GNU C Library is free software; you can redistribute it and/or
@@ -41,16 +41,16 @@ __DTOR_END__:
*/
.section .init,"ax","progbits"
{ .mlx
- movl r2 = @gprel(__do_global_ctors_aux#)
- ;;
+ movl r2 = @pcrel(__do_global_ctors_aux# - 16)
}
{ .mii
- nop.m 0
- add r2 = r2, gp
+ mov r3 = ip
+ ;;
+ add r2 = r2, r3
;;
- mov b6 = r2
}
- { .bbb
+ { .mib
+ mov b6 = r2
br.call.sptk.many b0 = b6
;;
}
diff --git a/gcc/config/ia64/fde-glibc.c b/gcc/config/ia64/fde-glibc.c
index 8000be2f0a5..c663f584458 100644
--- a/gcc/config/ia64/fde-glibc.c
+++ b/gcc/config/ia64/fde-glibc.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 Free Software Foundation, Inc.
+/* Copyright (C) 2000, 2001 Free Software Foundation, Inc.
Contributed by Richard Henderson <rth@cygnus.com>.
This file is part of GNU CC.
@@ -28,125 +28,135 @@
/* Locate the FDE entry for a given address, using glibc ld.so routines
to avoid register/deregister calls at DSO load/unload. */
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#include "config.h"
+#include <stddef.h>
#include <stdlib.h>
#include <link.h>
-#include <bits/libc-lock.h>
-#include "frame-ia64.h"
+#include "unwind-ia64.h"
+#if __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 2) \
+ || (__GLIBC__ == 2 && __GLIBC_MINOR__ == 2 && !defined(DT_CONFIG))
+# error You need GLIBC 2.2.4 or later on IA-64 Linux
+#endif
-/* Initialized by crtbegin from the main application. */
-extern Elf64_Ehdr *__ia64_app_header;
-
-/* ??? A redeclaration of the lock in ld.so. Perhaps this should
- appear in <link.h> in a new glibc version. */
-__libc_lock_define (extern, _dl_load_lock)
-
-/* ??? _dl_load_lock is not exported from glibc 2.1, but it is
- from glibc 2.2. Remove this when folks have migrated. */
-#pragma weak _dl_load_lock
-
-/* This always exists, even in a static application. */
-extern struct link_map *_dl_loaded;
-
-static fde *
-find_fde_for_dso (Elf64_Addr pc, Elf64_Ehdr *ehdr)
+struct unw_ia64_callback_data
+{
+ Elf64_Addr pc;
+ unsigned long *segment_base;
+ unsigned long *gp;
+ struct unw_table_entry *ret;
+};
+
+static int
+_Unwind_IteratePhdrCallback (struct dl_phdr_info *info, size_t size, void *ptr)
{
- Elf64_Phdr *phdr, *p_unwind;
+ struct unw_ia64_callback_data *data = (struct unw_ia64_callback_data *) ptr;
+ const Elf64_Phdr *phdr, *p_unwind, *p_dynamic;
long n, match;
Elf64_Addr load_base, seg_base;
- fde *f_base;
+ struct unw_table_entry *f_base, *f;
size_t lo, hi;
- /* Verify that we are looking at an ELF header. */
- if (ehdr->e_ident[0] != 0x7f
- || ehdr->e_ident[1] != 'E'
- || ehdr->e_ident[2] != 'L'
- || ehdr->e_ident[3] != 'F'
- || ehdr->e_ident[EI_CLASS] != ELFCLASS64
- || ehdr->e_ident[EI_DATA] != ELFDATA2LSB
- || ehdr->e_machine != EM_IA_64)
- abort ();
+ /* Make sure struct dl_phdr_info is at least as big as we need. */
+ if (size < offsetof (struct dl_phdr_info, dlpi_phnum)
+ + sizeof (info->dlpi_phnum))
+ return -1;
match = 0;
- phdr = (Elf64_Phdr *)((char *)ehdr + ehdr->e_phoff);
- load_base = (ehdr->e_type == ET_DYN ? (Elf64_Addr)ehdr : 0);
+ phdr = info->dlpi_phdr;
+ load_base = info->dlpi_addr;
p_unwind = NULL;
+ p_dynamic = NULL;
+ seg_base = ~(Elf64_Addr) 0;
/* See if PC falls into one of the loaded segments. Find the unwind
segment at the same time. */
- for (n = ehdr->e_phnum; --n >= 0; phdr++)
+ for (n = info->dlpi_phnum; --n >= 0; phdr++)
{
if (phdr->p_type == PT_LOAD)
{
Elf64_Addr vaddr = phdr->p_vaddr + load_base;
- if (pc >= vaddr && pc < vaddr + phdr->p_memsz)
+ if (data->pc >= vaddr && data->pc < vaddr + phdr->p_memsz)
match = 1;
+ if (vaddr < seg_base)
+ seg_base = vaddr;
}
else if (phdr->p_type == PT_IA_64_UNWIND)
p_unwind = phdr;
+ else if (phdr->p_type == PT_DYNAMIC)
+ p_dynamic = phdr;
}
if (!match || !p_unwind)
- return NULL;
+ return 0;
/* Search for the FDE within the unwind segment. */
- f_base = (fde *) (p_unwind->p_vaddr + load_base);
- seg_base = (Elf64_Addr) ehdr;
+ f_base = (struct unw_table_entry *) (p_unwind->p_vaddr + load_base);
lo = 0;
- hi = p_unwind->p_memsz / sizeof (fde);
+ hi = p_unwind->p_memsz / sizeof (struct unw_table_entry);
while (lo < hi)
{
size_t mid = (lo + hi) / 2;
- fde *f = f_base + mid;
- if (pc < f->start_offset + seg_base)
+ f = f_base + mid;
+ if (data->pc < f->start_offset + seg_base)
hi = mid;
- else if (pc >= f->end_offset + seg_base)
+ else if (data->pc >= f->end_offset + seg_base)
lo = mid + 1;
else
- return f;
+ goto found;
}
+ return 0;
- return NULL;
-}
-
-/* Return a pointer to the FDE for the function containing PC. */
-fde *
-__ia64_find_fde (void *pc, void **pc_base)
-{
- fde *ret;
- struct link_map *map;
+ found:
+ *data->segment_base = seg_base;
+ *data->gp = 0;
+ data->ret = f;
- /* Check the main application first, hoping that most of the user's
- code is there instead of in some library. */
- ret = find_fde_for_dso ((Elf64_Addr)pc, __ia64_app_header);
- if (ret)
+ if (p_dynamic)
{
- *pc_base = __ia64_app_header;
- return ret;
+ /* For dynamicly linked executables and shared libraries,
+ DT_PLTGOT is the gp value for that object. */
+ Elf64_Dyn *dyn = (Elf64_Dyn *)(p_dynamic->p_vaddr + load_base);
+ for (; dyn->d_tag != DT_NULL ; dyn++)
+ if (dyn->d_tag == DT_PLTGOT)
+ {
+ /* On IA-64, _DYNAMIC is writable and GLIBC has relocated it. */
+ *data->gp = dyn->d_un.d_ptr;
+ break;
+ }
+ }
+ else
+ {
+ /* Otherwise this is a static executable with no _DYNAMIC.
+ The gp is constant program-wide. */
+ register unsigned long gp __asm__("gp");
+ *data->gp = gp;
}
- /* Glibc is probably unique in that we can (with certain restrictions)
- dynamicly load libraries into staticly linked applications. Thus
- we _always_ check _dl_loaded. */
+ return 1;
+}
- if (&_dl_load_lock)
- __libc_lock_lock (_dl_load_lock);
+/* Return a pointer to the unwind table entry for the function
+ containing PC. */
- for (map = _dl_loaded; map ; map = map->l_next)
- {
- /* Skip the main application's entry. */
- if (map->l_name[0] == 0)
- continue;
- ret = find_fde_for_dso ((Elf64_Addr)pc, (Elf64_Ehdr *)map->l_addr);
- if (ret)
- break;
- }
+struct unw_table_entry *
+_Unwind_FindTableEntry (void *pc, unsigned long *segment_base,
+ unsigned long *gp)
+{
+ struct unw_ia64_callback_data data;
- if (&_dl_load_lock)
- __libc_lock_unlock (_dl_load_lock);
+ data.pc = (Elf64_Addr) pc;
+ data.segment_base = segment_base;
+ data.gp = gp;
+ data.ret = NULL;
+
+ if (dl_iterate_phdr (_Unwind_IteratePhdrCallback, &data) < 0)
+ return NULL;
- *pc_base = (void *)(map ? map->l_addr : 0);
- return ret;
+ return data.ret;
}
diff --git a/gcc/config/ia64/frame-ia64.c b/gcc/config/ia64/frame-ia64.c
deleted file mode 100644
index 4834a8b3cdf..00000000000
--- a/gcc/config/ia64/frame-ia64.c
+++ /dev/null
@@ -1,1272 +0,0 @@
-/* Subroutines needed for unwinding IA-64 standard format stack frame
- info for exception handling. */
-/* Compile this one with gcc. */
-/* Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
- Contributed by Andrew MacLeod <amacleod@cygnus.com>
- Andrew Haley <aph@cygnus.com>
-
-This file is part of GNU CC.
-
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* As a special exception, if you link this library with other files,
- some of which are compiled with GCC, to produce an executable,
- this library does not by itself cause the resulting executable
- to be covered by the GNU General Public License.
- This exception does not however invalidate any other reasons why
- the executable file might be covered by the GNU General Public License. */
-
-/* It is incorrect to include config.h here, because this file is being
- compiled for the target, and hence definitions concerning only the host
- do not apply. */
-
-#include "tconfig.h"
-
-/* We disable this when inhibit_libc, so that gcc can still be built without
- needing header files first. */
-/* ??? This is not a good solution, since prototypes may be required in
- some cases for correct code. See also libgcc2.c/crtstuff.c. */
-#ifndef inhibit_libc
-#include <stdlib.h>
-#include <unistd.h>
-#else
-#include <stddef.h>
-#endif
-
-#include "frame-ia64.h"
-#include "eh-common.h"
-
-/* Some types used by the DWARF 2 spec. */
-
-typedef int sword __attribute__ ((mode (SI)));
-typedef unsigned int uword __attribute__ ((mode (SI)));
-typedef unsigned int uaddr __attribute__ ((mode (pointer)));
-typedef int saddr __attribute__ ((mode (pointer)));
-typedef unsigned char ubyte;
-
-#include "frame.h"
-
-/* Decode the unsigned LEB128 constant at BUF and return it. The value at
- MEM is updated to reflect the next position in the buffer. */
-
-static unsigned long
-read_uleb128 (unsigned char **mem)
-{
- unsigned shift = 0;
- unsigned long result = 0;
- unsigned char *buf = *mem;
-
- while (1)
- {
- unsigned long byte = *buf++;
- result |= (byte & 0x7f) << shift;
- if ((byte & 0x80) == 0)
- break;
- shift += 7;
- }
- *mem = buf;
- return result;
-}
-
-
-static unsigned char *
-read_R_record (unwind_record *data, unsigned char val, unsigned char *ptr)
-{
- if ((val & 0x40) == 0)
- {
- /* R1 format. */
- if (val & 0x20)
- data->type = body;
- else
- data->type = prologue;
- data->record.r.rlen = (val & 0x1f);
- return ptr;
- }
-
- if ((val & 0xF8) == UNW_R2)
- {
- /* R2 format. */
- unsigned char mask = (val & 0x07) << 1;
- if (*ptr & 0x80)
- mask = mask | 1;
- data->type = prologue_gr;
- data->record.r.mask = mask;
- data->record.r.grsave = (*ptr++ & 0x7f);
- data->record.r.rlen = read_uleb128 (&ptr);
- return ptr;
- }
-
- if ((val & 0xFC) == UNW_R3)
- {
- /* R3 format. */
- val = (val & 0x03);
- if (val == 0)
- data->type = prologue;
- else
- if (val == 1)
- data->type = body;
- else
- abort ();
- data->record.r.rlen = read_uleb128 (&ptr);
- return ptr;
- }
- abort ();
-}
-
-static void
-process_a_b_reg_code(unwind_record *data, unsigned char val)
-{
- int code = (val & 0x60) >> 5;
- int reg = (val & 0x1f);
- switch (code)
- {
- case 0:
- data->record.x.reg = GR_REG (reg);
- break;
- case 1:
- data->record.x.reg = FR_REG (reg);
- break;
- case 2:
- data->record.x.reg = BR_REG (reg);
- break;
- case 3:
- /* TODO. We need to encode the specialty regs here. The table is
- on page B-9 of the runtime manual (under the X1 description.) */
- break;
- }
-}
-
-static unsigned char *
-read_X_record (unwind_record *data, unsigned char val, unsigned char *ptr)
-{
- unsigned long tmp;
- int byte1, byte2;
- switch (val)
- {
- case UNW_X1:
- byte1 = *ptr++;
- data->record.x.t = read_uleb128 (&ptr);
- tmp = read_uleb128 (&ptr);
- if ((byte1 & 0x80) == 0)
- {
- data->type = spill_psprel;
- data->record.x.pspoff = tmp;
- }
- else
- {
- data->type = spill_sprel;
- data->record.x.spoff = tmp;
- }
- process_a_b_reg_code (data, byte1);
- return ptr;
- case UNW_X4:
- byte1 = *ptr++;
- data->record.x.qp = PR_REG (byte1 & 0x3f);
- data->type = spill_reg_p;
- case UNW_X2:
- {
- int xy;
- int treg;
- /* Only set type if we didn't fall through the UNW_X4 case. */
- if (val == UNW_X2)
- data->type = spill_reg;
- byte1 = *ptr++;
- byte2 = *ptr++;
- process_a_b_reg_code (data, byte1);
- xy = (((byte1 >> 7) << 1 ) | (byte2 >> 7));
- treg = (byte2 & 0x7f);
- switch (xy)
- {
- case 0:
- data->record.x.treg = GR_REG (treg);
- break;
- case 1:
- data->record.x.treg = FR_REG (treg);
- break;
- case 2:
- data->record.x.treg = BR_REG (treg);
- break;
- case 3:
- abort ();
- }
- data->record.x.t = read_uleb128 (&ptr);
- }
- return ptr;
- case UNW_X3:
- byte1 = *ptr++;
- byte2 = *ptr++;
- data->record.x.qp = PR_REG (byte1 & 0x3f);
- process_a_b_reg_code (data, byte2);
- data->record.x.t = read_uleb128 (&ptr);
- tmp = read_uleb128 (&ptr);
- if ((byte1 & 0x80) == 0)
- {
- data->type = spill_psprel_p;
- data->record.x.pspoff = tmp;
- }
- else
- {
- data->type = spill_sprel_p;
- data->record.x.spoff = tmp;
- }
- return ptr;
- default:
- abort ();
- }
- return NULL;
-}
-
-static unsigned char *
-read_B_record (unwind_record *data, unsigned char val, unsigned char *ptr)
-{
- if ((val & 0xc0) == 0x80)
- {
- /* B1 format. */
- if ((val & 0x20) == 0)
- data->type = label_state;
- else
- data->type = copy_state;
- data->record.b.label = (val & 0x1f);
- return ptr;
- }
-
- if ((val & 0xe0) == 0xc0)
- {
- /* B2 format. */
- data->type = epilogue;
- data->record.b.ecount = (val & 0x1f);
- data->record.b.t = read_uleb128 (&ptr);
- return ptr;
- }
-
- if (val == UNW_B3)
- {
- /* B3 format. */
- data->type = epilogue;
- data->record.b.t = read_uleb128 (&ptr);
- data->record.b.ecount = read_uleb128 (&ptr);
- return ptr;
- }
-
- if (val == UNW_B4)
- {
- /* B4 format, with r == 0. */
- data->type = label_state;
- data->record.b.label = read_uleb128 (&ptr);
- return ptr;
- }
-
- if (val == (UNW_B4 | 0x08))
- {
- /* B4 format, with r == 1. */
- data->type = copy_state;
- data->record.b.label = read_uleb128 (&ptr);
- return ptr;
- }
- abort ();
-}
-
-/* This array is used to set the TYPE field for format P3. */
-static unw_record_type const P3_record_types[] = {
- psp_gr, rp_gr, pfs_gr, preds_gr, unat_gr, lc_gr, rp_br, rnat_gr,
- bsp_gr, bspstore_gr, fpsr_gr, priunat_gr
-};
-
-/* This array is used to set the TYPE field for format P7. */
-static unw_record_type const P7_record_types[] = {
- mem_stack_f, mem_stack_v, spill_base, psp_sprel, rp_when, rp_psprel,
- pfs_when, pfs_psprel, preds_when, preds_psprel, lc_when, lc_psprel,
- unat_when, unat_psprel, fpsr_when, fpsr_psprel
-};
-
-/* These values and the array are used to determine which additional ULEB128
- fields are required for the P7 format. */
-#define P7_T_SIZE 0
-#define P7_T 1
-#define P7_PSPOFF 2
-#define P7_SPOFF 3
-static unsigned char const P7_additional_fields [] = {
- P7_T_SIZE, P7_T, P7_PSPOFF, P7_SPOFF, P7_T, P7_PSPOFF,
- P7_T, P7_PSPOFF, P7_T, P7_PSPOFF, P7_T, P7_PSPOFF, P7_T, P7_PSPOFF
-};
-
-/* This array is used to set the TYPE field for format P8.
- Note that entry 0 is not used in this array, so it is filled with
- rp_spel for completely arbitrary reasons. */
-static unw_record_type const P8_record_types[] = {
- rp_sprel, rp_sprel, pfs_sprel, preds_sprel, lc_sprel, unat_sprel, fpsr_sprel,
- bsp_when, bsp_psprel, bsp_sprel, bspstore_when, bspstore_psprel,
- bspstore_sprel, rnat_when, rnat_psprel, rnat_sprel, priunat_when_gr,
- priunat_psprel, priunat_sprel, priunat_when_mem
-};
-
-/* These values and the array are used to determine which additional ULEB128
- fields are required for the P8 format. */
-#define P8_T 0
-#define P8_PSPOFF 1
-#define P8_SPOFF 2
-static unsigned char const P8_additional_fields [] = {
- P8_SPOFF, P8_SPOFF, P8_SPOFF, P8_SPOFF, P8_SPOFF, P8_SPOFF,
- P8_T, P8_PSPOFF, P8_SPOFF, P8_T, P8_PSPOFF, P8_SPOFF,
- P8_T, P8_PSPOFF, P8_SPOFF, P8_T, P8_PSPOFF, P8_SPOFF, P8_T
-};
-
-
-static unsigned char *
-read_P_record (unwind_record *data, unsigned char val, unsigned char *ptr,
- unwind_record *header)
-{
- if ((val & 0xe0) == 0x80)
- {
- /* P1 format. */
- data->type = br_mem;
- data->record.p.brmask = (val & 0x1f);
- return ptr;
- }
-
- if ((val & 0xf0) == 0xa0)
- {
- /* P2 format. */
- int byte1;
- data->type = br_gr;
- byte1 = *ptr++;
- data->record.p.brmask = ((val & 0x0f) << 1) + (byte1 >> 7);
- data->record.p.gr = GR_REG (byte1 & 0x7f);
- return ptr;
- }
-
- if ((val & 0xf8) == 0xB0)
- {
- /* P3 format. */
- int byte1 = *ptr++;
- int r = ((val & 0x07) << 1) + (byte1 >> 7);
- data->type = P3_record_types[r];
- if (r == 6)
- data->record.p.br = BR_REG (byte1 & 0x7f);
- else
- data->record.p.gr = GR_REG (byte1 & 0x7f);
- if (r > 11)
- abort ();
- return ptr;
- }
-
- if (val == UNW_P4)
- {
- /* P4 format. */
- int size = (header->record.r.rlen * 2 + 7) / 8;
-
- data->type = spill_mask;
- data->record.p.imask = ptr;
- return ptr+size;
- }
-
- if (val == UNW_P5)
- {
- /* P5 format. */
- int byte1 = *ptr++;
- int byte2 = *ptr++;
- int byte3 = *ptr++;
- data->type = frgr_mem;
- data->record.p.grmask = (byte1 >> 4);
- data->record.p.frmask = ((byte1 & 0x0f) << 16) | (byte2 << 8) | byte3;
- return ptr;
- }
-
- if ((val & 0xe0) == UNW_P6)
- {
- /* P6 format. */
- if ((val & 0x10) == 0)
- data->type = fr_mem;
- else
- data->type = gr_mem;
- data->record.p.rmask = (val & 0x0f);
- return ptr;
- }
-
- if ((val & 0xf0) == UNW_P7)
- {
- /* P7 format. */
- int r = (val & 0x0f);
- data->type = P7_record_types[r];
- switch (P7_additional_fields[r])
- {
- case P7_T_SIZE:
- data->record.p.t = read_uleb128 (&ptr);
- data->record.p.size = read_uleb128 (&ptr) << 4;
- break;
- case P7_T:
- data->record.p.t = read_uleb128 (&ptr);
- break;
- case P7_PSPOFF:
- data->record.p.pspoff = read_uleb128 (&ptr);
- break;
- case P7_SPOFF:
- data->record.p.spoff = read_uleb128 (&ptr);
- break;
- }
- return ptr;
- }
-
- if (val == UNW_P8)
- {
- /* P8 format. */
- int r = *ptr++;
- data->type = P8_record_types[r];
- switch (P8_additional_fields[r])
- {
- case P8_T:
- data->record.p.t = read_uleb128 (&ptr);
- break;
- case P8_PSPOFF:
- data->record.p.pspoff = read_uleb128 (&ptr);
- break;
- case P8_SPOFF:
- data->record.p.spoff = read_uleb128 (&ptr);
- break;
- }
- return ptr;
- }
-
- if (val == UNW_P9)
- {
- /* P9 format. */
- int byte1 = *ptr++;
- int byte2 = *ptr++;
- data->type = gr_gr;
- data->record.p.grmask = (byte1 & 0x0f);
- data->record.p.gr = GR_REG (byte2 & 0x7f);
- return ptr;
- }
-
- if (val == UNW_P10)
- {
-#if 0
- /* P10 format. */
- int abi = ptr[0];
- int context = ptr[1];
- /* TODO. something about abi entries. */
-#endif
- return ptr + 2;
- }
-
- return ptr;
-}
-
-/* This routine will determine what type of record the memory pointer
- is refering to, and fill in the appropriate fields for that record type.
- HEADER is a pointer to the last region header unwind record.
- DATA is a pointer to an unwind record which will be filled in.
- PTR is a pointer to the current location in the unwind table where we
- will read the next record from.
- The return value is the start of the next record. */
-
-static unsigned char *
-get_unwind_record (unwind_record *header, unwind_record *data,
- unsigned char *ptr)
-{
- unsigned char val = *ptr++;
-
- if ((val & 0x80) == 0)
- return read_R_record (data, val, ptr);
-
- if (val == UNW_X1 || val == UNW_X2 || val == UNW_X3 || val == UNW_X4)
- return read_X_record (data, val, ptr);
-
- if (header->type != body)
- return read_P_record (data, val, ptr, header);
- else
- return read_B_record (data, val, ptr);
-}
-
-/* Frame processing routines. */
-
-/* Initialize a single register structure. */
-static inline void
-init_ia64_reg_loc (ia64_reg_loc *reg, short size)
-{
- reg->when = -1;
- reg->loc_type = IA64_UNW_LOC_TYPE_NONE;
- reg->l.mem = (void *)0;
- reg->reg_size = size;
-}
-
-/* Iniitialize an entire frame to the default of nothing. */
-static void
-init_ia64_unwind_frame (ia64_frame_state *frame)
-{
- int x;
-
- for (x = 0; x < 4; x++)
- init_ia64_reg_loc (&frame->gr[x], 8);
- for (x = 0; x < 20; x++)
- init_ia64_reg_loc (&frame->fr[x], 16);
- for (x = 0; x < 5; x++)
- init_ia64_reg_loc (&frame->br[x], 8);
-
- init_ia64_reg_loc (&frame->rp, 8);
- init_ia64_reg_loc (&frame->fpsr, 8);
- init_ia64_reg_loc (&frame->bsp, 8);
- init_ia64_reg_loc (&frame->bspstore, 8);
- init_ia64_reg_loc (&frame->rnat, 8);
- init_ia64_reg_loc (&frame->pfs, 8);
- init_ia64_reg_loc (&frame->unat, 8);
- init_ia64_reg_loc (&frame->lc, 8);
- init_ia64_reg_loc (&frame->pr, 8);
- init_ia64_reg_loc (&frame->priunat, 8);
- init_ia64_reg_loc (&frame->sp, 8);
- init_ia64_reg_loc (&frame->psp, 8);
- init_ia64_reg_loc (&frame->spill_base, 8);
-}
-
-/* This fuction will process a single descriptor.
- addr is a pointer to the descriptor record to read,
- frame is the current frame state structure, which will be
- modified to reflect this descriptor.
- len is the length of a prologue region, or -1 if it wasn't one.
- the return value is a pointer to the start of the next descriptor. */
-
-static void *
-execute_one_ia64_descriptor (void *addr, ia64_frame_state *frame, long *len)
-{
- /* The last region_header. Needed to distinguish between prologue and body
- descriptors. Also needed for length of P4 format. */
- static unwind_record region_header;
-
- unwind_record r;
- ia64_reg_loc *loc_ptr = NULL;
- int grmask = 0, frmask = 0;
-
- *len = -1;
- addr = get_unwind_record (&region_header, &r, addr);
-
- /* Process it in 2 phases, the first phase will either do the work,
- or set up a pointer to the records we care about
- (ie a special purpose ar perhaps, and the second will actually
- fill in the record. */
- switch (r.type)
- {
- case prologue:
- case body:
- *len = r.record.r.rlen;
- region_header = r;
- break;
- case prologue_gr:
- {
- int val, reg;
-
- *len = r.record.r.rlen;
- val = r.record.r.mask;
- reg = r.record.r.grsave;
- if (val & 0x08)
- {
- frame->rp.when = 0;
- frame->rp.loc_type = IA64_UNW_LOC_TYPE_GR;
- frame->rp.l.regno = reg++;
- }
- if (val & 0x04)
- {
- frame->pfs.when = 0;
- frame->pfs.loc_type = IA64_UNW_LOC_TYPE_GR;
- frame->pfs.l.regno = reg++;
- }
- if (val & 0x02)
- {
- frame->psp.when = 0;
- frame->psp.loc_type = IA64_UNW_LOC_TYPE_GR;
- frame->psp.l.regno = reg++;
- }
- if (val & 0x01)
- {
- frame->pr.when = 0;
- frame->pr.loc_type = IA64_UNW_LOC_TYPE_GR;
- frame->pr.l.regno = reg++;
- }
- region_header = r;
- break;
- }
- case mem_stack_f:
- frame->sp.l.offset = r.record.p.size;
- frame->sp.loc_type = IA64_UNW_LOC_TYPE_OFFSET;
- frame->sp.when = r.record.p.t;
- break;
- case mem_stack_v:
- frame->psp.when = r.record.p.t;
- break;
- case psp_gr:
- case psp_sprel:
- loc_ptr = &frame->psp;
- break;
- case rp_br:
- case rp_gr:
- case rp_when:
- case rp_psprel:
- case rp_sprel:
- loc_ptr = &frame->rp;
- break;
- case pfs_gr:
- case pfs_when:
- case pfs_psprel:
- case pfs_sprel:
- loc_ptr = &frame->pfs;
- break;
- case preds_gr:
- case preds_when:
- case preds_psprel:
- case preds_sprel:
- loc_ptr = &frame->pr;
- break;
- case unat_gr:
- case unat_when:
- case unat_psprel:
- case unat_sprel:
- loc_ptr = &frame->unat;
- break;
- case lc_gr:
- case lc_when:
- case lc_psprel:
- case lc_sprel:
- loc_ptr = &frame->lc;
- break;
- case fpsr_gr:
- case fpsr_when:
- case fpsr_psprel:
- case fpsr_sprel:
- loc_ptr = &frame->fpsr;
- break;
- case priunat_gr:
- case priunat_sprel:
- case priunat_when_gr:
- case priunat_when_mem:
- case priunat_psprel:
- loc_ptr = &frame->priunat;
- break;
- case bsp_gr:
- case bsp_sprel:
- case bsp_when:
- case bsp_psprel:
- loc_ptr = &frame->bsp;
- break;
- case bspstore_gr:
- case bspstore_sprel:
- case bspstore_when:
- case bspstore_psprel:
- loc_ptr = &frame->bspstore;
- break;
- case rnat_gr:
- case rnat_sprel:
- case rnat_when:
- case rnat_psprel:
- loc_ptr = &frame->rnat;
- break;
- case spill_base:
- loc_ptr = &frame->spill_base;
- break;
- case fr_mem:
- frmask = r.record.p.rmask;
- break;
- case gr_mem:
- grmask = r.record.p.rmask;
- break;
- case frgr_mem:
- frmask = r.record.p.frmask;
- grmask = r.record.p.grmask;
- break;
- case br_mem:
- {
- int x, mask = 0x01;
- int saved = r.record.p.brmask;
- for (x = 0; x < 5; x++)
- {
- if (saved & mask)
- frame->br[x].loc_type = IA64_UNW_LOC_TYPE_SPILLBASE;
- mask = mask << 1;
- }
- break;
- }
- case br_gr:
- {
- int x, mask = 0x01;
- int reg = r.record.p.gr;
- int saved = r.record.p.brmask;
- for (x = 0; x < 5; x++)
- {
- if (saved & mask)
- {
- frame->br[x].loc_type = IA64_UNW_LOC_TYPE_GR;
- frame->br[x].l.regno = reg++;
- }
- mask = mask << 1;
- }
- break;
- }
- case gr_gr:
- {
- int x, mask = 0x01;
- int reg = r.record.p.gr;
- int saved = r.record.p.grmask;
- for (x = 0; x < 4; x++)
- {
- if (saved & mask)
- {
- frame->br[x].loc_type = IA64_UNW_LOC_TYPE_GR;
- frame->br[x].l.regno = reg++;
- }
- mask = mask << 1;
- }
- break;
- }
- case spill_mask:
- /* TODO. */
- break;
- case epilogue:
- /* TODO. */
- break;
- case label_state:
- /* TODO. */
- break;
- case copy_state:
- /* TODO. */
- break;
- case spill_psprel:
- case spill_sprel:
- case spill_reg:
- case spill_psprel_p:
- case spill_sprel_p:
- case spill_reg_p:
- /* TODO. */
- break;
- default:
- abort ();
- break;
- }
-
- if (frmask)
- {
- int x, mask = 0x01;
- for (x = 0; x < 20; x++)
- {
- if (frmask & mask)
- frame->fr[x].loc_type = IA64_UNW_LOC_TYPE_SPILLBASE;
- mask = mask << 1;
- }
- }
-
- if (grmask)
- {
- int x, mask = 0x01;
- for (x = 0; x < 4; x++)
- {
- if (grmask & mask)
- frame->gr[x].loc_type = IA64_UNW_LOC_TYPE_SPILLBASE;
- mask = mask << 1;
- }
- }
-
- /* If there is more to do: */
- if (loc_ptr != NULL)
- switch (r.type)
- {
- case psp_gr:
- case rp_gr:
- case pfs_gr:
- case preds_gr:
- case unat_gr:
- case lc_gr:
- case fpsr_gr:
- case priunat_gr:
- case bsp_gr:
- case bspstore_gr:
- case rnat_gr:
- loc_ptr->loc_type = IA64_UNW_LOC_TYPE_GR;
- loc_ptr->l.regno = r.record.p.gr;
- break;
- case rp_br:
- loc_ptr->loc_type = IA64_UNW_LOC_TYPE_BR;
- loc_ptr->l.regno = r.record.p.br;
- break;
- case rp_when:
- case pfs_when:
- case preds_when:
- case unat_when:
- case lc_when:
- case fpsr_when:
- case priunat_when_gr:
- case priunat_when_mem:
- case bsp_when:
- case bspstore_when:
- case rnat_when:
- loc_ptr->when = r.record.p.t;
- break;
- case rp_psprel:
- case pfs_psprel:
- case preds_psprel:
- case unat_psprel:
- case lc_psprel:
- case fpsr_psprel:
- case priunat_psprel:
- case bsp_psprel:
- case bspstore_psprel:
- case rnat_psprel:
- case spill_base:
- loc_ptr->loc_type = IA64_UNW_LOC_TYPE_PSPOFF;
- loc_ptr->l.offset = r.record.p.pspoff;
- break;
- case psp_sprel:
- case rp_sprel:
- case pfs_sprel:
- case preds_sprel:
- case unat_sprel:
- case lc_sprel:
- case fpsr_sprel:
- case priunat_sprel:
- case bsp_sprel:
- case bspstore_sprel:
- case rnat_sprel:
- loc_ptr->loc_type = IA64_UNW_LOC_TYPE_SPOFF;
- loc_ptr->l.offset = r.record.p.spoff;
- break;
- default:
- abort ();
- break;
- }
- return addr;
-}
-
-
-#define IS_NaT_COLLECTION_ADDR(addr) ((((long)(addr) >> 3) & 0x3f) == 0x3f)
-
-/* Returns the address of the slot that's NSLOTS slots away from
- the address ADDR. NSLOTS may be positive or negative. */
-static void *
-rse_address_add(unsigned char *addr, int nslots)
-{
- unsigned char *new_addr;
- int mandatory_nat_slots = nslots / 63;
- int direction = nslots < 0 ? -1 : 1;
-
- new_addr = addr + 8 * (nslots + mandatory_nat_slots);
-
- if (((long)new_addr >> 9)
- != ((long)(addr + 8 * 64 * mandatory_nat_slots) >> 9))
- new_addr += 8 * direction;
-
- if (IS_NaT_COLLECTION_ADDR(new_addr))
- new_addr += 8 * direction;
-
- return new_addr;
-}
-
-
-/* Normalize a record to originate in either a register or memory
- location. */
-static void
-normalize_reg_loc (ia64_frame_state *frame, ia64_reg_loc *reg)
-{
- unsigned char *tmp;
- switch (reg->loc_type)
- {
- case IA64_UNW_LOC_TYPE_MEM:
- /* Already done. */
- break;
- case IA64_UNW_LOC_TYPE_GR:
- /* If the register its saved in is a LOCAL register, we know
- its actually in memory, so we'll pick it up from there. */
- if (reg->l.regno >= 32 && frame->my_bsp != 0)
- {
- /* Get from backing store. */
- tmp = rse_address_add(frame->my_bsp, reg->l.regno - 32);
- reg->l.mem = tmp;
- reg->loc_type = IA64_UNW_LOC_TYPE_MEM;
- }
- break;
- case IA64_UNW_LOC_TYPE_FR:
- /* If the register its saved in is a LOCAL register, we know
- its actually in memory, so we'll pick it up from there. */
- if (reg->l.regno >= 32)
- {
- /* TODO. get from backing store. */
- }
- break;
- case IA64_UNW_LOC_TYPE_BR:
- break;
- case IA64_UNW_LOC_TYPE_SPOFF:
- /* Offset from the stack pointer, calculate the memory address
- now. */
- tmp = (unsigned char *)frame->my_sp + reg->l.offset * 4;
- reg->l.mem = tmp;
- reg->loc_type = IA64_UNW_LOC_TYPE_MEM;
- break;
- case IA64_UNW_LOC_TYPE_PSPOFF:
- /* Actualy go get the value of the PSP add the offset, and thats
- the mem location we can find this value at. */
- tmp = (unsigned char *)frame->my_psp + 16 - reg->l.offset * 4;
- reg->l.mem = tmp;
- reg->loc_type = IA64_UNW_LOC_TYPE_MEM;
- break;
- case IA64_UNW_LOC_TYPE_SPILLBASE:
- /* located at the current spill base memory location, and we
- have to bump it as well. */
- reg->l.mem = frame->spill_base.l.mem;
- reg->loc_type = IA64_UNW_LOC_TYPE_MEM;
- frame->spill_base.l.mem += 8;
- break;
- }
-
-}
-
-/* This function looks at a reg_loc and determines if its going
- to be an executed record or not between time start and end.
- It is executed if it is exectued at START time. It is NOT
- executed if it happens at END time. */
-static void
-maybe_normalize_reg_loc (ia64_frame_state *frame, ia64_reg_loc *reg,
- long start, long end)
-{
- if (reg->loc_type != IA64_UNW_LOC_TYPE_NONE
- && reg->when >= start && reg->when < end)
- normalize_reg_loc (frame, reg);
-}
-
-
-/* Only works for 8 byte or less registers. */
-void *
-__get_real_reg_value (ia64_reg_loc *reg)
-{
- if (reg->loc_type == IA64_UNW_LOC_TYPE_MEM)
- return *((void **)(reg->l.mem));
-
- /* All registers should be in memory if we've saved them. Local
- registers will be in backing store. */
- abort ();
-}
-
-void
-__set_real_reg_value (ia64_reg_loc *reg, void *val)
-{
- if (reg->loc_type == IA64_UNW_LOC_TYPE_MEM)
- {
- void **ptr = reg->l.mem;
- *ptr = val;
- return;
- }
- abort ();
-}
-
-static void
-copy_reg_value (ia64_reg_loc *src, ia64_reg_loc *dest)
-{
- void **p = dest->l.mem;
- if (src->loc_type == IA64_UNW_LOC_TYPE_NONE)
- return;
-
- if (src->reg_size != dest->reg_size)
- abort ();
- if (src->reg_size <= 8)
- *p = __get_real_reg_value (src);
- else
- {
- void **d;
- if (src->reg_size > 16)
- abort ();
- if (dest->loc_type != IA64_UNW_LOC_TYPE_MEM)
- abort ();
- d = (void **)(dest->l.mem);
- *p++ = *d++;
- *p = *d;
- }
- return;
-}
-
-/* Copy the values of any relevant saved registers in one frame
- to another for unwinding. */
-void
-__copy_saved_reg_state (ia64_frame_state *dest, ia64_frame_state *src)
-{
- int x;
- for (x = 0; x < 4 ; x++)
- copy_reg_value (&src->gr[x], &dest->gr[x]);
- for (x = 0; x < 20 ; x++)
- copy_reg_value (&src->fr[x], &dest->fr[x]);
- for (x = 0; x < 5 ; x++)
- copy_reg_value (&src->br[x], &dest->br[x]);
-
- copy_reg_value (&src->fpsr, &dest->fpsr);
- copy_reg_value (&src->rnat, &dest->rnat);
- copy_reg_value (&src->unat, &dest->unat);
- copy_reg_value (&src->lc, &dest->lc);
- copy_reg_value (&src->pr, &dest->pr);
- copy_reg_value (&src->priunat, &dest->priunat);
- copy_reg_value (&src->pfs, &dest->pfs);
-}
-
-
-static void
-process_state_between (ia64_frame_state *frame, long start, long end)
-{
- int x;
- /* PSP, RP, SP, and PFS are handled seperately from here. */
-
- /* GR's, FR's and BR's are saved at an arbitrary point, so we
- should handle them at the very beginning. */
- /* ??? Err, no they aren't. There's the spill_mask record that
- tells us when each is processed. */
- if (start == 0)
- {
- for (x = 0; x < 4 ; x++)
- normalize_reg_loc (frame, &frame->gr[x]);
- for (x = 0; x < 20 ; x++)
- normalize_reg_loc (frame, &frame->fr[x]);
- for (x = 0; x < 5 ; x++)
- normalize_reg_loc (frame, &frame->br[x]);
- }
-
- maybe_normalize_reg_loc (frame, &frame->fpsr, start, end);
- maybe_normalize_reg_loc (frame, &frame->bsp, start, end);
- maybe_normalize_reg_loc (frame, &frame->bspstore, start, end);
- maybe_normalize_reg_loc (frame, &frame->rnat, start, end);
- maybe_normalize_reg_loc (frame, &frame->unat, start, end);
- maybe_normalize_reg_loc (frame, &frame->lc, start, end);
- maybe_normalize_reg_loc (frame, &frame->pr, start, end);
- maybe_normalize_reg_loc (frame, &frame->priunat, start, end);
-}
-
-/* This function will take a frame state, and translate all the location
- records into actual memory address, or register numbers, based on
- what the ia64_reg_loc fields require to actually go get the values.
- (ie, this translates SPOFF and PSPOFF, etc into MEM types.
- frame is the frame to be changed.
- unwind_time is the insn slot number we are unwinding to. Anything
- that has a WHEN record beyond this time is cleared since it
- isn't relevant. */
-static void
-frame_translate (ia64_frame_state *frame, long unwind_time)
-{
- /* ??? Is this supposed to mark the end of the stack? */
- if (frame->rp.loc_type == IA64_UNW_LOC_TYPE_NONE)
- return;
-
- /* At function entry, SP == PSP. */
- frame->my_psp = frame->my_sp;
- if (frame->psp.loc_type != IA64_UNW_LOC_TYPE_NONE)
- {
- /* We've saved a frame pointer somewhere. This will be the
- canonical PSP for the function. */
- normalize_reg_loc (frame, &frame->psp);
- if (frame->psp.when < unwind_time)
- frame->my_psp = __get_real_reg_value (&frame->psp);
- }
- else if (frame->sp.loc_type == IA64_UNW_LOC_TYPE_OFFSET)
- {
- /* We've a fixed sized stack frame. The PSP is at a known offset. */
-
- if (frame->sp.when < unwind_time)
- frame->my_psp = frame->my_sp + frame->sp.l.offset;
- }
- /* Otherwise the stack frame size was zero and no adjustment needed. */
-
- /* Find PFS, RP and the spill base. All of which might have
- addresses based off the PSP computed above. */
- normalize_reg_loc (frame, &frame->pfs);
- normalize_reg_loc (frame, &frame->rp);
-
- if (frame->spill_base.loc_type != IA64_UNW_LOC_TYPE_NONE)
- normalize_reg_loc (frame, &frame->spill_base);
- else
- {
- /* Otherwise we're supposed to infer it from the size of the
- saved GR/BR/FR registers, putting the top at psp+16. */
- long size = 0, i;
- for (i = 0; i < 4; ++i)
- if (frame->gr[i].when >= 0)
- size += 8;
- for (i = 0; i < 5; ++i)
- if (frame->br[i].when >= 0)
- size += 8;
- for (i = 0; i < 20; ++i)
- if (frame->fr[i].when >= 0)
- size += 16;
- frame->spill_base.l.mem = frame->my_psp + 16 - size;
- }
-
- /* If the SP is adjusted, process records up to where it
- is adjusted, then adjust it, then process the rest. */
- if (frame->sp.when >= 0)
- {
- process_state_between (frame, 0, frame->sp.when);
- if (frame->sp.loc_type != IA64_UNW_LOC_TYPE_OFFSET)
- abort ();
- frame->my_sp = frame->my_psp - frame->sp.l.offset;
- process_state_between (frame, frame->sp.when, unwind_time);
- }
- else
- process_state_between (frame, 0, unwind_time);
-}
-
-/* This function will set a frame_state with all the required fields
- from a functions unwind descriptors.
- pc is the location we need info up until (ie, the unwind point)
- frame is the frame_state structure to be set up.
- Returns a pointer to the unwind info pointer for the frame. */
-unwind_info_ptr *
-__build_ia64_frame_state (unsigned char *pc, ia64_frame_state *frame,
- void *bsp, void *sp, void **pc_base_ptr)
-{
- long len;
- int region_offset = 0;
- int last_region_size = 0;
- void *addr, *end;
- unwind_table_entry *entry;
- unsigned char *start_pc;
- void *pc_base;
- int pc_offset;
- struct unwind_info_ptr *unw_info_ptr;
-
- entry = __ia64_find_fde (pc, &pc_base);
- if (!entry)
- return 0;
-
- start_pc = pc_base + entry->start_offset;
- unw_info_ptr = ((struct unwind_info_ptr *)(pc_base + entry->unwind_offset));
- addr = unw_info_ptr->unwind_descriptors;
- end = addr + IA64_UNW_HDR_LENGTH (unw_info_ptr->header) * 8;
- pc_offset = (pc - start_pc) / 16 * 3;
-
- init_ia64_unwind_frame (frame);
- frame->my_bsp = bsp;
- frame->my_sp = sp;
-
- /* Stop when we get to the end of the descriptor list, or if we
- encounter a region whose initial offset is already past the
- PC we are unwinding too. */
-
- while (addr < end && pc_offset > region_offset)
- {
- /* First one must be a record header. */
- addr = execute_one_ia64_descriptor (addr, frame, &len);
- if (len > 0)
- {
- region_offset += last_region_size;
- last_region_size = len;
- }
- }
-
- /* Now we go get the actual values. */
- frame_translate (frame, pc_offset);
- if (pc_base_ptr)
- *pc_base_ptr = pc_base;
- return unw_info_ptr;
-}
-
-/* Given an unwind info pointer, return the personality routine. */
-void *
-__get_personality (unwind_info_ptr *ptr)
-{
- void **p;
-
- /* There is a personality routine only if one of the EHANDLER or UHANDLER
- bits is set. */
- if (! (IA64_UNW_HDR_FLAGS (ptr->header)
- & (IA64_UNW_EHANDLER|IA64_UNW_UHANDLER)))
- return 0;
-
- p = (void **) (ptr->unwind_descriptors
- + IA64_UNW_HDR_LENGTH (ptr->header) * 8);
- return *p;
-}
-
-/* Given an unwind info pointer, return the exception table. */
-void *
-__get_except_table (unwind_info_ptr *ptr)
-{
- void *table;
-
- /* If there is no personality, there is no handler data.
- There is a personality routine only if one of the EHANDLER or UHANDLER
- bits is set. */
- if (! (IA64_UNW_HDR_FLAGS (ptr->header)
- & (IA64_UNW_EHANDLER|IA64_UNW_UHANDLER)))
- return 0;
-
- table = (void *) (ptr->unwind_descriptors
- + IA64_UNW_HDR_LENGTH (ptr->header) * 8 + 8);
- return table;
-}
-
-/* Given a PFS value, and the current BSp, calculate the BSp of the caller. */
-void *
-__calc_caller_bsp (long pfs, unsigned char *bsp)
-{
- int size_of_locals;
-
- /* The PFS looks like : xxxx SOL:7 SOF:7. The SOF is bits 0-7 and SOL
- is bits 8-15. We only care about SOL. */
-
- size_of_locals = (pfs >> 7) & 0x7f;
- return rse_address_add (bsp, -size_of_locals);
-}
-
-static int
-ia64_backtrace_helper (void **array, ia64_frame_state *throw_frame,
- ia64_frame_state *frame, void *bsp, void *sp, int size)
-{
- void *throw_pc = __builtin_return_address (0);
- void *pc = NULL;
- int frame_count = 0;
- unwind_info_ptr *info;
-
- __builtin_ia64_flushrs (); /* Make the local register stacks available. */
-
- /* Start at our stack frame, get our state. */
- info = __build_ia64_frame_state (throw_pc, throw_frame, bsp, sp, NULL);
-
- *frame = *throw_frame;
-
- while (info && frame_count < size)
- {
- pc = array[frame_count++] = __get_real_reg_value (&frame->rp);
- --pc;
- bsp = __calc_caller_bsp
- ((long)__get_real_reg_value (&frame->pfs), frame->my_bsp);
- info = __build_ia64_frame_state (pc, frame, bsp, frame->my_psp, NULL);
- if (frame->rp.loc_type == IA64_UNW_LOC_TYPE_NONE) /* We've finished. */
- break;
- }
-
- return frame_count;
-}
-
-/* This is equivalent to glibc's backtrace(). */
-
-extern int __ia64_backtrace (void **array, int size);
-
-int
-__ia64_backtrace (void **array, int size)
-{
- register void *stack_pointer __asm__("r12");
- ia64_frame_state my_frame;
- ia64_frame_state originator; /* For the context handler is in. */
- void *bsp;
-
- /* Do any necessary initialization to access arbitrary stack frames.
- This forces gcc to save memory in our stack frame for saved
- registers. */
- __builtin_unwind_init ();
-
- bsp = __builtin_ia64_bsp ();
-
- return ia64_backtrace_helper (array, &my_frame, &originator, bsp,
- stack_pointer, size);
-}
diff --git a/gcc/config/ia64/hpux.h b/gcc/config/ia64/hpux.h
new file mode 100644
index 00000000000..c08cd47154c
--- /dev/null
+++ b/gcc/config/ia64/hpux.h
@@ -0,0 +1,92 @@
+/* Definitions of target machine GNU compiler. IA-64 version.
+ Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
+ Contributed by Steve Ellcey <sje@cup.hp.com> and
+ Reva Cuthbertson <reva@cup.hp.com>
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES "\
+ -D__IA64__ -D__ia64 -D__ia64__ -D__hpux -D__hpux__ -Dhpux -Dunix \
+ -D__BIG_ENDIAN__ -D_LONGLONG -D__ELF__ \
+ -Asystem=hpux -Asystem=posix -Asystem=unix -Acpu=ia64 -Amachine=ia64 \
+ -D_UINT128_T"
+
+/* -D__fpreg=long double is needed to compensate for the lack of __fpreg
+ which is a primitive type in HP C but does not exist in GNU C. Same
+ for __float80 and __float128. These types appear in HP-UX header
+ files and so must have some definition. */
+
+#undef CPP_SPEC
+#define CPP_SPEC "\
+ %{mcpu=itanium:-D__itanium__} \
+ -D__LP64__ -D__LONG_MAX__=9223372036854775807L \
+ %{!ansi:%{!std=c*:%{!std=i*: -D_HPUX_SOURCE -D__STDC_EXT__}}} \
+ -D__fpreg=long\\ double \
+ -D__float80=long\\ double \
+ -D__float128=long\\ double"
+
+#undef ASM_SPEC
+#define ASM_SPEC "-x %{mconstant-gp} %{mauto-pic}"
+
+#undef ENDFILE_SPEC
+
+#undef STARTFILE_SPEC
+#ifdef CROSS_COMPILE
+#define STARTFILE_SPEC "%{!shared:crt0%O%s}"
+#else
+#define STARTFILE_SPEC "/usr/ccs/lib/hpux64/crt0%O"
+#endif
+
+#undef LINK_SPEC
+#define LINK_SPEC "\
+ +Accept TypeMismatch \
+ %{shared:-b} \
+ %{!shared: \
+ -u main \
+ %{!static: \
+ %{rdynamic:-export-dynamic}} \
+ %{static:-static}}"
+
+#undef LIB_SPEC
+#define LIB_SPEC "%{!shared:%{!symbolic:-lc}}"
+
+#define DONT_USE_BUILTIN_SETJMP
+#define JMP_BUF_SIZE (8 * 76)
+
+#undef CONST_SECTION_ASM_OP
+#define CONST_SECTION_ASM_OP "\t.section\t.rodata,\t\"a\",\t\"progbits\""
+
+#undef BITS_BIG_ENDIAN
+#define BITS_BIG_ENDIAN 1
+
+#undef TARGET_DEFAULT
+#define TARGET_DEFAULT (MASK_DWARF2_ASM | MASK_BIG_ENDIAN)
+
+/* We need this macro to output DWARF2 information correctly. The macro
+ is defined in dwarf2out.c, but it will not do section relative offsets
+ which messes up our ability to debug using gdb. */
+
+#undef ASM_OUTPUT_DWARF_OFFSET
+#define ASM_OUTPUT_DWARF_OFFSET(FILE,LABEL) \
+ do { \
+ fprintf ((FILE), "\t%s\t", UNALIGNED_OFFSET_ASM_OP); \
+ fprintf ((FILE), "@secrel("); \
+ assemble_name (FILE, LABEL); \
+ fprintf ((FILE), ")"); \
+ } while (0)
diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c
index 2eaafc7ca06..4e83dfdfbf6 100644
--- a/gcc/config/ia64/ia64.c
+++ b/gcc/config/ia64/ia64.c
@@ -30,7 +30,6 @@ Boston, MA 02111-1307, USA. */
#include "real.h"
#include "insn-config.h"
#include "conditions.h"
-#include "insn-flags.h"
#include "output.h"
#include "insn-attr.h"
#include "flags.h"
@@ -92,6 +91,10 @@ static const char * const ia64_output_reg_names[8] =
/* String used with the -mfixed-range= option. */
const char *ia64_fixed_range_string;
+/* Determines whether we run our final scheduling pass or not. We always
+ avoid the normal second scheduling pass. */
+static int ia64_flag_schedule_insns2;
+
/* Variables which are this size or smaller are put in the sdata/sbss
sections. */
@@ -119,6 +122,7 @@ static void ia64_free_machine_status PARAMS ((struct function *));
static void emit_insn_group_barriers PARAMS ((FILE *, rtx));
static void emit_all_insn_group_barriers PARAMS ((FILE *, rtx));
static void emit_predicate_relation_info PARAMS ((void));
+static void process_epilogue PARAMS ((void));
static int process_set PARAMS ((FILE *, rtx));
static rtx ia64_expand_fetch_and_op PARAMS ((optab, enum machine_mode,
@@ -1214,7 +1218,10 @@ find_gr_spill (try_locals)
if (try_locals)
{
regno = current_frame_info.n_local_regs;
- if (regno < 80)
+ /* If there is a frame pointer, then we can't use loc79, because
+ that is HARD_FRAME_POINTER_REGNUM. In particular, see the
+ reg_name switching code in ia64_expand_prologue. */
+ if (regno < (80 - frame_pointer_needed))
{
current_frame_info.n_local_regs = regno + 1;
return LOC_REG (0) + regno;
@@ -1317,7 +1324,13 @@ ia64_compute_frame_size (size)
break;
current_frame_info.n_local_regs = regno - LOC_REG (0) + 1;
- if (cfun->machine->n_varargs > 0)
+ /* For functions marked with the syscall_linkage attribute, we must mark
+ all eight input registers as in use, so that locals aren't visible to
+ the caller. */
+
+ if (cfun->machine->n_varargs > 0
+ || lookup_attribute ("syscall_linkage",
+ TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))))
current_frame_info.n_input_regs = 8;
else
{
@@ -1381,10 +1394,15 @@ ia64_compute_frame_size (size)
if (frame_pointer_needed)
{
current_frame_info.reg_fp = find_gr_spill (1);
- /* We should have gotten at least LOC79, since that's what
- HARD_FRAME_POINTER_REGNUM is. */
+ /* If we did not get a register, then we take LOC79. This is guaranteed
+ to be free, even if regs_ever_live is already set, because this is
+ HARD_FRAME_POINTER_REGNUM. This requires incrementing n_local_regs,
+ as we don't count loc79 above. */
if (current_frame_info.reg_fp == 0)
- abort ();
+ {
+ current_frame_info.reg_fp = LOC_REG (79);
+ current_frame_info.n_local_regs++;
+ }
}
if (! current_function_is_leaf)
@@ -1868,6 +1886,10 @@ ia64_expand_prologue ()
/* Set the frame pointer register name. The regnum is logically loc79,
but of course we'll not have allocated that many locals. Rather than
worrying about renumbering the existing rtxs, we adjust the name. */
+ /* ??? This code means that we can never use one local register when
+ there is a frame pointer. loc79 gets wasted in this case, as it is
+ renamed to a register that will never be used. See also the try_locals
+ code in find_gr_spill. */
if (current_frame_info.reg_fp)
{
const char *tmp = reg_names[HARD_FRAME_POINTER_REGNUM];
@@ -2377,6 +2399,30 @@ ia64_expand_epilogue (sibcall_p)
if (! sibcall_p)
emit_jump_insn (gen_return_internal (gen_rtx_REG (DImode, BR_REG (0))));
+ else
+ {
+ int fp = GR_REG (2);
+ /* We need a throw away register here, r0 and r1 are reserved, so r2 is the
+ first available call clobbered register. If there was a frame_pointer
+ register, we may have swapped the names of r2 and HARD_FRAME_POINTER_REGNUM,
+ so we have to make sure we're using the string "r2" when emitting
+ the register name for the assmbler. */
+ if (current_frame_info.reg_fp && current_frame_info.reg_fp == GR_REG (2))
+ fp = HARD_FRAME_POINTER_REGNUM;
+
+ /* We must emit an alloc to force the input registers to become output
+ registers. Otherwise, if the callee tries to pass its parameters
+ through to another call without an intervening alloc, then these
+ values get lost. */
+ /* ??? We don't need to preserve all input registers. We only need to
+ preserve those input registers used as arguments to the sibling call.
+ It is unclear how to compute that number here. */
+ if (current_frame_info.n_input_regs != 0)
+ emit_insn (gen_alloc (gen_rtx_REG (DImode, fp),
+ GEN_INT (0), GEN_INT (0),
+ GEN_INT (current_frame_info.n_input_regs),
+ GEN_INT (0)));
+ }
}
/* Return 1 if br.ret can do all the work required to return from a
@@ -2430,6 +2476,10 @@ ia64_hard_regno_rename_ok (from, to)
if (PR_REGNO_P (from) && PR_REGNO_P (to))
return (from & 1) == (to & 1);
+ /* Reg 4 contains the saved gp; we can't reliably rename this. */
+ if (from == GR_REG (4) && current_function_calls_setjmp)
+ return 0;
+
return 1;
}
@@ -2449,7 +2499,7 @@ ia64_function_prologue (file, size)
current_frame_info.n_output_regs,
current_frame_info.n_rotate_regs);
- if (!flag_unwind_tables && (!flag_exceptions || exceptions_via_longjmp))
+ if (!flag_unwind_tables && (!flag_exceptions || USING_SJLJ_EXCEPTIONS))
return;
/* Emit the .prologue directive. */
@@ -2508,7 +2558,7 @@ void
ia64_output_end_prologue (file)
FILE *file;
{
- if (!flag_unwind_tables && (!flag_exceptions || exceptions_via_longjmp))
+ if (!flag_unwind_tables && (!flag_exceptions || USING_SJLJ_EXCEPTIONS))
return;
fputs ("\t.body\n", file);
@@ -2815,13 +2865,17 @@ ia64_function_arg (cum, mode, type, named, incoming)
adjusted/little endian. */
else if (byte_size - offset == 4)
gr_mode = SImode;
+ /* Complex floats need to have float mode. */
+ if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT)
+ gr_mode = hfa_mode;
loc[i] = gen_rtx_EXPR_LIST (VOIDmode,
gen_rtx_REG (gr_mode, (basereg
+ int_regs)),
GEN_INT (offset));
offset += GET_MODE_SIZE (gr_mode);
- int_regs++;
+ int_regs += GET_MODE_SIZE (gr_mode) <= UNITS_PER_WORD
+ ? 1 : GET_MODE_SIZE (gr_mode) / UNITS_PER_WORD;
}
/* If we ended up using just one location, just return that one loc. */
@@ -3693,6 +3747,9 @@ ia64_override_options ()
if (ia64_fixed_range_string)
fix_range (ia64_fixed_range_string);
+ ia64_flag_schedule_insns2 = flag_schedule_insns_after_reload;
+ flag_schedule_insns_after_reload = 0;
+
ia64_section_threshold = g_switch_set ? g_switch_value : IA64_DEFAULT_GVALUE;
init_machine_status = ia64_init_machine_status;
@@ -3789,6 +3846,11 @@ struct reg_write_state rws_sum[NUM_REGS];
stop bit is emitted. */
struct reg_write_state rws_insn[NUM_REGS];
+/* Indicates whether this is the first instruction after a stop bit,
+ in which case we don't need another stop bit. Without this, we hit
+ the abort in ia64_variable_issue when scheduling an alloc. */
+static int first_instruction;
+
/* Misc flags needed to compute RAW/WAW dependencies while we are traversing
RTL for one instruction. */
struct reg_flags
@@ -3805,6 +3867,8 @@ static void rws_update PARAMS ((struct reg_write_state *, int,
struct reg_flags, int));
static int rws_access_regno PARAMS ((int, struct reg_flags, int));
static int rws_access_reg PARAMS ((rtx, struct reg_flags, int));
+static void update_set_flags PARAMS ((rtx, struct reg_flags *, int *, rtx *));
+static int set_src_needs_barrier PARAMS ((rtx, struct reg_flags, int, rtx));
static int rtx_needs_barrier PARAMS ((rtx, struct reg_flags, int));
static void init_insn_group_barriers PARAMS ((void));
static int group_barrier_needed_p PARAMS ((rtx));
@@ -3973,6 +4037,132 @@ rws_access_reg (reg, flags, pred)
}
}
+/* Examine X, which is a SET rtx, and update the flags, the predicate, and
+ the condition, stored in *PFLAGS, *PPRED and *PCOND. */
+
+static void
+update_set_flags (x, pflags, ppred, pcond)
+ rtx x;
+ struct reg_flags *pflags;
+ int *ppred;
+ rtx *pcond;
+{
+ rtx src = SET_SRC (x);
+
+ *pcond = 0;
+
+ switch (GET_CODE (src))
+ {
+ case CALL:
+ return;
+
+ case IF_THEN_ELSE:
+ if (SET_DEST (x) == pc_rtx)
+ /* X is a conditional branch. */
+ return;
+ else
+ {
+ int is_complemented = 0;
+
+ /* X is a conditional move. */
+ rtx cond = XEXP (src, 0);
+ if (GET_CODE (cond) == EQ)
+ is_complemented = 1;
+ cond = XEXP (cond, 0);
+ if (GET_CODE (cond) != REG
+ && REGNO_REG_CLASS (REGNO (cond)) != PR_REGS)
+ abort ();
+ *pcond = cond;
+ if (XEXP (src, 1) == SET_DEST (x)
+ || XEXP (src, 2) == SET_DEST (x))
+ {
+ /* X is a conditional move that conditionally writes the
+ destination. */
+
+ /* We need another complement in this case. */
+ if (XEXP (src, 1) == SET_DEST (x))
+ is_complemented = ! is_complemented;
+
+ *ppred = REGNO (cond);
+ if (is_complemented)
+ ++*ppred;
+ }
+
+ /* ??? If this is a conditional write to the dest, then this
+ instruction does not actually read one source. This probably
+ doesn't matter, because that source is also the dest. */
+ /* ??? Multiple writes to predicate registers are allowed
+ if they are all AND type compares, or if they are all OR
+ type compares. We do not generate such instructions
+ currently. */
+ }
+ /* ... fall through ... */
+
+ default:
+ if (GET_RTX_CLASS (GET_CODE (src)) == '<'
+ && GET_MODE_CLASS (GET_MODE (XEXP (src, 0))) == MODE_FLOAT)
+ /* Set pflags->is_fp to 1 so that we know we're dealing
+ with a floating point comparison when processing the
+ destination of the SET. */
+ pflags->is_fp = 1;
+
+ /* Discover if this is a parallel comparison. We only handle
+ and.orcm and or.andcm at present, since we must retain a
+ strict inverse on the predicate pair. */
+ else if (GET_CODE (src) == AND)
+ pflags->is_and = 1;
+ else if (GET_CODE (src) == IOR)
+ pflags->is_or = 1;
+
+ break;
+ }
+}
+
+/* Subroutine of rtx_needs_barrier; this function determines whether the
+ source of a given SET rtx found in X needs a barrier. FLAGS and PRED
+ are as in rtx_needs_barrier. COND is an rtx that holds the condition
+ for this insn. */
+
+static int
+set_src_needs_barrier (x, flags, pred, cond)
+ rtx x;
+ struct reg_flags flags;
+ int pred;
+ rtx cond;
+{
+ int need_barrier = 0;
+ rtx dst;
+ rtx src = SET_SRC (x);
+
+ if (GET_CODE (src) == CALL)
+ /* We don't need to worry about the result registers that
+ get written by subroutine call. */
+ return rtx_needs_barrier (src, flags, pred);
+ else if (SET_DEST (x) == pc_rtx)
+ {
+ /* X is a conditional branch. */
+ /* ??? This seems redundant, as the caller sets this bit for
+ all JUMP_INSNs. */
+ flags.is_branch = 1;
+ return rtx_needs_barrier (src, flags, pred);
+ }
+
+ need_barrier = rtx_needs_barrier (src, flags, pred);
+
+ /* This instruction unconditionally uses a predicate register. */
+ if (cond)
+ need_barrier |= rws_access_reg (cond, flags, 0);
+
+ dst = SET_DEST (x);
+ if (GET_CODE (dst) == ZERO_EXTRACT)
+ {
+ need_barrier |= rtx_needs_barrier (XEXP (dst, 1), flags, pred);
+ need_barrier |= rtx_needs_barrier (XEXP (dst, 2), flags, pred);
+ dst = XEXP (dst, 0);
+ }
+ return need_barrier;
+}
+
/* Handle an access to rtx X of type FLAGS using predicate register PRED.
Return 1 is this access creates a dependency with an earlier instruction
in the same group. */
@@ -3988,7 +4178,6 @@ rtx_needs_barrier (x, flags, pred)
int need_barrier = 0;
const char *format_ptr;
struct reg_flags new_flags;
- rtx src, dst;
rtx cond = 0;
if (! x)
@@ -3998,95 +4187,14 @@ rtx_needs_barrier (x, flags, pred)
switch (GET_CODE (x))
{
- case SET:
- src = SET_SRC (x);
- switch (GET_CODE (src))
- {
- case CALL:
- /* We don't need to worry about the result registers that
- get written by subroutine call. */
- need_barrier = rtx_needs_barrier (src, flags, pred);
- return need_barrier;
-
- case IF_THEN_ELSE:
- if (SET_DEST (x) == pc_rtx)
- {
- /* X is a conditional branch. */
- /* ??? This seems redundant, as the caller sets this bit for
- all JUMP_INSNs. */
- new_flags.is_branch = 1;
- need_barrier = rtx_needs_barrier (src, new_flags, pred);
- return need_barrier;
- }
- else
- {
- /* X is a conditional move. */
- cond = XEXP (src, 0);
- if (GET_CODE (cond) == EQ)
- is_complemented = 1;
- cond = XEXP (cond, 0);
- if (GET_CODE (cond) != REG
- && REGNO_REG_CLASS (REGNO (cond)) != PR_REGS)
- abort ();
-
- if (XEXP (src, 1) == SET_DEST (x)
- || XEXP (src, 2) == SET_DEST (x))
- {
- /* X is a conditional move that conditionally writes the
- destination. */
-
- /* We need another complement in this case. */
- if (XEXP (src, 1) == SET_DEST (x))
- is_complemented = ! is_complemented;
-
- pred = REGNO (cond);
- if (is_complemented)
- ++pred;
- }
-
- /* ??? If this is a conditional write to the dest, then this
- instruction does not actually read one source. This probably
- doesn't matter, because that source is also the dest. */
- /* ??? Multiple writes to predicate registers are allowed
- if they are all AND type compares, or if they are all OR
- type compares. We do not generate such instructions
- currently. */
- }
- /* ... fall through ... */
-
- default:
- if (GET_RTX_CLASS (GET_CODE (src)) == '<'
- && GET_MODE_CLASS (GET_MODE (XEXP (src, 0))) == MODE_FLOAT)
- /* Set new_flags.is_fp to 1 so that we know we're dealing
- with a floating point comparison when processing the
- destination of the SET. */
- new_flags.is_fp = 1;
-
- /* Discover if this is a parallel comparison. We only handle
- and.orcm and or.andcm at present, since we must retain a
- strict inverse on the predicate pair. */
- else if (GET_CODE (src) == AND)
- new_flags.is_and = flags.is_and = 1;
- else if (GET_CODE (src) == IOR)
- new_flags.is_or = flags.is_or = 1;
-
- break;
- }
- need_barrier = rtx_needs_barrier (src, flags, pred);
-
- /* This instruction unconditionally uses a predicate register. */
- if (cond)
- need_barrier |= rws_access_reg (cond, flags, 0);
-
- dst = SET_DEST (x);
- if (GET_CODE (dst) == ZERO_EXTRACT)
+ case SET:
+ update_set_flags (x, &new_flags, &pred, &cond);
+ need_barrier = set_src_needs_barrier (x, new_flags, pred, cond);
+ if (GET_CODE (SET_SRC (x)) != CALL)
{
- need_barrier |= rtx_needs_barrier (XEXP (dst, 1), flags, pred);
- need_barrier |= rtx_needs_barrier (XEXP (dst, 2), flags, pred);
- dst = XEXP (dst, 0);
+ new_flags.is_write = 1;
+ need_barrier |= rtx_needs_barrier (SET_DEST (x), new_flags, pred);
}
- new_flags.is_write = 1;
- need_barrier |= rtx_needs_barrier (dst, new_flags, pred);
break;
case CALL:
@@ -4159,8 +4267,35 @@ rtx_needs_barrier (x, flags, pred)
case PARALLEL:
for (i = XVECLEN (x, 0) - 1; i >= 0; --i)
- if (rtx_needs_barrier (XVECEXP (x, 0, i), flags, pred))
- need_barrier = 1;
+ {
+ rtx pat = XVECEXP (x, 0, i);
+ if (GET_CODE (pat) == SET)
+ {
+ update_set_flags (pat, &new_flags, &pred, &cond);
+ need_barrier |= set_src_needs_barrier (pat, new_flags, pred, cond);
+ }
+ else if (GET_CODE (pat) == USE
+ || GET_CODE (pat) == CALL
+ || GET_CODE (pat) == ASM_OPERANDS)
+ need_barrier |= rtx_needs_barrier (pat, flags, pred);
+ else if (GET_CODE (pat) != CLOBBER && GET_CODE (pat) != RETURN)
+ abort ();
+ }
+ for (i = XVECLEN (x, 0) - 1; i >= 0; --i)
+ {
+ rtx pat = XVECEXP (x, 0, i);
+ if (GET_CODE (pat) == SET)
+ {
+ if (GET_CODE (SET_SRC (pat)) != CALL)
+ {
+ new_flags.is_write = 1;
+ need_barrier |= rtx_needs_barrier (SET_DEST (pat), new_flags,
+ pred);
+ }
+ }
+ else if (GET_CODE (pat) == CLOBBER || GET_CODE (pat) == RETURN)
+ need_barrier |= rtx_needs_barrier (pat, flags, pred);
+ }
break;
case SUBREG:
@@ -4277,14 +4412,18 @@ rtx_needs_barrier (x, flags, pred)
switch (XINT (x, 1))
{
case 0: /* alloc */
- /* Alloc must always be the first instruction. Currently, we
- only emit it at the function start, so we don't need to worry
- about emitting a stop bit before it. */
- need_barrier = rws_access_regno (AR_PFS_REGNUM, flags, pred);
+ /* Alloc must always be the first instruction of a group.
+ We force this by always returning true. */
+ /* ??? We might get better scheduling if we explicitly check for
+ input/local/output register dependencies, and modify the
+ scheduler so that alloc is always reordered to the start of
+ the current group. We could then eliminate all of the
+ first_instruction code. */
+ rws_access_regno (AR_PFS_REGNUM, flags, pred);
new_flags.is_write = 1;
- need_barrier |= rws_access_regno (REG_AR_CFM, new_flags, pred);
- return need_barrier;
+ rws_access_regno (REG_AR_CFM, new_flags, pred);
+ return 1;
case 1: /* blockage */
case 2: /* insn group barrier */
@@ -4353,11 +4492,9 @@ static void
init_insn_group_barriers ()
{
memset (rws_sum, 0, sizeof (rws_sum));
+ first_instruction = 1;
}
-/* Cumulative info for the current instruction group. */
-struct reg_write_state rws_sum[NUM_REGS];
-
/* Given the current state, recorded by previous calls to this function,
determine whether a group barrier (a stop bit) is necessary before INSN.
Return nonzero if so. */
@@ -4388,11 +4525,28 @@ group_barrier_needed_p (insn)
flags.is_branch = 1;
flags.is_sibcall = SIBLING_CALL_P (insn);
memset (rws_insn, 0, sizeof (rws_insn));
+
+ /* Don't bundle a call following another call. */
+ if ((pat = prev_active_insn (insn))
+ && GET_CODE (pat) == CALL_INSN)
+ {
+ need_barrier = 1;
+ break;
+ }
+
need_barrier = rtx_needs_barrier (PATTERN (insn), flags, 0);
break;
case JUMP_INSN:
flags.is_branch = 1;
+
+ /* Don't bundle a jump following a call. */
+ if ((pat = prev_active_insn (insn))
+ && GET_CODE (pat) == CALL_INSN)
+ {
+ need_barrier = 1;
+ break;
+ }
/* FALLTHRU */
case INSN:
@@ -4435,12 +4589,18 @@ group_barrier_needed_p (insn)
asm. */
if (! need_barrier)
need_barrier = rws_access_regno (REG_VOLATILE, flags, 0);
-
break;
default:
abort ();
}
+
+ if (first_instruction)
+ {
+ need_barrier = 0;
+ first_instruction = 0;
+ }
+
return need_barrier;
}
@@ -4451,10 +4611,17 @@ safe_group_barrier_needed_p (insn)
rtx insn;
{
struct reg_write_state rws_saved[NUM_REGS];
+ int saved_first_instruction;
int t;
+
memcpy (rws_saved, rws_sum, NUM_REGS * sizeof *rws_saved);
+ saved_first_instruction = first_instruction;
+
t = group_barrier_needed_p (insn);
+
memcpy (rws_sum, rws_saved, NUM_REGS * sizeof *rws_saved);
+ first_instruction = saved_first_instruction;
+
return t;
}
@@ -4511,9 +4678,10 @@ emit_insn_group_barriers (dump, insns)
INSN_UID (last_label));
emit_insn_before (gen_insn_group_barrier (GEN_INT (3)), last_label);
insn = last_label;
+
+ init_insn_group_barriers ();
+ last_label = 0;
}
- init_insn_group_barriers ();
- last_label = 0;
}
}
}
@@ -4752,9 +4920,7 @@ static int itanium_split_issue PARAMS ((const struct ia64_packet *, int));
static rtx ia64_single_set PARAMS ((rtx));
static int insn_matches_slot PARAMS ((const struct ia64_packet *, enum attr_type, int, rtx));
static void ia64_emit_insn_before PARAMS ((rtx, rtx));
-#if 0
-static rtx gen_nop_type PARAMS ((enum attr_type));
-#endif
+static void maybe_rotate PARAMS ((FILE *));
static void finish_last_head PARAMS ((FILE *, int));
static void rotate_one_bundle PARAMS ((FILE *));
static void rotate_two_bundles PARAMS ((FILE *));
@@ -5643,6 +5809,15 @@ ia64_sched_reorder (dump, sched_verbose, ready, pn_ready, reorder_type)
dump_current_packet (dump);
}
+ if (reorder_type == 0)
+ {
+ if (sched_data.cur == 6)
+ rotate_two_bundles (sched_verbose ? dump : NULL);
+ else if (sched_data.cur >= 3)
+ rotate_one_bundle (sched_verbose ? dump : NULL);
+ sched_data.first_slot = sched_data.cur;
+ }
+
/* First, move all USEs, CLOBBERs and other crud out of the way. */
highest = ready[n_ready - 1];
for (insnp = ready; insnp < e_ready; insnp++)
@@ -5716,15 +5891,6 @@ ia64_sched_reorder (dump, sched_verbose, ready, pn_ready, reorder_type)
}
}
- if (reorder_type == 0)
- {
- if (sched_data.cur == 6)
- rotate_two_bundles (sched_verbose ? dump : NULL);
- else if (sched_data.cur >= 3)
- rotate_one_bundle (sched_verbose ? dump : NULL);
- sched_data.first_slot = sched_data.cur;
- }
-
return itanium_reorder (sched_verbose ? dump : NULL,
ready, e_ready, reorder_type == 1);
}
@@ -5993,7 +6159,7 @@ ia64_reorg (insns)
find_basic_blocks (insns, max_reg_num (), NULL);
life_analysis (insns, NULL, PROP_DEATH_NOTES);
- if (optimize)
+ if (ia64_flag_schedule_insns2)
{
ia64_final_schedule = 1;
schedule_ebbs (rtl_dump_file);
@@ -6006,6 +6172,33 @@ ia64_reorg (insns)
else
emit_all_insn_group_barriers (rtl_dump_file, insns);
+ /* A call must not be the last instruction in a function, so that the
+ return address is still within the function, so that unwinding works
+ properly. Note that IA-64 differs from dwarf2 on this point. */
+ if (flag_unwind_tables || (flag_exceptions && !USING_SJLJ_EXCEPTIONS))
+ {
+ rtx insn;
+ int saw_stop = 0;
+
+ insn = get_last_insn ();
+ if (! INSN_P (insn))
+ insn = prev_active_insn (insn);
+ if (GET_CODE (insn) == INSN
+ && GET_CODE (PATTERN (insn)) == UNSPEC_VOLATILE
+ && XINT (PATTERN (insn), 1) == 2)
+ {
+ saw_stop = 1;
+ insn = prev_active_insn (insn);
+ }
+ if (GET_CODE (insn) == CALL_INSN)
+ {
+ if (! saw_stop)
+ emit_insn (gen_insn_group_barrier (GEN_INT (3)));
+ emit_insn (gen_break_f ());
+ emit_insn (gen_insn_group_barrier (GEN_INT (3)));
+ }
+ }
+
fixup_errata ();
emit_predicate_relation_info ();
}
@@ -6030,10 +6223,10 @@ ia64_epilogue_uses (regno)
registers are marked as live at all function exits. This prevents the
register allocator from using the input registers, which in turn makes it
possible to restart a system call after an interrupt without having to
- save/restore the input registers. */
+ save/restore the input registers. This also prevents kernel data from
+ leaking to application code. */
if (IN_REGNO_P (regno)
- && (regno < IN_REG (current_function_args_info.words))
&& lookup_attribute ("syscall_linkage",
TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))))
return 1;
@@ -6187,7 +6380,32 @@ ia64_encode_section_info (decl)
}
}
-/* Output assmebly directives for prologue regions. */
+/* Output assembly directives for prologue regions. */
+
+/* The current basic block number. */
+
+static int block_num;
+
+/* True if we need a copy_state command at the start of the next block. */
+
+static int need_copy_state;
+
+/* The function emits unwind directives for the start of an epilogue. */
+
+static void
+process_epilogue ()
+{
+ /* If this isn't the last block of the function, then we need to label the
+ current state, and copy it back in at the start of the next block. */
+
+ if (block_num != n_basic_blocks - 1)
+ {
+ fprintf (asm_out_file, "\t.label_state 1\n");
+ need_copy_state = 1;
+ }
+
+ fprintf (asm_out_file, "\t.restore sp\n");
+}
/* This function processes a SET pattern looking for specific patterns
which result in emitting an assembly directive required for unwinding. */
@@ -6235,14 +6453,14 @@ process_set (asm_out_file, pat)
fputc ('\n', asm_out_file);
}
else
- fprintf (asm_out_file, "\t.restore sp\n");
+ process_epilogue ();
}
else
abort ();
}
else if (GET_CODE (src) == REG
&& REGNO (src) == HARD_FRAME_POINTER_REGNUM)
- fprintf (asm_out_file, "\t.restore sp\n");
+ process_epilogue ();
else
abort ();
@@ -6413,12 +6631,28 @@ process_for_unwind_directive (asm_out_file, insn)
FILE *asm_out_file;
rtx insn;
{
- if ((flag_unwind_tables
- || (flag_exceptions && !exceptions_via_longjmp))
- && RTX_FRAME_RELATED_P (insn))
+ if (flag_unwind_tables
+ || (flag_exceptions && !USING_SJLJ_EXCEPTIONS))
{
rtx pat;
+ if (GET_CODE (insn) == NOTE
+ && NOTE_LINE_NUMBER (insn) == NOTE_INSN_BASIC_BLOCK)
+ {
+ block_num = NOTE_BASIC_BLOCK (insn)->index;
+
+ /* Restore unwind state from immediately before the epilogue. */
+ if (need_copy_state)
+ {
+ fprintf (asm_out_file, "\t.body\n");
+ fprintf (asm_out_file, "\t.copy_state 1\n");
+ need_copy_state = 0;
+ }
+ }
+
+ if (! RTX_FRAME_RELATED_P (insn))
+ return;
+
pat = find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX);
if (pat)
pat = XEXP (pat, 0);
diff --git a/gcc/config/ia64/ia64.h b/gcc/config/ia64/ia64.h
index f0cd62e1a96..43d67d66123 100644
--- a/gcc/config/ia64/ia64.h
+++ b/gcc/config/ia64/ia64.h
@@ -227,7 +227,8 @@ extern const char *ia64_fixed_range_string;
`cc1'. It can also specify how to translate options you give to GNU CC into
options for GNU CC to pass to the `cc1'. */
-/* #define CC1_SPEC "" */
+#undef CC1_SPEC
+#define CC1_SPEC "%{G*}"
/* A C string constant that tells the GNU CC driver program options to pass to
`cc1plus'. It can also specify how to translate options you give to GNU CC
@@ -1382,11 +1383,15 @@ do { \
/* If defined, a C expression that gives the alignment boundary, in bits, of an
argument with the specified mode and type. */
-/* Arguments larger than 64 bits require 128 bit alignment. */
+/* Arguments with alignment larger than 8 bytes start at the next even
+ boundary. See ia64_function_arg. */
#define FUNCTION_ARG_BOUNDARY(MODE, TYPE) \
- (((((MODE) == BLKmode ? int_size_in_bytes (TYPE) : GET_MODE_SIZE (MODE)) \
- + UNITS_PER_WORD - 1) / UNITS_PER_WORD) > 1 ? 128 : PARM_BOUNDARY)
+ (((TYPE) ? (TYPE_ALIGN (TYPE) > 8 * BITS_PER_UNIT) \
+ : (((((MODE) == BLKmode \
+ ? int_size_in_bytes (TYPE) : GET_MODE_SIZE (MODE)) \
+ + UNITS_PER_WORD - 1) / UNITS_PER_WORD) > 1)) \
+ ? 128 : PARM_BOUNDARY)
/* A C expression that is nonzero if REGNO is the number of a hard register in
which function arguments are sometimes passed. This does *not* include
@@ -1966,7 +1971,9 @@ do { \
that encode section info. */
#define STRIP_NAME_ENCODING(VAR, SYMBOL_NAME) \
- (VAR) = (SYMBOL_NAME) + ((SYMBOL_NAME)[0] == SDATA_NAME_FLAG_CHAR)
+ (VAR) = ((SYMBOL_NAME) \
+ + (*(SYMBOL_NAME) == '*' || *(SYMBOL_NAME) == SDATA_NAME_FLAG_CHAR))
+
/* Position Independent Code. */
@@ -2144,19 +2151,6 @@ do { \
} while (0)
-/* Output EH data to the unwind segment. */
-#define ASM_OUTPUT_EH_CHAR(FILE, VALUE) \
- ASM_OUTPUT_XDATA_CHAR(FILE, ".IA_64.unwind_info", VALUE)
-
-#define ASM_OUTPUT_EH_SHORT(FILE, VALUE) \
- ASM_OUTPUT_XDATA_SHORT(FILE, ".IA_64.unwind_info", VALUE)
-
-#define ASM_OUTPUT_EH_INT(FILE, VALUE) \
- ASM_OUTPUT_XDATA_INT(FILE, ".IA_64.unwind_info", VALUE)
-
-#define ASM_OUTPUT_EH_DOUBLE_INT(FILE, VALUE) \
- ASM_OUTPUT_XDATA_DOUBLE_INT(FILE, ".IA_64.unwind_info", VALUE)
-
/* A C statement to output to the stdio stream STREAM an assembler instruction
to assemble a single byte containing the number VALUE. */
@@ -2468,70 +2462,33 @@ do { \
/* Assembler Commands for Exception Regions. */
-/* ??? This entire section of ia64.h needs to be implemented and then cleaned
- up. */
-
-/* A C expression to output text to mark the start of an exception region.
-
- This macro need not be defined on most platforms. */
-/* #define ASM_OUTPUT_EH_REGION_BEG() */
-
-/* A C expression to output text to mark the end of an exception region.
-
- This macro need not be defined on most platforms. */
-/* #define ASM_OUTPUT_EH_REGION_END() */
-
-/* A C expression to switch to the section in which the main exception table is
- to be placed. The default is a section named `.gcc_except_table' on machines
- that support named sections via `ASM_OUTPUT_SECTION_NAME', otherwise if `-fpic'
- or `-fPIC' is in effect, the `data_section', otherwise the
- `readonly_data_section'. */
-/* #define EXCEPTION_SECTION() */
-
-/* If defined, a C string constant for the assembler operation to switch to the
- section for exception handling frame unwind information. If not defined,
- GNU CC will provide a default definition if the target supports named
- sections. `crtstuff.c' uses this macro to switch to the appropriate
- section.
-
- You should define this symbol if your target supports DWARF 2 frame unwind
- information and the default definition does not work. */
-#define EH_FRAME_SECTION_ASM_OP "\t.section\t.IA_64.unwind,\"aw\""
-
-/* A C expression that is nonzero if the normal exception table output should
- be omitted.
-
- This macro need not be defined on most platforms. */
-/* #define OMIT_EH_TABLE() */
-
-/* Alternate runtime support for looking up an exception at runtime and finding
- the associated handler, if the default method won't work.
-
- This macro need not be defined on most platforms. */
-/* #define EH_TABLE_LOOKUP() */
-
-/* A C expression that decides whether or not the current function needs to
- have a function unwinder generated for it. See the file `except.c' for
- details on when to define this, and how. */
-/* #define DOESNT_NEED_UNWINDER */
-
-/* An rtx used to mask the return address found via RETURN_ADDR_RTX, so that it
- does not contain any extraneous set bits in it. */
-/* #define MASK_RETURN_ADDR */
-
-/* Define this macro to 0 if your target supports DWARF 2 frame unwind
- information, but it does not yet work with exception handling. Otherwise,
- if your target supports this information (if it defines
- `INCOMING_RETURN_ADDR_RTX' and either `UNALIGNED_INT_ASM_OP' or
- `OBJECT_FORMAT_ELF'), GCC will provide a default definition of 1.
-
- If this macro is defined to 1, the DWARF 2 unwinder will be the default
- exception handling mechanism; otherwise, setjmp/longjmp will be used by
- default.
-
- If this macro is defined to anything, the DWARF 2 unwinder will be used
- instead of inline unwinders and __unwind_function in the non-setjmp case. */
-/* #define DWARF2_UNWIND_INFO */
+/* Select a format to encode pointers in exception handling data. CODE
+ is 0 for data, 1 for code labels, 2 for function pointers. GLOBAL is
+ true if the symbol may be affected by dynamic relocations. */
+#define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL) \
+ (((CODE) == 1 ? DW_EH_PE_textrel : DW_EH_PE_datarel) \
+ | ((GLOBAL) ? DW_EH_PE_indirect : 0) | DW_EH_PE_udata8)
+
+/* Handle special EH pointer encodings. Absolute, pc-relative, and
+ indirect are handled automatically. */
+#define ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX(FILE, ENCODING, SIZE, ADDR, DONE) \
+ do { \
+ const char *reltag = NULL; \
+ if (((ENCODING) & 0xF0) == DW_EH_PE_textrel) \
+ reltag = "@segrel("; \
+ else if (((ENCODING) & 0xF0) == DW_EH_PE_datarel) \
+ reltag = "@gprel("; \
+ if (reltag) \
+ { \
+ fputs (((SIZE) == 4 ? UNALIGNED_INT_ASM_OP \
+ : (SIZE) == 8 ? UNALIGNED_DOUBLE_INT_ASM_OP \
+ : (abort (), "")), FILE); \
+ fputs (reltag, FILE); \
+ assemble_name (FILE, XSTR (ADDR, 0)); \
+ fputc (')', FILE); \
+ goto DONE; \
+ } \
+ } while (0)
/* Assembler Commands for Alignment. */
@@ -2838,9 +2795,10 @@ do { \
extern int ia64_final_schedule;
#define IA64_UNWIND_INFO 1
-#define HANDLER_SECTION fprintf (asm_out_file, "\t.personality\t__ia64_personality_v1\n\t.handlerdata\n");
#define IA64_UNWIND_EMIT(f,i) process_for_unwind_directive (f,i)
+#define EH_RETURN_DATA_REGNO(N) ((N) < 4 ? (N) + 15 : INVALID_REGNUM)
+
/* This function contains machine specific function data. */
struct machine_function
{
diff --git a/gcc/config/ia64/ia64.md b/gcc/config/ia64/ia64.md
index 7de8677ac21..b3f1f5d23eb 100644
--- a/gcc/config/ia64/ia64.md
+++ b/gcc/config/ia64/ia64.md
@@ -71,6 +71,7 @@
;; 0 alloc
;; 1 blockage
;; 2 insn_group_barrier
+;; 3 break
;; 5 set_bsp
;; 8 pred.safe_across_calls all
;; 9 pred.safe_across_calls normal
@@ -707,9 +708,9 @@
if (GET_CODE (operands[1]) == CONST_DOUBLE)
{
emit_move_insn (gen_rtx_REG (DImode, REGNO (operands[0])),
- operand_subword (operands[1], 0, 0, DImode));
+ operand_subword (operands[1], 0, 0, TFmode));
emit_move_insn (gen_rtx_REG (DImode, REGNO (operands[0]) + 1),
- operand_subword (operands[1], 1, 0, DImode));
+ operand_subword (operands[1], 1, 0, TFmode));
DONE;
}
@@ -821,80 +822,40 @@
;; Convert between floating point types of different sizes.
+;; At first glance, it would appear that emitting fnorm for an extending
+;; conversion is unnecessary. However, the stf and getf instructions work
+;; correctly only if the input is properly rounded for its type. In
+;; particular, we get the wrong result for getf.d/stfd if the input is a
+;; denorm single. Since we don't know what the next instruction will be, we
+;; have to emit an fnorm.
+
;; ??? Optimization opportunity here. Get rid of the insn altogether
;; when we can. Should probably use a scheme like has been proposed
;; for ia32 in dealing with operands that match unary operators. This
-;; would let combine merge the thing into adjacent insns.
+;; would let combine merge the thing into adjacent insns. See also how the
+;; mips port handles SIGN_EXTEND as operands to integer arithmetic insns via
+;; se_register_operand.
-(define_insn_and_split "extendsfdf2"
- [(set (match_operand:DF 0 "grfr_nonimmediate_operand" "=f,f,f,f,m,*r")
- (float_extend:DF
- (match_operand:SF 1 "grfr_nonimmediate_operand" "0,f,m,*r,f,f")))]
+(define_insn "extendsfdf2"
+ [(set (match_operand:DF 0 "fr_register_operand" "=f")
+ (float_extend:DF (match_operand:SF 1 "fr_register_operand" "f")))]
""
- "@
- mov %0 = %1
- mov %0 = %1
- ldfs %0 = %1%P1
- setf.s %0 = %1
- stfd %0 = %1%P0
- getf.d %0 = %1"
- "reload_completed"
- [(set (match_dup 0) (float_extend:DF (match_dup 1)))]
- "
-{
- if (true_regnum (operands[0]) == true_regnum (operands[1]))
- {
- emit_insn (gen_movdi (pic_offset_table_rtx, pic_offset_table_rtx));
- DONE;
- }
-}"
- [(set_attr "itanium_class" "unknown,fmisc,fld,tofr,stf,frfr")])
+ "fnorm.d %0 = %1"
+ [(set_attr "itanium_class" "fmac")])
-(define_insn_and_split "extendsftf2"
- [(set (match_operand:TF 0 "fr_nonimmediate_operand" "=f,f,f,f,Q")
- (float_extend:TF
- (match_operand:SF 1 "grfr_nonimmediate_operand" "0,f,Q,*r,f")))]
+(define_insn "extendsftf2"
+ [(set (match_operand:TF 0 "fr_register_operand" "=f")
+ (float_extend:TF (match_operand:SF 1 "fr_register_operand" "f")))]
""
- "@
- mov %0 = %1
- mov %0 = %1
- ldfs %0 = %1%P1
- setf.s %0 = %1
- stfe %0 = %1%P0"
- "reload_completed"
- [(set (match_dup 0) (float_extend:TF (match_dup 1)))]
- "
-{
- if (true_regnum (operands[0]) == true_regnum (operands[1]))
- {
- emit_insn (gen_movdi (pic_offset_table_rtx, pic_offset_table_rtx));
- DONE;
- }
-}"
- [(set_attr "itanium_class" "unknown,fmisc,fld,frfr,stf")])
+ "fnorm %0 = %1"
+ [(set_attr "itanium_class" "fmac")])
-(define_insn_and_split "extenddftf2"
- [(set (match_operand:TF 0 "fr_nonimmediate_operand" "=f,f,f,f,Q")
- (float_extend:TF
- (match_operand:DF 1 "grfr_nonimmediate_operand" "0,f,Q,*r,f")))]
+(define_insn "extenddftf2"
+ [(set (match_operand:TF 0 "fr_register_operand" "=f")
+ (float_extend:TF (match_operand:DF 1 "fr_register_operand" "f")))]
""
- "@
- mov %0 = %1
- mov %0 = %1
- ldfd %0 = %1%P1
- setf.d %0 = %1
- stfe %0 = %1%P0"
- "reload_completed"
- [(set (match_dup 0) (float_extend:TF (match_dup 1)))]
- "
-{
- if (true_regnum (operands[0]) == true_regnum (operands[1]))
- {
- emit_insn (gen_movdi (pic_offset_table_rtx, pic_offset_table_rtx));
- DONE;
- }
-}"
- [(set_attr "itanium_class" "unknown,fmisc,fld,frfr,stf")])
+ "fnorm %0 = %1"
+ [(set_attr "itanium_class" "fmac")])
(define_insn "truncdfsf2"
[(set (match_operand:SF 0 "fr_register_operand" "=f")
@@ -4980,6 +4941,11 @@
[(set_attr "itanium_class" "stop_bit")
(set_attr "predicable" "no")])
+(define_insn "break_f"
+ [(unspec_volatile [(const_int 0)] 3)]
+ ""
+ "break.f 0"
+ [(set_attr "itanium_class" "nop_f")])
;; Non-local goto support.
@@ -5005,7 +4971,7 @@
"
{
emit_library_call (gen_rtx_SYMBOL_REF (Pmode, \"__ia64_nonlocal_goto\"),
- 0, VOIDmode, 3,
+ LCT_NORETURN, VOIDmode, 3,
operands[1], Pmode,
copy_to_reg (XEXP (operands[2], 0)), Pmode,
operands[3], Pmode);
@@ -5013,13 +4979,6 @@
DONE;
}")
-;; Restore the GP after the exception/longjmp. The preceeding call will
-;; have tucked it away.
-(define_expand "exception_receiver"
- [(set (reg:DI 1) (match_dup 0))]
- ""
- "operands[0] = ia64_gp_save_reg (0);")
-
;; The rest of the setjmp processing happens with the nonlocal_goto expander.
;; ??? This is not tested.
(define_expand "builtin_setjmp_setup"
diff --git a/gcc/config/ia64/lib1funcs.asm b/gcc/config/ia64/lib1funcs.asm
index 67f0a89ce61..75e79b0a0f7 100644
--- a/gcc/config/ia64/lib1funcs.asm
+++ b/gcc/config/ia64/lib1funcs.asm
@@ -17,27 +17,26 @@ __divtf3:
(p6) cmp.ne p7, p0 = r0, r0
.pred.rel.mutex p6, p7
(p6) fnma.s1 f11 = farg1, f10, f1
-(p6) fmpy.s1 f12 = farg0, f10
+(p6) fma.s1 f12 = farg0, f10, f0
;;
-(p6) fmpy.s1 f13 = f11, f11
+(p6) fma.s1 f13 = f11, f11, f0
(p6) fma.s1 f14 = f11, f11, f11
;;
(p6) fma.s1 f11 = f13, f13, f11
(p6) fma.s1 f13 = f14, f10, f10
;;
(p6) fma.s1 f10 = f13, f11, f10
-(p6) fnma.s1 f12 = farg1, f12, farg0
+(p6) fnma.s1 f11 = farg1, f12, farg0
;;
(p6) fma.s1 f11 = f11, f10, f12
-(p6) fnma.s1 f13 = farg1, f10, f1
+(p6) fnma.s1 f12 = farg1, f10, f1
;;
(p6) fma.s1 f10 = f12, f10, f10
(p6) fnma.s1 f12 = farg1, f11, farg0
;;
-(p6) fma fret0 = f12, f10, f11
+(p6) fma.s0 fret0 = f12, f10, f11
(p7) mov fret0 = f10
br.ret.sptk rp
- ;;
.endp __divtf3
#endif
diff --git a/gcc/config/ia64/libgcc-ia64.ver b/gcc/config/ia64/libgcc-ia64.ver
index a03799f0d09..2ffb6936864 100644
--- a/gcc/config/ia64/libgcc-ia64.ver
+++ b/gcc/config/ia64/libgcc-ia64.ver
@@ -5,4 +5,5 @@ GCC_3.0 {
__ia64_restore_stack_nonlocal
__ia64_save_stack_nonlocal
__ia64_trampoline
+ __ia64_backtrace
}
diff --git a/gcc/config/ia64/linux.h b/gcc/config/ia64/linux.h
index 35934e9ebee..2bb71eb2c21 100644
--- a/gcc/config/ia64/linux.h
+++ b/gcc/config/ia64/linux.h
@@ -3,6 +3,10 @@
#include <linux.h>
#include "sysv4.h"
+/* This is for -profile to use -lc_p instead of -lc. */
+#undef CC1_SPEC
+#define CC1_SPEC "%{profile:-p} %{G*}"
+
/* ??? Maybe this should be in sysv4.h? */
#define CPP_PREDEFINES "\
-D__ia64 -D__ia64__ -D__linux -D__linux__ -D_LONGLONG -Dlinux -Dunix \
diff --git a/gcc/config/ia64/sysv4.h b/gcc/config/ia64/sysv4.h
index f4e40754fb6..99f561cb7ab 100644
--- a/gcc/config/ia64/sysv4.h
+++ b/gcc/config/ia64/sysv4.h
@@ -133,13 +133,6 @@ while (0)
#undef WCHAR_TYPE_SIZE
#define WCHAR_TYPE_SIZE 32
-/* We don't want any symbol at the beginning of the file. This is defined in
- dbxelf.h which is included from elfos.h, so we need to undef/define it
- here. */
-
-#undef ASM_IDENTIFY_GCC
-#define ASM_IDENTIFY_GCC(FILE)
-
/* We redefine this to use the ia64 .proc pseudo-op. */
#undef ASM_DECLARE_FUNCTION_NAME
diff --git a/gcc/config/ia64/t-hpux b/gcc/config/ia64/t-hpux
new file mode 100644
index 00000000000..4aa43876eaf
--- /dev/null
+++ b/gcc/config/ia64/t-hpux
@@ -0,0 +1,6 @@
+# HP-UX gets an undefined main when building LIBGCC1_TEST because the
+# linkspec has "-u main" and we want that for linking but it makes
+# LIBGCC1_TEST fail because it uses -nostdlib -nostartup and main is
+# not defined in the test program.
+
+LIBGCC1_TEST =
diff --git a/gcc/config/ia64/t-ia64 b/gcc/config/ia64/t-ia64
index f27c72957d0..274f9a44826 100644
--- a/gcc/config/ia64/t-ia64
+++ b/gcc/config/ia64/t-ia64
@@ -41,5 +41,4 @@ crtendS.o: $(srcdir)/config/ia64/crtend.asm $(GCC_PASSES)
$(GCC_FOR_TARGET) -DSHARED -c -o crtendS.o -x assembler-with-cpp $(srcdir)/config/ia64/crtend.asm
EXTRA_HEADERS = $(srcdir)/config/ia64/ia64intrin.h
-LIB2ADDEH = $(srcdir)/config/ia64/frame-ia64.c
-
+LIB2ADDEH = $(srcdir)/config/ia64/unwind-ia64.c $(srcdir)/unwind-sjlj.c
diff --git a/gcc/config/ia64/unwind-ia64.c b/gcc/config/ia64/unwind-ia64.c
new file mode 100644
index 00000000000..15d668303e1
--- /dev/null
+++ b/gcc/config/ia64/unwind-ia64.c
@@ -0,0 +1,2015 @@
+/* Subroutines needed for unwinding IA-64 standard format stack frame
+ info for exception handling.
+ Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+ Contributed by Andrew MacLeod <amacleod@cygnus.com>
+ Andrew Haley <aph@cygnus.com>
+ David Mosberger-Tang <davidm@hpl.hp.com>
+
+ This file is part of GNU CC.
+
+ GNU CC is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU CC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU CC; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+/* As a special exception, if you link this library with other files,
+ some of which are compiled with GCC, to produce an executable,
+ this library does not by itself cause the resulting executable
+ to be covered by the GNU General Public License.
+ This exception does not however invalidate any other reasons why
+ the executable file might be covered by the GNU General Public License. */
+
+
+#include "tconfig.h"
+#include "tsystem.h"
+#include "unwind.h"
+#include "unwind-ia64.h"
+
+#if !USING_SJLJ_EXCEPTIONS
+
+#define inline
+
+#define UNW_VER(x) ((x) >> 48)
+#define UNW_FLAG_MASK 0x0000ffff00000000
+#define UNW_FLAG_OSMASK 0x0000f00000000000
+#define UNW_FLAG_EHANDLER(x) ((x) & 0x0000000100000000L)
+#define UNW_FLAG_UHANDLER(x) ((x) & 0x0000000200000000L)
+#define UNW_LENGTH(x) ((x) & 0x00000000ffffffffL)
+
+enum unw_application_register
+{
+ UNW_AR_BSP,
+ UNW_AR_BSPSTORE,
+ UNW_AR_PFS,
+ UNW_AR_RNAT,
+ UNW_AR_UNAT,
+ UNW_AR_LC,
+ UNW_AR_EC,
+ UNW_AR_FPSR,
+ UNW_AR_RSC,
+ UNW_AR_CCV
+};
+
+enum unw_register_index
+{
+ /* Primary UNAT. */
+ UNW_REG_PRI_UNAT_GR,
+ UNW_REG_PRI_UNAT_MEM,
+
+ /* Memory Stack. */
+ UNW_REG_PSP, /* previous memory stack pointer */
+
+ /* Register Stack. */
+ UNW_REG_BSP, /* register stack pointer */
+ UNW_REG_BSPSTORE,
+ UNW_REG_PFS, /* previous function state */
+ UNW_REG_RNAT,
+ /* Return Pointer. */
+ UNW_REG_RP,
+
+ /* Special preserved registers. */
+ UNW_REG_UNAT, UNW_REG_PR, UNW_REG_LC, UNW_REG_FPSR,
+
+ /* Non-stacked general registers. */
+ UNW_REG_R2,
+ UNW_REG_R4 = UNW_REG_R2 + 2,
+ UNW_REG_R7 = UNW_REG_R2 + 5,
+ UNW_REG_R31 = UNW_REG_R2 + 29,
+
+ /* Non-stacked floating point registers. */
+ UNW_REG_F2,
+ UNW_REG_F5 = UNW_REG_F2 + 3,
+ UNW_REG_F16 = UNW_REG_F2 + 14,
+ UNW_REG_F31 = UNW_REG_F2 + 29,
+
+ /* Branch registers. */
+ UNW_REG_B1,
+ UNW_REG_B5 = UNW_REG_B1 + 4,
+
+ UNW_NUM_REGS
+};
+
+enum unw_where
+{
+ UNW_WHERE_NONE, /* register isn't saved at all */
+ UNW_WHERE_GR, /* register is saved in a general register */
+ UNW_WHERE_FR, /* register is saved in a floating-point register */
+ UNW_WHERE_BR, /* register is saved in a branch register */
+ UNW_WHERE_SPREL, /* register is saved on memstack (sp-relative) */
+ UNW_WHERE_PSPREL, /* register is saved on memstack (psp-relative) */
+
+ /* At the end of each prologue these locations get resolved to
+ UNW_WHERE_PSPREL and UNW_WHERE_GR, respectively. */
+ UNW_WHERE_SPILL_HOME, /* register is saved in its spill home */
+ UNW_WHERE_GR_SAVE /* register is saved in next general register */
+};
+
+#define UNW_WHEN_NEVER 0x7fffffff
+
+struct unw_reg_info
+{
+ unsigned long val; /* save location: register number or offset */
+ enum unw_where where; /* where the register gets saved */
+ int when; /* when the register gets saved */
+};
+
+typedef struct unw_state_record
+{
+ unsigned int first_region : 1; /* is this the first region? */
+ unsigned int done : 1; /* are we done scanning descriptors? */
+ unsigned int any_spills : 1; /* got any register spills? */
+ unsigned int in_body : 1; /* are we inside a body? */
+
+ unsigned char *imask; /* imask of of spill_mask record or NULL */
+ unsigned long pr_val; /* predicate values */
+ unsigned long pr_mask; /* predicate mask */
+ long spill_offset; /* psp-relative offset for spill base */
+ int region_start;
+ int region_len;
+ int epilogue_start;
+ int epilogue_count;
+ int when_target;
+
+ unsigned char gr_save_loc; /* next general register to use for saving */
+ unsigned char return_link_reg; /* branch register for return link */
+
+ struct unw_reg_state {
+ struct unw_reg_state *next;
+ unsigned long label; /* label of this state record */
+ struct unw_reg_info reg[UNW_NUM_REGS];
+ } curr, *stack, *reg_state_list;
+
+ _Unwind_Personality_Fn personality;
+
+} _Unwind_FrameState;
+
+enum unw_nat_type
+{
+ UNW_NAT_NONE, /* NaT not represented */
+ UNW_NAT_VAL, /* NaT represented by NaT value (fp reg) */
+ UNW_NAT_MEMSTK, /* NaT value is in unat word at offset OFF */
+ UNW_NAT_REGSTK /* NaT is in rnat */
+};
+
+struct unw_stack
+{
+ unsigned long limit;
+ unsigned long top;
+};
+
+struct _Unwind_Context
+{
+ /* Initial frame info. */
+ unsigned long rnat; /* rse nat collection */
+ unsigned long regstk_top; /* bsp for first frame */
+
+ /* Current frame info. */
+ unsigned long bsp; /* backing store pointer value */
+ unsigned long sp; /* stack pointer value */
+ unsigned long psp; /* previous sp value */
+ unsigned long rp; /* return pointer */
+ unsigned long pr; /* predicate collection */
+
+ unsigned long region_start; /* start of unwind region */
+ unsigned long gp; /* global pointer value */
+ void *lsda; /* language specific data area */
+
+ /* Preserved state. */
+ unsigned long *bsp_loc; /* previous bsp save location */
+ unsigned long *bspstore_loc;
+ unsigned long *pfs_loc;
+ unsigned long *pri_unat_loc;
+ unsigned long *unat_loc;
+ unsigned long *lc_loc;
+ unsigned long *fpsr_loc;
+
+ unsigned long eh_data[4];
+
+ struct unw_ireg
+ {
+ unsigned long *loc;
+ struct unw_ireg_nat
+ {
+ enum unw_nat_type type : 3;
+ signed long off : 61; /* NaT word is at loc+nat.off */
+ } nat;
+ } ireg[32 - 2];
+
+ unsigned long *br_loc[6 - 1];
+ void *fr_loc[32 - 2];
+};
+
+typedef unsigned long unw_word;
+
+/* Implicit register save order. See section 11.4.2.3 Rules for Using
+ Unwind Descriptors, rule 3. */
+
+static unsigned char const save_order[] =
+{
+ UNW_REG_RP, UNW_REG_PFS, UNW_REG_PSP, UNW_REG_PR,
+ UNW_REG_UNAT, UNW_REG_LC, UNW_REG_FPSR, UNW_REG_PRI_UNAT_GR
+};
+
+
+#define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
+
+/* Unwind decoder routines */
+
+static void
+push (struct unw_state_record *sr)
+{
+ struct unw_reg_state *rs;
+
+ rs = malloc (sizeof (struct unw_reg_state));
+ memcpy (rs, &sr->curr, sizeof (*rs));
+ rs->next = sr->stack;
+ sr->stack = rs;
+}
+
+static void
+pop (struct unw_state_record *sr)
+{
+ struct unw_reg_state *rs;
+
+ rs = sr->stack;
+ sr->stack = rs->next;
+ free (rs);
+}
+
+static enum unw_register_index __attribute__((const))
+decode_abreg (unsigned char abreg, int memory)
+{
+ switch (abreg)
+ {
+ case 0x04 ... 0x07: return UNW_REG_R4 + (abreg - 0x04);
+ case 0x22 ... 0x25: return UNW_REG_F2 + (abreg - 0x22);
+ case 0x30 ... 0x3f: return UNW_REG_F16 + (abreg - 0x30);
+ case 0x41 ... 0x45: return UNW_REG_B1 + (abreg - 0x41);
+ case 0x60: return UNW_REG_PR;
+ case 0x61: return UNW_REG_PSP;
+ case 0x62: return memory ? UNW_REG_PRI_UNAT_MEM : UNW_REG_PRI_UNAT_GR;
+ case 0x63: return UNW_REG_RP;
+ case 0x64: return UNW_REG_BSP;
+ case 0x65: return UNW_REG_BSPSTORE;
+ case 0x66: return UNW_REG_RNAT;
+ case 0x67: return UNW_REG_UNAT;
+ case 0x68: return UNW_REG_FPSR;
+ case 0x69: return UNW_REG_PFS;
+ case 0x6a: return UNW_REG_LC;
+ default:
+ abort ();
+ }
+}
+
+static void
+set_reg (struct unw_reg_info *reg, enum unw_where where,
+ int when, unsigned long val)
+{
+ reg->val = val;
+ reg->where = where;
+ if (reg->when == UNW_WHEN_NEVER)
+ reg->when = when;
+}
+
+static void
+alloc_spill_area (unsigned long *offp, unsigned long regsize,
+ struct unw_reg_info *lo, struct unw_reg_info *hi)
+{
+ struct unw_reg_info *reg;
+
+ for (reg = hi; reg >= lo; --reg)
+ {
+ if (reg->where == UNW_WHERE_SPILL_HOME)
+ {
+ reg->where = UNW_WHERE_PSPREL;
+ reg->val = 0x10 - *offp;
+ *offp += regsize;
+ }
+ }
+}
+
+static inline void
+spill_next_when (struct unw_reg_info **regp, struct unw_reg_info *lim,
+ unw_word t)
+{
+ struct unw_reg_info *reg;
+
+ for (reg = *regp; reg <= lim; ++reg)
+ {
+ if (reg->where == UNW_WHERE_SPILL_HOME)
+ {
+ reg->when = t;
+ *regp = reg + 1;
+ return;
+ }
+ }
+ /* Excess spill. */
+ abort ();
+}
+
+static void
+finish_prologue (struct unw_state_record *sr)
+{
+ struct unw_reg_info *reg;
+ unsigned long off;
+ int i;
+
+ /* First, resolve implicit register save locations
+ (see Section "11.4.2.3 Rules for Using Unwind Descriptors", rule 3). */
+
+ for (i = 0; i < (int) sizeof(save_order); ++i)
+ {
+ reg = sr->curr.reg + save_order[i];
+ if (reg->where == UNW_WHERE_GR_SAVE)
+ {
+ reg->where = UNW_WHERE_GR;
+ reg->val = sr->gr_save_loc++;
+ }
+ }
+
+ /* Next, compute when the fp, general, and branch registers get saved.
+ This must come before alloc_spill_area() because we need to know
+ which registers are spilled to their home locations. */
+ if (sr->imask)
+ {
+ static unsigned char const limit[3] = {
+ UNW_REG_F31, UNW_REG_R7, UNW_REG_B5
+ };
+
+ unsigned char kind, mask = 0, *cp = sr->imask;
+ int t;
+ struct unw_reg_info *(regs[3]);
+
+ regs[0] = sr->curr.reg + UNW_REG_F2;
+ regs[1] = sr->curr.reg + UNW_REG_R4;
+ regs[2] = sr->curr.reg + UNW_REG_B1;
+
+ for (t = 0; t < sr->region_len; ++t)
+ {
+ if ((t & 3) == 0)
+ mask = *cp++;
+ kind = (mask >> 2*(3-(t & 3))) & 3;
+ if (kind > 0)
+ spill_next_when(&regs[kind - 1], sr->curr.reg + limit[kind - 1],
+ sr->region_start + t);
+ }
+ }
+
+ /* Next, lay out the memory stack spill area. */
+ if (sr->any_spills)
+ {
+ off = sr->spill_offset;
+ alloc_spill_area(&off, 16, sr->curr.reg + UNW_REG_F2,
+ sr->curr.reg + UNW_REG_F31);
+ alloc_spill_area(&off, 8, sr->curr.reg + UNW_REG_B1,
+ sr->curr.reg + UNW_REG_B5);
+ alloc_spill_area(&off, 8, sr->curr.reg + UNW_REG_R4,
+ sr->curr.reg + UNW_REG_R7);
+ }
+}
+
+/*
+ * Region header descriptors.
+ */
+
+static void
+desc_prologue (int body, unw_word rlen, unsigned char mask,
+ unsigned char grsave, struct unw_state_record *sr)
+{
+ int i;
+
+ if (!(sr->in_body || sr->first_region))
+ finish_prologue(sr);
+ sr->first_region = 0;
+
+ /* Check if we're done. */
+ if (body && sr->when_target < sr->region_start + sr->region_len)
+ {
+ sr->done = 1;
+ return;
+ }
+
+ for (i = 0; i < sr->epilogue_count; ++i)
+ pop(sr);
+ sr->epilogue_count = 0;
+ sr->epilogue_start = UNW_WHEN_NEVER;
+
+ if (!body)
+ push(sr);
+
+ sr->region_start += sr->region_len;
+ sr->region_len = rlen;
+ sr->in_body = body;
+
+ if (!body)
+ {
+ for (i = 0; i < 4; ++i)
+ {
+ if (mask & 0x8)
+ set_reg (sr->curr.reg + save_order[i], UNW_WHERE_GR,
+ sr->region_start + sr->region_len - 1, grsave++);
+ mask <<= 1;
+ }
+ sr->gr_save_loc = grsave;
+ sr->any_spills = 0;
+ sr->imask = 0;
+ sr->spill_offset = 0x10; /* default to psp+16 */
+ }
+}
+
+/*
+ * Prologue descriptors.
+ */
+
+static inline void
+desc_abi (unsigned char abi __attribute__((unused)),
+ unsigned char context __attribute__((unused)),
+ struct unw_state_record *sr __attribute__((unused)))
+{
+ /* Anything to do? */
+}
+
+static inline void
+desc_br_gr (unsigned char brmask, unsigned char gr,
+ struct unw_state_record *sr)
+{
+ int i;
+
+ for (i = 0; i < 5; ++i)
+ {
+ if (brmask & 1)
+ set_reg (sr->curr.reg + UNW_REG_B1 + i, UNW_WHERE_GR,
+ sr->region_start + sr->region_len - 1, gr++);
+ brmask >>= 1;
+ }
+}
+
+static inline void
+desc_br_mem (unsigned char brmask, struct unw_state_record *sr)
+{
+ int i;
+
+ for (i = 0; i < 5; ++i)
+ {
+ if (brmask & 1)
+ {
+ set_reg (sr->curr.reg + UNW_REG_B1 + i, UNW_WHERE_SPILL_HOME,
+ sr->region_start + sr->region_len - 1, 0);
+ sr->any_spills = 1;
+ }
+ brmask >>= 1;
+ }
+}
+
+static inline void
+desc_frgr_mem (unsigned char grmask, unw_word frmask,
+ struct unw_state_record *sr)
+{
+ int i;
+
+ for (i = 0; i < 4; ++i)
+ {
+ if ((grmask & 1) != 0)
+ {
+ set_reg (sr->curr.reg + UNW_REG_R4 + i, UNW_WHERE_SPILL_HOME,
+ sr->region_start + sr->region_len - 1, 0);
+ sr->any_spills = 1;
+ }
+ grmask >>= 1;
+ }
+ for (i = 0; i < 20; ++i)
+ {
+ if ((frmask & 1) != 0)
+ {
+ set_reg (sr->curr.reg + UNW_REG_F2 + i, UNW_WHERE_SPILL_HOME,
+ sr->region_start + sr->region_len - 1, 0);
+ sr->any_spills = 1;
+ }
+ frmask >>= 1;
+ }
+}
+
+static inline void
+desc_fr_mem (unsigned char frmask, struct unw_state_record *sr)
+{
+ int i;
+
+ for (i = 0; i < 4; ++i)
+ {
+ if ((frmask & 1) != 0)
+ {
+ set_reg (sr->curr.reg + UNW_REG_F2 + i, UNW_WHERE_SPILL_HOME,
+ sr->region_start + sr->region_len - 1, 0);
+ sr->any_spills = 1;
+ }
+ frmask >>= 1;
+ }
+}
+
+static inline void
+desc_gr_gr (unsigned char grmask, unsigned char gr,
+ struct unw_state_record *sr)
+{
+ int i;
+
+ for (i = 0; i < 4; ++i)
+ {
+ if ((grmask & 1) != 0)
+ set_reg (sr->curr.reg + UNW_REG_R4 + i, UNW_WHERE_GR,
+ sr->region_start + sr->region_len - 1, gr++);
+ grmask >>= 1;
+ }
+}
+
+static inline void
+desc_gr_mem (unsigned char grmask, struct unw_state_record *sr)
+{
+ int i;
+
+ for (i = 0; i < 4; ++i)
+ {
+ if ((grmask & 1) != 0)
+ {
+ set_reg (sr->curr.reg + UNW_REG_R4 + i, UNW_WHERE_SPILL_HOME,
+ sr->region_start + sr->region_len - 1, 0);
+ sr->any_spills = 1;
+ }
+ grmask >>= 1;
+ }
+}
+
+static inline void
+desc_mem_stack_f (unw_word t, unw_word size, struct unw_state_record *sr)
+{
+ set_reg (sr->curr.reg + UNW_REG_PSP, UNW_WHERE_NONE,
+ sr->region_start + MIN ((int)t, sr->region_len - 1), 16*size);
+}
+
+static inline void
+desc_mem_stack_v (unw_word t, struct unw_state_record *sr)
+{
+ sr->curr.reg[UNW_REG_PSP].when
+ = sr->region_start + MIN ((int)t, sr->region_len - 1);
+}
+
+static inline void
+desc_reg_gr (unsigned char reg, unsigned char dst, struct unw_state_record *sr)
+{
+ set_reg (sr->curr.reg + reg, UNW_WHERE_GR,
+ sr->region_start + sr->region_len - 1, dst);
+}
+
+static inline void
+desc_reg_psprel (unsigned char reg, unw_word pspoff,
+ struct unw_state_record *sr)
+{
+ set_reg (sr->curr.reg + reg, UNW_WHERE_PSPREL,
+ sr->region_start + sr->region_len - 1,
+ 0x10 - 4*pspoff);
+}
+
+static inline void
+desc_reg_sprel (unsigned char reg, unw_word spoff, struct unw_state_record *sr)
+{
+ set_reg (sr->curr.reg + reg, UNW_WHERE_SPREL,
+ sr->region_start + sr->region_len - 1,
+ 4*spoff);
+}
+
+static inline void
+desc_rp_br (unsigned char dst, struct unw_state_record *sr)
+{
+ sr->return_link_reg = dst;
+}
+
+static inline void
+desc_reg_when (unsigned char regnum, unw_word t, struct unw_state_record *sr)
+{
+ struct unw_reg_info *reg = sr->curr.reg + regnum;
+
+ if (reg->where == UNW_WHERE_NONE)
+ reg->where = UNW_WHERE_GR_SAVE;
+ reg->when = sr->region_start + MIN ((int)t, sr->region_len - 1);
+}
+
+static inline void
+desc_spill_base (unw_word pspoff, struct unw_state_record *sr)
+{
+ sr->spill_offset = 0x10 - 4*pspoff;
+}
+
+static inline unsigned char *
+desc_spill_mask (unsigned char *imaskp, struct unw_state_record *sr)
+{
+ sr->imask = imaskp;
+ return imaskp + (2*sr->region_len + 7)/8;
+}
+
+/*
+ * Body descriptors.
+ */
+static inline void
+desc_epilogue (unw_word t, unw_word ecount, struct unw_state_record *sr)
+{
+ sr->epilogue_start = sr->region_start + sr->region_len - 1 - t;
+ sr->epilogue_count = ecount + 1;
+}
+
+static inline void
+desc_copy_state (unw_word label, struct unw_state_record *sr)
+{
+ struct unw_reg_state *rs;
+
+ for (rs = sr->reg_state_list; rs; rs = rs->next)
+ {
+ if (rs->label == label)
+ {
+ memcpy (&sr->curr, rs, sizeof(sr->curr));
+ return;
+ }
+ }
+ abort ();
+}
+
+static inline void
+desc_label_state (unw_word label, struct unw_state_record *sr)
+{
+ struct unw_reg_state *rs;
+
+ rs = malloc (sizeof (struct unw_reg_state));
+ memcpy (rs, &sr->curr, sizeof (*rs));
+ rs->label = label;
+ rs->next = sr->reg_state_list;
+ sr->reg_state_list = rs;
+}
+
+/*
+ * General descriptors.
+ */
+
+static inline int
+desc_is_active (unsigned char qp, unw_word t, struct unw_state_record *sr)
+{
+ if (sr->when_target <= sr->region_start + MIN ((int)t, sr->region_len - 1))
+ return 0;
+ if (qp > 0)
+ {
+ if ((sr->pr_val & (1UL << qp)) == 0)
+ return 0;
+ sr->pr_mask |= (1UL << qp);
+ }
+ return 1;
+}
+
+static inline void
+desc_restore_p (unsigned char qp, unw_word t, unsigned char abreg,
+ struct unw_state_record *sr)
+{
+ struct unw_reg_info *r;
+
+ if (! desc_is_active (qp, t, sr))
+ return;
+
+ r = sr->curr.reg + decode_abreg (abreg, 0);
+ r->where = UNW_WHERE_NONE;
+ r->when = sr->region_start + MIN ((int)t, sr->region_len - 1);
+ r->val = 0;
+}
+
+static inline void
+desc_spill_reg_p (unsigned char qp, unw_word t, unsigned char abreg,
+ unsigned char x, unsigned char ytreg,
+ struct unw_state_record *sr)
+{
+ enum unw_where where = UNW_WHERE_GR;
+ struct unw_reg_info *r;
+
+ if (! desc_is_active (qp, t, sr))
+ return;
+
+ if (x)
+ where = UNW_WHERE_BR;
+ else if (ytreg & 0x80)
+ where = UNW_WHERE_FR;
+
+ r = sr->curr.reg + decode_abreg (abreg, 0);
+ r->where = where;
+ r->when = sr->region_start + MIN ((int)t, sr->region_len - 1);
+ r->val = ytreg & 0x7f;
+}
+
+static inline void
+desc_spill_psprel_p (unsigned char qp, unw_word t, unsigned char abreg,
+ unw_word pspoff, struct unw_state_record *sr)
+{
+ struct unw_reg_info *r;
+
+ if (! desc_is_active (qp, t, sr))
+ return;
+
+ r = sr->curr.reg + decode_abreg (abreg, 1);
+ r->where = UNW_WHERE_PSPREL;
+ r->when = sr->region_start + MIN((int)t, sr->region_len - 1);
+ r->val = 0x10 - 4*pspoff;
+}
+
+static inline void
+desc_spill_sprel_p (unsigned char qp, unw_word t, unsigned char abreg,
+ unw_word spoff, struct unw_state_record *sr)
+{
+ struct unw_reg_info *r;
+
+ if (! desc_is_active (qp, t, sr))
+ return;
+
+ r = sr->curr.reg + decode_abreg (abreg, 1);
+ r->where = UNW_WHERE_SPREL;
+ r->when = sr->region_start + MIN ((int)t, sr->region_len - 1);
+ r->val = 4*spoff;
+}
+
+
+#define UNW_DEC_BAD_CODE(code) abort ();
+
+/* Region headers. */
+#define UNW_DEC_PROLOGUE_GR(fmt,r,m,gr,arg) desc_prologue(0,r,m,gr,arg)
+#define UNW_DEC_PROLOGUE(fmt,b,r,arg) desc_prologue(b,r,0,32,arg)
+
+/* Prologue descriptors. */
+#define UNW_DEC_ABI(fmt,a,c,arg) desc_abi(a,c,arg)
+#define UNW_DEC_BR_GR(fmt,b,g,arg) desc_br_gr(b,g,arg)
+#define UNW_DEC_BR_MEM(fmt,b,arg) desc_br_mem(b,arg)
+#define UNW_DEC_FRGR_MEM(fmt,g,f,arg) desc_frgr_mem(g,f,arg)
+#define UNW_DEC_FR_MEM(fmt,f,arg) desc_fr_mem(f,arg)
+#define UNW_DEC_GR_GR(fmt,m,g,arg) desc_gr_gr(m,g,arg)
+#define UNW_DEC_GR_MEM(fmt,m,arg) desc_gr_mem(m,arg)
+#define UNW_DEC_MEM_STACK_F(fmt,t,s,arg) desc_mem_stack_f(t,s,arg)
+#define UNW_DEC_MEM_STACK_V(fmt,t,arg) desc_mem_stack_v(t,arg)
+#define UNW_DEC_REG_GR(fmt,r,d,arg) desc_reg_gr(r,d,arg)
+#define UNW_DEC_REG_PSPREL(fmt,r,o,arg) desc_reg_psprel(r,o,arg)
+#define UNW_DEC_REG_SPREL(fmt,r,o,arg) desc_reg_sprel(r,o,arg)
+#define UNW_DEC_REG_WHEN(fmt,r,t,arg) desc_reg_when(r,t,arg)
+#define UNW_DEC_PRIUNAT_WHEN_GR(fmt,t,arg) desc_reg_when(UNW_REG_PRI_UNAT_GR,t,arg)
+#define UNW_DEC_PRIUNAT_WHEN_MEM(fmt,t,arg) desc_reg_when(UNW_REG_PRI_UNAT_MEM,t,arg)
+#define UNW_DEC_PRIUNAT_GR(fmt,r,arg) desc_reg_gr(UNW_REG_PRI_UNAT_GR,r,arg)
+#define UNW_DEC_PRIUNAT_PSPREL(fmt,o,arg) desc_reg_psprel(UNW_REG_PRI_UNAT_MEM,o,arg)
+#define UNW_DEC_PRIUNAT_SPREL(fmt,o,arg) desc_reg_sprel(UNW_REG_PRI_UNAT_MEM,o,arg)
+#define UNW_DEC_RP_BR(fmt,d,arg) desc_rp_br(d,arg)
+#define UNW_DEC_SPILL_BASE(fmt,o,arg) desc_spill_base(o,arg)
+#define UNW_DEC_SPILL_MASK(fmt,m,arg) (m = desc_spill_mask(m,arg))
+
+/* Body descriptors. */
+#define UNW_DEC_EPILOGUE(fmt,t,c,arg) desc_epilogue(t,c,arg)
+#define UNW_DEC_COPY_STATE(fmt,l,arg) desc_copy_state(l,arg)
+#define UNW_DEC_LABEL_STATE(fmt,l,arg) desc_label_state(l,arg)
+
+/* General unwind descriptors. */
+#define UNW_DEC_SPILL_REG_P(f,p,t,a,x,y,arg) desc_spill_reg_p(p,t,a,x,y,arg)
+#define UNW_DEC_SPILL_REG(f,t,a,x,y,arg) desc_spill_reg_p(0,t,a,x,y,arg)
+#define UNW_DEC_SPILL_PSPREL_P(f,p,t,a,o,arg) desc_spill_psprel_p(p,t,a,o,arg)
+#define UNW_DEC_SPILL_PSPREL(f,t,a,o,arg) desc_spill_psprel_p(0,t,a,o,arg)
+#define UNW_DEC_SPILL_SPREL_P(f,p,t,a,o,arg) desc_spill_sprel_p(p,t,a,o,arg)
+#define UNW_DEC_SPILL_SPREL(f,t,a,o,arg) desc_spill_sprel_p(0,t,a,o,arg)
+#define UNW_DEC_RESTORE_P(f,p,t,a,arg) desc_restore_p(p,t,a,arg)
+#define UNW_DEC_RESTORE(f,t,a,arg) desc_restore_p(0,t,a,arg)
+
+
+/*
+ * Generic IA-64 unwind info decoder.
+ *
+ * This file is used both by the Linux kernel and objdump. Please keep
+ * the copies of this file in sync.
+ *
+ * You need to customize the decoder by defining the following
+ * macros/constants before including this file:
+ *
+ * Types:
+ * unw_word Unsigned integer type with at least 64 bits
+ *
+ * Register names:
+ * UNW_REG_BSP
+ * UNW_REG_BSPSTORE
+ * UNW_REG_FPSR
+ * UNW_REG_LC
+ * UNW_REG_PFS
+ * UNW_REG_PR
+ * UNW_REG_RNAT
+ * UNW_REG_PSP
+ * UNW_REG_RP
+ * UNW_REG_UNAT
+ *
+ * Decoder action macros:
+ * UNW_DEC_BAD_CODE(code)
+ * UNW_DEC_ABI(fmt,abi,context,arg)
+ * UNW_DEC_BR_GR(fmt,brmask,gr,arg)
+ * UNW_DEC_BR_MEM(fmt,brmask,arg)
+ * UNW_DEC_COPY_STATE(fmt,label,arg)
+ * UNW_DEC_EPILOGUE(fmt,t,ecount,arg)
+ * UNW_DEC_FRGR_MEM(fmt,grmask,frmask,arg)
+ * UNW_DEC_FR_MEM(fmt,frmask,arg)
+ * UNW_DEC_GR_GR(fmt,grmask,gr,arg)
+ * UNW_DEC_GR_MEM(fmt,grmask,arg)
+ * UNW_DEC_LABEL_STATE(fmt,label,arg)
+ * UNW_DEC_MEM_STACK_F(fmt,t,size,arg)
+ * UNW_DEC_MEM_STACK_V(fmt,t,arg)
+ * UNW_DEC_PRIUNAT_GR(fmt,r,arg)
+ * UNW_DEC_PRIUNAT_WHEN_GR(fmt,t,arg)
+ * UNW_DEC_PRIUNAT_WHEN_MEM(fmt,t,arg)
+ * UNW_DEC_PRIUNAT_WHEN_PSPREL(fmt,pspoff,arg)
+ * UNW_DEC_PRIUNAT_WHEN_SPREL(fmt,spoff,arg)
+ * UNW_DEC_PROLOGUE(fmt,body,rlen,arg)
+ * UNW_DEC_PROLOGUE_GR(fmt,rlen,mask,grsave,arg)
+ * UNW_DEC_REG_PSPREL(fmt,reg,pspoff,arg)
+ * UNW_DEC_REG_REG(fmt,src,dst,arg)
+ * UNW_DEC_REG_SPREL(fmt,reg,spoff,arg)
+ * UNW_DEC_REG_WHEN(fmt,reg,t,arg)
+ * UNW_DEC_RESTORE(fmt,t,abreg,arg)
+ * UNW_DEC_RESTORE_P(fmt,qp,t,abreg,arg)
+ * UNW_DEC_SPILL_BASE(fmt,pspoff,arg)
+ * UNW_DEC_SPILL_MASK(fmt,imaskp,arg)
+ * UNW_DEC_SPILL_PSPREL(fmt,t,abreg,pspoff,arg)
+ * UNW_DEC_SPILL_PSPREL_P(fmt,qp,t,abreg,pspoff,arg)
+ * UNW_DEC_SPILL_REG(fmt,t,abreg,x,ytreg,arg)
+ * UNW_DEC_SPILL_REG_P(fmt,qp,t,abreg,x,ytreg,arg)
+ * UNW_DEC_SPILL_SPREL(fmt,t,abreg,spoff,arg)
+ * UNW_DEC_SPILL_SPREL_P(fmt,qp,t,abreg,pspoff,arg)
+ */
+
+static unw_word
+unw_decode_uleb128 (unsigned char **dpp)
+{
+ unsigned shift = 0;
+ unw_word byte, result = 0;
+ unsigned char *bp = *dpp;
+
+ while (1)
+ {
+ byte = *bp++;
+ result |= (byte & 0x7f) << shift;
+ if ((byte & 0x80) == 0)
+ break;
+ shift += 7;
+ }
+ *dpp = bp;
+ return result;
+}
+
+static unsigned char *
+unw_decode_x1 (unsigned char *dp,
+ unsigned char code __attribute__((unused)),
+ void *arg)
+{
+ unsigned char byte1, abreg;
+ unw_word t, off;
+
+ byte1 = *dp++;
+ t = unw_decode_uleb128 (&dp);
+ off = unw_decode_uleb128 (&dp);
+ abreg = (byte1 & 0x7f);
+ if (byte1 & 0x80)
+ UNW_DEC_SPILL_SPREL(X1, t, abreg, off, arg);
+ else
+ UNW_DEC_SPILL_PSPREL(X1, t, abreg, off, arg);
+ return dp;
+}
+
+static unsigned char *
+unw_decode_x2 (unsigned char *dp,
+ unsigned char code __attribute__((unused)),
+ void *arg)
+{
+ unsigned char byte1, byte2, abreg, x, ytreg;
+ unw_word t;
+
+ byte1 = *dp++; byte2 = *dp++;
+ t = unw_decode_uleb128 (&dp);
+ abreg = (byte1 & 0x7f);
+ ytreg = byte2;
+ x = (byte1 >> 7) & 1;
+ if ((byte1 & 0x80) == 0 && ytreg == 0)
+ UNW_DEC_RESTORE(X2, t, abreg, arg);
+ else
+ UNW_DEC_SPILL_REG(X2, t, abreg, x, ytreg, arg);
+ return dp;
+}
+
+static unsigned char *
+unw_decode_x3 (unsigned char *dp,
+ unsigned char code __attribute__((unused)),
+ void *arg)
+{
+ unsigned char byte1, byte2, abreg, qp;
+ unw_word t, off;
+
+ byte1 = *dp++; byte2 = *dp++;
+ t = unw_decode_uleb128 (&dp);
+ off = unw_decode_uleb128 (&dp);
+
+ qp = (byte1 & 0x3f);
+ abreg = (byte2 & 0x7f);
+
+ if (byte1 & 0x80)
+ UNW_DEC_SPILL_SPREL_P(X3, qp, t, abreg, off, arg);
+ else
+ UNW_DEC_SPILL_PSPREL_P(X3, qp, t, abreg, off, arg);
+ return dp;
+}
+
+static unsigned char *
+unw_decode_x4 (unsigned char *dp,
+ unsigned char code __attribute__((unused)),
+ void *arg)
+{
+ unsigned char byte1, byte2, byte3, qp, abreg, x, ytreg;
+ unw_word t;
+
+ byte1 = *dp++; byte2 = *dp++; byte3 = *dp++;
+ t = unw_decode_uleb128 (&dp);
+
+ qp = (byte1 & 0x3f);
+ abreg = (byte2 & 0x7f);
+ x = (byte2 >> 7) & 1;
+ ytreg = byte3;
+
+ if ((byte2 & 0x80) == 0 && byte3 == 0)
+ UNW_DEC_RESTORE_P(X4, qp, t, abreg, arg);
+ else
+ UNW_DEC_SPILL_REG_P(X4, qp, t, abreg, x, ytreg, arg);
+ return dp;
+}
+
+static unsigned char *
+unw_decode_r1 (unsigned char *dp, unsigned char code, void *arg)
+{
+ int body = (code & 0x20) != 0;
+ unw_word rlen;
+
+ rlen = (code & 0x1f);
+ UNW_DEC_PROLOGUE(R1, body, rlen, arg);
+ return dp;
+}
+
+static unsigned char *
+unw_decode_r2 (unsigned char *dp, unsigned char code, void *arg)
+{
+ unsigned char byte1, mask, grsave;
+ unw_word rlen;
+
+ byte1 = *dp++;
+
+ mask = ((code & 0x7) << 1) | ((byte1 >> 7) & 1);
+ grsave = (byte1 & 0x7f);
+ rlen = unw_decode_uleb128 (&dp);
+ UNW_DEC_PROLOGUE_GR(R2, rlen, mask, grsave, arg);
+ return dp;
+}
+
+static unsigned char *
+unw_decode_r3 (unsigned char *dp, unsigned char code, void *arg)
+{
+ unw_word rlen;
+
+ rlen = unw_decode_uleb128 (&dp);
+ UNW_DEC_PROLOGUE(R3, ((code & 0x3) == 1), rlen, arg);
+ return dp;
+}
+
+static unsigned char *
+unw_decode_p1 (unsigned char *dp, unsigned char code, void *arg)
+{
+ unsigned char brmask = (code & 0x1f);
+
+ UNW_DEC_BR_MEM(P1, brmask, arg);
+ return dp;
+}
+
+static unsigned char *
+unw_decode_p2_p5 (unsigned char *dp, unsigned char code, void *arg)
+{
+ if ((code & 0x10) == 0)
+ {
+ unsigned char byte1 = *dp++;
+
+ UNW_DEC_BR_GR(P2, ((code & 0xf) << 1) | ((byte1 >> 7) & 1),
+ (byte1 & 0x7f), arg);
+ }
+ else if ((code & 0x08) == 0)
+ {
+ unsigned char byte1 = *dp++, r, dst;
+
+ r = ((code & 0x7) << 1) | ((byte1 >> 7) & 1);
+ dst = (byte1 & 0x7f);
+ switch (r)
+ {
+ case 0: UNW_DEC_REG_GR(P3, UNW_REG_PSP, dst, arg); break;
+ case 1: UNW_DEC_REG_GR(P3, UNW_REG_RP, dst, arg); break;
+ case 2: UNW_DEC_REG_GR(P3, UNW_REG_PFS, dst, arg); break;
+ case 3: UNW_DEC_REG_GR(P3, UNW_REG_PR, dst, arg); break;
+ case 4: UNW_DEC_REG_GR(P3, UNW_REG_UNAT, dst, arg); break;
+ case 5: UNW_DEC_REG_GR(P3, UNW_REG_LC, dst, arg); break;
+ case 6: UNW_DEC_RP_BR(P3, dst, arg); break;
+ case 7: UNW_DEC_REG_GR(P3, UNW_REG_RNAT, dst, arg); break;
+ case 8: UNW_DEC_REG_GR(P3, UNW_REG_BSP, dst, arg); break;
+ case 9: UNW_DEC_REG_GR(P3, UNW_REG_BSPSTORE, dst, arg); break;
+ case 10: UNW_DEC_REG_GR(P3, UNW_REG_FPSR, dst, arg); break;
+ case 11: UNW_DEC_PRIUNAT_GR(P3, dst, arg); break;
+ default: UNW_DEC_BAD_CODE(r); break;
+ }
+ }
+ else if ((code & 0x7) == 0)
+ UNW_DEC_SPILL_MASK(P4, dp, arg);
+ else if ((code & 0x7) == 1)
+ {
+ unw_word grmask, frmask, byte1, byte2, byte3;
+
+ byte1 = *dp++; byte2 = *dp++; byte3 = *dp++;
+ grmask = ((byte1 >> 4) & 0xf);
+ frmask = ((byte1 & 0xf) << 16) | (byte2 << 8) | byte3;
+ UNW_DEC_FRGR_MEM(P5, grmask, frmask, arg);
+ }
+ else
+ UNW_DEC_BAD_CODE(code);
+ return dp;
+}
+
+static unsigned char *
+unw_decode_p6 (unsigned char *dp, unsigned char code, void *arg)
+{
+ int gregs = (code & 0x10) != 0;
+ unsigned char mask = (code & 0x0f);
+
+ if (gregs)
+ UNW_DEC_GR_MEM(P6, mask, arg);
+ else
+ UNW_DEC_FR_MEM(P6, mask, arg);
+ return dp;
+}
+
+static unsigned char *
+unw_decode_p7_p10 (unsigned char *dp, unsigned char code, void *arg)
+{
+ unsigned char r, byte1, byte2;
+ unw_word t, size;
+
+ if ((code & 0x10) == 0)
+ {
+ r = (code & 0xf);
+ t = unw_decode_uleb128 (&dp);
+ switch (r)
+ {
+ case 0:
+ size = unw_decode_uleb128 (&dp);
+ UNW_DEC_MEM_STACK_F(P7, t, size, arg);
+ break;
+
+ case 1: UNW_DEC_MEM_STACK_V(P7, t, arg); break;
+ case 2: UNW_DEC_SPILL_BASE(P7, t, arg); break;
+ case 3: UNW_DEC_REG_SPREL(P7, UNW_REG_PSP, t, arg); break;
+ case 4: UNW_DEC_REG_WHEN(P7, UNW_REG_RP, t, arg); break;
+ case 5: UNW_DEC_REG_PSPREL(P7, UNW_REG_RP, t, arg); break;
+ case 6: UNW_DEC_REG_WHEN(P7, UNW_REG_PFS, t, arg); break;
+ case 7: UNW_DEC_REG_PSPREL(P7, UNW_REG_PFS, t, arg); break;
+ case 8: UNW_DEC_REG_WHEN(P7, UNW_REG_PR, t, arg); break;
+ case 9: UNW_DEC_REG_PSPREL(P7, UNW_REG_PR, t, arg); break;
+ case 10: UNW_DEC_REG_WHEN(P7, UNW_REG_LC, t, arg); break;
+ case 11: UNW_DEC_REG_PSPREL(P7, UNW_REG_LC, t, arg); break;
+ case 12: UNW_DEC_REG_WHEN(P7, UNW_REG_UNAT, t, arg); break;
+ case 13: UNW_DEC_REG_PSPREL(P7, UNW_REG_UNAT, t, arg); break;
+ case 14: UNW_DEC_REG_WHEN(P7, UNW_REG_FPSR, t, arg); break;
+ case 15: UNW_DEC_REG_PSPREL(P7, UNW_REG_FPSR, t, arg); break;
+ default: UNW_DEC_BAD_CODE(r); break;
+ }
+ }
+ else
+ {
+ switch (code & 0xf)
+ {
+ case 0x0: /* p8 */
+ {
+ r = *dp++;
+ t = unw_decode_uleb128 (&dp);
+ switch (r)
+ {
+ case 1: UNW_DEC_REG_SPREL(P8, UNW_REG_RP, t, arg); break;
+ case 2: UNW_DEC_REG_SPREL(P8, UNW_REG_PFS, t, arg); break;
+ case 3: UNW_DEC_REG_SPREL(P8, UNW_REG_PR, t, arg); break;
+ case 4: UNW_DEC_REG_SPREL(P8, UNW_REG_LC, t, arg); break;
+ case 5: UNW_DEC_REG_SPREL(P8, UNW_REG_UNAT, t, arg); break;
+ case 6: UNW_DEC_REG_SPREL(P8, UNW_REG_FPSR, t, arg); break;
+ case 7: UNW_DEC_REG_WHEN(P8, UNW_REG_BSP, t, arg); break;
+ case 8: UNW_DEC_REG_PSPREL(P8, UNW_REG_BSP, t, arg); break;
+ case 9: UNW_DEC_REG_SPREL(P8, UNW_REG_BSP, t, arg); break;
+ case 10: UNW_DEC_REG_WHEN(P8, UNW_REG_BSPSTORE, t, arg); break;
+ case 11: UNW_DEC_REG_PSPREL(P8, UNW_REG_BSPSTORE, t, arg); break;
+ case 12: UNW_DEC_REG_SPREL(P8, UNW_REG_BSPSTORE, t, arg); break;
+ case 13: UNW_DEC_REG_WHEN(P8, UNW_REG_RNAT, t, arg); break;
+ case 14: UNW_DEC_REG_PSPREL(P8, UNW_REG_RNAT, t, arg); break;
+ case 15: UNW_DEC_REG_SPREL(P8, UNW_REG_RNAT, t, arg); break;
+ case 16: UNW_DEC_PRIUNAT_WHEN_GR(P8, t, arg); break;
+ case 17: UNW_DEC_PRIUNAT_PSPREL(P8, t, arg); break;
+ case 18: UNW_DEC_PRIUNAT_SPREL(P8, t, arg); break;
+ case 19: UNW_DEC_PRIUNAT_WHEN_MEM(P8, t, arg); break;
+ default: UNW_DEC_BAD_CODE(r); break;
+ }
+ }
+ break;
+
+ case 0x1:
+ byte1 = *dp++; byte2 = *dp++;
+ UNW_DEC_GR_GR(P9, (byte1 & 0xf), (byte2 & 0x7f), arg);
+ break;
+
+ case 0xf: /* p10 */
+ byte1 = *dp++; byte2 = *dp++;
+ UNW_DEC_ABI(P10, byte1, byte2, arg);
+ break;
+
+ case 0x9:
+ return unw_decode_x1 (dp, code, arg);
+
+ case 0xa:
+ return unw_decode_x2 (dp, code, arg);
+
+ case 0xb:
+ return unw_decode_x3 (dp, code, arg);
+
+ case 0xc:
+ return unw_decode_x4 (dp, code, arg);
+
+ default:
+ UNW_DEC_BAD_CODE(code);
+ break;
+ }
+ }
+ return dp;
+}
+
+static unsigned char *
+unw_decode_b1 (unsigned char *dp, unsigned char code, void *arg)
+{
+ unw_word label = (code & 0x1f);
+
+ if ((code & 0x20) != 0)
+ UNW_DEC_COPY_STATE(B1, label, arg);
+ else
+ UNW_DEC_LABEL_STATE(B1, label, arg);
+ return dp;
+}
+
+static unsigned char *
+unw_decode_b2 (unsigned char *dp, unsigned char code, void *arg)
+{
+ unw_word t;
+
+ t = unw_decode_uleb128 (&dp);
+ UNW_DEC_EPILOGUE(B2, t, (code & 0x1f), arg);
+ return dp;
+}
+
+static unsigned char *
+unw_decode_b3_x4 (unsigned char *dp, unsigned char code, void *arg)
+{
+ unw_word t, ecount, label;
+
+ if ((code & 0x10) == 0)
+ {
+ t = unw_decode_uleb128 (&dp);
+ ecount = unw_decode_uleb128 (&dp);
+ UNW_DEC_EPILOGUE(B3, t, ecount, arg);
+ }
+ else if ((code & 0x07) == 0)
+ {
+ label = unw_decode_uleb128 (&dp);
+ if ((code & 0x08) != 0)
+ UNW_DEC_COPY_STATE(B4, label, arg);
+ else
+ UNW_DEC_LABEL_STATE(B4, label, arg);
+ }
+ else
+ switch (code & 0x7)
+ {
+ case 1: return unw_decode_x1 (dp, code, arg);
+ case 2: return unw_decode_x2 (dp, code, arg);
+ case 3: return unw_decode_x3 (dp, code, arg);
+ case 4: return unw_decode_x4 (dp, code, arg);
+ default: UNW_DEC_BAD_CODE(code); break;
+ }
+ return dp;
+}
+
+typedef unsigned char *(*unw_decoder) (unsigned char *, unsigned char, void *);
+
+static unw_decoder unw_decode_table[2][8] =
+{
+ /* prologue table: */
+ {
+ unw_decode_r1, /* 0 */
+ unw_decode_r1,
+ unw_decode_r2,
+ unw_decode_r3,
+ unw_decode_p1, /* 4 */
+ unw_decode_p2_p5,
+ unw_decode_p6,
+ unw_decode_p7_p10
+ },
+ {
+ unw_decode_r1, /* 0 */
+ unw_decode_r1,
+ unw_decode_r2,
+ unw_decode_r3,
+ unw_decode_b1, /* 4 */
+ unw_decode_b1,
+ unw_decode_b2,
+ unw_decode_b3_x4
+ }
+};
+
+/*
+ * Decode one descriptor and return address of next descriptor.
+ */
+static inline unsigned char *
+unw_decode (unsigned char *dp, int inside_body, void *arg)
+{
+ unw_decoder decoder;
+ unsigned char code;
+
+ code = *dp++;
+ decoder = unw_decode_table[inside_body][code >> 5];
+ dp = (*decoder) (dp, code, arg);
+ return dp;
+}
+
+
+/* RSE helper functions. */
+
+static inline unsigned long
+ia64_rse_slot_num (unsigned long *addr)
+{
+ return (((unsigned long) addr) >> 3) & 0x3f;
+}
+
+/* Return TRUE if ADDR is the address of an RNAT slot. */
+static inline unsigned long
+ia64_rse_is_rnat_slot (unsigned long *addr)
+{
+ return ia64_rse_slot_num (addr) == 0x3f;
+}
+
+/* Returns the address of the RNAT slot that covers the slot at
+ address SLOT_ADDR. */
+static inline unsigned long *
+ia64_rse_rnat_addr (unsigned long *slot_addr)
+{
+ return (unsigned long *) ((unsigned long) slot_addr | (0x3f << 3));
+}
+
+/* Calcuate the number of registers in the dirty partition starting at
+ BSPSTORE with a size of DIRTY bytes. This isn't simply DIRTY
+ divided by eight because the 64th slot is used to store ar.rnat. */
+static inline unsigned long
+ia64_rse_num_regs (unsigned long *bspstore, unsigned long *bsp)
+{
+ unsigned long slots = (bsp - bspstore);
+
+ return slots - (ia64_rse_slot_num (bspstore) + slots)/0x40;
+}
+
+/* The inverse of the above: given bspstore and the number of
+ registers, calculate ar.bsp. */
+static inline unsigned long *
+ia64_rse_skip_regs (unsigned long *addr, long num_regs)
+{
+ long delta = ia64_rse_slot_num (addr) + num_regs;
+
+ if (num_regs < 0)
+ delta -= 0x3e;
+ return addr + num_regs + delta/0x3f;
+}
+
+
+/* Unwind accessors. */
+
+static void
+unw_access_gr (struct _Unwind_Context *info, int regnum,
+ unsigned long *val, char *nat, int write)
+{
+ unsigned long *addr, *nat_addr = 0, nat_mask = 0, dummy_nat;
+ struct unw_ireg *ireg;
+
+ if ((unsigned) regnum - 1 >= 127)
+ abort ();
+
+ if (regnum < 1)
+ {
+ nat_addr = addr = &dummy_nat;
+ dummy_nat = 0;
+ }
+ else if (regnum < 32)
+ {
+ /* Access a non-stacked register. */
+ ireg = &info->ireg[regnum - 1];
+ addr = ireg->loc;
+ if (addr)
+ {
+ nat_addr = addr + ireg->nat.off;
+ switch (ireg->nat.type)
+ {
+ case UNW_NAT_VAL:
+ /* Simulate getf.sig/setf.sig. */
+ if (write)
+ {
+ if (*nat)
+ {
+ /* Write NaTVal and be done with it. */
+ addr[0] = 0;
+ addr[1] = 0x1fffe;
+ return;
+ }
+ addr[1] = 0x1003e;
+ }
+ else if (addr[0] == 0 && addr[1] == 0x1ffe)
+ {
+ /* Return NaT and be done with it. */
+ *val = 0;
+ *nat = 1;
+ return;
+ }
+ /* FALLTHRU */
+
+ case UNW_NAT_NONE:
+ dummy_nat = 0;
+ nat_addr = &dummy_nat;
+ break;
+
+ case UNW_NAT_MEMSTK:
+ nat_mask = 1UL << ((long) addr & 0x1f8)/8;
+ break;
+
+ case UNW_NAT_REGSTK:
+ nat_addr = ia64_rse_rnat_addr (addr);
+ if ((unsigned long) nat_addr >= info->regstk_top)
+ nat_addr = &info->rnat;
+ nat_mask = 1UL << ia64_rse_slot_num (addr);
+ break;
+ }
+ }
+ }
+ else
+ {
+ /* Access a stacked register. */
+ addr = ia64_rse_skip_regs ((unsigned long *) info->bsp, regnum - 32);
+ nat_addr = ia64_rse_rnat_addr (addr);
+ if ((unsigned long) nat_addr >= info->regstk_top)
+ nat_addr = &info->rnat;
+ nat_mask = 1UL << ia64_rse_slot_num (addr);
+ }
+
+ if (write)
+ {
+ *addr = *val;
+ if (*nat)
+ *nat_addr |= nat_mask;
+ else
+ *nat_addr &= ~nat_mask;
+ }
+ else
+ {
+ *val = *addr;
+ *nat = (*nat_addr & nat_mask) != 0;
+ }
+}
+
+/* Get the value of register REG as saved in CONTEXT. */
+
+_Unwind_Word
+_Unwind_GetGR (struct _Unwind_Context *context, int index)
+{
+ _Unwind_Word ret;
+ char nat;
+
+ if (index == 1)
+ return context->gp;
+ else if (index >= 15 && index <= 18)
+ return context->eh_data[index - 15];
+ else
+ unw_access_gr (context, index, &ret, &nat, 0);
+
+ return ret;
+}
+
+/* Overwrite the saved value for register REG in CONTEXT with VAL. */
+
+void
+_Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val)
+{
+ char nat = 0;
+
+ if (index == 1)
+ context->gp = val;
+ else if (index >= 15 && index <= 18)
+ context->eh_data[index - 15] = val;
+ else
+ unw_access_gr (context, index, &val, &nat, 1);
+}
+
+/* Retrieve the return address for CONTEXT. */
+
+inline _Unwind_Ptr
+_Unwind_GetIP (struct _Unwind_Context *context)
+{
+ return context->rp;
+}
+
+/* Overwrite the return address for CONTEXT with VAL. */
+
+inline void
+_Unwind_SetIP (struct _Unwind_Context *context, _Unwind_Ptr val)
+{
+ context->rp = val;
+}
+
+void *
+_Unwind_GetLanguageSpecificData (struct _Unwind_Context *context)
+{
+ return context->lsda;
+}
+
+_Unwind_Ptr
+_Unwind_GetRegionStart (struct _Unwind_Context *context)
+{
+ return context->region_start;
+}
+
+
+static _Unwind_Reason_Code
+uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
+{
+ struct unw_table_entry *ent;
+ unsigned long *unw, header, length;
+ unsigned char *insn, *insn_end;
+ unsigned long segment_base;
+
+ memset (fs, 0, sizeof (*fs));
+ context->lsda = 0;
+
+ ent = _Unwind_FindTableEntry ((void *) context->rp,
+ &segment_base, &context->gp);
+ if (ent == NULL)
+ {
+ /* Couldn't find unwind info for this function. Try an
+ os-specific fallback mechanism. This will necessarily
+ not profide a personality routine or LSDA. */
+#ifdef MD_FALLBACK_FRAME_STATE_FOR
+ MD_FALLBACK_FRAME_STATE_FOR (context, fs, success);
+ return _URC_END_OF_STACK;
+ success:
+ return _URC_NO_REASON;
+#else
+ return _URC_END_OF_STACK;
+#endif
+ }
+
+ context->region_start = ent->start_offset + segment_base;
+ fs->when_target = (context->rp - context->region_start) / 16 * 3;
+
+ unw = (unsigned long *) (ent->info_offset + segment_base);
+ header = *unw;
+ length = UNW_LENGTH (header);
+
+ /* ??? Perhaps check UNW_VER / UNW_FLAG_OSMASK. */
+
+ if (UNW_FLAG_EHANDLER (header) | UNW_FLAG_UHANDLER (header))
+ {
+ fs->personality =
+ *(_Unwind_Personality_Fn *) (unw[length + 1] + context->gp);
+ context->lsda = unw + length + 2;
+ }
+
+ insn = (unsigned char *) (unw + 1);
+ insn_end = (unsigned char *) (unw + 1 + length);
+ while (!fs->done && insn < insn_end)
+ insn = unw_decode (insn, fs->in_body, fs);
+
+ /* If we're in the epilogue, sp has been restored and all values
+ on the memory stack below psp also have been restored. */
+ if (fs->when_target > fs->epilogue_start)
+ {
+ struct unw_reg_info *r;
+
+ fs->curr.reg[UNW_REG_PSP].where = UNW_WHERE_NONE;
+ fs->curr.reg[UNW_REG_PSP].val = 0;
+ for (r = fs->curr.reg; r < fs->curr.reg + UNW_NUM_REGS; ++r)
+ if ((r->where == UNW_WHERE_PSPREL && r->val <= 0x10)
+ || r->where == UNW_WHERE_SPREL)
+ r->where = UNW_WHERE_NONE;
+ }
+
+ /* If RP did't get saved, generate entry for the return link register. */
+ if (fs->curr.reg[UNW_REG_RP].when >= fs->when_target)
+ {
+ fs->curr.reg[UNW_REG_RP].where = UNW_WHERE_BR;
+ fs->curr.reg[UNW_REG_RP].when = -1;
+ fs->curr.reg[UNW_REG_RP].val = fs->return_link_reg;
+ }
+
+ return _URC_NO_REASON;
+}
+
+static void
+uw_update_reg_address (struct _Unwind_Context *context,
+ _Unwind_FrameState *fs,
+ enum unw_register_index regno)
+{
+ struct unw_reg_info *r = fs->curr.reg + regno;
+ void *addr;
+ unsigned long rval;
+
+ if (r->where == UNW_WHERE_NONE || r->when >= fs->when_target)
+ return;
+
+ rval = r->val;
+ switch (r->where)
+ {
+ case UNW_WHERE_GR:
+ if (rval >= 32)
+ addr = ia64_rse_skip_regs ((unsigned long *) context->bsp, rval - 32);
+ else if (rval >= 2)
+ addr = context->ireg[rval - 2].loc;
+ else
+ abort ();
+ break;
+
+ case UNW_WHERE_FR:
+ if (rval >= 2 && rval < 32)
+ addr = context->fr_loc[rval - 2];
+ else
+ abort ();
+ break;
+
+ case UNW_WHERE_BR:
+ if (rval >= 1 && rval <= 5)
+ addr = context->br_loc[rval - 1];
+ else
+ abort ();
+ break;
+
+ case UNW_WHERE_SPREL:
+ addr = (void *)(context->sp + rval);
+ break;
+
+ case UNW_WHERE_PSPREL:
+ addr = (void *)(context->psp + rval);
+ break;
+
+ default:
+ abort ();
+ }
+
+ switch (regno)
+ {
+ case UNW_REG_R2 ... UNW_REG_R31:
+ context->ireg[regno - UNW_REG_R2].loc = addr;
+ switch (r->where)
+ {
+ case UNW_WHERE_GR:
+ if (rval >= 32)
+ {
+ context->ireg[regno - UNW_REG_R2].nat.type = UNW_NAT_MEMSTK;
+ context->ireg[regno - UNW_REG_R2].nat.off
+ = context->pri_unat_loc - (unsigned long *) addr;
+ }
+ else if (rval >= 2)
+ {
+ context->ireg[regno - UNW_REG_R2].nat
+ = context->ireg[rval - 2].nat;
+ }
+ else
+ abort ();
+ break;
+
+ case UNW_WHERE_FR:
+ context->ireg[regno - UNW_REG_R2].nat.type = UNW_NAT_VAL;
+ context->ireg[regno - UNW_REG_R2].nat.off = 0;
+ break;
+
+ case UNW_WHERE_BR:
+ context->ireg[regno - UNW_REG_R2].nat.type = UNW_NAT_NONE;
+ context->ireg[regno - UNW_REG_R2].nat.off = 0;
+ break;
+
+ case UNW_WHERE_PSPREL:
+ case UNW_WHERE_SPREL:
+ context->ireg[regno - UNW_REG_R2].nat.type = UNW_NAT_MEMSTK;
+ context->ireg[regno - UNW_REG_R2].nat.off
+ = context->pri_unat_loc - (unsigned long *) addr;
+ break;
+
+ default:
+ abort ();
+ }
+ break;
+
+ case UNW_REG_F2 ... UNW_REG_F31:
+ context->fr_loc[regno - UNW_REG_F2] = addr;
+ break;
+
+ case UNW_REG_B1 ... UNW_REG_B5:
+ context->br_loc[regno - UNW_REG_B1] = addr;
+ break;
+
+ case UNW_REG_BSP:
+ context->bsp_loc = addr;
+ break;
+ case UNW_REG_BSPSTORE:
+ context->bspstore_loc = addr;
+ break;
+ case UNW_REG_PFS:
+ context->pfs_loc = addr;
+ break;
+ case UNW_REG_RP:
+ context->rp = *(unsigned long *)addr;
+ break;
+ case UNW_REG_UNAT:
+ context->unat_loc = addr;
+ break;
+ case UNW_REG_PR:
+ context->pr = *(unsigned long *) addr;
+ break;
+ case UNW_REG_LC:
+ context->lc_loc = addr;
+ break;
+ case UNW_REG_FPSR:
+ context->fpsr_loc = addr;
+ break;
+
+ case UNW_REG_PSP:
+ context->psp = *(unsigned long *)addr;
+ break;
+
+ case UNW_REG_RNAT:
+ case UNW_NUM_REGS:
+ abort ();
+ }
+}
+
+static void
+uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
+{
+ long i;
+
+ context->sp = context->psp;
+
+ /* First, set PSP. Subsequent instructions may depend on this value. */
+ if (fs->when_target > fs->curr.reg[UNW_REG_PSP].when)
+ {
+ if (fs->curr.reg[UNW_REG_PSP].where == UNW_WHERE_NONE)
+ context->psp = context->psp + fs->curr.reg[UNW_REG_PSP].val;
+ else
+ uw_update_reg_address (context, fs, UNW_REG_PSP);
+ }
+
+ /* Determine the location of the primary UNaT. */
+ {
+ int i;
+ if (fs->when_target < fs->curr.reg[UNW_REG_PRI_UNAT_GR].when)
+ i = UNW_REG_PRI_UNAT_MEM;
+ else if (fs->when_target < fs->curr.reg[UNW_REG_PRI_UNAT_MEM].when)
+ i = UNW_REG_PRI_UNAT_GR;
+ else if (fs->curr.reg[UNW_REG_PRI_UNAT_MEM].when
+ > fs->curr.reg[UNW_REG_PRI_UNAT_GR].when)
+ i = UNW_REG_PRI_UNAT_MEM;
+ else
+ i = UNW_REG_PRI_UNAT_GR;
+ uw_update_reg_address (context, fs, i);
+ }
+
+ /* Compute the addresses of all registers saved in this frame. */
+ for (i = UNW_REG_BSP; i < UNW_NUM_REGS; ++i)
+ uw_update_reg_address (context, fs, i);
+
+ /* Unwind BSP for the local registers allocated this frame. */
+ /* ??? What to do with stored BSP or BSPSTORE registers. */
+ if (fs->when_target > fs->curr.reg[UNW_REG_PFS].when)
+ {
+ unsigned long pfs = *context->pfs_loc;
+ unsigned long sol = (pfs >> 7) & 0x7f;
+ context->bsp = (unsigned long)
+ ia64_rse_skip_regs ((unsigned long *) context->bsp, -sol);
+ }
+}
+
+/* Fill in CONTEXT for top-of-stack. The only valid registers at this
+ level will be the return address and the CFA. */
+
+#define uw_init_context(CONTEXT) \
+ uw_init_context_1 (CONTEXT, __builtin_dwarf_cfa (), __builtin_ia64_bsp ())
+
+static void
+uw_init_context_1 (struct _Unwind_Context *context, void *psp, void *bsp)
+{
+ void *rp = __builtin_extract_return_addr (__builtin_return_address (0));
+ void *sp = __builtin_dwarf_cfa ();
+ _Unwind_FrameState fs;
+
+ /* Flush the register stack to memory so that we can access it. */
+ __builtin_ia64_flushrs ();
+
+ memset (context, 0, sizeof (struct _Unwind_Context));
+ context->bsp = (unsigned long) bsp;
+ context->sp = (unsigned long) sp;
+ context->psp = (unsigned long) psp;
+ context->rp = (unsigned long) rp;
+
+ asm ("mov %0 = pr" : "=r" (context->pr));
+ /* ??? Get rnat. Don't we have to turn off the rse for that? */
+
+ if (uw_frame_state_for (context, &fs) != _URC_NO_REASON)
+ abort ();
+
+ /* Force the frame state to use the known cfa value. */
+ fs.curr.reg[UNW_REG_PSP].when = -1;
+ fs.curr.reg[UNW_REG_PSP].where = UNW_WHERE_NONE;
+ fs.curr.reg[UNW_REG_PSP].val = sp - psp;
+
+ uw_update_context (context, &fs);
+}
+
+/* Install (ie longjmp to) the contents of TARGET. */
+
+static void __attribute__((noreturn))
+uw_install_context (struct _Unwind_Context *current __attribute__((unused)),
+ struct _Unwind_Context *target)
+{
+ unsigned long ireg_buf[4], ireg_nat = 0, ireg_pr = 0;
+ long i;
+
+ /* Copy integer register data from the target context to a
+ temporary buffer. Do this so that we can frob AR.UNAT
+ to get the NaT bits for these registers set properly. */
+ for (i = 4; i <= 7; ++i)
+ {
+ char nat;
+ void *t = target->ireg[i - 2].loc;
+ if (t)
+ {
+ unw_access_gr (target, i, &ireg_buf[i - 4], &nat, 0);
+ ireg_nat |= (long)nat << (((size_t)&ireg_buf[i - 4] >> 3) & 0x3f);
+ /* Set p6 - p9. */
+ ireg_pr |= 4L << i;
+ }
+ }
+
+ /* The value in uc_bsp that we've computed is that for the
+ target function. The value that we install below will be
+ adjusted by the BR.RET instruction based on the contents
+ of AR.PFS. So we must unadjust that here. */
+ target->bsp
+ = ia64_rse_skip_regs (target->bsp, (*target->pfs_loc >> 7) & 0x7f);
+
+ /* Provide assembly with the offsets into the _Unwind_Context. */
+ asm volatile ("uc_rnat = %0"
+ : : "i"(offsetof (struct _Unwind_Context, rnat)));
+ asm volatile ("uc_bsp = %0"
+ : : "i"(offsetof (struct _Unwind_Context, bsp)));
+ asm volatile ("uc_psp = %0"
+ : : "i"(offsetof (struct _Unwind_Context, psp)));
+ asm volatile ("uc_rp = %0"
+ : : "i"(offsetof (struct _Unwind_Context, rp)));
+ asm volatile ("uc_pr = %0"
+ : : "i"(offsetof (struct _Unwind_Context, pr)));
+ asm volatile ("uc_gp = %0"
+ : : "i"(offsetof (struct _Unwind_Context, gp)));
+ asm volatile ("uc_pfs_loc = %0"
+ : : "i"(offsetof (struct _Unwind_Context, pfs_loc)));
+ asm volatile ("uc_unat_loc = %0"
+ : : "i"(offsetof (struct _Unwind_Context, unat_loc)));
+ asm volatile ("uc_lc_loc = %0"
+ : : "i"(offsetof (struct _Unwind_Context, lc_loc)));
+ asm volatile ("uc_fpsr_loc = %0"
+ : : "i"(offsetof (struct _Unwind_Context, fpsr_loc)));
+ asm volatile ("uc_eh_data = %0"
+ : : "i"(offsetof (struct _Unwind_Context, eh_data)));
+ asm volatile ("uc_br_loc = %0"
+ : : "i"(offsetof (struct _Unwind_Context, br_loc)));
+ asm volatile ("uc_fr_loc = %0"
+ : : "i"(offsetof (struct _Unwind_Context, fr_loc)));
+
+ asm volatile (
+ /* Load up call-saved non-window integer registers from ireg_buf. */
+ "add r20 = 8, %1 \n\t"
+ "mov ar.unat = %2 \n\t"
+ "mov pr = %3, 0x3c0 \n\t"
+ ";; \n\t"
+ "(p6) ld8.fill r4 = [%1] \n\t"
+ "(p7) ld8.fill r5 = [r20] \n\t"
+ "add r21 = uc_br_loc + 8, %0 \n\t"
+ "adds %1 = 16, %1 \n\t"
+ "adds r20 = 16, r20 \n\t"
+ ";; \n\t"
+ "(p8) ld8.fill r6 = [%1] \n\t"
+ "(p9) ld8.fill r7 = [r20] \n\t"
+ "add r20 = uc_br_loc, %0 \n\t"
+ ";; \n\t"
+ /* Load up call-saved branch registers. */
+ "ld8 r22 = [r20], 16 \n\t"
+ "ld8 r23 = [r21], 16 \n\t"
+ ";; \n\t"
+ "ld8 r24 = [r20], 16 \n\t"
+ "ld8 r25 = [r21], uc_fr_loc - (uc_br_loc + 24)\n\t"
+ ";; \n\t"
+ "ld8 r26 = [r20], uc_fr_loc + 8 - (uc_br_loc + 32)\n\t"
+ "ld8 r27 = [r21], 24 \n\t"
+ "cmp.ne p6, p0 = r0, r22 \n\t"
+ ";; \n\t"
+ "ld8 r28 = [r20], 8 \n\t"
+ "(p6) ld8 r22 = [r22] \n\t"
+ "cmp.ne p7, p0 = r0, r23 \n\t"
+ ";; \n\t"
+ "(p7) ld8 r23 = [r23] \n\t"
+ "cmp.ne p8, p0 = r0, r24 \n\t"
+ ";; \n\t"
+ "(p8) ld8 r24 = [r24] \n\t"
+ "(p6) mov b1 = r22 \n\t"
+ "cmp.ne p9, p0 = r0, r25 \n\t"
+ ";; \n\t"
+ "(p9) ld8 r25 = [r25] \n\t"
+ "(p7) mov b2 = r23 \n\t"
+ "cmp.ne p6, p0 = r0, r26 \n\t"
+ ";; \n\t"
+ "(p6) ld8 r26 = [r26] \n\t"
+ "(p8) mov b3 = r24 \n\t"
+ "cmp.ne p7, p0 = r0, r27 \n\t"
+ ";; \n\t"
+ /* Load up call-saved fp registers. */
+ "(p7) ldf.fill f2 = [r27] \n\t"
+ "(p9) mov b4 = r25 \n\t"
+ "cmp.ne p8, p0 = r0, r28 \n\t"
+ ";; \n\t"
+ "(p8) ldf.fill f3 = [r28] \n\t"
+ "(p6) mov b5 = r26 \n\t"
+ ";; \n\t"
+ "ld8 r29 = [r20], 16*8 - 4*8 \n\t"
+ "ld8 r30 = [r21], 17*8 - 5*8 \n\t"
+ ";; \n\t"
+ "ld8 r22 = [r20], 16 \n\t"
+ "ld8 r23 = [r21], 16 \n\t"
+ ";; \n\t"
+ "ld8 r24 = [r20], 16 \n\t"
+ "ld8 r25 = [r21] \n\t"
+ "cmp.ne p6, p0 = r0, r29 \n\t"
+ ";; \n\t"
+ "ld8 r26 = [r20], 8 \n\t"
+ "(p6) ldf.fill f4 = [r29] \n\t"
+ "cmp.ne p7, p0 = r0, r30 \n\t"
+ ";; \n\t"
+ "ld8 r27 = [r20], 8 \n\t"
+ "(p7) ldf.fill f5 = [r30] \n\t"
+ "cmp.ne p6, p0 = r0, r22 \n\t"
+ ";; \n\t"
+ "ld8 r28 = [r20], 8 \n\t"
+ "(p6) ldf.fill f16 = [r22] \n\t"
+ "cmp.ne p7, p0 = r0, r23 \n\t"
+ ";; \n\t"
+ "ld8 r29 = [r20], 8 \n\t"
+ "(p7) ldf.fill f17 = [r23] \n\t"
+ "cmp.ne p6, p0 = r0, r24 \n\t"
+ ";; \n\t"
+ "ld8 r22 = [r20], 8 \n\t"
+ "(p6) ldf.fill f18 = [r24] \n\t"
+ "cmp.ne p7, p0 = r0, r25 \n\t"
+ ";; \n\t"
+ "ld8 r23 = [r20], 8 \n\t"
+ "(p7) ldf.fill f19 = [r25] \n\t"
+ "cmp.ne p6, p0 = r0, r26 \n\t"
+ ";; \n\t"
+ "ld8 r24 = [r20], 8 \n\t"
+ "(p6) ldf.fill f20 = [r26] \n\t"
+ "cmp.ne p7, p0 = r0, r27 \n\t"
+ ";; \n\t"
+ "ld8 r25 = [r20], 8 \n\t"
+ "(p7) ldf.fill f21 = [r27] \n\t"
+ "cmp.ne p6, p0 = r0, r28 \n\t"
+ ";; \n\t"
+ "ld8 r26 = [r20], 8 \n\t"
+ "(p6) ldf.fill f22 = [r28] \n\t"
+ "cmp.ne p7, p0 = r0, r29 \n\t"
+ ";; \n\t"
+ "ld8 r28 = [r20], 8 \n\t"
+ "(p7) ldf.fill f23 = [r29] \n\t"
+ "cmp.ne p6, p0 = r0, r22 \n\t"
+ ";; \n\t"
+ "ld8 r29 = [r20], 8 \n\t"
+ "(p6) ldf.fill f24 = [r22] \n\t"
+ "cmp.ne p7, p0 = r0, r23 \n\t"
+ ";; \n\t"
+ "(p7) ldf.fill f25 = [r23] \n\t"
+ "cmp.ne p6, p0 = r0, r24 \n\t"
+ "cmp.ne p7, p0 = r0, r25 \n\t"
+ ";; \n\t"
+ "(p6) ldf.fill f26 = [r24] \n\t"
+ "(p7) ldf.fill f27 = [r25] \n\t"
+ "cmp.ne p6, p0 = r0, r26 \n\t"
+ ";; \n\t"
+ "(p6) ldf.fill f28 = [r26] \n\t"
+ "cmp.ne p7, p0 = r0, r27 \n\t"
+ "cmp.ne p6, p0 = r0, r28 \n\t"
+ ";; \n\t"
+ "(p7) ldf.fill f29 = [r27] \n\t"
+ "(p6) ldf.fill f30 = [r28] \n\t"
+ "cmp.ne p7, p0 = r0, r29 \n\t"
+ ";; \n\t"
+ "(p7) ldf.fill f31 = [r29] \n\t"
+ "add r20 = uc_rnat, %0 \n\t"
+ "add r21 = uc_bsp, %0 \n\t"
+ ";; \n\t"
+ /* Load the balance of the thread state from the context. */
+ "ld8 r22 = [r20], uc_psp - uc_rnat \n\t"
+ "ld8 r23 = [r21], uc_gp - uc_bsp \n\t"
+ ";; \n\t"
+ "ld8 r24 = [r20], uc_pfs_loc - uc_psp \n\t"
+ "ld8 r1 = [r21], uc_rp - uc_gp \n\t"
+ ";; \n\t"
+ "ld8 r25 = [r20], uc_unat_loc - uc_pfs_loc\n\t"
+ "ld8 r26 = [r21], uc_pr - uc_rp \n\t"
+ ";; \n\t"
+ "ld8 r27 = [r20], uc_lc_loc - uc_unat_loc\n\t"
+ "ld8 r28 = [r21], uc_fpsr_loc - uc_pr \n\t"
+ ";; \n\t"
+ "ld8 r29 = [r20], uc_eh_data - uc_lc_loc\n\t"
+ "ld8 r30 = [r21], uc_eh_data + 8 - uc_fpsr_loc\n\t"
+ ";; \n\t"
+ /* Load data for the exception handler. */
+ "ld8 r15 = [r20], 16 \n\t"
+ "ld8 r16 = [r21], 16 \n\t"
+ ";; \n\t"
+ "ld8 r17 = [r20] \n\t"
+ "ld8 r18 = [r21] \n\t"
+ ";; \n\t"
+ /* Install the balance of the thread state loaded above. */
+ "cmp.ne p6, p0 = r0, r25 \n\t"
+ "cmp.ne p7, p0 = r0, r27 \n\t"
+ ";; \n\t"
+ "(p6) ld8 r25 = [r25] \n\t"
+ "(p7) ld8 r27 = [r27] \n\t"
+ ";; \n\t"
+ "(p7) mov.m ar.unat = r27 \n\t"
+ "(p6) mov.i ar.pfs = r25 \n\t"
+ "cmp.ne p9, p0 = r0, r29 \n\t"
+ ";; \n\t"
+ "(p9) ld8 r29 = [r29] \n\t"
+ "cmp.ne p6, p0 = r0, r30 \n\t"
+ ";; \n\t"
+ "(p6) ld8 r30 = [r30] \n\t"
+ /* Don't clobber p6-p9, which are in use at present. */
+ "mov pr = r28, ~0x3c0 \n\t"
+ "(p9) mov.i ar.lc = r29 \n\t"
+ ";; \n\t"
+ "mov.m r25 = ar.rsc \n\t"
+ "(p6) mov.i ar.fpsr = r30 \n\t"
+ ";; \n\t"
+ "and r25 = 0x1c, r25 \n\t"
+ "mov b0 = r26 \n\t"
+ ";; \n\t"
+ "mov.m ar.rsc = r25 \n\t"
+ ";; \n\t"
+ /* This must be done before setting AR.BSPSTORE, otherwise
+ AR.BSP will be initialized with a random displacement
+ below the value we want, based on the current number of
+ dirty stacked registers. */
+ "loadrs \n\t"
+ "invala \n\t"
+ ";; \n\t"
+ "mov.m ar.bspstore = r23 \n\t"
+ ";; \n\t"
+ "or r25 = 0x3, r25 \n\t"
+ "mov.m ar.rnat = r22 \n\t"
+ ";; \n\t"
+ "mov.m ar.rsc = r25 \n\t"
+ "mov sp = r24 \n\t"
+ "br.ret.sptk.few b0"
+ : : "r"(target), "r"(ireg_buf), "r"(ireg_nat), "r"(ireg_pr)
+ : "r15", "r16", "r17", "r18", "r20", "r21", "r22",
+ "r23", "r24", "r25", "r26", "r27", "r28", "r29",
+ "r30", "r31");
+ /* NOTREACHED */
+ while (1);
+}
+
+static inline _Unwind_Ptr
+uw_identify_context (struct _Unwind_Context *context)
+{
+ return _Unwind_GetIP (context);
+}
+
+#include "unwind.inc"
+#endif
diff --git a/gcc/config/ia64/frame-ia64.h b/gcc/config/ia64/unwind-ia64.h
index d638ca3862b..a6b850df80a 100644
--- a/gcc/config/ia64/frame-ia64.h
+++ b/gcc/config/ia64/unwind-ia64.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999, 2000 Free Software Foundation, Inc.
+/* Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
Contributed by Andrew MacLeod <amacleod@cygnus.com>
Andrew Haley <aph@cygnus.com>
@@ -19,18 +19,13 @@
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* This structure represents a single unwind table entry. We lie and say
- its the dwarf_fde structure to use the common object in frame.h */
-
-typedef struct dwarf_fde
+struct unw_table_entry
{
- long start_offset;
- long end_offset;
- long unwind_offset;
-} unwind_table_entry;
-
-/* Defining dwarf_fde allows us to use the common object registration. */
-typedef unwind_table_entry dwarf_fde;
-typedef unwind_table_entry fde;
+ unsigned long start_offset;
+ unsigned long end_offset;
+ unsigned long info_offset;
+};
-extern fde *__ia64_find_fde (void *, void **);
+extern struct unw_table_entry *
+_Unwind_FindTableEntry (void *pc, unsigned long *segment_base,
+ unsigned long *gp);
diff --git a/gcc/config/ia64/xm-ia64.h b/gcc/config/ia64/xm-ia64.h
index 481de923085..7f29198701b 100644
--- a/gcc/config/ia64/xm-ia64.h
+++ b/gcc/config/ia64/xm-ia64.h
@@ -18,10 +18,6 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* #defines that need visibility everywhere. */
-#define FALSE 0
-#define TRUE 1
-
/* A C expression for the status code to be returned when the compiler exits
after serious errors. */
#define FATAL_EXIT_CODE 33
diff --git a/gcc/config/linux.h b/gcc/config/linux.h
index 1ef26b3f194..dc1a4c72113 100644
--- a/gcc/config/linux.h
+++ b/gcc/config/linux.h
@@ -47,15 +47,6 @@ Boston, MA 02111-1307, USA. */
#undef MD_EXEC_PREFIX
#undef MD_STARTFILE_PREFIX
-/* Output at beginning of assembler file. */
-/* The .file command should always begin the output. */
-#undef ASM_FILE_START
-#define ASM_FILE_START(FILE) \
- do { \
- output_file_directive (FILE, main_input_filename); \
- fprintf (FILE, "\t.version\t\"01.01\"\n"); \
- } while (0)
-
/* Provide a STARTFILE_SPEC appropriate for GNU/Linux. Here we add
the GNU/Linux magical crtbegin.o file (see crtstuff.c) which
provides part of the support for getting C++ file-scope static
@@ -84,6 +75,10 @@ Boston, MA 02111-1307, USA. */
#define CC1_SPEC "%{profile:-p}"
#endif
+/* The GNU C++ standard library requires that these macros be defined. */
+#undef CPLUSPLUS_CPP_SPEC
+#define CPLUSPLUS_CPP_SPEC "-D_GNU_SOURCE %(cpp)"
+
#ifndef USE_GNULIBC_1
#undef DEFAULT_VTABLE_THUNKS
#define DEFAULT_VTABLE_THUNKS 1
diff --git a/gcc/config/m32r/m32r.c b/gcc/config/m32r/m32r.c
index 09b7e43e6c5..f57e2798edf 100644
--- a/gcc/config/m32r/m32r.c
+++ b/gcc/config/m32r/m32r.c
@@ -27,7 +27,6 @@ Boston, MA 02111-1307, USA. */
#include "real.h"
#include "insn-config.h"
#include "conditions.h"
-#include "insn-flags.h"
#include "output.h"
#include "insn-attr.h"
#include "flags.h"
diff --git a/gcc/config/m32r/xm-m32r.h b/gcc/config/m32r/xm-m32r.h
index 57100c875cd..b49f76b2918 100644
--- a/gcc/config/m32r/xm-m32r.h
+++ b/gcc/config/m32r/xm-m32r.h
@@ -18,10 +18,6 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* #defines that need visibility everywhere. */
-#define FALSE 0
-#define TRUE 1
-
/* This describes the machine the compiler is hosted on. */
#define HOST_BITS_PER_CHAR 8
#define HOST_BITS_PER_SHORT 16
diff --git a/gcc/config/m68hc11/larith.asm b/gcc/config/m68hc11/larith.asm
index e75772964f1..6ec9ba57f4d 100644
--- a/gcc/config/m68hc11/larith.asm
+++ b/gcc/config/m68hc11/larith.asm
@@ -1,5 +1,5 @@
-/* libgcc1 routines for M68HC11.
- Copyright (C) 1999, 2000 Free Software Foundation, Inc.
+/* libgcc1 routines for M68HC11 & M68HC12.
+ Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -47,35 +47,74 @@ NAME: .word 0; \
/* Pseudo hard registers used by gcc.
They must be located in page0.
They will normally appear at the end of .page0 section. */
+#ifdef mc68hc12
+ .sect .bss
+#else
.sect .page0
- .globl _.tmp,_.frame
+#endif
+ .globl _.tmp
.globl _.z,_.xy
REG(_.tmp)
REG(_.z)
REG(_.xy)
-REG(_.frame)
#endif
-#ifdef L_regs_d1_8
-/* Pseudo hard registers used by gcc.
- They must be located in page0.
- They will normally appear at the end of .page0 section. */
+#ifdef L_regs_frame
+#ifdef mc68hc12
+ .sect .bss
+#else
.sect .page0
- .globl _.d1,_.d2,_.d3,_.d4,_.d5,_.d6
- .globl _.d7,_.d8
+#endif
+ .globl _.frame
+REG(_.frame)
+#endif
+
+#ifdef L_regs_d1_2
+#ifdef mc68hc12
+ .sect .bss
+#else
+ .sect .page0
+#endif
+ .globl _.d1,_.d2
REG(_.d1)
REG(_.d2)
+#endif
+
+#ifdef L_regs_d3_4
+#ifdef mc68hc12
+ .sect .bss
+#else
+ .sect .page0
+#endif
+ .globl _.d3,_.d4
REG(_.d3)
REG(_.d4)
+#endif
+
+#ifdef L_regs_d5_6
+#ifdef mc68hc12
+ .sect .bss
+#else
+ .sect .page0
+#endif
+ .globl _.d5,_.d6
REG(_.d5)
REG(_.d6)
+#endif
+
+#ifdef L_regs_d7_8
+#ifdef mc68hc12
+ .sect .bss
+#else
+ .sect .page0
+#endif
+ .globl _.d7,_.d8
REG(_.d7)
REG(_.d8)
-
#endif
-#ifdef L_regs_d8_16
+#ifdef L_regs_d9_16
/* Pseudo hard registers used by gcc.
They must be located in page0.
They will normally appear at the end of .page0 section. */
@@ -97,7 +136,11 @@ REG(_.d16)
/* Pseudo hard registers used by gcc.
They must be located in page0.
They will normally appear at the end of .page0 section. */
+#ifdef mc68hc12
+ .sect .bss
+#else
.sect .page0
+#endif
.globl _.d17,_.d18,_.d19,_.d20,_.d21,_.d22
.globl _.d23,_.d24,_.d25,_.d26,_.d27,_.d28
.globl _.d29,_.d30,_.d31,_.d32
@@ -136,13 +179,26 @@ __premain:
;;
;; 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.
;;
- .sect .text
- .globl _exit
+;; _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
exit:
_exit:
+
+ .sect .fini4,"ax",@progbits
fatal:
cli
wai
@@ -157,8 +213,12 @@ fatal:
.globl abort
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
@@ -189,6 +249,23 @@ _cleanup:
;;;
__memcpy:
memcpy:
+#ifdef mc68hc12
+ ldx 2,sp
+ ldy 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
+ rts
+#else
xgdy
tsx
ldd 4,x
@@ -214,6 +291,7 @@ End:
xgdy
rts
#endif
+#endif
#ifdef L_memset
.sect .text
@@ -237,6 +315,19 @@ End:
#endif
__memset:
memset:
+#ifdef mc68hc12
+ xgdx
+ ldab val,sp
+ ldy size,sp
+ pshx
+ beq End
+Loop:
+ stab 1,x+
+ dbne y,Loop
+End:
+ puld
+ rts
+#else
xgdx
tsy
ldab val,y
@@ -253,6 +344,7 @@ End:
xgdx
rts
#endif
+#endif
#ifdef L_adddi3
.sect .text
@@ -260,29 +352,28 @@ End:
___adddi3:
tsx
- tsy
pshb
psha
ldd 8,x
- addd 16,y
+ addd 16,x
pshb
psha
ldd 6,x
- adcb 15,y
- adca 14,y
+ adcb 15,x
+ adca 14,x
pshb
psha
ldd 4,x
- adcb 13,y
- adca 12,y
+ adcb 13,x
+ adca 12,x
pshb
psha
ldd 2,x
- adcb 11,y
- adca 10,y
+ adcb 11,x
+ adca 10,x
tsx
ldy 6,x
@@ -303,29 +394,28 @@ ___adddi3:
___subdi3:
tsx
- tsy
pshb
psha
ldd 8,x
- subd 16,y
+ subd 16,x
pshb
psha
ldd 6,x
- sbcb 15,y
- sbca 14,y
+ sbcb 15,x
+ sbca 14,x
pshb
psha
ldd 4,x
- sbcb 13,y
- sbca 12,y
+ sbcb 13,x
+ sbca 12,x
pshb
psha
ldd 2,x
- sbcb 11,y
- sbca 10,y
+ sbcb 11,x
+ sbca 10,x
tsx
ldy 6,x
@@ -582,6 +672,9 @@ Return_zero:
#endif
#ifdef L_divmodhi4
+#ifndef mc68hc12
+/* 68HC12 signed divisions are generated inline (idivs). */
+
.sect .text
.globl __divmodhi4
@@ -646,6 +739,7 @@ Numerator_neg_denominator_pos:
comb
addd #1
rts
+#endif /* !mc68hc12 */
#endif
#ifdef L_mulqi3
@@ -681,7 +775,6 @@ A_or_B_neg:
addd #1
rts
AB_neg:
- nega
negb
mul
rts
@@ -699,6 +792,13 @@ AB_neg:
; b = register X
;
___mulhi3:
+#ifdef mc68hc12
+ pshx ; Preserve X
+ exg x,y
+ emul
+ exg x,y
+ pulx
+#else
stx *_.tmp
pshb
ldab *_.tmp+1
@@ -714,6 +814,7 @@ ___mulhi3:
pulb
mul ; A.low * B.low
adda *_.tmp
+#endif
rts
#endif
@@ -750,6 +851,11 @@ ___mulhi3:
; <A-high> 0,x
;
__mulhi32:
+#ifdef mc68hc12
+ ldy 2,sp
+ emul
+ exg x,y
+#else
pshb
psha
tsx
@@ -781,6 +887,7 @@ N:
Ret:
pshy
pulx
+#endif
rts
#endif
@@ -806,11 +913,27 @@ Ret:
;
;
+__mulsi3:
+#ifdef mc68hc12
+ pshd ; Save A.low
+ ldy 4,sp
+ emul ; A.low * B.high
+ ldy 6,sp
+ exg x,d
+ emul ; A.high * B.low
+ leax d,x
+ ldy 6,sp
+ puld
+ emul ; A.low * B.low
+ exg d,y
+ leax d,x
+ exg d,y
+ rts
+#else
B_low = 8
B_high = 6
A_low = 0
A_high = 2
-__mulsi3:
pshx
pshb
psha
@@ -921,10 +1044,11 @@ A_low_B_low:
bsr __mulhi32
bra Return
#endif
+#endif
#ifdef L_map_data
- .sect .install3,"ax",@progbits
+ .sect .install2,"ax",@progbits
.globl __map_data_section
__map_data_section:
@@ -933,6 +1057,10 @@ __map_data_section:
ldx #__data_image
ldy #__data_section_start
Loop:
+#ifdef mc68hc12
+ movb 1,x+,1,y+
+ dbne d,Loop
+#else
psha
ldaa 0,x
staa 0,y
@@ -941,13 +1069,14 @@ Loop:
iny
subd #1
bne Loop
+#endif
Done:
#endif
#ifdef L_init_bss
- .sect .install3,"ax",@progbits
+ .sect .install2,"ax",@progbits
.globl __init_bss_section
__init_bss_section:
@@ -955,14 +1084,70 @@ __init_bss_section:
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__
+ blt 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__
+ bge dtors_done
+ pshx
+ ldx 0,x
+ jsr 0,x
+ pulx
+ inx
+ inx
+ bra dtors_loop
+dtors_done:
+ pula ; Restore exit code
+ pulb
+
+#endif
+
;-----------------------------------------
; end required gcclib code
;-----------------------------------------
diff --git a/gcc/config/m68hc11/m68hc11-protos.h b/gcc/config/m68hc11/m68hc11-protos.h
index b63fa30f20e..22eccd02cab 100644
--- a/gcc/config/m68hc11/m68hc11-protos.h
+++ b/gcc/config/m68hc11/m68hc11-protos.h
@@ -1,5 +1,5 @@
/* Prototypes for exported functions defined in m68hc11.c
- Copyright (C) 1999, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
Contributed by Stephane Carrez (stcarrez@worldnet.fr)
This file is part of GNU CC.
@@ -53,15 +53,15 @@ extern void m68hc11_encode_section_info PARAMS((tree));
#endif
#ifdef RTX_CODE
-#if GCC_VERSION > 2095
extern rtx m68hc11_compare_op0;
extern rtx m68hc11_compare_op1;
-#endif
extern rtx m68hc11_soft_tmp_reg;
extern rtx iy_reg;
extern rtx d_reg;
+extern void m68hc11_initialize_trampoline PARAMS((rtx, rtx, rtx));
+
extern rtx m68hc11_expand_compare_and_branch PARAMS((enum rtx_code,
rtx, rtx, rtx));
extern enum reg_class preferred_reload_class PARAMS((rtx, enum reg_class));
@@ -73,6 +73,7 @@ extern int m68hc11_go_if_legitimate_address PARAMS((rtx,
extern int m68hc11_legitimize_address PARAMS((rtx*, rtx, enum machine_mode));
extern void m68hc11_notice_update_cc PARAMS((rtx, rtx));
+extern void m68hc11_notice_keep_cc PARAMS((rtx));
extern void m68hc11_reorg PARAMS((rtx));
@@ -140,8 +141,6 @@ extern int hard_reg_operand PARAMS((rtx, enum machine_mode));
extern int soft_reg_operand PARAMS((rtx, enum machine_mode));
extern int reg_or_some_mem_operand PARAMS((rtx, enum machine_mode));
-extern enum reg_class limit_reload_class PARAMS((enum machine_mode, enum reg_class));
-
#if defined TREE_CODE
extern void m68hc11_init_cumulative_args PARAMS((CUMULATIVE_ARGS*,
tree,
@@ -165,10 +164,8 @@ extern void m68hc11_function_epilogue PARAMS((FILE*,int));
#endif /* TREE_CODE */
-#if GCC_VERSION > 2095
extern HOST_WIDE_INT m68hc11_min_offset;
extern HOST_WIDE_INT m68hc11_max_offset;
-#endif
#endif /* HAVE_MACHINE_MODES */
#endif /* RTX_CODE */
diff --git a/gcc/config/m68hc11/m68hc11.c b/gcc/config/m68hc11/m68hc11.c
index 2fcf4ce6dab..33f78d7bf57 100644
--- a/gcc/config/m68hc11/m68hc11.c
+++ b/gcc/config/m68hc11/m68hc11.c
@@ -37,15 +37,12 @@ Note:
#include "system.h"
#include "rtl.h"
#include "tree.h"
-#if GCC_VERSION > 2095
#include "tm_p.h"
-#endif
#include "regs.h"
#include "hard-reg-set.h"
#include "real.h"
#include "insn-config.h"
#include "conditions.h"
-#include "insn-flags.h"
#include "output.h"
#include "insn-attr.h"
#include "flags.h"
@@ -53,16 +50,8 @@ Note:
#include "expr.h"
#include "toplev.h"
#include "basic-block.h"
-#if GCC_VERSION > 2095
#include "function.h"
#include "ggc.h"
-#else
-#include "m68hc11-protos.h"
-#endif
-
-#if GCC_VERSION == 2095
-extern char *version_string;
-#endif
static void print_options PARAMS ((FILE *));
static void emit_move_after_reload PARAMS ((rtx, rtx, rtx));
@@ -73,7 +62,7 @@ static int go_if_legitimate_address_internal PARAMS((rtx, enum machine_mode,
static int register_indirect_p PARAMS((rtx, enum machine_mode, int));
static rtx m68hc11_expand_compare PARAMS((enum rtx_code, rtx, rtx));
static int must_parenthesize PARAMS ((rtx));
-
+static int m68hc11_shift_cost PARAMS ((enum machine_mode, rtx, int));
static int m68hc11_auto_inc_p PARAMS ((rtx));
void create_regs_rtx PARAMS ((void));
@@ -131,6 +120,78 @@ rtx m68hc11_compare_op0;
rtx m68hc11_compare_op1;
+struct processor_costs *m68hc11_cost;
+
+/* Costs for a 68HC11. */
+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. */
+struct processor_costs m6812_cost = {
+ /* add */
+ COSTS_N_INSNS (1),
+ /* logical */
+ COSTS_N_INSNS (1),
+ /* 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)
+};
+
/* Machine specific options */
const char *m68hc11_regparm_string;
@@ -141,32 +202,23 @@ static void m68hc11_add_gc_roots PARAMS ((void));
static int nb_soft_regs;
-#if GCC_VERSION > 2095
-/* Flag defined in c-decl.c
-
- Nonzero means don't recognize the non-ANSI builtin functions.
- -ansi sets this.
-
- It is set by 'm68hc11_override_options' to ensure that bcmp() and
- bzero() are not defined. Their prototype are wrong and they
- conflict with newlib definition. Don't define as external to
- avoid a link problem for f77. */
-int flag_no_nonansi_builtin;
-#endif
-
int
m68hc11_override_options ()
{
m68hc11_add_gc_roots ();
-#if GCC_VERSION > 2095
- flag_no_nonansi_builtin = 1;
-#endif
-
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 ("-f%s ignored for 68HC11/68HC12 (not supported)",
+ (flag_pic > 1) ? "PIC" : "pic");
+ flag_pic = 0;
+ }
+
/* Configure for a 68hc11 processor. */
if (TARGET_M6811)
{
@@ -174,7 +226,8 @@ m68hc11_override_options ()
a -m68hc11 option was specified on the command line. */
if (TARGET_DEFAULT != MASK_M6811)
target_flags &= ~TARGET_DEFAULT;
-
+
+ m68hc11_cost = &m6811_cost;
m68hc11_min_offset = 0;
m68hc11_max_offset = 256;
m68hc11_index_reg_class = NO_REGS;
@@ -191,7 +244,8 @@ m68hc11_override_options ()
/* Configure for a 68hc12 processor. */
if (TARGET_M6812)
{
- m68hc11_min_offset = 0;
+ 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;
@@ -293,29 +347,6 @@ hard_regno_mode_ok (regno, mode)
}
enum reg_class
-limit_reload_class (mode, class)
- enum machine_mode mode;
- enum reg_class class;
-{
- if (mode == Pmode)
- {
- if (class == m68hc11_base_reg_class || class == SP_REGS
- || class == Y_REGS || class == X_REGS
- || class == X_OR_SP_REGS || class == Y_OR_S_REGS
- || class == A_OR_SP_REGS)
- return class;
-
- if (debug_m6811)
- {
- printf ("Forcing to A_REGS\n");
- fflush (stdout);
- }
- return m68hc11_base_reg_class;
- }
- return class;
-}
-
-enum reg_class
preferred_reload_class (operand, class)
rtx operand;
enum reg_class class;
@@ -748,13 +779,14 @@ m68hc11_emit_libcall (name, code, dmode, smode, noperands, operands)
switch (noperands)
{
case 2:
- ret = emit_library_call_value (libcall, NULL_RTX, 1, dmode, 1,
- operands[1], smode);
+ ret = emit_library_call_value (libcall, NULL_RTX, LCT_CONST,
+ dmode, 1, operands[1], smode);
equiv = gen_rtx (code, dmode, operands[1]);
break;
case 3:
- ret = emit_library_call_value (libcall, operands[0], 1, dmode, 2,
+ ret = emit_library_call_value (libcall, NULL_RTX,
+ LCT_CONST, dmode, 2,
operands[1], smode, operands[2],
smode);
equiv = gen_rtx (code, dmode, operands[1], operands[2]);
@@ -1032,6 +1064,54 @@ m68hc11_function_block_profiler (out, block_or_label)
{
return 0;
}
+
+/* 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
+
+*/
+void
+m68hc11_initialize_trampoline (tramp, fnaddr, cxt)
+ rtx tramp;
+ rtx fnaddr;
+ rtx cxt;
+{
+ char *static_chain_reg = reg_names[STATIC_CHAIN_REGNUM];
+
+ /* Skip the '*'. */
+ if (*static_chain_reg == '*')
+ static_chain_reg++;
+ if (TARGET_M6811)
+ {
+ emit_move_insn (gen_rtx_MEM (HImode, tramp), GEN_INT (0x18ce));
+ emit_move_insn (gen_rtx_MEM (HImode, plus_constant (tramp, 2)), cxt);
+ emit_move_insn (gen_rtx_MEM (HImode, plus_constant (tramp, 4)),
+ GEN_INT (0x18df));
+ emit_move_insn (gen_rtx_MEM (QImode, plus_constant (tramp, 6)),
+ gen_rtx_CONST (QImode,
+ gen_rtx_SYMBOL_REF (Pmode,
+ static_chain_reg)));
+ emit_move_insn (gen_rtx_MEM (QImode, plus_constant (tramp, 7)),
+ GEN_INT (0x7e));
+ emit_move_insn (gen_rtx_MEM (HImode, plus_constant (tramp, 8)), fnaddr);
+ }
+ else
+ {
+ emit_move_insn (gen_rtx_MEM (HImode, tramp), GEN_INT (0x1803));
+ emit_move_insn (gen_rtx_MEM (HImode, plus_constant (tramp, 2)), cxt);
+ emit_move_insn (gen_rtx_MEM (HImode, plus_constant (tramp, 4)),
+ gen_rtx_CONST (HImode,
+ gen_rtx_SYMBOL_REF (Pmode,
+ static_chain_reg)));
+ emit_move_insn (gen_rtx_MEM (QImode, plus_constant (tramp, 6)),
+ GEN_INT (0x06));
+ emit_move_insn (gen_rtx_MEM (HImode, plus_constant (tramp, 7)), fnaddr);
+ }
+}
/* Declaration of types. */
@@ -1174,7 +1254,7 @@ m68hc11_initial_elimination_offset (from, to)
if (from == FRAME_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
{
- return 0;
+ return m68hc11_sp_correction;
}
/* Push any 2 byte pseudo hard registers that we need to save. */
@@ -1193,7 +1273,7 @@ m68hc11_initial_elimination_offset (from, to)
if (from == FRAME_POINTER_REGNUM && to == HARD_SP_REGNUM)
{
- return size - m68hc11_sp_correction;
+ return size;
}
return 0;
}
@@ -1325,8 +1405,6 @@ m68hc11_function_arg (cum, mode, type, named)
return NULL_RTX;
}
-#if GCC_VERSION > 2095
-
/* The "standard" implementation of va_start: just assign `nextarg' to
the variable. */
void
@@ -1394,7 +1472,6 @@ m68hc11_va_arg (valist, type)
return addr;
}
-#endif
/* 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
@@ -1862,18 +1939,30 @@ m68hc11_gen_highpart (mode, x)
}
/* gen_highpart crashes when it is called with a SUBREG. */
- if (GET_CODE (x) == SUBREG && SUBREG_WORD (x) != 0)
+ if (GET_CODE (x) == SUBREG)
{
return gen_rtx (SUBREG, mode, XEXP (x, 0), XEXP (x, 1));
}
- x = gen_highpart (mode, x);
+ if (GET_CODE (x) == REG)
+ {
+ if (REGNO (x) < FIRST_PSEUDO_REGISTER)
+ return gen_rtx (REG, mode, REGNO (x));
+ else
+ return gen_rtx_SUBREG (mode, x, 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;
+ {
+ 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;
+ }
+ abort ();
}
@@ -2143,9 +2232,19 @@ print_operand (file, op, letter)
}
else
{
+ int need_parenthesize = 0;
+
if (letter != 'i')
asm_fprintf (file, "%0I");
+ else
+ need_parenthesize = must_parenthesize (op);
+
+ if (need_parenthesize)
+ asm_fprintf (file, "(");
+
output_addr_const (file, op);
+ if (need_parenthesize)
+ asm_fprintf (file, ")");
}
}
@@ -2526,6 +2625,7 @@ m68hc11_split_move (to, from, scratch)
rtx low_to, low_from;
rtx high_to, high_from;
enum machine_mode mode;
+ int offset = 0;
mode = GET_MODE (to);
if (GET_MODE_SIZE (mode) == 8)
@@ -2535,6 +2635,22 @@ m68hc11_split_move (to, from, scratch)
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);
@@ -2549,6 +2665,11 @@ m68hc11_split_move (to, from, scratch)
else
high_from = m68hc11_gen_highpart (mode, from);
+ if (offset)
+ {
+ high_from = adj_offsettable_operand (high_from, offset);
+ low_from = high_from;
+ }
if (mode == SImode)
{
m68hc11_split_move (low_to, low_from, scratch);
@@ -2841,6 +2962,7 @@ m68hc11_gen_movhi (insn, operands)
{
if (IS_STACK_PUSH (operands[0]) && H_REG_P (operands[1]))
{
+ cc_status = cc_prev_status;
switch (REGNO (operands[1]))
{
case HARD_X_REGNUM:
@@ -2855,6 +2977,7 @@ m68hc11_gen_movhi (insn, operands)
}
if (IS_STACK_POP (operands[1]) && H_REG_P (operands[0]))
{
+ cc_status = cc_prev_status;
switch (REGNO (operands[0]))
{
case HARD_X_REGNUM:
@@ -2869,6 +2992,7 @@ m68hc11_gen_movhi (insn, operands)
}
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]))
@@ -2910,6 +3034,7 @@ m68hc11_gen_movhi (insn, operands)
else
{
/* !!!! SCz wrong here. */
+ fatal_insn ("Move insn not handled", insn);
}
}
else
@@ -2921,6 +3046,7 @@ m68hc11_gen_movhi (insn, operands)
}
else
{
+ m68hc11_notice_keep_cc (operands[0]);
output_asm_insn ("movw\t%1,%0", operands);
}
}
@@ -2930,6 +3056,7 @@ m68hc11_gen_movhi (insn, operands)
if (IS_STACK_POP (operands[1]) && H_REG_P (operands[0]))
{
+ cc_status = cc_prev_status;
switch (REGNO (operands[0]))
{
case HARD_X_REGNUM:
@@ -2965,7 +3092,7 @@ m68hc11_gen_movhi (insn, operands)
}
else
{
- cc_status = cc_prev_status;
+ m68hc11_notice_keep_cc (operands[0]);
output_asm_insn ("pshx\n\tpula\n\tpulb", operands);
}
}
@@ -3020,7 +3147,7 @@ m68hc11_gen_movhi (insn, operands)
}
else
{
- cc_status = cc_prev_status;
+ m68hc11_notice_keep_cc (operands[0]);
output_asm_insn ("pshb", operands);
output_asm_insn ("psha", operands);
output_asm_insn ("pulx", operands);
@@ -3028,8 +3155,20 @@ m68hc11_gen_movhi (insn, operands)
}
else if (Y_REG_P (operands[1]))
{
- output_asm_insn ("sty\t%t1", operands);
- output_asm_insn ("ldx\t%t1", operands);
+ /* 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
+ {
+ output_asm_insn ("sty\t%t1", operands);
+ output_asm_insn ("ldx\t%t1", operands);
+ }
}
else if (SP_REG_P (operands[1]))
{
@@ -3058,8 +3197,20 @@ m68hc11_gen_movhi (insn, operands)
}
else if (X_REG_P (operands[1]))
{
- output_asm_insn ("stx\t%t1", operands);
- output_asm_insn ("ldy\t%t1", operands);
+ /* 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
+ {
+ output_asm_insn ("stx\t%t1", operands);
+ output_asm_insn ("ldy\t%t1", operands);
+ }
}
else if (SP_REG_P (operands[1]))
{
@@ -3076,7 +3227,7 @@ m68hc11_gen_movhi (insn, operands)
case HARD_SP_REGNUM:
if (D_REG_P (operands[1]))
{
- cc_status = cc_prev_status;
+ m68hc11_notice_keep_cc (operands[0]);
output_asm_insn ("xgdx", operands);
output_asm_insn ("txs", operands);
output_asm_insn ("xgdx", operands);
@@ -3117,6 +3268,7 @@ m68hc11_gen_movhi (insn, operands)
if (IS_STACK_PUSH (operands[0]) && H_REG_P (operands[1]))
{
+ cc_status = cc_prev_status;
switch (REGNO (operands[1]))
{
case HARD_X_REGNUM:
@@ -3200,25 +3352,26 @@ m68hc11_gen_movqi (insn, operands)
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 (Q_REG_P (operands[0]))
- output_asm_insn ("lda%0\t%1", operands);
+ output_asm_insn ("lda%0\t%b1", operands);
else if (D_REG_P (operands[0]))
- output_asm_insn ("ldab\t%1", operands);
+ output_asm_insn ("ldab\t%b1", operands);
else
- output_asm_insn ("ld%0\t%1", operands);
+ goto m6811_move;
}
else if (H_REG_P (operands[1]))
{
if (Q_REG_P (operands[1]))
- output_asm_insn ("sta%1\t%0", operands);
+ output_asm_insn ("sta%1\t%b0", operands);
else if (D_REG_P (operands[1]))
- output_asm_insn ("staa\t%0", operands);
+ output_asm_insn ("stab\t%b0", operands);
else
- output_asm_insn ("st%1\t%0", operands);
+ goto m6811_move;
}
else
{
@@ -3245,6 +3398,7 @@ m68hc11_gen_movqi (insn, operands)
else
{
/* !!!! SCz wrong here. */
+ fatal_insn ("Move insn not handled", insn);
}
}
else
@@ -3255,13 +3409,15 @@ m68hc11_gen_movqi (insn, operands)
}
else
{
- output_asm_insn ("movb\t%1,%0", operands);
+ 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]))
@@ -3636,6 +3792,24 @@ m68hc11_notice_update_cc (exp, insn)
&& reg_overlap_mentioned_p (cc_status.value1, 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 (reg)
+ 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;
+}
+
/* Machine Specific Reorg. */
@@ -3721,6 +3895,7 @@ m68hc11_check_z_replacement (insn, 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;
@@ -3824,10 +3999,13 @@ m68hc11_check_z_replacement (insn, info)
{
if (!reg_mentioned_p (z_reg, src))
{
- if (insn == info->first)
+ /* Z reg is used before being set. Treat this as
+ a new sequence of Z register replacement. */
+ if (insn != info->first)
{
- info->must_load_z = 0;
+ return 0;
}
+ info->must_load_z = 0;
}
info->z_set_count++;
info->z_value = src;
@@ -3847,9 +4025,23 @@ m68hc11_check_z_replacement (insn, info)
/* 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))
+ 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 |= reg_mentioned_p (z_reg, dst);
+
+ 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)
{
@@ -3866,6 +4058,9 @@ m68hc11_check_z_replacement (insn, info)
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)
@@ -3928,8 +4123,8 @@ m68hc11_check_z_replacement (insn, info)
return 0;
}
info->x_used = 1;
- if (z_dies_here && !reg_mentioned_p (src, ix_reg)
- && GET_CODE (src) == REG && REGNO (src) == HARD_X_REGNUM)
+ 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;
@@ -3939,6 +4134,13 @@ m68hc11_check_z_replacement (insn, info)
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)
{
@@ -3999,8 +4201,8 @@ m68hc11_check_z_replacement (insn, info)
return 0;
}
info->y_used = 1;
- if (z_dies_here && !reg_mentioned_p (src, iy_reg)
- && GET_CODE (src) == REG && REGNO (src) == HARD_Y_REGNUM)
+ 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;
@@ -4010,6 +4212,13 @@ m68hc11_check_z_replacement (insn, info)
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)
{
@@ -4063,6 +4272,9 @@ m68hc11_check_z_replacement (insn, info)
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;
}
@@ -4374,6 +4586,8 @@ m68hc11_z_replacement (insn)
&& 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;
}
}
@@ -4589,73 +4803,24 @@ m68hc11_reassign_regs (first)
}
}
-#if GCC_VERSION == 2095
-/* Split all insns in the function. If UPD_LIFE, update life info after. */
-
-static int
-m68hc11_split_all_insns (first)
- rtx first;
-{
- rtx insn;
- int split_done = 0;
-
- for (insn = first; insn; insn = NEXT_INSN (insn))
- {
- rtx last;
-
- if (INSN_DELETED_P (insn))
- continue;
- if (GET_RTX_CLASS (GET_CODE (insn)) != 'i')
- continue;
-
- last = try_split (PATTERN (insn), insn, 1);
-
- /* When not optimizing, the old insn will be still left around
- with only the 'deleted' bit set. Transform it into a note
- to avoid confusion of subsequent processing. */
- if (INSN_DELETED_P (insn))
- {
- PUT_CODE (insn, NOTE);
- NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
- NOTE_SOURCE_FILE (insn) = 0;
- split_done = 1;
- }
-
- if (last != insn)
- {
- PUT_CODE (insn, NOTE);
- NOTE_SOURCE_FILE (insn) = 0;
- NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
- split_done = 1;
- }
- }
- return split_done;
-}
-#endif /* GCC_VERSION == 2095 */
-
void
m68hc11_reorg (first)
rtx first;
{
int split_done = 0;
+ rtx insn;
z_replacement_completed = 0;
z_reg = gen_rtx (REG, HImode, HARD_Z_REGNUM);
-#if GCC_VERSION > 2095
/* Some RTX are shared at this point. This breaks the Z register
replacement, unshare everything. */
unshare_all_rtl_again (first);
-#endif
/* Force a split of all splitable insn. This is necessary for the
Z register replacement mechanism because we end up with basic insns. */
-#if GCC_VERSION > 2095
split_all_insns (0);
split_done = 1;
-#else
- split_done = m68hc11_split_all_insns (first);
-#endif
z_replacement_completed = 1;
m68hc11_reassign_regs (first);
@@ -4669,14 +4834,30 @@ m68hc11_reorg (first)
description to use the best assembly directives. */
if (optimize)
{
-#if GCC_VERSION > 2095
+ /* Before recomputing the REG_DEAD notes, remove all of them.
+ This is necessary because the reload_cse_regs() pass can
+ have replaced some (MEM) with a register. In that case,
+ the REG_DEAD that could exist for that register may become
+ wrong. */
+ for (insn = first; insn; insn = NEXT_INSN (insn))
+ {
+ if (INSN_P (insn))
+ {
+ rtx *pnote;
+
+ pnote = &REG_NOTES (insn);
+ while (*pnote != 0)
+ {
+ if (REG_NOTE_KIND (*pnote) == REG_DEAD)
+ *pnote = XEXP (*pnote, 1);
+ else
+ pnote = &XEXP (*pnote, 1);
+ }
+ }
+ }
+
find_basic_blocks (first, max_reg_num (), 0);
life_analysis (first, 0, PROP_REG_INFO | PROP_DEATH_NOTES);
-#else
- find_basic_blocks (first, max_reg_num (), 0, 1);
- life_analysis (first, max_reg_num (), 0,
- 1 /* SCz: dead code elim fails. Must investigate. */ );
-#endif
}
z_replacement_completed = 2;
@@ -4685,11 +4866,7 @@ m68hc11_reorg (first)
split after Z register replacement. This gives more opportunities
for peephole (in particular for consecutives xgdx/xgdy). */
if (optimize > 0)
-#if GCC_VERSION > 2095
split_all_insns (0);
-#else
- m68hc11_split_all_insns (first);
-#endif
/* Once insns are split after the z_replacement_completed == 2,
we must not re-run the life_analysis. The xgdx/xgdy patterns
@@ -4728,8 +4905,6 @@ m68hc11_reorg (first)
/* Cost functions. */
-#define COSTS_N_INSNS(N) ((N) * 4 - 2)
-
/* Cost of moving memory. */
int
m68hc11_memory_move_cost (mode, class, in)
@@ -4860,10 +5035,43 @@ m68hc11_address_cost (addr)
return cost;
}
+static int
+m68hc11_shift_cost (mode, x, shift)
+ enum machine_mode mode;
+ rtx x;
+ int shift;
+{
+ int total;
+
+ total = rtx_cost (x, SET);
+ 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 prefered. */
+ if (optimize_size && (shift % 8) != 0)
+ total *= 2;
+
+ return total;
+}
+
int
m68hc11_rtx_costs (x, code, outer_code)
rtx x;
- enum rtx_code code, outer_code;
+ enum rtx_code code;
+ enum rtx_code outer_code ATTRIBUTE_UNUSED;
{
enum machine_mode mode = GET_MODE (x);
int extra_cost = 0;
@@ -4871,9 +5079,6 @@ m68hc11_rtx_costs (x, code, outer_code)
switch (code)
{
- case MEM:
- return m68hc11_address_cost (XEXP (x, 0)) + 4;
-
case ROTATE:
case ROTATERT:
case ASHIFT:
@@ -4881,82 +5086,87 @@ m68hc11_rtx_costs (x, code, outer_code)
case ASHIFTRT:
if (GET_CODE (XEXP (x, 1)) == CONST_INT)
{
- int val = INTVAL (XEXP (x, 1));
- int cost;
-
- /* 8 or 16 shift instructions are fast.
- Others are proportional to the shift counter. */
- if (val == 8 || val == 16 || val == -8 || val == -16)
- {
- val = 0;
- }
- cost = COSTS_N_INSNS (val + 1);
- cost += rtx_cost (XEXP (x, 0), outer_code);
- if (GET_MODE_SIZE (mode) >= 4 && val)
- {
- cost *= 4;
- }
- return cost;
- }
- total = rtx_cost (XEXP (x, 0), outer_code);
- if (GET_MODE_SIZE (mode) >= 4)
- {
- total += COSTS_N_INSNS (16);
- }
- else
- {
- total += COSTS_N_INSNS (8);
+ return m68hc11_shift_cost (mode, XEXP (x, 0), INTVAL (XEXP (x, 1)));
}
+
+ total = rtx_cost (XEXP (x, 0), code) + rtx_cost (XEXP (x, 1), code);
+ total += m68hc11_cost->shift_var;
return total;
- case MINUS:
- case PLUS:
case AND:
case XOR:
case IOR:
- extra_cost = 0;
+ total = rtx_cost (XEXP (x, 0), code) + rtx_cost (XEXP (x, 1), code);
+ total += m68hc11_cost->logical;
- total = rtx_cost (XEXP (x, 0), outer_code)
- + rtx_cost (XEXP (x, 1), outer_code);
- if (GET_MODE_SIZE (mode) <= 2)
- {
- total += COSTS_N_INSNS (2);
- }
- else
+ /* Logical instructions are byte instructions only. */
+ total *= GET_MODE_SIZE (mode);
+ return total;
+
+ case MINUS:
+ case PLUS:
+ total = rtx_cost (XEXP (x, 0), code) + rtx_cost (XEXP (x, 1), code);
+ total += m68hc11_cost->add;
+ if (GET_MODE_SIZE (mode) > 2)
{
- total += COSTS_N_INSNS (4);
+ total *= GET_MODE_SIZE (mode) / 2;
}
return total;
+ case UDIV:
case DIV:
case MOD:
- if (mode == QImode || mode == HImode)
- {
- return 30;
- }
- else if (mode == SImode)
- {
- return 100;
- }
- else
- {
- return 150;
- }
-
+ total = rtx_cost (XEXP (x, 0), code) + rtx_cost (XEXP (x, 1), code);
+ 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:
- if (mode == QImode)
- {
- return TARGET_OP_TIME ? 10 : 2;
- }
- if (mode == HImode)
- {
- return TARGET_OP_TIME ? 30 : 4;
- }
- if (mode == SImode)
- {
- return TARGET_OP_TIME ? 100 : 20;
- }
- return 150;
+ /* 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)
+ + rtx_cost (XEXP (XEXP (x, 1), 0), code);
+
+ /* 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)
+ + rtx_cost (XEXP (XEXP (x, 1), 0), code);
+
+ total = rtx_cost (XEXP (x, 0), code) + rtx_cost (XEXP (x, 1), code);
+ 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:
@@ -4967,20 +5177,20 @@ m68hc11_rtx_costs (x, code, outer_code)
case COMPARE:
case ABS:
case ZERO_EXTEND:
- total = rtx_cost (XEXP (x, 0), outer_code);
+ total = extra_cost + rtx_cost (XEXP (x, 0), code);
if (mode == QImode)
{
- return total + extra_cost + COSTS_N_INSNS (1);
+ return total + COSTS_N_INSNS (1);
}
if (mode == HImode)
{
- return total + extra_cost + COSTS_N_INSNS (2);
+ return total + COSTS_N_INSNS (2);
}
if (mode == SImode)
{
- return total + extra_cost + COSTS_N_INSNS (4);
+ return total + COSTS_N_INSNS (4);
}
- return total + extra_cost + COSTS_N_INSNS (8);
+ return total + COSTS_N_INSNS (8);
case IF_THEN_ELSE:
if (GET_CODE (XEXP (x, 1)) == PC || GET_CODE (XEXP (x, 2)) == PC)
@@ -4997,9 +5207,6 @@ m68hc11_rtx_costs (x, code, outer_code)
/* print_options - called at the start of the code generation for a
module. */
-#if GCC_VERSION == 2095
-extern char *main_input_filename;
-#endif
extern char *asm_file_name;
#include <time.h>
@@ -5053,7 +5260,6 @@ m68hc11_asm_file_start (out, main_file)
static void
m68hc11_add_gc_roots ()
{
-#if GCC_VERSION > 2095
ggc_add_rtx_root (&m68hc11_soft_tmp_reg, 1);
ggc_add_rtx_root (&ix_reg, 1);
ggc_add_rtx_root (&iy_reg, 1);
@@ -5063,5 +5269,4 @@ m68hc11_add_gc_roots ()
ggc_add_rtx_root (&z_reg_qi, 1);
ggc_add_rtx_root (&stack_push_word, 1);
ggc_add_rtx_root (&stack_pop_word, 1);
-#endif
}
diff --git a/gcc/config/m68hc11/m68hc11.h b/gcc/config/m68hc11/m68hc11.h
index 26ea8aa9e18..b8ccdcf31db 100644
--- a/gcc/config/m68hc11/m68hc11.h
+++ b/gcc/config/m68hc11/m68hc11.h
@@ -33,16 +33,6 @@ Note:
*/
-#undef GCC_VERSION
-#if 1 /* def N_*/
-# define GCC_VERSION 2096
-#else
-# define GCC_VERSION 2095
-
-/* NLS support in 2.96 */
-# define N_(X) X
-#endif
-
#include "elfos.h"
/*****************************************************************************
@@ -77,7 +67,8 @@ Note:
"%{mshort:-D__HAVE_SHORT_INT__ -D__INT__=16 -D__INT_MAX__=32767}\
%{!mshort:-D__INT__=32 -D__INT_MAX__=2147483647}\
%{m68hc12:-Dmc6812 -DMC6812 -Dmc68hc12}\
- %{!m68hc12:-Dmc6811 -DMC6811 -Dmc68hc11}"
+ %{!m68hc12:-Dmc6811 -DMC6811 -Dmc68hc11}\
+ %{fshort-double:-D__HAVE_SHORT_DOUBLE__}"
#endif
#undef STARTFILE_SPEC
@@ -93,30 +84,6 @@ Note:
#include "gansidecl.h"
-#if GCC_VERSION == 2095
-#ifndef PARAMS
-#if defined(ANSI_PROTOTYPES) || defined(__cplusplus)
-#define PARAMS(args) args
-#else
-#define PARAMS(args) ()
-#endif
-#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;
-#endif
-
/*****************************************************************************
**
** Run-time Target Specification
@@ -234,6 +201,25 @@ extern const char *m68hc11_soft_reg_count;
`-O'. That is what `OPTIMIZATION_OPTIONS' is for. */
#define OVERRIDE_OPTIONS m68hc11_override_options ();
+
+
+/* Define cost parameters for a given processor variant. */
+struct processor_costs {
+ int add; /* cost of an add instruction */
+ int logical; /* cost of a logical instruction */
+ int shift_var;
+ int shiftQI_const[8];
+ int shiftHI_const[16];
+ int multQI;
+ int multHI;
+ int multSI;
+ int divQI;
+ int divHI;
+ int divSI;
+};
+
+/* Costs for the current processor. */
+extern struct processor_costs *m68hc11_cost;
/* target machine storage layout */
@@ -722,6 +708,9 @@ enum reg_class
#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)))
@@ -796,9 +785,6 @@ extern enum reg_class m68hc11_tmp_regs_class;
#define PREFERRED_RELOAD_CLASS(X,CLASS) preferred_reload_class(X,CLASS)
-
-#define LIMIT_RELOAD_CLASS(MODE, CLASS) limit_reload_class(MODE,CLASS)
-
#define SMALL_REGISTER_CLASSES 1
/* A C expression whose value is nonzero if pseudos that have been
@@ -891,8 +877,7 @@ extern enum reg_class m68hc11_tmp_regs_class;
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. */
-extern int m68hc11_sp_correction;
-#define STARTING_FRAME_OFFSET m68hc11_sp_correction
+#define STARTING_FRAME_OFFSET 0
/* Offset of first parameter from the argument pointer register value. */
@@ -908,6 +893,12 @@ extern int m68hc11_sp_correction;
#define INCOMING_RETURN_ADDR_RTX \
gen_rtx_MEM (VOIDmode, gen_rtx_REG (VOIDmode, STACK_POINTER_REGNUM))
+/* 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
@@ -943,7 +934,7 @@ extern int m68hc11_sp_correction;
#define ARG_POINTER_REGNUM SOFT_AP_REGNUM
/* Register in which static-chain is passed to a function. */
-#define STATIC_CHAIN_REGNUM SOFT_REG_FIRST
+#define STATIC_CHAIN_REGNUM SOFT_Z_REGNUM
/* Definitions for register eliminations.
@@ -986,8 +977,6 @@ extern int m68hc11_sp_correction;
#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
{ OFFSET = m68hc11_initial_elimination_offset (FROM, TO); }
-/* LONGJMP_RESTORE_FROM_STACK */
-
/* Passing Function Arguments on the Stack. */
@@ -1194,21 +1183,17 @@ typedef struct m68hc11_args
asm ("puly"); \
}
-/* Output assembler code for a block containing the constant parts
- of a trampoline, leaving space for the variable parts. */
-#define TRAMPOLINE_TEMPLATE(FILE) { \
- fprintf (FILE, "\t.bogus\t\t; TRAMPOLINE_TEMPLATE unimplemented\n"); }
-
/* Length in units of the trampoline for entering a nested function. */
-#define TRAMPOLINE_SIZE 0
+#define TRAMPOLINE_SIZE (TARGET_M6811 ? 11 : 9)
/* A C statement to initialize the variable parts of a trampoline.
ADDR is an RTX for the address of the trampoline; FNADDR is an
RTX for the address of the nested function; STATIC_CHAIN is an
RTX for the static chain value that should be passed to the
function when it is called. */
-#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) { \
- }
+#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \
+ m68hc11_initialize_trampoline ((TRAMP), (FNADDR), (CXT))
+
/* If defined, a C expression whose value is nonzero if IDENTIFIER
@@ -1297,11 +1282,7 @@ extern enum reg_class m68hc11_index_reg_class;
/* Internal macro, return 1 if REGNO is a valid base register. */
-#if GCC_VERSION == 2095
-# define REG_VALID_P(REGNO) ((REGNO) >= 0)
-#else
-# define REG_VALID_P(REGNO) (1) /* ? */
-#endif
+#define REG_VALID_P(REGNO) (1) /* ? */
extern unsigned char m68hc11_reg_valid_for_base[FIRST_PSEUDO_REGISTER];
#define REG_VALID_FOR_BASE_P(REGNO) \
@@ -1487,22 +1468,54 @@ extern unsigned char m68hc11_reg_valid_for_index[FIRST_PSEUDO_REGISTER];
/* Compute the cost of computing a constant rtl expression RTX whose rtx-code
is CODE. The body of this macro is a portion of a switch statement. If
- the code is computed here, return it with a return statement. Otherwise,
- break from the switch. */
-#define CONST_COSTS(RTX,CODE,OUTER_CODE) \
- case CONST_INT: \
- if (RTX == const0_rtx) return 0; \
- case CONST: \
- return 0; \
- case LABEL_REF: \
- case SYMBOL_REF: \
- return 1; \
- case CONST_DOUBLE: \
+ the code is computed here, return it with a return statement. Otherwise,
+ break from the switch.
+
+ Constants are cheap. Moving them in registers must be avoided
+ because most instructions do not handle two register operands. */
+#define CONST_COSTS(RTX,CODE,OUTER_CODE) \
+ case CONST_INT: \
+ /* 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 && (RTX) == const0_rtx) \
+ /* After reload, the reload_cse pass checks the cost */ \
+ /* to change a SET into a PLUS. Make const0 cheap. */ \
+ return 1 - reload_completed; \
+ else \
+ return 0; \
+ case CONST: \
+ case LABEL_REF: \
+ case SYMBOL_REF: \
+ if ((OUTER_CODE) == SET) \
+ return 1 - reload_completed; \
+ return 0; \
+ case CONST_DOUBLE: \
return 0;
-#define DEFAULT_RTX_COSTS(X,CODE,OUTER_CODE) \
- return m68hc11_rtx_costs (X, CODE, OUTER_CODE);
-
+#define RTX_COSTS(X,CODE,OUTER_CODE) \
+ 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: \
+ return m68hc11_rtx_costs (X, CODE, OUTER_CODE);
/* An expression giving the cost of an addressing mode that contains
ADDRESS. If not defined, the cost is computed from the ADDRESS
@@ -1600,6 +1613,52 @@ do { \
/* Output before uninitialized data. */
#define BSS_SECTION_ASM_OP ("\t.sect\t.bss")
+/* This is the pseudo-op used to generate a reference to a specific
+ symbol in some section. It is only used in machine-specific
+ configuration files, typically only in ASM_OUTPUT_CONSTRUCTOR and
+ ASM_OUTPUT_DESTRUCTOR. This is the same for all known svr4
+ assemblers, except those in targets that don't use 32-bit pointers.
+ Those should override INT_ASM_OP. Yes, the name of the macro is
+ misleading. */
+#undef INT_ASM_OP
+#define INT_ASM_OP "\t.word\t"
+
+/* 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\""
+
+#undef CTORS_SECTION_FUNCTION
+#define CTORS_SECTION_FUNCTION \
+void \
+ctors_section () \
+{ \
+ if (in_section != in_ctors) \
+ { \
+ fprintf (asm_out_file, "\t.globl\t__do_global_ctors\n"); \
+ fprintf (asm_out_file, "%s\n", CTORS_SECTION_ASM_OP); \
+ in_section = in_ctors; \
+ } \
+}
+
+#undef DTORS_SECTION_FUNCTION
+#define DTORS_SECTION_FUNCTION \
+void \
+dtors_section () \
+{ \
+ if (in_section != in_dtors) \
+ { \
+ fprintf (asm_out_file, "\t.globl\t__do_global_dtors\n"); \
+ fprintf (asm_out_file, "%s\n", DTORS_SECTION_ASM_OP); \
+ in_section = in_dtors; \
+ } \
+}
+
/* This is how to begin an assembly language file. Most svr4 assemblers want
at least a .file directive to come first, and some want to see a .version
directive come right after that. Here we just establish a default
@@ -1882,14 +1941,3 @@ extern int debug_m6811;
extern int z_replacement_completed;
extern int current_function_interrupt;
extern int current_function_trap;
-
-#if GCC_VERSION == 2095
-extern rtx_ptr iy_reg;
-extern rtx_ptr iy_reg;
-extern rtx_ptr d_reg;
-extern rtx_ptr m68hc11_soft_tmp_reg;
-extern rtx_ptr m68hc11_compare_op0;
-extern rtx_ptr m68hc11_compare_op1;
-extern long m68hc11_min_offset;
-extern long m68hc11_max_offset;
-#endif
diff --git a/gcc/config/m68hc11/m68hc11.md b/gcc/config/m68hc11/m68hc11.md
index 4cd495aad37..f073913318c 100644
--- a/gcc/config/m68hc11/m68hc11.md
+++ b/gcc/config/m68hc11/m68hc11.md
@@ -115,6 +115,24 @@
;; 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
+])
;;--------------------------------------------------------------------
;;- Test
@@ -156,7 +174,7 @@
""
"*
{
- if (D_REG_P (operands[0]))
+ if (D_REG_P (operands[0]) && !TARGET_M6812)
return \"std\\t%t0\";
else
return \"cp%0\\t#0\";
@@ -189,11 +207,11 @@
(define_insn "tstqi_1"
[(set (cc0)
- (match_operand:QI 0 "tst_operand" "d,m,*A,!u"))]
+ (match_operand:QI 0 "tst_operand" "m,d,*A,!u"))]
""
"@
- tstb
tst\\t%0
+ tstb
#
tst\\t%b0")
@@ -222,10 +240,10 @@
(use (match_operand:HI 1 "hard_reg_operand" "dxy"))
(use (reg:HI 11))]
"z_replacement_completed == 2"
- [(set (mem:HI (pre_dec:HI (reg:HI 3))) (match_dup 1))
+ [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 1))
(set (match_dup 1) (match_dup 2))
(set (cc0) (match_dup 0))
- (set (match_dup 1) (mem:HI (post_inc:HI (reg:HI 3))))]
+ (set (match_dup 1) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
"operands[2] = gen_rtx (REG, HImode, SOFT_Z_REGNUM);")
@@ -285,13 +303,18 @@
(define_insn "cmphi_1"
[(set (cc0)
(compare (match_operand:HI 0 "tst_operand"
- "xy,d,?xy,d,dxy,dxy,dxy")
+ "x,dy,xyd,?xy,d,m,!u,dxy,dxy")
(match_operand:HI 1 "cmp_operand"
- "i,i,m,m,?*d*A,?u,!*w")))]
+ "i,i,!u,m,m,dxy,dxy,?*d*A,!*w")))]
""
"*
{
- if (H_REG_P (operands[1]))
+ 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\";
@@ -299,24 +322,24 @@
(define_insn "cmphi_z_used"
[(set (cc0)
- (compare (match_operand:HI 0 "hard_reg_operand" "dxy")
- (match_operand:HI 1 "cmp_operand" "m")))
- (use (match_operand:HI 2 "hard_reg_operand" "dxy"))
+ (compare (match_operand:HI 0 "tst_operand" "dxy,m")
+ (match_operand:HI 1 "cmp_operand" "m,dxy")))
+ (use (match_operand:HI 2 "hard_reg_operand" "dxy,dxy"))
(use (reg:HI 11))]
""
"#")
(define_split /* "cmphi_z_used" */
[(set (cc0)
- (compare (match_operand:HI 0 "hard_reg_operand" "dxy")
- (match_operand:HI 1 "cmp_operand" "m")))
- (use (match_operand:HI 2 "hard_reg_operand" "dxy"))
+ (compare (match_operand:HI 0 "tst_operand" "dxy,m")
+ (match_operand:HI 1 "cmp_operand" "m,dxy")))
+ (use (match_operand:HI 2 "hard_reg_operand" "dxy,dxy"))
(use (reg:HI 11))]
"z_replacement_completed == 2"
- [(set (mem:HI (pre_dec:HI (reg:HI 3))) (match_dup 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 3))))]
+ (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
"operands[3] = gen_rtx (REG, HImode, SOFT_Z_REGNUM);")
;;
@@ -330,12 +353,12 @@
(compare (match_operand:QI 0 "hard_addr_reg_operand" "xy")
(match_operand:QI 1 "cmp_operand" "uimA")))]
"z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode"
- [(parallel [(set (reg:HI 1) (match_dup 3))
- (set (match_dup 3) (reg:HI 1))])
+ [(parallel [(set (reg:HI D_REGNUM) (match_dup 3))
+ (set (match_dup 3) (reg:HI D_REGNUM))])
(set (cc0)
- (compare (reg:QI 1) (match_dup 1)))
- (parallel [(set (reg:HI 1) (match_dup 3))
- (set (match_dup 3) (reg:HI 1))])]
+ (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
@@ -365,37 +388,139 @@
DONE;
}")
-(define_insn "cmpqi_1"
+(define_insn "bitcmpqi"
[(set (cc0)
- (compare (match_operand:QI 0 "tst_operand" "d,d,*x*y,*x*y")
- (match_operand:QI 1 "cmp_operand" "im,?u,?u,?dim*x*y")))]
+ (and:QI (match_operand:QI 0 "tst_operand" "d,d,d,m,!u")
+ (match_operand:QI 1 "cmp_operand" "im,*B,u,d,d")))]
""
"@
- cmpb\\t%1
- cmpb\\t%b1
+ bitb\\t%b1
#
- #")
+ bitb\\t%b1
+ bitb\\t%b0
+ bitb\\t%b0")
+
+(define_split /* "bitcmpqi" */
+ [(set (cc0)
+ (and:QI (match_operand:QI 0 "tst_operand" "d")
+ (match_operand:QI 1 "hard_addr_reg_operand" "xy")))]
+ "z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode"
+ [(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 "bitcmpqi_z_used"
+ [(set (cc0)
+ (and:QI (match_operand:QI 0 "tst_operand" "d,m")
+ (match_operand:QI 1 "cmp_operand" "m,d")))
+ (use (match_operand:HI 2 "hard_reg_operand" "xy,xy"))
+ (use (reg:HI 11))]
+ ""
+ "#")
+
+(define_split /* "bitcmpqi_z_used" */
+ [(set (cc0)
+ (and:QI (match_operand:QI 0 "tst_operand" "d,m")
+ (match_operand:QI 1 "cmp_operand" "m,d")))
+ (use (match_operand:HI 2 "hard_reg_operand" "xy,xy"))
+ (use (reg:HI 11))]
+ "z_replacement_completed == 2"
+ [(set (mem:HI (pre_dec:HI (reg:HI 3))) (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 3))))]
+ "operands[3] = gen_rtx (REG, HImode, SOFT_Z_REGNUM);")
+
+(define_insn "bitcmphi"
+ [(set (cc0)
+ (and:HI (match_operand:HI 0 "tst_operand" "d")
+ (match_operand:HI 1 "const_int_operand" "i")))]
+ "(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)
+ (zero_extract (match_operand:HI 0 "tst_operand" "d")
+ (match_operand:HI 1 "const_int_operand" "i")
+ (match_operand:HI 2 "const_int_operand" "i")))]
+ "(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")
+ (match_operand:QI 1 "cmp_operand" "im,d,!u,d,?dim*B,*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 "cmpqi_z_used"
[(set (cc0)
- (compare (match_operand:QI 0 "hard_reg_operand" "dxy")
- (match_operand:QI 1 "cmp_operand" "m")))
- (use (match_operand:HI 2 "hard_reg_operand" "dxy"))
+ (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 11))]
""
"#")
(define_split /* cmpqi_z_used */
[(set (cc0)
- (compare (match_operand:QI 0 "hard_reg_operand" "dxy")
- (match_operand:QI 1 "cmp_operand" "m")))
- (use (match_operand:HI 2 "hard_reg_operand" "dxy"))
+ (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 11))]
"z_replacement_completed == 2"
- [(set (mem:HI (pre_dec:HI (reg:HI 3))) (match_dup 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 3))))]
+ (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
"operands[3] = gen_rtx (REG, HImode, SOFT_Z_REGNUM);")
(define_expand "cmpdf"
@@ -432,40 +557,40 @@
;; description but not for GCC optimization passes.
;;
(define_insn "movstrictsi"
- [(set (strict_low_part (match_operand:SI 0 "non_push_operand" "+um,+D,+D"))
+ [(set (strict_low_part (match_operand:SI 0 "non_push_operand" "+um,D,D"))
(match_operand:SI 1 "general_operand" "D,Dim,uD"))]
""
"#")
(define_split
- [(set (strict_low_part (match_operand:SI 0 "non_push_operand" "+um,+D,+D"))
+ [(set (strict_low_part (match_operand:SI 0 "non_push_operand" "+um,D,D"))
(match_operand:SI 1 "general_operand" "D,Dim,u"))]
"z_replacement_completed == 2"
[(set (match_dup 0) (match_dup 1))]
"")
(define_insn "movstricthi"
- [(set (strict_low_part (match_operand:HI 0 "non_push_operand" "+um,+d,+d"))
- (match_operand:HI 1 "general_operand" "d,dim,u"))]
+ [(set (strict_low_part (match_operand:HI 0 "non_push_operand" "+um,dA,dA"))
+ (match_operand:HI 1 "general_operand" "dA,dAim,u"))]
""
"#")
(define_split
- [(set (strict_low_part (match_operand:HI 0 "non_push_operand" "+um,+d,+d"))
- (match_operand:HI 1 "general_operand" "d,dim,u"))]
+ [(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 "movstrictqi"
- [(set (strict_low_part (match_operand:QI 0 "non_push_operand" "+mu,+!d"))
- (match_operand:QI 1 "general_operand" "d,imu"))]
+ [(set (strict_low_part (match_operand:QI 0 "non_push_operand" "+mu,!dA"))
+ (match_operand:QI 1 "general_operand" "d,imudA"))]
""
"#")
(define_split
- [(set (strict_low_part (match_operand:QI 0 "non_push_operand" "+mu,+d,+d"))
- (match_operand:QI 1 "general_operand" "d,dim,u"))]
+ [(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))]
"")
@@ -488,7 +613,28 @@
;; 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_insn "movdi"
+(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;
+ }
+")
+
+(define_insn "movdi_internal"
[(set (match_operand:DI 0 "nonimmediate_operand" "=U,!u,U,m,m,!u")
(match_operand:DI 1 "general_operand" "iU,iU,!u,mi,!u,!mu"))
(clobber (match_scratch:HI 2 "=&d,&d,&d,&d,&d,&d"))]
@@ -504,7 +650,27 @@
"m68hc11_split_move (operands[0], operands[1], operands[2]);
DONE;")
-(define_insn "movdf"
+(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;
+ }
+")
+
+(define_insn "movdf_internal"
[(set (match_operand:DF 0 "nonimmediate_operand" "=U,!u,U,m,m,!u")
(match_operand:DF 1 "general_operand" "iU,iU,!u,mi,!u,!mu"))
(clobber (match_scratch:HI 2 "=&d,&d,&d,&d,&d,&d"))]
@@ -519,7 +685,7 @@
[(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.
@@ -529,7 +695,27 @@
;; pass does not give us a register that dies in the insn and is used
;; for input/output operands.
;;--------------------------------------------------------------------
-(define_insn "movsi"
+(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 "movsi_internal"
[(set (match_operand:SI 0 "nonimmediate_operand" "=mu,?D,m,?D,?u,?u,!u,D")
(match_operand:SI 1 "general_operand" "imu,im,?D,!u,?D,mi,!u,!D"))
(clobber (match_scratch:HI 2 "=&d,X,X,X,X,&d,&d,X"))]
@@ -545,7 +731,27 @@
"m68hc11_split_move (operands[0], operands[1], operands[2]);
DONE;")
-(define_insn "movsf"
+(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 "movsf_internal"
[(set (match_operand:SF 0 "nonimmediate_operand" "=m,D,m,D,!u,!u,!u,D")
(match_operand:SF 1 "general_operand" "im,im,D,!u,D,mi,!u,!D"))
(clobber (match_scratch:HI 2 "=&d,X,X,X,X,&d,&d,X"))]
@@ -640,6 +846,19 @@
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_const0"
@@ -703,11 +922,11 @@
"z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode
&& !reg_mentioned_p (operands[0], operands[1])
&& !D_REG_P (operands[1])"
- [(parallel [(set (reg:HI 1) (match_dup 2))
- (set (match_dup 2) (reg:HI 1))])
- (set (reg:QI 1) (match_dup 1))
- (parallel [(set (reg:HI 1) (match_dup 2))
- (set (match_dup 2) (reg:HI 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]));")
;;
@@ -719,11 +938,11 @@
"z_replacement_completed == 2 && GET_MODE (operands[1]) == QImode
&& !reg_mentioned_p (operands[1], operands[0])
&& !D_REG_P (operands[0])"
- [(parallel [(set (reg:HI 1) (match_dup 2))
- (set (match_dup 2) (reg:HI 1))])
- (set (match_dup 0) (reg:QI 1))
- (parallel [(set (reg:HI 1) (match_dup 2))
- (set (match_dup 2) (reg:HI 1))])]
+ [(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"
@@ -767,6 +986,19 @@
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"
@@ -1048,15 +1280,11 @@
[(set (match_operand:SI 0 "non_push_operand" "=mu")
(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "dxy")))]
"reload_completed && !X_REG_P (operands[0])"
- [(set (match_dup 2) (match_dup 3))
- (set (match_dup 4) (const_int 0))
- (set (match_dup 5) (const_int 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] = gen_rtx (REG, HImode, REGNO (operands[1]));
- operands[4] = m68hc11_gen_lowpart (HImode, operands[0]);
- operands[4] = m68hc11_gen_highpart (QImode, operands[4]);
- operands[5] = m68hc11_gen_highpart (HImode, operands[0]);")
+ operands[3] = m68hc11_gen_highpart (HImode, operands[0]);")
(define_split
[(set (match_operand:SI 0 "hard_reg_operand" "=D")
@@ -1178,6 +1406,20 @@
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]))
@@ -1273,6 +1515,16 @@
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]))
{
@@ -1320,25 +1572,23 @@
[(set (match_operand:SI 0 "register_operand" "=D")
(sign_extend:SI (match_operand:HI 1 "register_operand" "A")))]
"reload_completed && (Y_REG_P (operands[1]) || Z_REG_P (operands[1]))"
- [(set (reg:HI 1) (match_dup 1))
- (set (match_dup 0) (sign_extend:SI (reg:HI 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")
- (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "dm,!uA")))]
+ [(set (match_operand:SI 0 "register_operand" "=D,D,D")
+ (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "m,!r,dA")))]
""
"*
{
extern rtx ix_reg;
- rtx ops[1];
+ rtx ops[2];
int x_reg_used;
if (Y_REG_P (operands[1]))
return \"#\";
- ops[0] = gen_label_rtx ();
-
if (X_REG_P (operands[1]))
{
output_asm_insn (\"xgdx\", operands);
@@ -1351,9 +1601,29 @@
x_reg_used = reg_mentioned_p (ix_reg, operands[1]);
if (x_reg_used)
{
- output_asm_insn (\"ldd\\t%1\", operands);
+ 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)
{
@@ -1361,18 +1631,107 @@
}
else
{
- output_asm_insn (\"ldd\\t%1\", operands);
+ 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);
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
- CC_STATUS_INIT;
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"
+ "*
+{
+ /* 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"
+ "*
+{
+ /* 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"
+ "*
+{
+ /* 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"
+ "*
+{
+ /* 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.
@@ -1409,13 +1768,13 @@
(match_dup 0)))
(clobber (match_scratch:HI 1 "=X"))]
"reload_completed && z_replacement_completed == 2"
- [(set (reg:HI 1) (ashift:HI (reg:HI 1) (const_int 1)))
- (parallel [(set (reg:HI 1) (reg:HI 0))
- (set (reg:HI 0) (reg:HI 1))])
- (set (reg:QI 6) (rotate:QI (reg:QI 6) (reg:QI 7)))
- (set (reg:QI 5) (rotate:QI (reg:QI 5) (reg:QI 7)))
- (parallel [(set (reg:HI 1) (reg:HI 0))
- (set (reg:HI 0) (reg:HI 1))])]
+ [(set (reg:HI D_REGNUM) (ashift:HI (reg:HI D_REGNUM) (const_int 1)))
+ (parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
+ (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])
+ (set (reg:QI B_REGNUM) (rotate:QI (reg:QI B_REGNUM) (reg:QI CC_REGNUM)))
+ (set (reg:QI A_REGNUM) (rotate:QI (reg:QI A_REGNUM) (reg:QI CC_REGNUM)))
+ (parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
+ (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])]
"")
@@ -1472,9 +1831,9 @@
(match_operand:SI 2 "memory_operand" "m,m")))
(clobber (match_scratch:HI 3 "=X,X"))]
"reload_completed"
- [(set (reg:HI 1) (zero_extend:HI (match_dup 1)))
+ [(set (reg:HI D_REGNUM) (zero_extend:HI (match_dup 1)))
(parallel [(set (match_dup 0)
- (plus:SI (zero_extend:SI (reg:HI 1)) (match_dup 2)))
+ (plus:SI (zero_extend:SI (reg:HI D_REGNUM)) (match_dup 2)))
(clobber (match_dup 3))])]
"")
@@ -1550,9 +1909,9 @@
}")
(define_insn "*addsi3"
- [(set (match_operand:SI 0 "non_push_operand" "=m,D,!u,D,!D")
+ [(set (match_operand:SI 0 "non_push_operand" "=m,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,L,?miu,!D")))
+ (match_operand:SI 2 "general_operand" "ML,i,ML,?D,?miu")))
(clobber (match_scratch:HI 3 "=d,X,d,X,X"))]
""
"*
@@ -1652,14 +2011,26 @@
}")
(define_split
- [(set (match_operand:SI 0 "register_operand" "=D")
- (plus:SI (match_operand:SI 1 "register_operand" "%0")
+ [(set (match_operand:SI 0 "register_operand" "=D,u")
+ (plus:SI (match_operand:SI 1 "register_operand" "%0,0")
(match_operand:SI 2 "const_int_operand" "")))
- (clobber (match_scratch:HI 3 "=X"))]
+ (clobber (match_scratch:HI 3 "=X,d"))]
"reload_completed && z_replacement_completed == 2
&& ((INTVAL (operands[2]) & 0x0FFFF) == 0)"
- [(set (reg:HI 0) (plus:HI (reg:HI 0) (match_dup 3)))]
- "operands[3] = m68hc11_gen_highpart (HImode, operands[2]);")
+ [(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" "=D")
@@ -1669,13 +2040,13 @@
"reload_completed && z_replacement_completed == 2
&& (GET_CODE (operands[2]) != CONST_INT ||
(!(INTVAL (operands[2]) >= -65536 && INTVAL (operands[2]) <= 65535)))"
- [(set (reg:HI 1) (plus:HI (reg:HI 1) (match_dup 3)))
- (parallel [(set (reg:HI 1) (reg:HI 0))
- (set (reg:HI 0) (reg:HI 1))])
- (set (reg:QI 6) (plus:QI (plus:QI (reg:QI 7) (reg:QI 6)) (match_dup 4)))
- (set (reg:QI 5) (plus:QI (plus:QI (reg:QI 7) (reg:QI 5)) (match_dup 5)))
- (parallel [(set (reg:HI 1) (reg:HI 0))
- (set (reg:HI 0) (reg:HI 1))])]
+ [(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]);
@@ -1689,7 +2060,7 @@
[(set (match_operand:HI 0 "register_operand" "=x")
(plus:HI (plus:HI (match_operand:HI 1 "register_operand" "0")
(const_int 0))
- (reg:HI 7)))]
+ (reg:HI CC_REGNUM)))]
""
"*
{
@@ -1746,25 +2117,39 @@
"")
(define_insn "*addhi3_68hc12"
- [(set (match_operand:HI 0 "register_operand" "=d,A*w,A*w")
- (plus:HI (match_operand:HI 1 "register_operand" "%0,0,Aw")
- (match_operand:HI 2 "general_operand" "imA*wu,id,id")))]
+ [(set (match_operand:HI 0 "register_operand" "=*d,A*w,A*w,A")
+ (plus:HI (match_operand:HI 1 "register_operand" "%0,0,Aw,0")
+ (match_operand:HI 2 "general_operand" "imA*wu,id,id,!muA")))]
"TARGET_M6812"
"*
{
int val;
const char* insn_code;
+ if (which_alternative >= 3)
+ {
+ 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\";
@@ -1784,7 +2169,7 @@
if (val != -1 || val != 1 || !rtx_equal_p (operands[0], operands[1]))
{
- cc_status = cc_prev_status;
+ m68hc11_notice_keep_cc (operands[0]);
switch (REGNO (operands[0]))
{
case HARD_X_REGNUM:
@@ -1922,9 +2307,9 @@
"")
(define_insn "*addhi3"
- [(set (match_operand:HI 0 "hard_reg_operand" "=A,d,!A,d*A,!d,!w")
- (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0,0,0")
- (match_operand:HI 2 "general_operand" "N,i,I,umi*A*d,!*d*w,i")))]
+ [(set (match_operand:HI 0 "hard_reg_operand" "=A,d,!A,d*A,!d")
+ (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0,0")
+ (match_operand:HI 2 "general_operand" "N,i,I,mi*A*d,!u*d*w")))]
"TARGET_M6811"
"*
{
@@ -2110,7 +2495,7 @@
;;
(define_insn "*adcq"
[(set (match_operand:QI 0 "register_operand" "=q")
- (plus:QI (plus:QI (reg:QI 7)
+ (plus:QI (plus:QI (reg:QI CC_REGNUM)
(match_operand:QI 1 "register_operand" "%0"))
(match_operand:QI 2 "general_operand" "ium")))]
""
@@ -2201,13 +2586,13 @@
(clobber (match_scratch:HI 3 "=X"))]
"reload_completed && z_replacement_completed == 2
&& X_REG_P (operands[1])"
- [(set (reg:HI 1) (minus:HI (reg:HI 1) (match_dup 3)))
- (parallel [(set (reg:HI 0) (reg:HI 1))
- (set (reg:HI 1) (reg:HI 0))])
- (set (reg:QI 6) (minus:QI (minus:QI (reg:QI 7) (reg:QI 6)) (match_dup 4)))
- (set (reg:QI 5) (minus:QI (minus:QI (reg:QI 7) (reg:QI 5)) (match_dup 5)))
- (parallel [(set (reg:HI 0) (reg:HI 1))
- (set (reg:HI 1) (reg:HI 0))])]
+ [(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]);
@@ -2220,13 +2605,13 @@
(clobber (match_scratch:HI 3 "=X"))]
"reload_completed && z_replacement_completed == 2
&& X_REG_P (operands[2])"
- [(set (reg:HI 1) (minus:HI (reg:HI 1) (match_dup 3)))
- (parallel [(set (reg:HI 0) (reg:HI 1))
- (set (reg:HI 1) (reg:HI 0))])
- (set (reg:QI 6) (minus:QI (minus:QI (reg:QI 7) (reg:QI 6)) (match_dup 4)))
- (set (reg:QI 5) (minus:QI (minus:QI (reg:QI 7) (reg:QI 5)) (match_dup 5)))
- (parallel [(set (reg:HI 0) (reg:HI 1))
- (set (reg:HI 1) (reg:HI 0))])
+ [(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]);
@@ -2262,7 +2647,7 @@
(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" "uim*d,!*A")))
+ (match_operand:HI 2 "general_operand" "im*d,!u*A")))
(clobber (match_scratch:HI 3 "=A*d,A*d"))]
""
"*
@@ -2311,9 +2696,9 @@
(define_insn "*subhi3"
- [(set (match_operand:HI 0 "register_operand" "=d,*A")
- (minus:HI (match_operand:HI 1 "register_operand" "0,0")
- (match_operand:HI 2 "general_operand" "uim*A*d,uim*d*A")))]
+ [(set (match_operand:HI 0 "register_operand" "=d,*A,d*A")
+ (minus:HI (match_operand:HI 1 "register_operand" "0,0,0")
+ (match_operand:HI 2 "general_operand" "im*A*d,im*d*A,!u")))]
""
"*
{
@@ -2346,9 +2731,9 @@
}")
(define_insn "subqi3"
- [(set (match_operand:QI 0 "hard_reg_operand" "=dq*x*y")
- (minus:QI (match_operand:QI 1 "hard_reg_operand" "0")
- (match_operand:QI 2 "general_operand" "uim*x*y*d")))]
+ [(set (match_operand:QI 0 "hard_reg_operand" "=dq,!*x*y")
+ (minus:QI (match_operand:QI 1 "hard_reg_operand" "0,0")
+ (match_operand:QI 2 "general_operand" "uim*A*d,uim*A*d")))]
""
"*
{
@@ -2365,7 +2750,7 @@
;;
(define_insn "*subcq"
[(set (match_operand:QI 0 "register_operand" "=q")
- (minus:QI (minus:QI (reg:QI 7)
+ (minus:QI (minus:QI (reg:QI CC_REGNUM)
(match_operand:QI 1 "register_operand" "0"))
(match_operand:QI 2 "general_operand" "ium")))]
""
@@ -2378,11 +2763,28 @@
;; 32 and 64-bit multiply are handled by the library
;;
-(define_insn "mulhi3"
+(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")))]
- ""
+ (match_operand:HI 2 "register_operand" "x")))
+ (clobber (match_scratch:HI 3 "=X"))]
+ "TARGET_M6811"
"*
{
CC_STATUS_INIT;
@@ -2390,6 +2792,59 @@
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
@@ -2501,7 +2956,7 @@
[(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")
+ (set (match_operand:HI 3 "register_operand" "=&x,&x")
(mod:HI (match_dup 1) (match_dup 2)))]
""
"*
@@ -2518,8 +2973,16 @@
output_asm_insn (\"ldx\\t%2\", operands);
}
}
- CC_STATUS_INIT;
- return \"bsr\\t__divmodhi4\";
+ if (TARGET_M6812)
+ {
+ /* Flags are ok after that. */
+ return \"idivs\\n\\txgdx\";
+ }
+ else
+ {
+ CC_STATUS_INIT;
+ return \"bsr\\t__divmodhi4\";
+ }
}")
(define_insn "udivmodhi4"
@@ -2663,7 +3126,7 @@
(define_insn "andqi3"
[(set (match_operand:QI 0 "register_operand" "=d,!u,d,d,?*A,?*A,!*q")
(and:QI (match_operand:QI 1 "register_operand" "%0,0,0,0,0,0,0")
- (match_operand:QI 2 "general_operand" "i,i,!um,?*A,i!um,?*A,i!um*A")))]
+ (match_operand:QI 2 "general_operand" "i,i,!um,?*A,!ium,?*A*d,!ium*A")))]
""
"*
{
@@ -2770,7 +3233,7 @@
(define_insn "iorqi3"
[(set (match_operand:QI 0 "register_operand" "=d,!u,d,d,?*A,?*A,!*q")
(ior:QI (match_operand:QI 1 "register_operand" "%0,0,0,0,0,0,0")
- (match_operand:QI 2 "general_operand" "i,i,!um,!*A,i!um,!*A,i!um*A")))]
+ (match_operand:QI 2 "general_operand" "i,i,!um,!*A,!ium,?*A*d,!ium*A")))]
""
"*
{
@@ -2864,9 +3327,9 @@
}")
(define_insn "xorqi3"
- [(set (match_operand:QI 0 "register_operand" "=d,d,!*u*A,!*u*A,!*q")
- (xor:QI (match_operand:QI 1 "register_operand" "%0,0,0,0,0")
- (match_operand:QI 2 "general_operand" "ium,!*A,ium,!*A,ium*A*u")))]
+ [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q")
+ (xor:QI (match_operand:QI 1 "register_operand" "%0,0,0,0,0,0")
+ (match_operand:QI 2 "general_operand" "i,!um,!*A,!ium,?*A*d,!ium*A")))]
""
"*
{
@@ -2927,10 +3390,10 @@
(match_operand:QI 1 "general_operand" "dxy,imu"))
(match_operand:SI 2 "general_operand" "imuD,imuD")]))]
"z_replacement_completed == 2"
- [(set (reg:QI 5) (match_dup 4))
- (set (reg:QI 1) (match_dup 7))
- (set (reg:QI 6) (match_op_dup 3 [(reg:QI 6) (match_dup 5)]))
- (set (reg:HI 0) (match_dup 6))]
+ [(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]))
{
@@ -2957,9 +3420,9 @@
(match_operand:HI 1 "general_operand" "dA,imu"))
(match_operand:SI 2 "general_operand" "imuD,imuD")]))]
"reload_completed"
- [(set (reg:HI 1) (match_dup 4))
- (set (reg:HI 1) (match_op_dup 3 [(reg:HI 1) (match_dup 5)]))
- (set (reg:HI 0) (match_dup 6))]
+ [(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]))
{
@@ -3003,9 +3466,9 @@
(match_operand:QI 1 "general_operand" "imud"))
(match_operand:HI 2 "general_operand" "dimu")]))]
"z_replacement_completed == 2"
- [(set (reg:QI 6) (match_dup 6))
- (set (reg:QI 5) (match_dup 4))
- (set (reg:QI 6) (match_op_dup 3 [(reg:QI 6) (match_dup 5)]))]
+ [(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]))
@@ -3034,8 +3497,8 @@
(match_operand:HI 2 "general_operand" "dimu")
(const_int 8))]))]
"z_replacement_completed == 2"
- [(set (reg:QI 6) (match_dup 5))
- (set (reg:QI 5) (match_dup 4))]
+ [(set (reg:QI A_REGNUM) (match_dup 4))
+ (set (reg:QI B_REGNUM) (match_dup 5))]
"
if (GET_CODE (operands[3]) == AND)
{
@@ -3060,7 +3523,7 @@
[(set (match_operand:SI 0 "register_operand" "=D,D")
(match_operator:SI 3 "m68hc11_logical_operator"
[(lshiftrt:SI
- (match_operand:SI 1 "general_operand" "uim,!D")
+ (match_operand:SI 1 "general_operand" "uim,?D")
(const_int 16))
(match_operand:SI 2 "general_operand" "uim,0")]))]
""
@@ -3070,13 +3533,13 @@
[(set (match_operand:SI 0 "register_operand" "=D,D")
(match_operator:SI 3 "m68hc11_logical_operator"
[(lshiftrt:SI
- (match_operand:SI 1 "general_operand" "uim,!D")
+ (match_operand:SI 1 "general_operand" "uim,?D")
(const_int 16))
(match_operand:SI 2 "general_operand" "uim,0")]))]
"reload_completed"
- [(set (reg:HI 1) (match_dup 4))
- (set (reg:HI 1) (match_op_dup 3 [(reg:HI 1) (match_dup 5)]))
- (set (reg:HI 0) (match_dup 6))]
+ [(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]))
{
@@ -3096,7 +3559,7 @@
[(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")
+ (match_operand:SI 1 "general_operand" "uim,?D")
(const_int 16))
(match_operand:SI 2 "general_operand" "0,0")]))]
""
@@ -3106,15 +3569,15 @@
[(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")
+ (match_operand:SI 1 "general_operand" "uim,?D")
(const_int 16))
(match_operand:SI 2 "general_operand" "0,0")]))]
"z_replacement_completed == 2"
- [(parallel [(set (reg:HI 1) (reg:HI 0))
- (set (reg:HI 0) (reg:HI 1))])
- (set (reg:HI 1) (match_op_dup 3 [(reg:HI 1) (match_dup 4)]))
- (parallel [(set (reg:HI 1) (reg:HI 0))
- (set (reg:HI 0) (reg:HI 1))])]
+ [(parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
+ (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])
+ (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 4)]))
+ (parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
+ (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])]
"operands[4] = m68hc11_gen_lowpart (HImode, operands[1]);
PUT_MODE (operands[3], HImode);")
@@ -3177,17 +3640,19 @@
/* 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
+ && ((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 4) (match_dup 5))
(set (match_dup 8) (match_dup 7))
- (parallel [(set (reg:HI 1) (match_dup 0))
- (set (match_dup 0) (reg:HI 1))])
- (set (reg:HI 1) (match_op_dup 3 [(reg:HI 1) (match_dup 6)]))
- (parallel [(set (reg:HI 1) (match_dup 0))
- (set (match_dup 0) (reg:HI 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))])]
"
/* Save the operand2 in a temporary location and use it. */
if (H_REG_P (operands[2])
@@ -3224,16 +3689,18 @@
/* 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
+ && ((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 1) (match_dup 0))
- (set (match_dup 0) (reg:HI 1))])
- (set (reg:HI 1) (match_op_dup 3 [(reg:HI 1) (match_dup 2)]))
- (parallel [(set (reg:HI 1) (match_dup 0))
- (set (match_dup 0) (reg:HI 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))])]
"
")
@@ -3283,11 +3750,11 @@
[(match_operand 1 "general_operand" "uim*d*A")]))]
"z_replacement_completed == 2"
[(set (match_dup 4) (match_dup 5))
- (parallel [(set (reg:HI 1) (match_dup 0))
- (set (match_dup 0) (reg:HI 1))])
- (set (reg:HI 1) (match_op_dup 2 [(match_dup 3)]))
- (parallel [(set (reg:HI 1) (match_dup 0))
- (set (match_dup 0) (reg:HI 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 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])
@@ -3331,11 +3798,11 @@
&& 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 1) (match_dup 4))
- (set (match_dup 4) (reg:HI 1))])
- (set (reg:QI 1) (match_op_dup 3 [(reg:QI 1) (match_dup 7)]))
- (parallel [(set (reg:HI 1) (match_dup 4))
- (set (match_dup 4) (reg:HI 1))])]
+ (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
@@ -3410,11 +3877,11 @@
[(match_operand:QI 1 "general_operand" "uim*d*x*y")]))]
"z_replacement_completed == 2"
[(set (match_dup 4) (match_dup 5))
- (parallel [(set (reg:HI 1) (match_dup 3))
- (set (match_dup 3) (reg:HI 1))])
- (set (reg:QI 1) (match_op_dup 2 [(match_dup 6)]))
- (parallel [(set (reg:HI 1) (match_dup 3))
- (set (match_dup 3) (reg:HI 1))])]
+ (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]));
@@ -3530,12 +3997,12 @@
(not:SI (match_operand:SI 1 "non_push_operand" "0")))]
"z_replacement_completed == 2
&& (!D_REG_P (operands[0]) || (optimize && optimize_size == 0))"
- [(set (reg:HI 1) (not:HI (reg:HI 1)))
- (parallel [(set (reg:HI 0) (reg:HI 1))
- (set (reg:HI 1) (reg:HI 0))])
- (set (reg:HI 1) (not:HI (reg:HI 1)))
- (parallel [(set (reg:HI 0) (reg:HI 1))
- (set (reg:HI 1) (reg:HI 0))])]
+ [(set (reg:HI D_REGNUM) (not:HI (reg:HI D_REGNUM)))
+ (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
+ (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
+ (set (reg:HI D_REGNUM) (not:HI (reg:HI D_REGNUM)))
+ (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
+ (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])]
"
{
/* The result pattern only works for D register.
@@ -3576,7 +4043,7 @@
[(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"))]
+ (clobber (match_scratch:HI 2 "=&A,d,d"))]
""
"#")
@@ -3584,7 +4051,7 @@
[(set (match_operand:DI 0 "nonimmediate_operand" "=<,um")
(ashift:DI (match_operand:DI 1 "general_operand" "umi,umi")
(const_int 32)))
- (clobber (match_scratch:HI 2 "=A,d"))]
+ (clobber (match_scratch:HI 2 "=&A,d"))]
"reload_completed"
[(const_int 0)]
"/* Move the lowpart in the highpart first in case the shift
@@ -3623,15 +4090,15 @@
(set (match_dup 4) (match_dup 2))
(set (match_dup 2) (match_dup 5))
- (set (match_dup 2) (rotate:HI (match_dup 2) (reg:HI 7)))
+ (set (match_dup 2) (rotate:HI (match_dup 2) (reg:HI CC_REGNUM)))
(set (match_dup 6) (match_dup 2))
(set (match_dup 2) (match_dup 7))
- (set (match_dup 2) (rotate:HI (match_dup 2) (reg:HI 7)))
+ (set (match_dup 2) (rotate:HI (match_dup 2) (reg:HI CC_REGNUM)))
(set (match_dup 8) (match_dup 2))
(set (match_dup 2) (match_dup 9))
- (set (match_dup 2) (rotate:HI (match_dup 2) (reg:HI 7)))
+ (set (match_dup 2) (rotate:HI (match_dup 2) (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]);
@@ -3663,8 +4130,8 @@
(const_int 16))
(match_operand:SI 2 "general_operand" "0")))]
"z_replacement_completed == 2"
- [(set (reg:HI 1) (plus:HI (reg:HI 1) (match_dup 3)))
- (set (reg:HI 0) (plus:HI (plus:HI (reg:HI 0) (const_int 0)) (reg:HI 7)))]
+ [(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_insn "addsi_ashift16"
@@ -3685,7 +4152,7 @@
(match_operand:SI 1 "general_operand" "0")))
(clobber (match_scratch:HI 3 "=X"))]
"0 && reload_completed && z_replacement_completed == 2"
- [(set (reg:HI 0) (plus:HI (reg:HI 0) (match_dup 4)))]
+ [(set (reg:HI X_REGNUM) (plus:HI (reg:HI X_REGNUM) (match_dup 4)))]
"
{
operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
@@ -3705,8 +4172,8 @@
(const_int 65535))
(match_operand:SI 2 "general_operand" "0")))]
"z_replacement_completed == 2"
- [(set (reg:HI 1) (plus:HI (reg:HI 1) (match_dup 3)))
- (set (reg:HI 0) (plus:HI (plus:HI (reg:HI 0) (const_int 0)) (reg:HI 7)))]
+ [(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]);")
;;
@@ -3766,8 +4233,8 @@
(const_int 16)))
(clobber (match_scratch:HI 2 "=X"))]
"reload_completed"
- [(set (reg:HI 0) (match_dup 1))
- (set (reg:HI 1) (const_int 0))]
+ [(set (reg:HI X_REGNUM) (match_dup 1))
+ (set (reg:HI D_REGNUM) (const_int 0))]
"")
(define_insn "*ashlsi3_const1"
@@ -3856,8 +4323,15 @@
is true for 68hc11 only, we save temporary the value of Y. */
if (!Y_REG_P (operands[2]))
{
+ rtx ops[1];
+
+ ops[0] = operands[1];
output_asm_insn (\"pshy\", operands);
- output_asm_insn (\"ldy\\t%1\", operands);
+ if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
+ {
+ ops[0] = adj_offsettable_operand (operands[1], 2);
+ }
+ output_asm_insn (\"ldy\\t%0\", ops);
output_asm_insn (\"bsr\\t___ashlsi3\", operands);
return \"puly\";
}
@@ -3910,7 +4384,7 @@
(define_insn "*ashlhi3_2"
[(set (match_operand:HI 0 "register_operand" "=d")
(ashift:HI (match_operand:HI 1 "register_operand" "0")
- (match_operand:HI 2 "register_operand" "x")))
+ (match_operand:HI 2 "register_operand" "+x")))
(clobber (match_dup 2))]
""
"*
@@ -3919,10 +4393,10 @@
return \"bsr\\t___lshlhi3\";
}")
-(define_insn ""
+(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")))
+ (match_operand:HI 1 "register_operand" "+x")))
(clobber (match_dup 1))]
""
"*
@@ -4177,9 +4651,9 @@
output_asm_insn (\"rolb\", operands);
output_asm_insn (\"rola\", operands);
output_asm_insn (\"tab\", operands);
- output_asm_insn (\"anda\\t#1\", operands);
+ output_asm_insn (\"anda\\t#0\", operands);
output_asm_insn (\"bcc\\t%l0\", ops);
- output_asm_insn (\"oraa\\t#0xFE\", ops);
+ output_asm_insn (\"coma\", ops);
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
CODE_LABEL_NUMBER (ops[0]));
@@ -4199,7 +4673,7 @@
(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")))
+ (match_operand:HI 2 "register_operand" "+x,+d")))
(clobber (match_dup 2))]
""
"*
@@ -4257,8 +4731,15 @@
is true for 68hc11 only, we save temporary the value of Y. */
if (!Y_REG_P (operands[2]))
{
+ rtx ops[1];
+
+ ops[0] = operands[1];
output_asm_insn (\"pshy\", operands);
- output_asm_insn (\"ldy\\t%1\", operands);
+ if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
+ {
+ ops[0] = adj_offsettable_operand (operands[1], 2);
+ }
+ output_asm_insn (\"ldy\\t%0\", ops);
output_asm_insn (\"bsr\\t___ashrsi3\", operands);
return \"puly\";
}
@@ -4355,7 +4836,7 @@
[(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"))]
+ (clobber (match_scratch:HI 2 "=&A,d,d"))]
""
"#")
@@ -4363,7 +4844,7 @@
[(set (match_operand:DI 0 "nonimmediate_operand" "=<,um")
(lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi")
(const_int 32)))
- (clobber (match_scratch:HI 2 "=A,d"))]
+ (clobber (match_scratch:HI 2 "=&A,d"))]
"reload_completed"
[(const_int 0)]
"m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]),
@@ -4387,14 +4868,14 @@
(match_operand:DI 2 "const_int_operand" "")))
(clobber (match_scratch:HI 3 "=d"))]
"z_replacement_completed && INTVAL (operands[2]) >= 56"
- [(set (reg:QI 1) (match_dup 9))
- (set (reg:QI 1) (lshiftrt:QI (reg:QI 1) (match_dup 8)))
- (set (reg:HI 1) (zero_extend:HI (reg:QI 1)))
- (set (match_dup 4) (reg:HI 1))
- (set (reg:QI 1) (const_int 0))
- (set (match_dup 5) (reg:HI 1))
- (set (match_dup 6) (reg:HI 1))
- (set (match_dup 7) (reg:HI 1))]
+ [(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_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) - 56);
operands[4] = m68hc11_gen_lowpart (SImode, operands[0]);
operands[5] = m68hc11_gen_highpart (HImode, operands[4]);
@@ -4415,13 +4896,13 @@
(clobber (match_scratch:HI 3 "=d"))]
"z_replacement_completed && INTVAL (operands[2]) >= 48
&& INTVAL (operands[2]) < 56"
- [(set (reg:HI 1) (match_dup 9))
- (set (reg:HI 1) (lshiftrt:HI (reg:HI 1) (match_dup 8)))
- (set (match_dup 4) (reg:HI 1))
- (set (reg:HI 1) (const_int 0))
- (set (match_dup 5) (reg:HI 1))
- (set (match_dup 6) (reg:HI 1))
- (set (match_dup 7) (reg:HI 1))]
+ [(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_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) - 48);
operands[4] = m68hc11_gen_lowpart (SImode, operands[0]);
operands[5] = m68hc11_gen_highpart (HImode, operands[4]);
@@ -4452,15 +4933,15 @@
(set (match_dup 4) (match_dup 2))
(set (match_dup 2) (match_dup 5))
- (set (match_dup 2) (rotatert:HI (match_dup 2) (reg:HI 7)))
+ (set (match_dup 2) (rotatert:HI (match_dup 2) (reg:HI CC_REGNUM)))
(set (match_dup 6) (match_dup 2))
(set (match_dup 2) (match_dup 7))
- (set (match_dup 2) (rotatert:HI (match_dup 2) (reg:HI 7)))
+ (set (match_dup 2) (rotatert:HI (match_dup 2) (reg:HI CC_REGNUM)))
(set (match_dup 8) (match_dup 2))
(set (match_dup 2) (match_dup 9))
- (set (match_dup 2) (rotatert:HI (match_dup 2) (reg:HI 7)))
+ (set (match_dup 2) (rotatert:HI (match_dup 2) (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]);
@@ -4508,8 +4989,10 @@
(const_int 16)))
(clobber (match_scratch:HI 2 "=X,X,X,X"))]
""
- "#
+ "@
+ #
xgdx\\n\\tldx\\t#0
+ #
#")
(define_insn "*lshrsi3_const1"
@@ -4592,8 +5075,15 @@
is true for 68hc11 only, we save temporary the value of Y. */
if (!Y_REG_P (operands[2]))
{
+ rtx ops[1];
+
+ ops[0] = operands[1];
output_asm_insn (\"pshy\", operands);
- output_asm_insn (\"ldy\\t%1\", operands);
+ if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
+ {
+ ops[0] = adj_offsettable_operand (operands[1], 2);
+ }
+ output_asm_insn (\"ldy\\t%0\", ops);
output_asm_insn (\"bsr\\t___lshrsi3\", operands);
return \"puly\";
}
@@ -4637,7 +5127,7 @@
return \"lsrd\";
CC_STATUS_INIT;
- return \"lsr\\t%h0\\n\\trol\\t%b0\";
+ return \"lsr\\t%h0\\n\\tror\\t%b0\";
}")
(define_insn "lshrhi3_const"
@@ -4727,7 +5217,7 @@
(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")))
+ (match_operand:HI 2 "register_operand" "+x,+d")))
(clobber (match_dup 2))]
""
"*
@@ -4751,13 +5241,13 @@
"")
(define_insn "*lshrqi3_const1"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m,!u,!*q,!*A")
+ [(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)))]
""
"@
- lsrb
lsr\\t%b0
+ lsrb
lsr\\t%b0
lsr%0
#")
@@ -4868,7 +5358,7 @@
(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 7)))]
+ (reg:QI CC_REGNUM)))]
""
"*
{
@@ -4881,7 +5371,7 @@
(define_insn "*rotlhi3_with_carry"
[(set (match_operand:HI 0 "register_operand" "=d")
(rotate:HI (match_operand:HI 1 "register_operand" "0")
- (reg:HI 7)))]
+ (reg:HI CC_REGNUM)))]
""
"*
{
@@ -4892,7 +5382,7 @@
(define_insn "*rotrhi3_with_carry"
[(set (match_operand:HI 0 "register_operand" "=d")
(rotatert:HI (match_operand:HI 1 "register_operand" "0")
- (reg:HI 7)))]
+ (reg:HI CC_REGNUM)))]
""
"*
{
@@ -5103,6 +5593,78 @@
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]))
+ 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]))
+ 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]))
+ 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]))
+ return \"bne\\t%l1\";
+ else
+ return \"tbne\\tb,%l1\";
+}")
+
(define_insn "*beq"
[(set (pc)
(if_then_else (eq (cc0)
@@ -5328,7 +5890,7 @@
;;
;;- Call a function that returns no value.
(define_insn "call"
- [(call (match_operand:QI 0 "memory_operand" "mAi")
+ [(call (match_operand:QI 0 "memory_operand" "m")
(match_operand:SI 1 "general_operand" "g"))]
;; Operand 1 not really used on the m68hc11.
""
@@ -5349,7 +5911,7 @@
(define_insn "call_value"
[(set (match_operand 0 "" "=g")
- (call (match_operand:QI 1 "general_operand" "mAi")
+ (call (match_operand:QI 1 "memory_operand" "m")
(match_operand:SI 2 "general_operand" "g")))]
""
"*
@@ -5478,7 +6040,7 @@
(define_insn "*return_16bit"
[(return)
- (use (reg:HI 1))]
+ (use (reg:HI D_REGNUM))]
"reload_completed && m68hc11_total_frame_size () == 0"
"*
{
@@ -5545,13 +6107,13 @@
(define_peephole
[(set (match_operand:HI 0 "hard_reg_operand" "xy")
(match_operand:HI 1 "const_int_operand" ""))
- (parallel [(set (reg:HI 1) (match_dup 0))
- (set (match_dup 0) (reg:HI 1))])
- (set (reg:HI 1)
- (plus (reg:HI 1)
+ (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 1) (match_dup 0))
- (set (match_dup 0) (reg:HI 1))])]
+ (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
+ (set (match_dup 0) (reg:HI D_REGNUM))])]
"(INTVAL (operands[1]) & 0x0FF) == 0"
"*
{
@@ -5634,9 +6196,9 @@
;; (set ...) insn.
;;
(define_peephole
- [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI 1))
- (parallel [(set (reg:HI 1) (match_dup 0))
- (set (match_dup 0) (reg:HI 1))])]
+ [(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)"
"*
{
@@ -5648,10 +6210,10 @@
;; 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 1))
+ [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM))
(set (match_dup 0) (match_dup 0))
- (parallel [(set (reg:HI 1) (match_dup 0))
- (set (match_dup 0) (reg:HI 1))])]
+ (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)"
"*
{
@@ -5665,9 +6227,9 @@
;; 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 1))
- (parallel [(set (reg:HI 1) (match_dup 0))
- (set (match_dup 0) (reg:HI 1))])]
+ [(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))])]
""
"*
{
@@ -5685,9 +6247,9 @@
;;; need to emit anything. Otherwise, we just need an copy of D to X/Y.
;;;
(define_peephole
- [(parallel [(set (reg:HI 1) (match_operand:HI 0 "hard_reg_operand" "A"))
- (set (match_dup 0) (reg:HI 1))])
- (set (reg:HI 1) (match_dup 0))]
+ [(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]))"
"*
{
@@ -5701,9 +6263,9 @@
;;; need to emit anything. Otherwise, we just need an copy of D to X/Y.
;;;
(define_peephole
- [(parallel [(set (reg:HI 1) (match_operand:HI 0 "hard_reg_operand" "A"))
- (set (match_dup 0) (reg:HI 1))])
- (set (reg:QI 1) (match_operand:QI 1 "hard_reg_operand" "A"))]
+ [(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]))"
"*
@@ -5718,9 +6280,9 @@
;;; need to emit anything. Otherwise, we just need a copy of D to X/Y.
;;;
(define_peephole
- [(parallel [(set (reg:HI 1) (match_operand:HI 0 "hard_reg_operand" "A"))
- (set (match_dup 0) (reg:HI 1))])
- (set (reg:HI 1) (match_dup 0))]
+ [(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))]
""
"*
{
@@ -5738,9 +6300,9 @@
;;; with the xgdx.
;;;
(define_peephole
- [(parallel [(set (reg:HI 1) (match_operand:HI 0 "hard_reg_operand" "A"))
- (set (match_dup 0) (reg:HI 1))])
- (set (reg:QI 1) (match_operand:QI 1 "hard_reg_operand" "A"))]
+ [(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])"
"*
{
@@ -5757,10 +6319,10 @@
;;; Catch two consecutive xgdx or xgdy, emit nothing.
;;;
(define_peephole
- [(parallel [(set (reg:HI 1) (match_operand:HI 0 "hard_reg_operand" "A"))
- (set (match_dup 0) (reg:HI 1))])
- (parallel [(set (reg:HI 1) (match_dup 0))
- (set (match_dup 0) (reg:HI 1))])]
+ [(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))])]
""
"*
{
@@ -5770,44 +6332,6 @@
")
(define_peephole
- [(set (match_operand:HI 0 "stack_register_operand" "")
- (plus:HI (match_dup 0)
- (const_int -2)))
- (set (match_operand:HI 2 "memory_operand" "m")
- (match_operand:HI 3 "stack_register_operand" ""))]
- "0 && GET_CODE (operands[2]) == MEM"
- "*
-{
- rtx ops[2];
-
- ops[0] = gen_rtx (MEM, HImode,
- gen_rtx (PRE_DEC, HImode, stack_pointer_rtx));
- ops[1] = operands[3];
- m68hc11_gen_movhi (insn, ops);
- return \"\";
-}
-")
-
-(define_peephole
- [(set (match_operand:HI 0 "hard_reg_operand" "")
- (match_operand:HI 1 "memory_operand" "m"))
- (set (match_operand:HI 2 "stack_register_operand" "")
- (plus:HI (match_dup 2)
- (const_int 2)))]
- "GET_CODE (operands[1]) == MEM"
- "*
-{
- rtx ops[2];
-
- ops[0] = operands[0];
- ops[1] = gen_rtx (MEM, HImode,
- gen_rtx (POST_INC, HImode, stack_pointer_rtx));
- m68hc11_gen_movhi (insn, ops);
- 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" "")
@@ -5834,7 +6358,7 @@
;;
(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 3)))]
+ (set (match_dup 0) (plus:HI (match_dup 0) (reg:HI SP_REGNUM)))]
"TARGET_M6811"
"*
{
diff --git a/gcc/config/m68hc11/m68hc12.h b/gcc/config/m68hc11/m68hc12.h
index c911c47f879..e36e0f3fc10 100644
--- a/gcc/config/m68hc11/m68hc12.h
+++ b/gcc/config/m68hc11/m68hc12.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler, for m68hc12.
- Copyright (C) 1999, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
Contributed by Stephane Carrez (stcarrez@worldnet.fr).
This file is part of GNU CC.
@@ -32,7 +32,8 @@ Boston, MA 02111-1307, USA. */
"%{mshort:-D__HAVE_SHORT_INT__ -D__INT__=16 -D__INT_MAX__=32767}\
%{!mshort:-D__INT__=32 -D__INT_MAX__=2147483647}\
%{m68hc11:-Dmc6811 -DMC6811 -Dmc68hc11}\
- %{!m68hc11:-Dmc6812 -DMC6812 -Dmc68hc12}"
+ %{!m68hc11:-Dmc6812 -DMC6812 -Dmc68hc12}\
+ %{fshort-double:-D__HAVE_SHORT_DOUBLE__}"
/* Default target_flags if no switches specified. */
#define TARGET_DEFAULT (MASK_M6812)
diff --git a/gcc/config/m68hc11/t-m68hc11-gas b/gcc/config/m68hc11/t-m68hc11-gas
index ec4b59e027b..13ca1902b2c 100644
--- a/gcc/config/m68hc11/t-m68hc11-gas
+++ b/gcc/config/m68hc11/t-m68hc11-gas
@@ -21,10 +21,12 @@ LIB1ASMFUNCS = _mulsi3 \
_mulqi3 _ashlsi3 _ashrsi3 _lshrsi3 \
_divmodhi4 _mulhi3 _mulhi32 \
_memcpy _memset _negsi2 _one_cmplsi2 \
- _regs_min _regs_d1_8 _regs_d8_16 _regs_d17_32 \
+ _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 \
- _ashrhi3 _lshrhi3 _lshlhi3 _ashrqi3 _lshlqi3 _map_data _init_bss
+ _ashrhi3 _lshrhi3 _lshlhi3 _ashrqi3 _lshlqi3 _map_data _init_bss \
+ _ctor _dtor
TARGET_LIBGCC2_CFLAGS = -DUSE_GAS -DIN_GCC
diff --git a/gcc/config/m68k/3b1.h b/gcc/config/m68k/3b1.h
index 739a28b92e0..0dac874744f 100644
--- a/gcc/config/m68k/3b1.h
+++ b/gcc/config/m68k/3b1.h
@@ -64,10 +64,6 @@ Boston, MA 02111-1307, USA. */
#define ASM_FILE_START(FILE) \
output_file_directive ((FILE), main_input_filename)
-/* Don't try to define `gcc_compiled.' since the assembler might not
- accept symbols with periods and GDB doesn't run on this machine anyway. */
-#define ASM_IDENTIFY_GCC(FILE)
-
/* Define __HAVE_68881__ in preprocessor if -m68881 is specified.
This will control the use of inline 68881 insns in certain macros. */
diff --git a/gcc/config/m68k/auxgas.h b/gcc/config/m68k/auxgas.h
index c2e0d567b45..c3c76352f93 100644
--- a/gcc/config/m68k/auxgas.h
+++ b/gcc/config/m68k/auxgas.h
@@ -31,14 +31,6 @@ Boston, MA 02111-1307, USA. */
#define ASM_OUTPUT_IDENT(FILE, NAME) \
fprintf (FILE, "\t.ident \"%s\"\n", NAME);
-#ifdef IDENTIFY_WITH_IDENT
-/* Put the GCC identification somewhere nicer, I think.
- Does the COFF GDB use the "gcc2_complied." symbol anyway? */
-#define ASM_IDENTIFY_GCC(FILE) /* nothing */
-#define ASM_IDENTIFY_LANGUAGE(FILE) \
- fprintf (FILE, "\t.ident \"GCC (%s) %s\"\n", lang_identify(), version_string)
-#endif
-
#ifdef USE_COLLECT2
#undef ASM_OUTPUT_CONSTRUCTOR
#undef ASM_OUTPUT_DESTRUCTOR
diff --git a/gcc/config/m68k/crds.h b/gcc/config/m68k/crds.h
index b3e807843f4..12f0fb797bc 100644
--- a/gcc/config/m68k/crds.h
+++ b/gcc/config/m68k/crds.h
@@ -90,10 +90,6 @@ Boston, MA 02111-1307, USA. */
#define TARGET_MEM_FUNCTIONS
-/* Don't try to define `gcc_compiled.' since the assembler might not
- accept symbols with periods and GDB doesn't run on this machine anyway. */
-#define ASM_IDENTIFY_GCC(FILE)
-
/* Define __HAVE_68881__ in preprocessor if -m68881 is specified.
This will control the use of inline 68881 insns in certain macros. */
diff --git a/gcc/config/m68k/hp320.h b/gcc/config/m68k/hp320.h
index 83140058d2d..64a0e0d2c90 100644
--- a/gcc/config/m68k/hp320.h
+++ b/gcc/config/m68k/hp320.h
@@ -607,10 +607,6 @@ do { register int i; \
{ fprintf ((FILE), "mov"); (PTR) += 4; } \
}
-/* Prevent output of `gcc_compiled.:'. */
-
-#define ASM_IDENTIFY_GCC(FILE)
-
#else /* not HPUX_ASM */
#undef FUNCTION_PROFILER
diff --git a/gcc/config/m68k/linux-aout.h b/gcc/config/m68k/linux-aout.h
index d4e5ec47573..dd07a4e983e 100644
--- a/gcc/config/m68k/linux-aout.h
+++ b/gcc/config/m68k/linux-aout.h
@@ -41,7 +41,8 @@ Boston, MA 02111-1307, USA. */
#endif
#undef SUBTARGET_SWITCHES
-#define SUBTARGET_SWITCHES {"ieee-fp", 0},
+#define SUBTARGET_SWITCHES {"ieee-fp", 0, \
+ N_("Use IEEE math for fp comparisons") },
#undef ASM_SPEC
#define ASM_SPEC \
diff --git a/gcc/config/m68k/linux.h b/gcc/config/m68k/linux.h
index 2dea947a07a..bf420917a1d 100644
--- a/gcc/config/m68k/linux.h
+++ b/gcc/config/m68k/linux.h
@@ -42,7 +42,8 @@ Boston, MA 02111-1307, USA. */
#define STRICT_ALIGNMENT 0
#undef SUBTARGET_SWITCHES
-#define SUBTARGET_SWITCHES {"ieee-fp", 0},
+#define SUBTARGET_SWITCHES {"ieee-fp", 0, \
+ N_("Use IEEE math for fp comparisons")},
/* Here are four prefixes that are used by asm_fprintf to
facilitate customization for alternate assembler syntaxes.
diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
index 430e618e37e..4dd8850f1a4 100644
--- a/gcc/config/m68k/m68k.c
+++ b/gcc/config/m68k/m68k.c
@@ -29,11 +29,12 @@ Boston, MA 02111-1307, USA. */
#include "real.h"
#include "insn-config.h"
#include "conditions.h"
-#include "insn-flags.h"
#include "output.h"
#include "insn-attr.h"
#include "recog.h"
#include "toplev.h"
+#include "expr.h"
+#include "reload.h"
#include "tm_p.h"
/* Needed for use_return_insn. */
@@ -878,7 +879,7 @@ not_sp_operand (op, mode)
register rtx op;
enum machine_mode mode;
{
- return op != stack_pointer_rtx && general_operand (op, mode);
+ return op != stack_pointer_rtx && nonimmediate_operand (op, mode);
}
/* Return TRUE if X is a valid comparison operator for the dbcc
@@ -3334,7 +3335,7 @@ const_uint32_operand (op, mode)
return (GET_CODE (op) == CONST_INT
&& (INTVAL (op) >= 0 && INTVAL (op) <= 0xffffffffL));
#else
- return ((GET_CODE (op) == CONST_INT && INTVAL (op) >= 0)
+ return (GET_CODE (op) == CONST_INT
|| (GET_CODE (op) == CONST_DOUBLE && CONST_DOUBLE_HIGH (op) == 0));
#endif
}
diff --git a/gcc/config/m68k/m68k.h b/gcc/config/m68k/m68k.h
index c20cba1b99d..382edbf5f20 100644
--- a/gcc/config/m68k/m68k.h
+++ b/gcc/config/m68k/m68k.h
@@ -147,63 +147,96 @@ extern int target_flags;
where VALUE is the bits to set or minus the bits to clear.
An empty string NAME is used to identify the default VALUE. */
-#define TARGET_SWITCHES \
- { { "68020", - (MASK_5200|MASK_68060|MASK_68040|MASK_68040_ONLY)}, \
- { "c68020", - (MASK_5200|MASK_68060|MASK_68040|MASK_68040_ONLY)}, \
- { "68020", (MASK_68020|MASK_BITFIELD)}, \
- { "c68020", (MASK_68020|MASK_BITFIELD)}, \
+#define TARGET_SWITCHES \
+ { { "68020", - (MASK_5200|MASK_68060|MASK_68040|MASK_68040_ONLY), \
+ N_("Generate code for a 68020") }, \
+ { "c68020", - (MASK_5200|MASK_68060|MASK_68040|MASK_68040_ONLY), \
+ N_("Generate code for a 68020") }, \
+ { "68020", (MASK_68020|MASK_BITFIELD), "" }, \
+ { "c68020", (MASK_68020|MASK_BITFIELD), "" }, \
{ "68000", - (MASK_5200|MASK_68060|MASK_68040|MASK_68040_ONLY \
- |MASK_68020|MASK_BITFIELD|MASK_68881)}, \
+ |MASK_68020|MASK_BITFIELD|MASK_68881), \
+ N_("Generate code for a 68000") }, \
{ "c68000", - (MASK_5200|MASK_68060|MASK_68040|MASK_68040_ONLY \
- |MASK_68020|MASK_BITFIELD|MASK_68881)}, \
- { "bitfield", MASK_BITFIELD}, \
- { "nobitfield", - MASK_BITFIELD}, \
- { "rtd", MASK_RTD}, \
- { "nortd", - MASK_RTD}, \
- { "short", MASK_SHORT}, \
- { "noshort", - MASK_SHORT}, \
- { "fpa", -(MASK_SKY|MASK_68040_ONLY|MASK_68881)}, \
- { "fpa", MASK_FPA}, \
- { "nofpa", - MASK_FPA}, \
- { "sky", -(MASK_FPA|MASK_68040_ONLY|MASK_68881)}, \
- { "sky", MASK_SKY}, \
- { "nosky", - MASK_SKY}, \
- { "68881", - (MASK_FPA|MASK_SKY)}, \
- { "68881", MASK_68881}, \
- { "soft-float", - (MASK_FPA|MASK_SKY|MASK_68040_ONLY|MASK_68881)}, \
- { "68020-40", -(MASK_5200|MASK_68060|MASK_68040_ONLY)}, \
- { "68020-40", (MASK_BITFIELD|MASK_68881|MASK_68020|MASK_68040)}, \
- { "68020-60", -(MASK_5200|MASK_68040_ONLY)}, \
+ |MASK_68020|MASK_BITFIELD|MASK_68881), \
+ N_("Generate code for a 68000") }, \
+ { "bitfield", MASK_BITFIELD, \
+ N_("Use the bit-field instructions") }, \
+ { "nobitfield", - MASK_BITFIELD, \
+ N_("Do not use the bit-field instructions") }, \
+ { "rtd", MASK_RTD, \
+ N_("Use different calling convention using 'rtd'") }, \
+ { "nortd", - MASK_RTD, \
+ N_("Use normal calling convention") }, \
+ { "short", MASK_SHORT, \
+ N_("Consider type `int' to be 16 bits wide") }, \
+ { "noshort", - MASK_SHORT, \
+ N_("Consider type `int' to be 32 bits wide") }, \
+ { "fpa", -(MASK_SKY|MASK_68040_ONLY|MASK_68881), \
+ N_("Generate code for a Sun FPA") }, \
+ { "fpa", MASK_FPA, "" }, \
+ { "nofpa", - MASK_FPA, \
+ N_("Do not generate code for a Sun FPA") }, \
+ { "sky", -(MASK_FPA|MASK_68040_ONLY|MASK_68881), \
+ N_("") }, \
+ { "sky", MASK_SKY, \
+ N_("") }, \
+ { "nosky", - MASK_SKY, \
+ N_("") }, \
+ { "68881", - (MASK_FPA|MASK_SKY), \
+ N_("Generate code for a 68881") }, \
+ { "68881", MASK_68881, "" }, \
+ { "soft-float", - (MASK_FPA|MASK_SKY|MASK_68040_ONLY|MASK_68881), \
+ N_("Generate code with library calls for floating point") }, \
+ { "68020-40", -(MASK_5200|MASK_68060|MASK_68040_ONLY), \
+ N_("Generate code for a 68040, without any new instructions") }, \
+ { "68020-40", (MASK_BITFIELD|MASK_68881|MASK_68020|MASK_68040), ""},\
+ { "68020-60", -(MASK_5200|MASK_68040_ONLY), \
+ N_("Generate code for a 68060, without any new instructions") }, \
{ "68020-60", (MASK_BITFIELD|MASK_68881|MASK_68020|MASK_68040 \
- |MASK_68060)}, \
- { "68030", - (MASK_5200|MASK_68060|MASK_68040|MASK_68040_ONLY)}, \
- { "68030", (MASK_68020|MASK_BITFIELD)}, \
- { "68040", - (MASK_5200|MASK_68060)}, \
+ |MASK_68060), "" }, \
+ { "68030", - (MASK_5200|MASK_68060|MASK_68040|MASK_68040_ONLY), \
+ N_("Generate code for a 68030") }, \
+ { "68030", (MASK_68020|MASK_BITFIELD), "" }, \
+ { "68040", - (MASK_5200|MASK_68060), \
+ N_("Generate code for a 68040") }, \
{ "68040", (MASK_68020|MASK_68881|MASK_BITFIELD \
- |MASK_68040_ONLY|MASK_68040)}, \
- { "68060", - (MASK_5200|MASK_68040)}, \
+ |MASK_68040_ONLY|MASK_68040), "" }, \
+ { "68060", - (MASK_5200|MASK_68040), \
+ N_("Generate code for a 68060") }, \
{ "68060", (MASK_68020|MASK_68881|MASK_BITFIELD \
- |MASK_68040_ONLY|MASK_68060)}, \
+ |MASK_68040_ONLY|MASK_68060), "" }, \
{ "5200", - (MASK_68060|MASK_68040|MASK_68040_ONLY|MASK_68020 \
- |MASK_BITFIELD|MASK_68881)}, \
- { "5200", (MASK_5200)}, \
- { "68851", 0}, \
- { "no-68851", 0}, \
+ |MASK_BITFIELD|MASK_68881), \
+ N_("Generate code for a 520X") }, \
+ { "5200", (MASK_5200), "" }, \
+ { "68851", 0, \
+ N_("Generate code for a 68851") }, \
+ { "no-68851", 0, \
+ N_("Do no generate code for a 68851") }, \
{ "68302", - (MASK_5200|MASK_68060|MASK_68040|MASK_68040_ONLY \
- |MASK_68020|MASK_BITFIELD|MASK_68881)}, \
+ |MASK_68020|MASK_BITFIELD|MASK_68881), \
+ N_("Generate code for a 68302") }, \
{ "68332", - (MASK_5200|MASK_68060|MASK_68040|MASK_68040_ONLY \
- |MASK_BITFIELD|MASK_68881)}, \
- { "68332", MASK_68020}, \
+ |MASK_BITFIELD|MASK_68881), \
+ N_("Generate code for a 68332") }, \
+ { "68332", MASK_68020, "" }, \
{ "cpu32", - (MASK_5200|MASK_68060|MASK_68040|MASK_68040_ONLY \
- |MASK_BITFIELD|MASK_68881)}, \
- { "cpu32", MASK_68020}, \
- { "align-int", MASK_ALIGN_INT }, \
- { "no-align-int", -MASK_ALIGN_INT }, \
- { "pcrel", MASK_PCREL}, \
- { "strict-align", -MASK_NO_STRICT_ALIGNMENT}, \
- { "no-strict-align", MASK_NO_STRICT_ALIGNMENT}, \
+ |MASK_BITFIELD|MASK_68881), \
+ N_("Generate code for a cpu32") }, \
+ { "cpu32", MASK_68020, "" }, \
+ { "align-int", MASK_ALIGN_INT, \
+ N_("Align variables on a 32-bit boundary") }, \
+ { "no-align-int", -MASK_ALIGN_INT, \
+ N_("Align variables on a 16-bit boundary") }, \
+ { "pcrel", MASK_PCREL, \
+ N_("Generate pc-relative code") }, \
+ { "strict-align", -MASK_NO_STRICT_ALIGNMENT, \
+ N_("Do not use unaligned memory references") }, \
+ { "no-strict-align", MASK_NO_STRICT_ALIGNMENT, \
+ N_("Use unaligned memory references") }, \
SUBTARGET_SWITCHES \
- { "", TARGET_DEFAULT}}
+ { "", TARGET_DEFAULT, "" }}
/* TARGET_DEFAULT is defined in sun*.h and isi.h, etc. */
/* This macro is similar to `TARGET_SWITCHES' but defines names of
@@ -216,9 +249,12 @@ extern int target_flags;
option if the fixed part matches. The actual option name is made
by appending `-m' to the specified name. */
#define TARGET_OPTIONS \
-{ { "align-loops=", &m68k_align_loops_string }, \
- { "align-jumps=", &m68k_align_jumps_string }, \
- { "align-functions=", &m68k_align_funcs_string }, \
+{ { "align-loops=", &m68k_align_loops_string, \
+ N_("Loop code aligned to this power of 2") }, \
+ { "align-jumps=", &m68k_align_jumps_string, \
+ N_("Jump targets are aligned to this power of 2") }, \
+ { "align-functions=", &m68k_align_funcs_string, \
+ N_("Function starts are aligned to this power of 2") }, \
SUBTARGET_OPTIONS \
}
diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md
index 75c552535c9..2f4af6cde99 100644
--- a/gcc/config/m68k/m68k.md
+++ b/gcc/config/m68k/m68k.md
@@ -885,7 +885,7 @@
;This is never used.
;(define_insn "swapsi"
-; [(set (match_operand:SI 0 "general_operand" "+r")
+; [(set (match_operand:SI 0 "nonimmediate_operand" "+r")
; (match_operand:SI 1 "general_operand" "+r"))
; (set (match_dup 1) (match_dup 0))]
; ""
@@ -896,7 +896,7 @@
;; into a data reg with moveq in order to store it elsewhere.
(define_insn "movsi_const0"
- [(set (match_operand:SI 0 "general_operand" "=g")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
(const_int 0))]
;; clr insns on 68000 read before writing.
;; This isn't so on the 68010, but we have no TARGET_68010.
@@ -943,7 +943,7 @@
;; In both the PIC and non-PIC cases the patterns generated will
;; matched by the next define_insn.
(define_expand "movsi"
- [(set (match_operand:SI 0 "general_operand" "")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "")
(match_operand:SI 1 "general_operand" ""))]
""
"
@@ -977,7 +977,7 @@
;; Notes: make sure no alternative allows g vs g.
;; We don't allow f-regs since fixed point cannot go in them.
;; We do allow y and x regs since fixed point is allowed in them.
- [(set (match_operand:SI 0 "general_operand" "=g,d,a<,y,!*x*r*m")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=g,d,a<,y,!*x*r*m")
(match_operand:SI 1 "general_src_operand" "daymSKT,n,i,g,*x*r*m"))]
"!TARGET_5200"
@@ -991,7 +991,7 @@
}")
(define_insn ""
- [(set (match_operand:SI 0 "general_operand" "=r<Q>,g")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=r<Q>,g")
(match_operand:SI 1 "general_operand" "g,r<Q>"))]
"TARGET_5200"
"* return output_move_simode (operands);")
@@ -999,7 +999,7 @@
;; Special case of fullword move, where we need to get a non-GOT PIC
;; reference into an address register.
(define_insn ""
- [(set (match_operand:SI 0 "general_operand" "=a<")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=a<")
(match_operand:SI 1 "pcrel_address" ""))]
"TARGET_PCREL"
"*
@@ -1010,87 +1010,87 @@
}")
(define_expand "movhi"
- [(set (match_operand:HI 0 "general_operand" "")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "")
(match_operand:HI 1 "general_operand" ""))]
""
"")
(define_insn ""
- [(set (match_operand:HI 0 "general_operand" "=g")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=g")
(match_operand:HI 1 "general_src_operand" "gS"))]
"!TARGET_5200"
"* return output_move_himode (operands);")
(define_insn ""
- [(set (match_operand:HI 0 "general_operand" "=r<Q>,g")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=r<Q>,g")
(match_operand:HI 1 "general_operand" "g,r<Q>"))]
"TARGET_5200"
"* return output_move_himode (operands);")
(define_expand "movstricthi"
- [(set (strict_low_part (match_operand:HI 0 "general_operand" ""))
+ [(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" ""))
(match_operand:HI 1 "general_src_operand" ""))]
""
"")
(define_insn ""
- [(set (strict_low_part (match_operand:HI 0 "general_operand" "+dm"))
+ [(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "+dm"))
(match_operand:HI 1 "general_src_operand" "rmSn"))]
"!TARGET_5200"
"* return output_move_stricthi (operands);")
(define_insn ""
- [(set (strict_low_part (match_operand:HI 0 "general_operand" "+d,m"))
+ [(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "+d,m"))
(match_operand:HI 1 "general_src_operand" "rmn,r"))]
"TARGET_5200"
"* return output_move_stricthi (operands);")
(define_expand "movqi"
- [(set (match_operand:QI 0 "general_operand" "")
+ [(set (match_operand:QI 0 "nonimmediate_operand" "")
(match_operand:QI 1 "general_src_operand" ""))]
""
"")
(define_insn ""
- [(set (match_operand:QI 0 "general_operand" "=d,*a,m")
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=d,*a,m")
(match_operand:QI 1 "general_src_operand" "dmSi*a,di*a,dmSi"))]
"!TARGET_5200"
"* return output_move_qimode (operands);")
(define_insn ""
- [(set (match_operand:QI 0 "general_operand" "=d<Q>,dm,d*a")
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=d<Q>,dm,d*a")
(match_operand:QI 1 "general_src_operand" "dmi,d<Q>,di*a"))]
"TARGET_5200"
"* return output_move_qimode (operands);")
(define_expand "movstrictqi"
- [(set (strict_low_part (match_operand:QI 0 "general_operand" ""))
+ [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" ""))
(match_operand:QI 1 "general_src_operand" ""))]
""
"")
(define_insn ""
- [(set (strict_low_part (match_operand:QI 0 "general_operand" "+dm"))
+ [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+dm"))
(match_operand:QI 1 "general_src_operand" "dmSn"))]
"!TARGET_5200"
"* return output_move_strictqi (operands);")
(define_insn ""
- [(set (strict_low_part (match_operand:QI 0 "general_operand" "+d,m"))
+ [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+d,m"))
(match_operand:QI 1 "general_src_operand" "dmn,d"))]
"TARGET_5200"
"* return output_move_strictqi (operands);")
(define_expand "movsf"
- [(set (match_operand:SF 0 "general_operand" "")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "")
(match_operand:SF 1 "general_operand" ""))]
""
"")
(define_insn ""
- [(set (match_operand:SF 0 "general_operand" "=rmf,x,y,rm,!x,!rm")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=rmf,x,y,rm,!x,!rm")
(match_operand:SF 1 "general_operand" "rmfF,xH,rmF,y,rm,x"))]
-; [(set (match_operand:SF 0 "general_operand" "=rmf")
+; [(set (match_operand:SF 0 "nonimmediate_operand" "=rmf")
; (match_operand:SF 1 "general_operand" "rmfF"))]
"!TARGET_5200"
"*
@@ -1170,23 +1170,23 @@
}")
(define_insn ""
- [(set (match_operand:SF 0 "general_operand" "=r,g")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=r,g")
(match_operand:SF 1 "general_operand" "g,r"))]
"TARGET_5200"
"* return \"move%.l %1,%0\";")
(define_expand "movdf"
- [(set (match_operand:DF 0 "general_operand" "")
+ [(set (match_operand:DF 0 "nonimmediate_operand" "")
(match_operand:DF 1 "general_operand" ""))]
""
"")
(define_insn ""
- [(set (match_operand:DF 0 "general_operand"
+ [(set (match_operand:DF 0 "nonimmediate_operand"
"=*rm,*rf,*rf,&*rof<>,y,*rm,x,!x,!*rm")
(match_operand:DF 1 "general_operand"
"*rf,m,0,*rofE<>,*rmE,y,xH,*rm,x"))]
-; [(set (match_operand:DF 0 "general_operand" "=rm,&rf,&rof<>")
+; [(set (match_operand:DF 0 "nonimmediate_operand" "=rm,&rf,&rof<>")
; (match_operand:DF 1 "general_operand" "rf,m,rofF<>"))]
"!TARGET_5200"
"*
@@ -1239,7 +1239,7 @@
}")
(define_insn ""
- [(set (match_operand:DF 0 "general_operand" "=r,g")
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=r,g")
(match_operand:DF 1 "general_operand" "g,r"))]
"TARGET_5200"
"* return output_move_double (operands);")
@@ -1359,7 +1359,7 @@
(define_expand "movdi"
;; Let's see if it really still needs to handle fp regs, and, if so, why.
- [(set (match_operand:DI 0 "general_operand" "")
+ [(set (match_operand:DI 0 "nonimmediate_operand" "")
(match_operand:DI 1 "general_operand" ""))]
""
"")
@@ -1367,11 +1367,11 @@
;; movdi can apply to fp regs in some cases
(define_insn ""
;; Let's see if it really still needs to handle fp regs, and, if so, why.
- [(set (match_operand:DI 0 "general_operand" "=rm,r,&ro<>,y,rm,!*x,!rm")
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r,&ro<>,y,rm,!*x,!rm")
(match_operand:DI 1 "general_operand" "rF,m,roi<>F,rmiF,y,rmF,*x"))]
-; [(set (match_operand:DI 0 "general_operand" "=rm,&r,&ro<>,!&rm,!&f,y,rm,x,!x,!rm")
+; [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,&r,&ro<>,!&rm,!&f,y,rm,x,!x,!rm")
; (match_operand:DI 1 "general_operand" "r,m,roi<>,fF,rfmF,rmi,y,rm,x"))]
-; [(set (match_operand:DI 0 "general_operand" "=rm,&rf,&ro<>,!&rm,!&f")
+; [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,&rf,&ro<>,!&rm,!&f")
; (match_operand:DI 1 "general_operand" "r,m,roi<>,fF,rfF"))]
"!TARGET_5200"
"*
@@ -1411,7 +1411,7 @@
}")
(define_insn ""
- [(set (match_operand:DI 0 "general_operand" "=r,g")
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,g")
(match_operand:DI 1 "general_operand" "g,r"))]
"TARGET_5200"
"* return output_move_double (operands);")
@@ -1429,7 +1429,7 @@
;; truncation instructions
(define_insn "truncsiqi2"
- [(set (match_operand:QI 0 "general_operand" "=dm,d")
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=dm,d")
(truncate:QI
(match_operand:SI 1 "general_src_operand" "doJS,i")))]
""
@@ -1448,7 +1448,7 @@
}")
(define_insn "trunchiqi2"
- [(set (match_operand:QI 0 "general_operand" "=dm,d")
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=dm,d")
(truncate:QI
(match_operand:HI 1 "general_src_operand" "doJS,i")))]
""
@@ -1476,7 +1476,7 @@
}")
(define_insn "truncsihi2"
- [(set (match_operand:HI 0 "general_operand" "=dm,d")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=dm,d")
(truncate:HI
(match_operand:SI 1 "general_src_operand" "roJS,i")))]
""
@@ -1497,7 +1497,7 @@
;; zero extension instructions
(define_insn "zero_extendqidi2"
- [(set (match_operand:DI 0 "general_operand" "=&d")
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=&d")
(zero_extend:DI (match_operand:QI 1 "general_operand" "dm")))]
""
"*
@@ -1508,7 +1508,7 @@
}")
(define_insn "zero_extendhidi2"
- [(set (match_operand:DI 0 "general_operand" "=&d")
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=&d")
(zero_extend:DI (match_operand:HI 1 "general_operand" "rm")))]
""
"*
@@ -1520,7 +1520,7 @@
;; this is the canonical form for (lshiftrt:DI x 32)
(define_insn "zero_extendsidi2"
- [(set (match_operand:DI 0 "general_operand" "=rm")
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
(zero_extend:DI (match_operand:SI 1 "general_operand" "rm")))]
""
"*
@@ -1597,7 +1597,7 @@
;; of this case will result in worse code than the uncombined patterns.
(define_insn ""
- [(set (match_operand:SI 0 "general_operand" "=do<>,d<")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=do<>,d<")
(zero_extend:SI (match_operand:HI 1 "nonimmediate_src_operand" "r,mS")))]
"GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
"*
@@ -1626,7 +1626,7 @@
}")
(define_insn ""
- [(set (match_operand:HI 0 "general_operand" "=do<>,d")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=do<>,d")
(zero_extend:HI (match_operand:QI 1 "nonimmediate_src_operand" "d,mS")))]
"GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
"*
@@ -1667,7 +1667,7 @@
}")
(define_insn ""
- [(set (match_operand:SI 0 "general_operand" "=do<>,d")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=do<>,d")
(zero_extend:SI (match_operand:QI 1 "nonimmediate_src_operand" "d,mS")))]
"GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
"*
@@ -1720,7 +1720,7 @@
;; sign extension instructions
(define_insn "extendqidi2"
- [(set (match_operand:DI 0 "general_operand" "=d")
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=d")
(sign_extend:DI (match_operand:QI 1 "general_src_operand" "rmS")))]
""
"*
@@ -1734,7 +1734,7 @@
}")
(define_insn "extendhidi2"
- [(set (match_operand:DI 0 "general_operand" "=d")
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=d")
(sign_extend:DI
(match_operand:HI 1 "general_src_operand" "rmS")))]
""
@@ -1749,7 +1749,7 @@
}")
(define_insn "extendsidi2"
- [(set (match_operand:DI 0 "general_operand" "=d")
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=d")
(sign_extend:DI
(match_operand:SI 1 "general_operand" "rm")))]
""
@@ -1796,7 +1796,7 @@
}")
(define_insn "extendhisi2"
- [(set (match_operand:SI 0 "general_operand" "=*d,a")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=*d,a")
(sign_extend:SI
(match_operand:HI 1 "nonimmediate_src_operand" "0,rmS")))]
""
@@ -1808,13 +1808,13 @@
}")
(define_insn "extendqihi2"
- [(set (match_operand:HI 0 "general_operand" "=d")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=d")
(sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "0")))]
""
"ext%.w %0")
(define_insn "extendqisi2"
- [(set (match_operand:SI 0 "general_operand" "=d")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
(sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "0")))]
"TARGET_68020 || TARGET_5200"
"extb%.l %0")
@@ -1822,21 +1822,21 @@
;; Conversions between float and double.
(define_expand "extendsfdf2"
- [(set (match_operand:DF 0 "general_operand" "")
+ [(set (match_operand:DF 0 "nonimmediate_operand" "")
(float_extend:DF
(match_operand:SF 1 "general_operand" "")))]
"TARGET_68881 || TARGET_FPA"
"")
(define_insn ""
- [(set (match_operand:DF 0 "general_operand" "=x,y")
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=x,y")
(float_extend:DF
(match_operand:SF 1 "general_operand" "xH,rmF")))]
"TARGET_FPA"
"fpstod %w1,%0")
(define_insn ""
- [(set (match_operand:DF 0 "general_operand" "=*fdm,f")
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=*fdm,f")
(float_extend:DF
(match_operand:SF 1 "general_operand" "f,dmF")))]
"TARGET_68881"
@@ -1869,14 +1869,14 @@
;; sure of truncating in that case.
;; But on the Sun FPA, we can be sure.
(define_expand "truncdfsf2"
- [(set (match_operand:SF 0 "general_operand" "")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "")
(float_truncate:SF
(match_operand:DF 1 "general_operand" "")))]
"TARGET_68881 || TARGET_FPA"
"")
(define_insn ""
- [(set (match_operand:SF 0 "general_operand" "=x,y")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=x,y")
(float_truncate:SF
(match_operand:DF 1 "general_operand" "xH,rmF")))]
"TARGET_FPA"
@@ -1884,7 +1884,7 @@
;; On the '040 we can truncate in a register accurately and easily.
(define_insn ""
- [(set (match_operand:SF 0 "general_operand" "=f")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=f")
(float_truncate:SF
(match_operand:DF 1 "general_operand" "fmG")))]
"TARGET_68040_ONLY"
@@ -1896,7 +1896,7 @@
}")
(define_insn ""
- [(set (match_operand:SF 0 "general_operand" "=dm")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=dm")
(float_truncate:SF
(match_operand:DF 1 "general_operand" "f")))]
"TARGET_68881"
@@ -1911,61 +1911,61 @@
;; rather than as QImode or HImode.
(define_expand "floatsisf2"
- [(set (match_operand:SF 0 "general_operand" "")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "")
(float:SF (match_operand:SI 1 "general_operand" "")))]
"TARGET_68881 || TARGET_FPA"
"")
(define_insn ""
- [(set (match_operand:SF 0 "general_operand" "=y,x")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=y,x")
(float:SF (match_operand:SI 1 "general_operand" "rmi,x")))]
"TARGET_FPA"
"fpltos %1,%0")
(define_insn ""
- [(set (match_operand:SF 0 "general_operand" "=f")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=f")
(float:SF (match_operand:SI 1 "general_operand" "dmi")))]
"TARGET_68881"
"f%$move%.l %1,%0")
(define_expand "floatsidf2"
- [(set (match_operand:DF 0 "general_operand" "")
+ [(set (match_operand:DF 0 "nonimmediate_operand" "")
(float:DF (match_operand:SI 1 "general_operand" "")))]
"TARGET_68881 || TARGET_FPA"
"")
(define_insn ""
- [(set (match_operand:DF 0 "general_operand" "=y,x")
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=y,x")
(float:DF (match_operand:SI 1 "general_operand" "rmi,x")))]
"TARGET_FPA"
"fpltod %1,%0")
(define_insn ""
- [(set (match_operand:DF 0 "general_operand" "=f")
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f")
(float:DF (match_operand:SI 1 "general_operand" "dmi")))]
"TARGET_68881"
"f%&move%.l %1,%0")
(define_insn "floathisf2"
- [(set (match_operand:SF 0 "general_operand" "=f")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=f")
(float:SF (match_operand:HI 1 "general_operand" "dmn")))]
"TARGET_68881"
"f%$move%.w %1,%0")
(define_insn "floathidf2"
- [(set (match_operand:DF 0 "general_operand" "=f")
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f")
(float:DF (match_operand:HI 1 "general_operand" "dmn")))]
"TARGET_68881"
"fmove%.w %1,%0")
(define_insn "floatqisf2"
- [(set (match_operand:SF 0 "general_operand" "=f")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=f")
(float:SF (match_operand:QI 1 "general_operand" "dmn")))]
"TARGET_68881"
"fmove%.b %1,%0")
(define_insn "floatqidf2"
- [(set (match_operand:DF 0 "general_operand" "=f")
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f")
(float:DF (match_operand:QI 1 "general_operand" "dmn")))]
"TARGET_68881"
"f%&move%.b %1,%0")
@@ -1976,7 +1976,7 @@
;; than calling the subroutines fixsfsi or fixdfsi.
(define_insn "fix_truncdfsi2"
- [(set (match_operand:SI 0 "general_operand" "=dm")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=dm")
(fix:SI (fix:DF (match_operand:DF 1 "register_operand" "f"))))
(clobber (match_scratch:SI 2 "=d"))
(clobber (match_scratch:SI 3 "=d"))]
@@ -1988,7 +1988,7 @@
}")
(define_insn "fix_truncdfhi2"
- [(set (match_operand:HI 0 "general_operand" "=dm")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=dm")
(fix:HI (fix:DF (match_operand:DF 1 "register_operand" "f"))))
(clobber (match_scratch:SI 2 "=d"))
(clobber (match_scratch:SI 3 "=d"))]
@@ -2000,7 +2000,7 @@
}")
(define_insn "fix_truncdfqi2"
- [(set (match_operand:QI 0 "general_operand" "=dm")
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=dm")
(fix:QI (fix:DF (match_operand:DF 1 "register_operand" "f"))))
(clobber (match_scratch:SI 2 "=d"))
(clobber (match_scratch:SI 3 "=d"))]
@@ -2015,7 +2015,7 @@
;; This is the first stage of converting it to an integer type.
(define_insn "ftruncdf2"
- [(set (match_operand:DF 0 "general_operand" "=f")
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f")
(fix:DF (match_operand:DF 1 "general_operand" "fFm")))]
"TARGET_68881 && !TARGET_68040"
"*
@@ -2026,7 +2026,7 @@
}")
(define_insn "ftruncsf2"
- [(set (match_operand:SF 0 "general_operand" "=f")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=f")
(fix:SF (match_operand:SF 1 "general_operand" "dfFm")))]
"TARGET_68881 && !TARGET_68040"
"*
@@ -2039,37 +2039,37 @@
;; Convert a float whose value is an integer
;; to an actual integer. Second stage of converting float to integer type.
(define_insn "fixsfqi2"
- [(set (match_operand:QI 0 "general_operand" "=dm")
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=dm")
(fix:QI (match_operand:SF 1 "general_operand" "f")))]
"TARGET_68881"
"fmove%.b %1,%0")
(define_insn "fixsfhi2"
- [(set (match_operand:HI 0 "general_operand" "=dm")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=dm")
(fix:HI (match_operand:SF 1 "general_operand" "f")))]
"TARGET_68881"
"fmove%.w %1,%0")
(define_insn "fixsfsi2"
- [(set (match_operand:SI 0 "general_operand" "=dm")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=dm")
(fix:SI (match_operand:SF 1 "general_operand" "f")))]
"TARGET_68881"
"fmove%.l %1,%0")
(define_insn "fixdfqi2"
- [(set (match_operand:QI 0 "general_operand" "=dm")
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=dm")
(fix:QI (match_operand:DF 1 "general_operand" "f")))]
"TARGET_68881"
"fmove%.b %1,%0")
(define_insn "fixdfhi2"
- [(set (match_operand:HI 0 "general_operand" "=dm")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=dm")
(fix:HI (match_operand:DF 1 "general_operand" "f")))]
"TARGET_68881"
"fmove%.w %1,%0")
(define_insn "fixdfsi2"
- [(set (match_operand:SI 0 "general_operand" "=dm")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=dm")
(fix:SI (match_operand:DF 1 "general_operand" "f")))]
"TARGET_68881"
"fmove%.l %1,%0")
@@ -2078,13 +2078,13 @@
;; On the Sun FPA, this is done in one step.
(define_insn ""
- [(set (match_operand:SI 0 "general_operand" "=x,y")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=x,y")
(fix:SI (fix:SF (match_operand:SF 1 "general_operand" "xH,rmF"))))]
"TARGET_FPA"
"fpstol %w1,%0")
(define_insn ""
- [(set (match_operand:SI 0 "general_operand" "=x,y")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=x,y")
(fix:SI (fix:DF (match_operand:DF 1 "general_operand" "xH,rmF"))))]
"TARGET_FPA"
"fpdtol %y1,%0")
@@ -2092,7 +2092,7 @@
;; add instructions
(define_insn "adddi_lshrdi_63"
- [(set (match_operand:DI 0 "general_operand" "=d")
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=d")
(plus:DI (lshiftrt:DI (match_operand:DI 1 "general_operand" "rm")
(const_int 63))
(match_dup 1)))
@@ -2126,7 +2126,7 @@
}")
(define_insn "adddi_sexthishl32"
- [(set (match_operand:DI 0 "general_operand" "=o,a,*d,*d")
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=o,a,*d,*d")
(plus:DI (ashift:DI (sign_extend:DI
(match_operand:HI 1 "general_operand" "rm,rm,rm,rm"))
(const_int 32))
@@ -2145,7 +2145,7 @@
} ")
(define_insn "adddi_dilshr32"
- [(set (match_operand:DI 0 "general_operand" "=d,o")
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=d,o")
;; (plus:DI (match_operand:DI 2 "general_operand" "%0")
;; (lshiftrt:DI (match_operand:DI 1 "general_operand" "ro")
;; (const_int 32))))]
@@ -2164,7 +2164,7 @@
} ")
(define_insn "adddi_dishl32"
- [(set (match_operand:DI 0 "general_operand" "=r,o")
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o")
;; (plus:DI (match_operand:DI 2 "general_operand" "%0")
;; (ashift:DI (match_operand:DI 1 "general_operand" "ro")
;; (const_int 32))))]
@@ -2183,7 +2183,7 @@
} ")
(define_insn "adddi3"
- [(set (match_operand:DI 0 "general_operand" "=<,o<>,d,d,d")
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=<,o<>,d,d,d")
(plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,0,0")
(match_operand:DI 2 "general_operand" "<,d,no>,d,a")))
(clobber (match_scratch:SI 3 "=X,&d,&d,X,&d"))]
@@ -2275,7 +2275,7 @@
} ")
(define_insn "addsi_lshrsi_31"
- [(set (match_operand:SI 0 "general_operand" "=dm")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=dm")
(plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "rm")
(const_int 31))
(match_dup 1)))]
@@ -2308,7 +2308,7 @@
}")
(define_expand "addsi3"
- [(set (match_operand:SI 0 "general_operand" "")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "")
(plus:SI (match_operand:SI 1 "general_operand" "")
(match_operand:SI 2 "general_src_operand" "")))]
""
@@ -2319,7 +2319,7 @@
;; This is needed since they are not themselves reloaded,
;; so commutativity won't apply to them.
(define_insn "*addsi3_internal"
- [(set (match_operand:SI 0 "general_operand" "=m,?a,?a,d,a")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=m,?a,?a,d,a")
(plus:SI (match_operand:SI 1 "general_operand" "%0,a,rJK,0,0")
(match_operand:SI 2 "general_src_operand" "dIKLT,rJK,a,mSrIKLT,mSrIKLs")))]
@@ -2328,14 +2328,14 @@
"* return output_addsi3 (operands);")
(define_insn "*addsi3_5200"
- [(set (match_operand:SI 0 "general_operand" "=m,?a,?a,r")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=m,?a,?a,r")
(plus:SI (match_operand:SI 1 "general_operand" "%0,a,rJK,0")
(match_operand:SI 2 "general_src_operand" "d,rJK,a,mrIKLs")))]
"TARGET_5200"
"* return output_addsi3 (operands);")
(define_insn ""
- [(set (match_operand:SI 0 "general_operand" "=a")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=a")
(plus:SI (match_operand:SI 1 "general_operand" "0")
(sign_extend:SI
(match_operand:HI 2 "nonimmediate_src_operand" "rmS"))))]
@@ -2343,7 +2343,7 @@
"add%.w %2,%0")
(define_insn "addhi3"
- [(set (match_operand:HI 0 "general_operand" "=m,r")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=m,r")
(plus:HI (match_operand:HI 1 "general_operand" "%0,0")
(match_operand:HI 2 "general_src_operand" "dn,rmSn")))]
"!TARGET_5200"
@@ -2405,7 +2405,7 @@
;; operand in both positions.
(define_insn ""
- [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
+ [(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "+m,d"))
(plus:HI (match_dup 0)
(match_operand:HI 1 "general_src_operand" "dn,rmSn")))]
"!TARGET_5200"
@@ -2461,7 +2461,7 @@
}")
(define_insn ""
- [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
+ [(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "+m,d"))
(plus:HI (match_operand:HI 1 "general_src_operand" "dn,rmSn")
(match_dup 0)))]
"!TARGET_5200"
@@ -2517,7 +2517,7 @@
}")
(define_insn "addqi3"
- [(set (match_operand:QI 0 "general_operand" "=m,d")
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=m,d")
(plus:QI (match_operand:QI 1 "general_operand" "%0,0")
(match_operand:QI 2 "general_src_operand" "dn,dmSn")))]
"!TARGET_5200"
@@ -2543,7 +2543,7 @@
}")
(define_insn ""
- [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
+ [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+m,d"))
(plus:QI (match_dup 0)
(match_operand:QI 1 "general_src_operand" "dn,dmSn")))]
"!TARGET_5200"
@@ -2569,7 +2569,7 @@
}")
(define_insn ""
- [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
+ [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+m,d"))
(plus:QI (match_operand:QI 1 "general_src_operand" "dn,dmSn")
(match_dup 0)))]
"!TARGET_5200"
@@ -2595,14 +2595,14 @@
}")
(define_expand "adddf3"
- [(set (match_operand:DF 0 "general_operand" "")
+ [(set (match_operand:DF 0 "nonimmediate_operand" "")
(plus:DF (match_operand:DF 1 "general_operand" "")
(match_operand:DF 2 "general_operand" "")))]
"TARGET_68881 || TARGET_FPA"
"")
(define_insn ""
- [(set (match_operand:DF 0 "general_operand" "=x,y")
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=x,y")
(plus:DF (match_operand:DF 1 "general_operand" "%xH,y")
(match_operand:DF 2 "general_operand" "xH,dmF")))]
"TARGET_FPA"
@@ -2618,28 +2618,28 @@
}")
(define_insn ""
- [(set (match_operand:DF 0 "general_operand" "=f")
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f")
(plus:DF (float:DF (match_operand:SI 2 "general_operand" "dmi"))
(match_operand:DF 1 "general_operand" "0")))]
"TARGET_68881"
"f%&add%.l %2,%0")
(define_insn ""
- [(set (match_operand:DF 0 "general_operand" "=f")
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f")
(plus:DF (float:DF (match_operand:HI 2 "general_operand" "dmn"))
(match_operand:DF 1 "general_operand" "0")))]
"TARGET_68881"
"f%&add%.w %2,%0")
(define_insn ""
- [(set (match_operand:DF 0 "general_operand" "=f")
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f")
(plus:DF (float:DF (match_operand:QI 2 "general_operand" "dmn"))
(match_operand:DF 1 "general_operand" "0")))]
"TARGET_68881"
"f%&add%.b %2,%0")
(define_insn ""
- [(set (match_operand:DF 0 "general_operand" "=f")
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f")
(plus:DF (match_operand:DF 1 "general_operand" "%0")
(match_operand:DF 2 "general_operand" "fmG")))]
"TARGET_68881"
@@ -2651,14 +2651,14 @@
}")
(define_expand "addsf3"
- [(set (match_operand:SF 0 "general_operand" "")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "")
(plus:SF (match_operand:SF 1 "general_operand" "")
(match_operand:SF 2 "general_operand" "")))]
"TARGET_68881 || TARGET_FPA"
"")
(define_insn ""
- [(set (match_operand:SF 0 "general_operand" "=x,y")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=x,y")
(plus:SF (match_operand:SF 1 "general_operand" "%xH,y")
(match_operand:SF 2 "general_operand" "xH,rmF")))]
"TARGET_FPA"
@@ -2674,28 +2674,28 @@
}")
(define_insn ""
- [(set (match_operand:SF 0 "general_operand" "=f")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=f")
(plus:SF (float:SF (match_operand:SI 2 "general_operand" "dmi"))
(match_operand:SF 1 "general_operand" "0")))]
"TARGET_68881"
"f%$add%.l %2,%0")
(define_insn ""
- [(set (match_operand:SF 0 "general_operand" "=f")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=f")
(plus:SF (float:SF (match_operand:HI 2 "general_operand" "dmn"))
(match_operand:SF 1 "general_operand" "0")))]
"TARGET_68881"
"f%$add%.w %2,%0")
(define_insn ""
- [(set (match_operand:SF 0 "general_operand" "=f")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=f")
(plus:SF (float:SF (match_operand:QI 2 "general_operand" "dmn"))
(match_operand:SF 1 "general_operand" "0")))]
"TARGET_68881"
"f%$add%.b %2,%0")
(define_insn ""
- [(set (match_operand:SF 0 "general_operand" "=f")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=f")
(plus:SF (match_operand:SF 1 "general_operand" "%0")
(match_operand:SF 2 "general_operand" "fdmF")))]
"TARGET_68881"
@@ -2709,7 +2709,7 @@
;; subtract instructions
(define_insn "subdi_sexthishl32"
- [(set (match_operand:DI 0 "general_operand" "=o,a,*d,*d")
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=o,a,*d,*d")
(minus:DI (match_operand:DI 1 "general_operand" "0,0,0,0")
(ashift:DI (sign_extend:DI (match_operand:HI 2 "general_operand" "rm,rm,rm,rm"))
(const_int 32))))
@@ -2727,7 +2727,7 @@
} ")
(define_insn "subdi_dishl32"
- [(set (match_operand:DI 0 "general_operand" "+ro")
+ [(set (match_operand:DI 0 "nonimmediate_operand" "+ro")
(minus:DI (match_dup 0)
(ashift:DI (match_operand:DI 1 "general_operand" "ro")
(const_int 32))))]
@@ -2743,7 +2743,7 @@
} ")
(define_insn "subdi3"
- [(set (match_operand:DI 0 "general_operand" "=<,o<>,d,d,d")
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=<,o<>,d,d,d")
(minus:DI (match_operand:DI 1 "general_operand" "0,0,0,0,0")
(match_operand:DI 2 "general_operand" "<,d,no>,d,a")))
(clobber (match_scratch:SI 3 "=X,&d,&d,X,&d"))]
@@ -2837,14 +2837,14 @@
} ")
(define_insn "subsi3"
- [(set (match_operand:SI 0 "general_operand" "=m,d,a")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=m,d,a")
(minus:SI (match_operand:SI 1 "general_operand" "0,0,0")
(match_operand:SI 2 "general_src_operand" "dT,mSrT,mSrs")))]
""
"sub%.l %2,%0")
(define_insn ""
- [(set (match_operand:SI 0 "general_operand" "=a")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=a")
(minus:SI (match_operand:SI 1 "general_operand" "0")
(sign_extend:SI
(match_operand:HI 2 "nonimmediate_src_operand" "rmS"))))]
@@ -2852,42 +2852,42 @@
"sub%.w %2,%0")
(define_insn "subhi3"
- [(set (match_operand:HI 0 "general_operand" "=m,r")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=m,r")
(minus:HI (match_operand:HI 1 "general_operand" "0,0")
(match_operand:HI 2 "general_src_operand" "dn,rmSn")))]
"!TARGET_5200"
"sub%.w %2,%0")
(define_insn ""
- [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
+ [(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "+m,d"))
(minus:HI (match_dup 0)
(match_operand:HI 1 "general_src_operand" "dn,rmSn")))]
"!TARGET_5200"
"sub%.w %1,%0")
(define_insn "subqi3"
- [(set (match_operand:QI 0 "general_operand" "=m,d")
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=m,d")
(minus:QI (match_operand:QI 1 "general_operand" "0,0")
(match_operand:QI 2 "general_src_operand" "dn,dmSn")))]
"!TARGET_5200"
"sub%.b %2,%0")
(define_insn ""
- [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
+ [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+m,d"))
(minus:QI (match_dup 0)
(match_operand:QI 1 "general_src_operand" "dn,dmSn")))]
"!TARGET_5200"
"sub%.b %1,%0")
(define_expand "subdf3"
- [(set (match_operand:DF 0 "general_operand" "")
+ [(set (match_operand:DF 0 "nonimmediate_operand" "")
(minus:DF (match_operand:DF 1 "general_operand" "")
(match_operand:DF 2 "general_operand" "")))]
"TARGET_68881 || TARGET_FPA"
"")
(define_insn ""
- [(set (match_operand:DF 0 "general_operand" "=x,y,y")
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=x,y,y")
(minus:DF (match_operand:DF 1 "general_operand" "xH,y,dmF")
(match_operand:DF 2 "general_operand" "xH,dmF,0")))]
"TARGET_FPA"
@@ -2903,28 +2903,28 @@
}")
(define_insn ""
- [(set (match_operand:DF 0 "general_operand" "=f")
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f")
(minus:DF (match_operand:DF 1 "general_operand" "0")
(float:DF (match_operand:SI 2 "general_operand" "dmi"))))]
"TARGET_68881"
"f%&sub%.l %2,%0")
(define_insn ""
- [(set (match_operand:DF 0 "general_operand" "=f")
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f")
(minus:DF (match_operand:DF 1 "general_operand" "0")
(float:DF (match_operand:HI 2 "general_operand" "dmn"))))]
"TARGET_68881"
"f%&sub%.w %2,%0")
(define_insn ""
- [(set (match_operand:DF 0 "general_operand" "=f")
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f")
(minus:DF (match_operand:DF 1 "general_operand" "0")
(float:DF (match_operand:QI 2 "general_operand" "dmn"))))]
"TARGET_68881"
"f%&sub%.b %2,%0")
(define_insn ""
- [(set (match_operand:DF 0 "general_operand" "=f")
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f")
(minus:DF (match_operand:DF 1 "general_operand" "0")
(match_operand:DF 2 "general_operand" "fmG")))]
"TARGET_68881"
@@ -2936,14 +2936,14 @@
}")
(define_expand "subsf3"
- [(set (match_operand:SF 0 "general_operand" "")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "")
(minus:SF (match_operand:SF 1 "general_operand" "")
(match_operand:SF 2 "general_operand" "")))]
"TARGET_68881 || TARGET_FPA"
"")
(define_insn ""
- [(set (match_operand:SF 0 "general_operand" "=x,y,y")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=x,y,y")
(minus:SF (match_operand:SF 1 "general_operand" "xH,y,rmF")
(match_operand:SF 2 "general_operand" "xH,rmF,0")))]
"TARGET_FPA"
@@ -2959,28 +2959,28 @@
}")
(define_insn ""
- [(set (match_operand:SF 0 "general_operand" "=f")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=f")
(minus:SF (match_operand:SF 1 "general_operand" "0")
(float:SF (match_operand:SI 2 "general_operand" "dmi"))))]
"TARGET_68881"
"f%$sub%.l %2,%0")
(define_insn ""
- [(set (match_operand:SF 0 "general_operand" "=f")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=f")
(minus:SF (match_operand:SF 1 "general_operand" "0")
(float:SF (match_operand:HI 2 "general_operand" "dmn"))))]
"TARGET_68881"
"f%$sub%.w %2,%0")
(define_insn ""
- [(set (match_operand:SF 0 "general_operand" "=f")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=f")
(minus:SF (match_operand:SF 1 "general_operand" "0")
(float:SF (match_operand:QI 2 "general_operand" "dmn"))))]
"TARGET_68881"
"f%$sub%.b %2,%0")
(define_insn ""
- [(set (match_operand:SF 0 "general_operand" "=f")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=f")
(minus:SF (match_operand:SF 1 "general_operand" "0")
(match_operand:SF 2 "general_operand" "fdmF")))]
"TARGET_68881"
@@ -2994,7 +2994,7 @@
;; multiply instructions
(define_insn "mulhi3"
- [(set (match_operand:HI 0 "general_operand" "=d")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=d")
(mult:HI (match_operand:HI 1 "general_operand" "%0")
(match_operand:HI 2 "general_src_operand" "dmSn")))]
""
@@ -3008,7 +3008,7 @@
}")
(define_insn "mulhisi3"
- [(set (match_operand:SI 0 "general_operand" "=d")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
(mult:SI (sign_extend:SI
(match_operand:HI 1 "nonimmediate_operand" "%0"))
(sign_extend:SI
@@ -3024,7 +3024,7 @@
}")
(define_insn ""
- [(set (match_operand:SI 0 "general_operand" "=d")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
(mult:SI (sign_extend:SI
(match_operand:HI 1 "nonimmediate_operand" "%0"))
(match_operand:SI 2 "const_int_operand" "n")))]
@@ -3039,14 +3039,14 @@
}")
(define_expand "mulsi3"
- [(set (match_operand:SI 0 "general_operand" "")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "")
(mult:SI (match_operand:SI 1 "general_operand" "")
(match_operand:SI 2 "general_operand" "")))]
"TARGET_68020 || TARGET_5200"
"")
(define_insn ""
- [(set (match_operand:SI 0 "general_operand" "=d")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
(mult:SI (match_operand:SI 1 "general_operand" "%0")
(match_operand:SI 2 "general_src_operand" "dmSTK")))]
@@ -3054,14 +3054,14 @@
"muls%.l %2,%0")
(define_insn ""
- [(set (match_operand:SI 0 "general_operand" "=d")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
(mult:SI (match_operand:SI 1 "general_operand" "%0")
(match_operand:SI 2 "general_operand" "d<Q>")))]
"TARGET_5200"
"muls%.l %2,%0")
(define_insn "umulhisi3"
- [(set (match_operand:SI 0 "general_operand" "=d")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
(mult:SI (zero_extend:SI
(match_operand:HI 1 "nonimmediate_operand" "%0"))
(zero_extend:SI
@@ -3077,7 +3077,7 @@
}")
(define_insn ""
- [(set (match_operand:SI 0 "general_operand" "=d")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
(mult:SI (zero_extend:SI
(match_operand:HI 1 "nonimmediate_operand" "%0"))
(match_operand:SI 2 "const_int_operand" "n")))]
@@ -3262,14 +3262,14 @@
"muls%.l %3,%0:%1")
(define_expand "muldf3"
- [(set (match_operand:DF 0 "general_operand" "")
+ [(set (match_operand:DF 0 "nonimmediate_operand" "")
(mult:DF (match_operand:DF 1 "general_operand" "")
(match_operand:DF 2 "general_operand" "")))]
"TARGET_68881 || TARGET_FPA"
"")
(define_insn ""
- [(set (match_operand:DF 0 "general_operand" "=x,y")
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=x,y")
(mult:DF (match_operand:DF 1 "general_operand" "%xH,y")
(match_operand:DF 2 "general_operand" "xH,rmF")))]
"TARGET_FPA"
@@ -3287,28 +3287,28 @@
}")
(define_insn ""
- [(set (match_operand:DF 0 "general_operand" "=f")
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f")
(mult:DF (float:DF (match_operand:SI 2 "general_operand" "dmi"))
(match_operand:DF 1 "general_operand" "0")))]
"TARGET_68881"
"f%&mul%.l %2,%0")
(define_insn ""
- [(set (match_operand:DF 0 "general_operand" "=f")
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f")
(mult:DF (float:DF (match_operand:HI 2 "general_operand" "dmn"))
(match_operand:DF 1 "general_operand" "0")))]
"TARGET_68881"
"f%&mul%.w %2,%0")
(define_insn ""
- [(set (match_operand:DF 0 "general_operand" "=f")
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f")
(mult:DF (float:DF (match_operand:QI 2 "general_operand" "dmn"))
(match_operand:DF 1 "general_operand" "0")))]
"TARGET_68881"
"f%&mul%.b %2,%0")
(define_insn ""
- [(set (match_operand:DF 0 "general_operand" "=f")
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f")
(mult:DF (match_operand:DF 1 "general_operand" "%0")
(match_operand:DF 2 "general_operand" "fmG")))]
"TARGET_68881"
@@ -3327,14 +3327,14 @@
}")
(define_expand "mulsf3"
- [(set (match_operand:SF 0 "general_operand" "")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "")
(mult:SF (match_operand:SF 1 "general_operand" "")
(match_operand:SF 2 "general_operand" "")))]
"TARGET_68881 || TARGET_FPA"
"")
(define_insn ""
- [(set (match_operand:SF 0 "general_operand" "=x,y")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=x,y")
(mult:SF (match_operand:SF 1 "general_operand" "%xH,y")
(match_operand:SF 2 "general_operand" "xH,rmF")))]
"TARGET_FPA"
@@ -3352,7 +3352,7 @@
}")
(define_insn ""
- [(set (match_operand:SF 0 "general_operand" "=f")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=f")
(mult:SF (float:SF (match_operand:SI 2 "general_operand" "dmi"))
(match_operand:SF 1 "general_operand" "0")))]
"TARGET_68881"
@@ -3364,7 +3364,7 @@
}")
(define_insn ""
- [(set (match_operand:SF 0 "general_operand" "=f")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=f")
(mult:SF (float:SF (match_operand:HI 2 "general_operand" "dmn"))
(match_operand:SF 1 "general_operand" "0")))]
"TARGET_68881"
@@ -3376,7 +3376,7 @@
}")
(define_insn ""
- [(set (match_operand:SF 0 "general_operand" "=f")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=f")
(mult:SF (float:SF (match_operand:QI 2 "general_operand" "dmn"))
(match_operand:SF 1 "general_operand" "0")))]
"TARGET_68881"
@@ -3388,7 +3388,7 @@
}")
(define_insn ""
- [(set (match_operand:SF 0 "general_operand" "=f")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=f")
(mult:SF (match_operand:SF 1 "general_operand" "%0")
(match_operand:SF 2 "general_operand" "fdmF")))]
"TARGET_68881"
@@ -3413,14 +3413,14 @@
;; divide instructions
(define_expand "divdf3"
- [(set (match_operand:DF 0 "general_operand" "")
+ [(set (match_operand:DF 0 "nonimmediate_operand" "")
(div:DF (match_operand:DF 1 "general_operand" "")
(match_operand:DF 2 "general_operand" "")))]
"TARGET_68881 || TARGET_FPA"
"")
(define_insn ""
- [(set (match_operand:DF 0 "general_operand" "=x,y,y")
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=x,y,y")
(div:DF (match_operand:DF 1 "general_operand" "xH,y,rmF")
(match_operand:DF 2 "general_operand" "xH,rmF,0")))]
"TARGET_FPA"
@@ -3436,28 +3436,28 @@
}")
(define_insn ""
- [(set (match_operand:DF 0 "general_operand" "=f")
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f")
(div:DF (match_operand:DF 1 "general_operand" "0")
(float:DF (match_operand:SI 2 "general_operand" "dmi"))))]
"TARGET_68881"
"f%&div%.l %2,%0")
(define_insn ""
- [(set (match_operand:DF 0 "general_operand" "=f")
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f")
(div:DF (match_operand:DF 1 "general_operand" "0")
(float:DF (match_operand:HI 2 "general_operand" "dmn"))))]
"TARGET_68881"
"f%&div%.w %2,%0")
(define_insn ""
- [(set (match_operand:DF 0 "general_operand" "=f")
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f")
(div:DF (match_operand:DF 1 "general_operand" "0")
(float:DF (match_operand:QI 2 "general_operand" "dmn"))))]
"TARGET_68881"
"f%&div%.b %2,%0")
(define_insn ""
- [(set (match_operand:DF 0 "general_operand" "=f")
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f")
(div:DF (match_operand:DF 1 "general_operand" "0")
(match_operand:DF 2 "general_operand" "fmG")))]
"TARGET_68881"
@@ -3469,14 +3469,14 @@
}")
(define_expand "divsf3"
- [(set (match_operand:SF 0 "general_operand" "")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "")
(div:SF (match_operand:SF 1 "general_operand" "")
(match_operand:SF 2 "general_operand" "")))]
"TARGET_68881 || TARGET_FPA"
"")
(define_insn ""
- [(set (match_operand:SF 0 "general_operand" "=x,y,y")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=x,y,y")
(div:SF (match_operand:SF 1 "general_operand" "xH,y,rmF")
(match_operand:SF 2 "general_operand" "xH,rmF,0")))]
"TARGET_FPA"
@@ -3492,7 +3492,7 @@
}")
(define_insn ""
- [(set (match_operand:SF 0 "general_operand" "=f")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=f")
(div:SF (match_operand:SF 1 "general_operand" "0")
(float:SF (match_operand:SI 2 "general_operand" "dmi"))))]
"TARGET_68881"
@@ -3504,7 +3504,7 @@
}")
(define_insn ""
- [(set (match_operand:SF 0 "general_operand" "=f")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=f")
(div:SF (match_operand:SF 1 "general_operand" "0")
(float:SF (match_operand:HI 2 "general_operand" "dmn"))))]
"TARGET_68881"
@@ -3516,7 +3516,7 @@
}")
(define_insn ""
- [(set (match_operand:SF 0 "general_operand" "=f")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=f")
(div:SF (match_operand:SF 1 "general_operand" "0")
(float:SF (match_operand:QI 2 "general_operand" "dmn"))))]
"TARGET_68881"
@@ -3528,7 +3528,7 @@
}")
(define_insn ""
- [(set (match_operand:SF 0 "general_operand" "=f")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=f")
(div:SF (match_operand:SF 1 "general_operand" "0")
(match_operand:SF 2 "general_operand" "fdmF")))]
"TARGET_68881"
@@ -3553,10 +3553,10 @@
;; Remainder instructions.
(define_insn "divmodsi4"
- [(set (match_operand:SI 0 "general_operand" "=d")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
(div:SI (match_operand:SI 1 "general_operand" "0")
(match_operand:SI 2 "general_src_operand" "dmSTK")))
- (set (match_operand:SI 3 "general_operand" "=d")
+ (set (match_operand:SI 3 "nonimmediate_operand" "=d")
(mod:SI (match_dup 1) (match_dup 2)))]
"TARGET_68020 && !TARGET_5200"
"*
@@ -3568,10 +3568,10 @@
}")
(define_insn "udivmodsi4"
- [(set (match_operand:SI 0 "general_operand" "=d")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
(udiv:SI (match_operand:SI 1 "general_operand" "0")
(match_operand:SI 2 "general_src_operand" "dmSTK")))
- (set (match_operand:SI 3 "general_operand" "=d")
+ (set (match_operand:SI 3 "nonimmediate_operand" "=d")
(umod:SI (match_dup 1) (match_dup 2)))]
"TARGET_68020 && !TARGET_5200"
"*
@@ -3583,10 +3583,10 @@
}")
(define_insn "divmodhi4"
- [(set (match_operand:HI 0 "general_operand" "=d")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=d")
(div:HI (match_operand:HI 1 "general_operand" "0")
(match_operand:HI 2 "general_src_operand" "dmSKT")))
- (set (match_operand:HI 3 "general_operand" "=d")
+ (set (match_operand:HI 3 "nonimmediate_operand" "=d")
(mod:HI (match_dup 1) (match_dup 2)))]
"!TARGET_5200"
"*
@@ -3606,10 +3606,10 @@
}")
(define_insn "udivmodhi4"
- [(set (match_operand:HI 0 "general_operand" "=d")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=d")
(udiv:HI (match_operand:HI 1 "general_operand" "0")
(match_operand:HI 2 "general_src_operand" "dmSKT")))
- (set (match_operand:HI 3 "general_operand" "=d")
+ (set (match_operand:HI 3 "nonimmediate_operand" "=d")
(umod:HI (match_dup 1) (match_dup 2)))]
"!TARGET_5200"
"*
@@ -3632,7 +3632,7 @@
;; "anddi3" is mainly here to help combine().
(define_insn "anddi3"
- [(set (match_operand:DI 0 "general_operand" "=o,d")
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=o,d")
(and:DI (match_operand:DI 1 "general_operand" "%0,0")
(match_operand:DI 2 "general_operand" "dn,don")))]
"!TARGET_5200"
@@ -3726,42 +3726,42 @@
"and%.l %2,%0")
(define_insn "andhi3"
- [(set (match_operand:HI 0 "general_operand" "=m,d")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=m,d")
(and:HI (match_operand:HI 1 "general_operand" "%0,0")
(match_operand:HI 2 "general_src_operand" "dn,dmSn")))]
"!TARGET_5200"
"and%.w %2,%0")
(define_insn ""
- [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
+ [(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "+m,d"))
(and:HI (match_dup 0)
(match_operand:HI 1 "general_src_operand" "dn,dmSn")))]
"!TARGET_5200"
"and%.w %1,%0")
(define_insn ""
- [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
+ [(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "+m,d"))
(and:HI (match_operand:HI 1 "general_src_operand" "dn,dmSn")
(match_dup 0)))]
"!TARGET_5200"
"and%.w %1,%0")
(define_insn "andqi3"
- [(set (match_operand:QI 0 "general_operand" "=m,d")
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=m,d")
(and:QI (match_operand:QI 1 "general_operand" "%0,0")
(match_operand:QI 2 "general_src_operand" "dn,dmSn")))]
"!TARGET_5200"
"and%.b %2,%0")
(define_insn ""
- [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
+ [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+m,d"))
(and:QI (match_dup 0)
(match_operand:QI 1 "general_src_operand" "dn,dmSn")))]
"!TARGET_5200"
"and%.b %1,%0")
(define_insn ""
- [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
+ [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+m,d"))
(and:QI (match_operand:QI 1 "general_src_operand" "dn,dmSn")
(match_dup 0)))]
"!TARGET_5200"
@@ -3770,7 +3770,7 @@
;; inclusive-or instructions
(define_insn "iordi_zext"
- [(set (match_operand:DI 0 "general_operand" "=o,d")
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=o,d")
(ior:DI (zero_extend:DI (match_operand 1 "general_operand" "dn,dmn"))
(match_operand:DI 2 "general_operand" "0,0")))]
"!TARGET_5200"
@@ -3796,7 +3796,7 @@
;; "iordi3" is mainly here to help combine().
(define_insn "iordi3"
- [(set (match_operand:DI 0 "general_operand" "=o,d")
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=o,d")
(ior:DI (match_operand:DI 1 "general_operand" "%0,0")
(match_operand:DI 2 "general_operand" "dn,don")))]
"!TARGET_5200"
@@ -3866,14 +3866,14 @@
}")
(define_expand "iorsi3"
- [(set (match_operand:SI 0 "general_operand" "")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "")
(ior:SI (match_operand:SI 1 "general_operand" "")
(match_operand:SI 2 "general_src_operand" "")))]
""
"")
(define_insn "iorsi3_internal"
- [(set (match_operand:SI 0 "general_operand" "=m,d")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=m,d")
(ior:SI (match_operand:SI 1 "general_operand" "%0,0")
(match_operand:SI 2 "general_src_operand" "dKT,dmSMT")))]
"! TARGET_5200"
@@ -3883,49 +3883,49 @@
}")
(define_insn "iorsi3_5200"
- [(set (match_operand:SI 0 "general_operand" "=m,d")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=m,d")
(ior:SI (match_operand:SI 1 "general_operand" "%0,0")
(match_operand:SI 2 "general_src_operand" "d,dmsK")))]
"TARGET_5200"
"or%.l %2,%0")
(define_insn "iorhi3"
- [(set (match_operand:HI 0 "general_operand" "=m,d")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=m,d")
(ior:HI (match_operand:HI 1 "general_operand" "%0,0")
(match_operand:HI 2 "general_src_operand" "dn,dmSn")))]
"!TARGET_5200"
"or%.w %2,%0")
(define_insn ""
- [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
+ [(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "+m,d"))
(ior:HI (match_dup 0)
(match_operand:HI 1 "general_src_operand" "dn,dmSn")))]
"!TARGET_5200"
"or%.w %1,%0")
(define_insn ""
- [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
+ [(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "+m,d"))
(ior:HI (match_operand:HI 1 "general_src_operand" "dn,dmSn")
(match_dup 0)))]
"!TARGET_5200"
"or%.w %1,%0")
(define_insn "iorqi3"
- [(set (match_operand:QI 0 "general_operand" "=m,d")
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=m,d")
(ior:QI (match_operand:QI 1 "general_operand" "%0,0")
(match_operand:QI 2 "general_src_operand" "dn,dmSn")))]
"!TARGET_5200"
"or%.b %2,%0")
(define_insn ""
- [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
+ [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+m,d"))
(ior:QI (match_dup 0)
(match_operand:QI 1 "general_src_operand" "dn,dmSn")))]
"!TARGET_5200"
"or%.b %1,%0")
(define_insn ""
- [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
+ [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+m,d"))
(ior:QI (match_operand:QI 1 "general_src_operand" "dn,dmSn")
(match_dup 0)))]
"!TARGET_5200"
@@ -3935,7 +3935,7 @@
;; See also ashlsi_16, ashrsi_16 and lshrsi_16.
(define_insn "iorsi_zexthi_ashl16"
- [(set (match_operand:SI 0 "general_operand" "=&d")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=&d")
(ior:SI (zero_extend:SI (match_operand:HI 1 "general_operand" "rmn"))
(ashift:SI (match_operand:SI 2 "general_operand" "or")
(const_int 16))))]
@@ -3952,7 +3952,7 @@
}")
(define_insn "iorsi_zext"
- [(set (match_operand:SI 0 "general_operand" "=o,d")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=o,d")
(ior:SI (zero_extend:SI (match_operand 1 "general_operand" "dn,dmn"))
(match_operand:SI 2 "general_operand" "0,0")))]
"!TARGET_5200"
@@ -3974,7 +3974,7 @@
;; "xordi3" is mainly here to help combine().
(define_insn "xordi3"
- [(set (match_operand:DI 0 "general_operand" "=od")
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=od")
(xor:DI (match_operand:DI 1 "general_operand" "%0")
(match_operand:DI 2 "general_operand" "dn")))]
"!TARGET_5200"
@@ -4047,14 +4047,14 @@
}")
(define_expand "xorsi3"
- [(set (match_operand:SI 0 "general_operand" "")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "")
(xor:SI (match_operand:SI 1 "general_operand" "")
(match_operand:SI 2 "general_operand" "")))]
""
"")
(define_insn "xorsi3_internal"
- [(set (match_operand:SI 0 "general_operand" "=do,m")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=do,m")
(xor:SI (match_operand:SI 1 "general_operand" "%0,0")
(match_operand:SI 2 "general_operand" "di,dKT")))]
@@ -4065,49 +4065,49 @@
}")
(define_insn "xorsi3_5200"
- [(set (match_operand:SI 0 "general_operand" "=dm,d")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=dm,d")
(xor:SI (match_operand:SI 1 "general_operand" "%0,0")
(match_operand:SI 2 "general_operand" "d,Ks")))]
"TARGET_5200"
"eor%.l %2,%0")
(define_insn "xorhi3"
- [(set (match_operand:HI 0 "general_operand" "=dm")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=dm")
(xor:HI (match_operand:HI 1 "general_operand" "%0")
(match_operand:HI 2 "general_operand" "dn")))]
"!TARGET_5200"
"eor%.w %2,%0")
(define_insn ""
- [(set (strict_low_part (match_operand:HI 0 "general_operand" "+dm"))
+ [(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "+dm"))
(xor:HI (match_dup 0)
(match_operand:HI 1 "general_operand" "dn")))]
"!TARGET_5200"
"eor%.w %1,%0")
(define_insn ""
- [(set (strict_low_part (match_operand:HI 0 "general_operand" "+dm"))
+ [(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "+dm"))
(xor:HI (match_operand:HI 1 "general_operand" "dn")
(match_dup 0)))]
"!TARGET_5200"
"eor%.w %1,%0")
(define_insn "xorqi3"
- [(set (match_operand:QI 0 "general_operand" "=dm")
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=dm")
(xor:QI (match_operand:QI 1 "general_operand" "%0")
(match_operand:QI 2 "general_operand" "dn")))]
"!TARGET_5200"
"eor%.b %2,%0")
(define_insn ""
- [(set (strict_low_part (match_operand:QI 0 "general_operand" "+dm"))
+ [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+dm"))
(xor:QI (match_dup 0)
(match_operand:QI 1 "general_operand" "dn")))]
"!TARGET_5200"
"eor%.b %1,%0")
(define_insn ""
- [(set (strict_low_part (match_operand:QI 0 "general_operand" "+dm"))
+ [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+dm"))
(xor:QI (match_operand:QI 1 "general_operand" "dn")
(match_dup 0)))]
"!TARGET_5200"
@@ -4116,7 +4116,7 @@
;; negation instructions
(define_expand "negdi2"
- [(set (match_operand:DI 0 "general_operand" "")
+ [(set (match_operand:DI 0 "nonimmediate_operand" "")
(neg:DI (match_operand:DI 1 "general_operand" "")))]
""
"
@@ -4129,7 +4129,7 @@
}")
(define_insn "negdi2_internal"
- [(set (match_operand:DI 0 "general_operand" "=<,do,!*a")
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=<,do,!*a")
(neg:DI (match_operand:DI 1 "general_operand" "0,0,0")))]
"!TARGET_5200"
"*
@@ -4147,7 +4147,7 @@
} ")
(define_insn "negdi2_5200"
- [(set (match_operand:DI 0 "general_operand" "=d")
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=d")
(neg:DI (match_operand:DI 1 "general_operand" "0")))]
"TARGET_5200"
"*
@@ -4157,7 +4157,7 @@
} ")
(define_expand "negsi2"
- [(set (match_operand:SI 0 "general_operand" "")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "")
(neg:SI (match_operand:SI 1 "general_operand" "")))]
""
"
@@ -4170,37 +4170,37 @@
}")
(define_insn "negsi2_internal"
- [(set (match_operand:SI 0 "general_operand" "=dm")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=dm")
(neg:SI (match_operand:SI 1 "general_operand" "0")))]
"!TARGET_5200"
"neg%.l %0")
(define_insn "negsi2_5200"
- [(set (match_operand:SI 0 "general_operand" "=d")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
(neg:SI (match_operand:SI 1 "general_operand" "0")))]
"TARGET_5200"
"neg%.l %0")
(define_insn "neghi2"
- [(set (match_operand:HI 0 "general_operand" "=dm")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=dm")
(neg:HI (match_operand:HI 1 "general_operand" "0")))]
"!TARGET_5200"
"neg%.w %0")
(define_insn ""
- [(set (strict_low_part (match_operand:HI 0 "general_operand" "+dm"))
+ [(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "+dm"))
(neg:HI (match_dup 0)))]
"!TARGET_5200"
"neg%.w %0")
(define_insn "negqi2"
- [(set (match_operand:QI 0 "general_operand" "=dm")
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=dm")
(neg:QI (match_operand:QI 1 "general_operand" "0")))]
"!TARGET_5200"
"neg%.b %0")
(define_insn ""
- [(set (strict_low_part (match_operand:QI 0 "general_operand" "+dm"))
+ [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+dm"))
(neg:QI (match_dup 0)))]
"!TARGET_5200"
"neg%.b %0")
@@ -4208,7 +4208,7 @@
;; If using software floating point, just flip the sign bit.
(define_expand "negsf2"
- [(set (match_operand:SF 0 "general_operand" "")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "")
(neg:SF (match_operand:SF 1 "general_operand" "")))]
""
"
@@ -4235,13 +4235,13 @@
}")
(define_insn ""
- [(set (match_operand:SF 0 "general_operand" "=x,y")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=x,y")
(neg:SF (match_operand:SF 1 "general_operand" "xH,rmF")))]
"TARGET_FPA"
"fpneg%.s %w1,%0")
(define_insn ""
- [(set (match_operand:SF 0 "general_operand" "=f,d")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=f,d")
(neg:SF (match_operand:SF 1 "general_operand" "fdmF,0")))]
"TARGET_68881"
"*
@@ -4257,7 +4257,7 @@
}")
(define_expand "negdf2"
- [(set (match_operand:DF 0 "general_operand" "")
+ [(set (match_operand:DF 0 "nonimmediate_operand" "")
(neg:DF (match_operand:DF 1 "general_operand" "")))]
""
"
@@ -4291,13 +4291,13 @@
}")
(define_insn ""
- [(set (match_operand:DF 0 "general_operand" "=x,y")
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=x,y")
(neg:DF (match_operand:DF 1 "general_operand" "xH,rmF")))]
"TARGET_FPA"
"fpneg%.d %y1, %0")
(define_insn ""
- [(set (match_operand:DF 0 "general_operand" "=f,d")
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f,d")
(neg:DF (match_operand:DF 1 "general_operand" "fmF,0")))]
"TARGET_68881"
"*
@@ -4315,7 +4315,7 @@
;; Sqrt instruction for the 68881
(define_insn "sqrtsf2"
- [(set (match_operand:SF 0 "general_operand" "=f")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=f")
(sqrt:SF (match_operand:SF 1 "general_operand" "fm")))]
"TARGET_68881"
"*
@@ -4327,7 +4327,7 @@
}")
(define_insn "sqrtdf2"
- [(set (match_operand:DF 0 "general_operand" "=f")
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f")
(sqrt:DF (match_operand:DF 1 "general_operand" "fm")))]
"TARGET_68881"
"*
@@ -4342,7 +4342,7 @@
;; If using software floating point, just zero the sign bit.
(define_expand "abssf2"
- [(set (match_operand:SF 0 "general_operand" "")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "")
(abs:SF (match_operand:SF 1 "general_operand" "")))]
""
"
@@ -4369,13 +4369,13 @@
}")
(define_insn ""
- [(set (match_operand:SF 0 "general_operand" "=x,y")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=x,y")
(abs:SF (match_operand:SF 1 "general_operand" "xH,rmF")))]
"TARGET_FPA"
"fpabs%.s %y1,%0")
(define_insn ""
- [(set (match_operand:SF 0 "general_operand" "=f")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=f")
(abs:SF (match_operand:SF 1 "general_operand" "fdmF")))]
"TARGET_68881"
"*
@@ -4386,7 +4386,7 @@
}")
(define_expand "absdf2"
- [(set (match_operand:DF 0 "general_operand" "")
+ [(set (match_operand:DF 0 "nonimmediate_operand" "")
(abs:DF (match_operand:DF 1 "general_operand" "")))]
""
"
@@ -4420,13 +4420,13 @@
}")
(define_insn ""
- [(set (match_operand:DF 0 "general_operand" "=x,y")
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=x,y")
(abs:DF (match_operand:DF 1 "general_operand" "xH,rmF")))]
"TARGET_FPA"
"fpabs%.d %y1,%0")
(define_insn ""
- [(set (match_operand:DF 0 "general_operand" "=f")
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f")
(abs:DF (match_operand:DF 1 "general_operand" "fmF")))]
"TARGET_68881"
"*
@@ -4440,7 +4440,7 @@
;; "one_cmpldi2" is mainly here to help combine().
(define_insn "one_cmpldi2"
- [(set (match_operand:DI 0 "general_operand" "=dm")
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=dm")
(not:DI (match_operand:DI 1 "general_operand" "0")))]
"!TARGET_5200"
"*
@@ -4457,7 +4457,7 @@
}")
(define_expand "one_cmplsi2"
- [(set (match_operand:SI 0 "general_operand" "")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "")
(not:SI (match_operand:SI 1 "general_operand" "")))]
""
"
@@ -4470,37 +4470,37 @@
}")
(define_insn "one_cmplsi2_internal"
- [(set (match_operand:SI 0 "general_operand" "=dm")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=dm")
(not:SI (match_operand:SI 1 "general_operand" "0")))]
"!TARGET_5200"
"not%.l %0")
(define_insn "one_cmplsi2_5200"
- [(set (match_operand:SI 0 "general_operand" "=d")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
(not:SI (match_operand:SI 1 "general_operand" "0")))]
"TARGET_5200"
"not%.l %0")
(define_insn "one_cmplhi2"
- [(set (match_operand:HI 0 "general_operand" "=dm")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=dm")
(not:HI (match_operand:HI 1 "general_operand" "0")))]
"!TARGET_5200"
"not%.w %0")
(define_insn ""
- [(set (strict_low_part (match_operand:HI 0 "general_operand" "+dm"))
+ [(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "+dm"))
(not:HI (match_dup 0)))]
"!TARGET_5200"
"not%.w %0")
(define_insn "one_cmplqi2"
- [(set (match_operand:QI 0 "general_operand" "=dm")
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=dm")
(not:QI (match_operand:QI 1 "general_operand" "0")))]
"!TARGET_5200"
"not%.b %0")
(define_insn ""
- [(set (strict_low_part (match_operand:QI 0 "general_operand" "+dm"))
+ [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+dm"))
(not:QI (match_dup 0)))]
"!TARGET_5200"
"not%.b %0")
@@ -4509,7 +4509,7 @@
;; We don't need the shift memory by 1 bit instruction
(define_insn "ashldi_extsi"
- [(set (match_operand:DI 0 "general_operand" "=ro")
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=ro")
(ashift:DI
(match_operator:DI 2 "extend_operator"
[(match_operand:SI 1 "general_operand" "rm")])
@@ -4529,7 +4529,7 @@
} ")
(define_insn "ashldi_sexthi"
- [(set (match_operand:DI 0 "general_operand" "=m,a*d")
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=m,a*d")
(ashift:DI (sign_extend:DI (match_operand:HI 1 "general_operand" "rm,rm"))
(const_int 32)))
(clobber (match_scratch:SI 2 "=a,X"))]
@@ -4556,7 +4556,7 @@
} ")
(define_insn "ashldi_const32"
- [(set (match_operand:DI 0 "general_operand" "=rm")
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
(ashift:DI (match_operand:DI 1 "general_operand" "ro")
(const_int 32)))]
""
@@ -4583,7 +4583,7 @@
;; The predicate below must be general_operand, because ashldi3 allows that
(define_insn "ashldi_const"
- [(set (match_operand:DI 0 "general_operand" "=d")
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=d")
(ashift:DI (match_operand:DI 1 "general_operand" "0")
(match_operand 2 "const_int_operand" "n")))]
"(!TARGET_5200
@@ -4615,7 +4615,7 @@
} ")
(define_expand "ashldi3"
- [(set (match_operand:DI 0 "general_operand" "")
+ [(set (match_operand:DI 0 "nonimmediate_operand" "")
(ashift:DI (match_operand:DI 1 "general_operand" "")
(match_operand 2 "const_int_operand" "")))]
"!TARGET_5200"
@@ -4729,7 +4729,7 @@
}")
(define_insn "subreghi1ashrdi_const32"
- [(set (match_operand:HI 0 "general_operand" "=rm")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
(subreg:HI (ashiftrt:DI (match_operand:DI 1 "general_operand" "ro")
(const_int 32)) 1))]
""
@@ -4741,7 +4741,7 @@
} ")
(define_insn "subregsi1ashrdi_const32"
- [(set (match_operand:SI 0 "general_operand" "=rm")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
(subreg:SI (ashiftrt:DI (match_operand:DI 1 "general_operand" "ro")
(const_int 32)) 1))]
""
@@ -4766,7 +4766,7 @@
} ")
(define_insn "ashrdi_const32_mem"
- [(set (match_operand:DI 0 "general_operand" "=o,<")
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=o,<")
(ashiftrt:DI (match_operand:DI 1 "general_operand" "ro,ro")
(const_int 32)))
(clobber (match_scratch:SI 2 "=d,d"))]
@@ -4786,7 +4786,7 @@
;; The predicate below must be general_operand, because ashrdi3 allows that
(define_insn "ashrdi_const"
- [(set (match_operand:DI 0 "general_operand" "=d")
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=d")
(ashiftrt:DI (match_operand:DI 1 "general_operand" "0")
(match_operand 2 "const_int_operand" "n")))]
"(!TARGET_5200
@@ -4805,7 +4805,7 @@
else if (INTVAL (operands[2]) == 8)
return \"move%.b %0,%1\;asr%.l %#8,%0\;ror%.l %#8,%1\";
else if (INTVAL (operands[2]) == 16)
- return \"move%.w %0,%1\;clr%.w %0\;swap %1\;ext%.l %0\";
+ return \"move%.w %0,%1\;swap %0\;ext%.l %0\;swap %1\";
else if (INTVAL (operands[2]) == 48)
return \"swap %0\;ext%.l %0\;move%.l %0,%1\;smi %0\;ext%.w %0\";
else if (INTVAL (operands[2]) == 31)
@@ -4826,7 +4826,7 @@
} ")
(define_expand "ashrdi3"
- [(set (match_operand:DI 0 "general_operand" "")
+ [(set (match_operand:DI 0 "nonimmediate_operand" "")
(ashiftrt:DI (match_operand:DI 1 "general_operand" "")
(match_operand 2 "const_int_operand" "")))]
"!TARGET_5200"
@@ -4895,7 +4895,7 @@
;; [(set (cc0)
;; (subreg:SI (lshiftrt:DI (match_operand:DI 0 "general_operand" "ro")
;; (const_int 32)) 1))
-;; (set (match_operand:SI 1 "general_operand" "=dm")
+;; (set (match_operand:SI 1 "nonimmediate_operand" "=dm")
;; (subreg:SI (lshiftrt:DI (match_dup 0)
;; (const_int 32)) 1))]
;; ""
@@ -4908,7 +4908,7 @@
;; [(set (cc0)
;; (subreg:SI (lshiftrt:DI (match_operand:DI 0 "general_operand" "ro")
;; (const_int 32)) 0))
-;; (set (match_operand:DI 1 "general_operand" "=do")
+;; (set (match_operand:DI 1 "nonimmediate_operand" "=do")
;; (lshiftrt:DI (match_dup 0)
;; (const_int 32)))]
;; ""
@@ -4922,7 +4922,7 @@
;;} ")
(define_insn "subreg1lshrdi_const32"
- [(set (match_operand:SI 0 "general_operand" "=rm")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
(subreg:SI (lshiftrt:DI (match_operand:DI 1 "general_operand" "ro")
(const_int 32)) 1))]
""
@@ -4932,7 +4932,7 @@
} ")
(define_insn "lshrdi_const32"
- [(set (match_operand:DI 0 "general_operand" "=ro,<,>")
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=ro,<,>")
(lshiftrt:DI (match_operand:DI 1 "general_operand" "ro,ro,ro")
(const_int 32)))]
""
@@ -4959,7 +4959,7 @@
;; The predicate below must be general_operand, because lshrdi3 allows that
(define_insn "lshrdi_const"
- [(set (match_operand:DI 0 "general_operand" "=d")
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=d")
(lshiftrt:DI (match_operand:DI 1 "general_operand" "0")
(match_operand 2 "const_int_operand" "n")))]
"(!TARGET_5200
@@ -4994,7 +4994,7 @@
} ")
(define_expand "lshrdi3"
- [(set (match_operand:DI 0 "general_operand" "")
+ [(set (match_operand:DI 0 "nonimmediate_operand" "")
(lshiftrt:DI (match_operand:DI 1 "general_operand" "")
(match_operand 2 "const_int_operand" "")))]
"!TARGET_5200"
@@ -5328,7 +5328,7 @@
; than an odd byte aligned bit field instruction.
;
(define_insn ""
- [(set (match_operand:SI 0 "general_operand" "=rm")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
(zero_extract:SI (match_operand:QI 1 "memory_src_operand" "oS")
(const_int 32)
(match_operand:SI 2 "const_int_operand" "n")))]
@@ -5344,7 +5344,7 @@
}")
(define_insn ""
- [(set (match_operand:SI 0 "general_operand" "=&d")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=&d")
(zero_extract:SI (match_operand:SI 1 "register_operand" "do")
(match_operand:SI 2 "const_int_operand" "n")
(match_operand:SI 3 "const_int_operand" "n")))]
@@ -5382,7 +5382,7 @@
; than an odd byte aligned bit field instruction.
;
(define_insn ""
- [(set (match_operand:SI 0 "general_operand" "=rm")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
(sign_extract:SI (match_operand:QI 1 "memory_src_operand" "oS")
(const_int 32)
(match_operand:SI 2 "const_int_operand" "n")))]
@@ -5398,7 +5398,7 @@
}")
(define_insn ""
- [(set (match_operand:SI 0 "general_operand" "=d")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
(sign_extract:SI (match_operand:SI 1 "register_operand" "do")
(match_operand:SI 2 "const_int_operand" "n")
(match_operand:SI 3 "const_int_operand" "n")))]
@@ -5428,7 +5428,7 @@
;; so that its address is reloaded.
(define_expand "extv"
- [(set (match_operand:SI 0 "general_operand" "")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "")
(sign_extract:SI (match_operand:SI 1 "general_operand" "")
(match_operand:SI 2 "general_operand" "")
(match_operand:SI 3 "general_operand" "")))]
@@ -5436,7 +5436,7 @@
"")
(define_insn ""
- [(set (match_operand:SI 0 "general_operand" "=d")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
(sign_extract:SI (match_operand:QI 1 "memory_operand" "o")
(match_operand:SI 2 "general_operand" "di")
(match_operand:SI 3 "general_operand" "di")))]
@@ -5444,7 +5444,7 @@
"bfexts %1{%b3:%b2},%0")
(define_expand "extzv"
- [(set (match_operand:SI 0 "general_operand" "")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "")
(zero_extract:SI (match_operand:SI 1 "general_operand" "")
(match_operand:SI 2 "general_operand" "")
(match_operand:SI 3 "general_operand" "")))]
@@ -5452,7 +5452,7 @@
"")
(define_insn ""
- [(set (match_operand:SI 0 "general_operand" "=d,d")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d")
(zero_extract:SI (match_operand:QI 1 "memory_operand" "o,d")
(match_operand:SI 2 "general_operand" "di,di")
(match_operand:SI 3 "general_operand" "di,di")))]
@@ -5512,7 +5512,7 @@
}")
(define_expand "insv"
- [(set (zero_extract:SI (match_operand:SI 0 "general_operand" "")
+ [(set (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "")
(match_operand:SI 1 "general_operand" "")
(match_operand:SI 2 "general_operand" ""))
(match_operand:SI 3 "register_operand" ""))]
@@ -5531,7 +5531,7 @@
;; (or at least were intended to do so).
(define_insn ""
- [(set (match_operand:SI 0 "general_operand" "=d")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
(sign_extract:SI (match_operand:SI 1 "register_operand" "d")
(match_operand:SI 2 "general_operand" "di")
(match_operand:SI 3 "general_operand" "di")))]
@@ -5539,7 +5539,7 @@
"bfexts %1{%b3:%b2},%0")
(define_insn ""
- [(set (match_operand:SI 0 "general_operand" "=d")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
(zero_extract:SI (match_operand:SI 1 "register_operand" "d")
(match_operand:SI 2 "general_operand" "di")
(match_operand:SI 3 "general_operand" "di")))]
@@ -5654,7 +5654,7 @@
}")
(define_insn "scc0_di"
- [(set (match_operand:QI 0 "general_operand" "=dm")
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=dm")
(match_operator 1 "valid_dbcc_comparison_p"
[(match_operand:DI 2 "general_operand" "ro") (const_int 0)]))]
"! TARGET_5200"
@@ -5664,7 +5664,7 @@
} ")
(define_insn "scc0_di_5200"
- [(set (match_operand:QI 0 "general_operand" "=d")
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=d")
(match_operator 1 "valid_dbcc_comparison_p"
[(match_operand:DI 2 "general_operand" "ro") (const_int 0)]))]
"TARGET_5200"
@@ -5674,7 +5674,7 @@
} ")
(define_insn "scc_di"
- [(set (match_operand:QI 0 "general_operand" "=dm,dm")
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=dm,dm")
(match_operator 1 "valid_dbcc_comparison_p"
[(match_operand:DI 2 "general_operand" "ro,r")
(match_operand:DI 3 "general_operand" "r,ro")]))]
@@ -5685,7 +5685,7 @@
} ")
(define_insn "scc_di_5200"
- [(set (match_operand:QI 0 "general_operand" "=d,d")
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d")
(match_operator 1 "valid_dbcc_comparison_p"
[(match_operand:DI 2 "general_operand" "ro,r")
(match_operand:DI 3 "general_operand" "r,ro")]))]
@@ -6560,7 +6560,7 @@
(define_insn ""
[(set (pc)
(if_then_else
- (ne (match_operand:HI 0 "general_operand" "+d*g")
+ (ne (match_operand:HI 0 "nonimmediate_operand" "+d*g")
(const_int 0))
(label_ref (match_operand 1 "" ""))
(pc)))
@@ -6603,7 +6603,7 @@
(define_insn ""
[(set (pc)
(if_then_else
- (ne (match_operand:SI 0 "general_operand" "+d*g")
+ (ne (match_operand:SI 0 "nonimmediate_operand" "+d*g")
(const_int 0))
(label_ref (match_operand 1 "" ""))
(pc)))
@@ -6649,7 +6649,7 @@
(define_insn ""
[(set (pc)
(if_then_else
- (ge (plus:HI (match_operand:HI 0 "general_operand" "+d*am")
+ (ge (plus:HI (match_operand:HI 0 "nonimmediate_operand" "+d*am")
(const_int -1))
(const_int 0))
(label_ref (match_operand 1 "" ""))
@@ -6694,7 +6694,7 @@
(define_expand "decrement_and_branch_until_zero"
[(parallel [(set (pc)
(if_then_else
- (ge (plus:SI (match_operand:SI 0 "general_operand" "")
+ (ge (plus:SI (match_operand:SI 0 "nonimmediate_operand" "")
(const_int -1))
(const_int 0))
(label_ref (match_operand 1 "" ""))
@@ -6708,7 +6708,7 @@
(define_insn ""
[(set (pc)
(if_then_else
- (ge (plus:SI (match_operand:SI 0 "general_operand" "+d*am")
+ (ge (plus:SI (match_operand:SI 0 "nonimmediate_operand" "+d*am")
(const_int -1))
(const_int 0))
(label_ref (match_operand 1 "" ""))
@@ -6997,7 +6997,7 @@
;; This should not be used unless the add/sub insns can't be.
(define_insn ""
- [(set (match_operand:SI 0 "general_operand" "=a")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=a")
(match_operand:QI 1 "address_operand" "p"))]
""
"*
@@ -7464,7 +7464,7 @@
}")
(define_insn "extendsfxf2"
- [(set (match_operand:XF 0 "general_operand" "=fm,f")
+ [(set (match_operand:XF 0 "nonimmediate_operand" "=fm,f")
(float_extend:XF (match_operand:SF 1 "general_operand" "f,rmF")))]
"TARGET_68881"
"*
@@ -7496,7 +7496,7 @@
(define_insn "extenddfxf2"
- [(set (match_operand:XF 0 "general_operand" "=fm,f")
+ [(set (match_operand:XF 0 "nonimmediate_operand" "=fm,f")
(float_extend:XF
(match_operand:DF 1 "general_operand" "f,rmE")))]
"TARGET_68881"
@@ -7532,7 +7532,7 @@
}")
(define_insn "truncxfdf2"
- [(set (match_operand:DF 0 "general_operand" "=m,!r")
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=m,!r")
(float_truncate:DF
(match_operand:XF 1 "general_operand" "f,f")))]
"TARGET_68881"
@@ -7548,32 +7548,32 @@
}")
(define_insn "truncxfsf2"
- [(set (match_operand:SF 0 "general_operand" "=dm")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=dm")
(float_truncate:SF
(match_operand:XF 1 "general_operand" "f")))]
"TARGET_68881"
"fmove%.s %f1,%0")
(define_insn "floatsixf2"
- [(set (match_operand:XF 0 "general_operand" "=f")
+ [(set (match_operand:XF 0 "nonimmediate_operand" "=f")
(float:XF (match_operand:SI 1 "general_operand" "dmi")))]
"TARGET_68881"
"fmove%.l %1,%0")
(define_insn "floathixf2"
- [(set (match_operand:XF 0 "general_operand" "=f")
+ [(set (match_operand:XF 0 "nonimmediate_operand" "=f")
(float:XF (match_operand:HI 1 "general_operand" "dmn")))]
"TARGET_68881"
"fmove%.w %1,%0")
(define_insn "floatqixf2"
- [(set (match_operand:XF 0 "general_operand" "=f")
+ [(set (match_operand:XF 0 "nonimmediate_operand" "=f")
(float:XF (match_operand:QI 1 "general_operand" "dmn")))]
"TARGET_68881"
"fmove%.b %1,%0")
(define_insn "ftruncxf2"
- [(set (match_operand:XF 0 "general_operand" "=f")
+ [(set (match_operand:XF 0 "nonimmediate_operand" "=f")
(fix:XF (match_operand:XF 1 "general_operand" "fFm")))]
"TARGET_68881"
"*
@@ -7584,46 +7584,46 @@
}")
(define_insn "fixxfqi2"
- [(set (match_operand:QI 0 "general_operand" "=dm")
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=dm")
(fix:QI (match_operand:XF 1 "general_operand" "f")))]
"TARGET_68881"
"fmove%.b %1,%0")
(define_insn "fixxfhi2"
- [(set (match_operand:HI 0 "general_operand" "=dm")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=dm")
(fix:HI (match_operand:XF 1 "general_operand" "f")))]
"TARGET_68881"
"fmove%.w %1,%0")
(define_insn "fixxfsi2"
- [(set (match_operand:SI 0 "general_operand" "=dm")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=dm")
(fix:SI (match_operand:XF 1 "general_operand" "f")))]
"TARGET_68881"
"fmove%.l %1,%0")
(define_insn ""
- [(set (match_operand:XF 0 "general_operand" "=f")
+ [(set (match_operand:XF 0 "nonimmediate_operand" "=f")
(plus:XF (float:XF (match_operand:SI 2 "general_operand" "dmi"))
(match_operand:XF 1 "nonimmediate_operand" "0")))]
"TARGET_68881"
"fadd%.l %2,%0")
(define_insn ""
- [(set (match_operand:XF 0 "general_operand" "=f")
+ [(set (match_operand:XF 0 "nonimmediate_operand" "=f")
(plus:XF (float:XF (match_operand:HI 2 "general_operand" "dmn"))
(match_operand:XF 1 "nonimmediate_operand" "0")))]
"TARGET_68881"
"fadd%.w %2,%0")
(define_insn ""
- [(set (match_operand:XF 0 "general_operand" "=f")
+ [(set (match_operand:XF 0 "nonimmediate_operand" "=f")
(plus:XF (float:XF (match_operand:QI 2 "general_operand" "dmn"))
(match_operand:XF 1 "general_operand" "0")))]
"TARGET_68881"
"fadd%.b %2,%0")
(define_insn "addxf3"
- [(set (match_operand:XF 0 "general_operand" "=f")
+ [(set (match_operand:XF 0 "nonimmediate_operand" "=f")
(plus:XF (match_operand:XF 1 "nonimmediate_operand" "%0")
(match_operand:XF 2 "nonimmediate_operand" "fm")))]
"TARGET_68881"
@@ -7635,28 +7635,28 @@
}")
(define_insn ""
- [(set (match_operand:XF 0 "general_operand" "=f")
+ [(set (match_operand:XF 0 "nonimmediate_operand" "=f")
(minus:XF (match_operand:XF 1 "nonimmediate_operand" "0")
(float:XF (match_operand:SI 2 "general_operand" "dmi"))))]
"TARGET_68881"
"fsub%.l %2,%0")
(define_insn ""
- [(set (match_operand:XF 0 "general_operand" "=f")
+ [(set (match_operand:XF 0 "nonimmediate_operand" "=f")
(minus:XF (match_operand:XF 1 "nonimmediate_operand" "0")
(float:XF (match_operand:HI 2 "general_operand" "dmn"))))]
"TARGET_68881"
"fsub%.w %2,%0")
(define_insn ""
- [(set (match_operand:XF 0 "general_operand" "=f")
+ [(set (match_operand:XF 0 "nonimmediate_operand" "=f")
(minus:XF (match_operand:XF 1 "nonimmediate_operand" "0")
(float:XF (match_operand:QI 2 "general_operand" "dmn"))))]
"TARGET_68881"
"fsub%.b %2,%0")
(define_insn "subxf3"
- [(set (match_operand:XF 0 "general_operand" "=f")
+ [(set (match_operand:XF 0 "nonimmediate_operand" "=f")
(minus:XF (match_operand:XF 1 "nonimmediate_operand" "0")
(match_operand:XF 2 "nonimmediate_operand" "fm")))]
"TARGET_68881"
@@ -7668,28 +7668,28 @@
}")
(define_insn ""
- [(set (match_operand:XF 0 "general_operand" "=f")
+ [(set (match_operand:XF 0 "nonimmediate_operand" "=f")
(mult:XF (float:XF (match_operand:SI 2 "general_operand" "dmi"))
(match_operand:XF 1 "nonimmediate_operand" "0")))]
"TARGET_68881"
"fmul%.l %2,%0")
(define_insn ""
- [(set (match_operand:XF 0 "general_operand" "=f")
+ [(set (match_operand:XF 0 "nonimmediate_operand" "=f")
(mult:XF (float:XF (match_operand:HI 2 "general_operand" "dmn"))
(match_operand:XF 1 "nonimmediate_operand" "0")))]
"TARGET_68881"
"fmul%.w %2,%0")
(define_insn ""
- [(set (match_operand:XF 0 "general_operand" "=f")
+ [(set (match_operand:XF 0 "nonimmediate_operand" "=f")
(mult:XF (float:XF (match_operand:QI 2 "general_operand" "dmn"))
(match_operand:XF 1 "nonimmediate_operand" "0")))]
"TARGET_68881"
"fmul%.b %2,%0")
(define_insn "mulxf3"
- [(set (match_operand:XF 0 "general_operand" "=f")
+ [(set (match_operand:XF 0 "nonimmediate_operand" "=f")
(mult:XF (match_operand:XF 1 "nonimmediate_operand" "%0")
(match_operand:XF 2 "nonimmediate_operand" "fm")))]
"TARGET_68881"
@@ -7701,28 +7701,28 @@
}")
(define_insn ""
- [(set (match_operand:XF 0 "general_operand" "=f")
+ [(set (match_operand:XF 0 "nonimmediate_operand" "=f")
(div:XF (match_operand:XF 1 "nonimmediate_operand" "0")
(float:XF (match_operand:SI 2 "general_operand" "dmi"))))]
"TARGET_68881"
"fdiv%.l %2,%0")
(define_insn ""
- [(set (match_operand:XF 0 "general_operand" "=f")
+ [(set (match_operand:XF 0 "nonimmediate_operand" "=f")
(div:XF (match_operand:XF 1 "nonimmediate_operand" "0")
(float:XF (match_operand:HI 2 "general_operand" "dmn"))))]
"TARGET_68881"
"fdiv%.w %2,%0")
(define_insn ""
- [(set (match_operand:XF 0 "general_operand" "=f")
+ [(set (match_operand:XF 0 "nonimmediate_operand" "=f")
(div:XF (match_operand:XF 1 "nonimmediate_operand" "0")
(float:XF (match_operand:QI 2 "general_operand" "dmn"))))]
"TARGET_68881"
"fdiv%.b %2,%0")
(define_insn "divxf3"
- [(set (match_operand:XF 0 "general_operand" "=f")
+ [(set (match_operand:XF 0 "nonimmediate_operand" "=f")
(div:XF (match_operand:XF 1 "nonimmediate_operand" "0")
(match_operand:XF 2 "nonimmediate_operand" "fm")))]
"TARGET_68881"
@@ -7734,7 +7734,7 @@
}")
(define_expand "negxf2"
- [(set (match_operand:XF 0 "general_operand" "")
+ [(set (match_operand:XF 0 "nonimmediate_operand" "")
(neg:XF (match_operand:XF 1 "nonimmediate_operand" "")))]
""
"
@@ -7772,7 +7772,7 @@
}")
(define_insn "negxf2_68881"
- [(set (match_operand:XF 0 "general_operand" "=f")
+ [(set (match_operand:XF 0 "nonimmediate_operand" "=f")
(neg:XF (match_operand:XF 1 "nonimmediate_operand" "fm")))]
"TARGET_68881"
"*
@@ -7783,7 +7783,7 @@
}")
(define_expand "absxf2"
- [(set (match_operand:XF 0 "general_operand" "")
+ [(set (match_operand:XF 0 "nonimmediate_operand" "")
(abs:XF (match_operand:XF 1 "nonimmediate_operand" "")))]
""
"
@@ -7821,7 +7821,7 @@
}")
(define_insn "absxf2_68881"
- [(set (match_operand:XF 0 "general_operand" "=f")
+ [(set (match_operand:XF 0 "nonimmediate_operand" "=f")
(abs:XF (match_operand:XF 1 "nonimmediate_operand" "fm")))]
"TARGET_68881"
"*
@@ -7832,13 +7832,13 @@
}")
(define_insn "sqrtxf2"
- [(set (match_operand:XF 0 "general_operand" "=f")
+ [(set (match_operand:XF 0 "nonimmediate_operand" "=f")
(sqrt:XF (match_operand:XF 1 "nonimmediate_operand" "fm")))]
"TARGET_68881"
"fsqrt%.x %1,%0")
(define_insn "sinsf2"
- [(set (match_operand:SF 0 "general_operand" "=f")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=f")
(unspec:SF [(match_operand:SF 1 "general_operand" "fm")] 1))]
"TARGET_68881 && flag_fast_math"
"*
@@ -7850,7 +7850,7 @@
}")
(define_insn "sindf2"
- [(set (match_operand:DF 0 "general_operand" "=f")
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f")
(unspec:DF [(match_operand:DF 1 "general_operand" "fm")] 1))]
"TARGET_68881 && flag_fast_math"
"*
@@ -7862,13 +7862,13 @@
}")
(define_insn "sinxf2"
- [(set (match_operand:XF 0 "general_operand" "=f")
+ [(set (match_operand:XF 0 "nonimmediate_operand" "=f")
(unspec:XF [(match_operand:XF 1 "nonimmediate_operand" "fm")] 1))]
"TARGET_68881 && flag_fast_math"
"fsin%.x %1,%0")
(define_insn "cossf2"
- [(set (match_operand:SF 0 "general_operand" "=f")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=f")
(unspec:SF [(match_operand:SF 1 "general_operand" "fm")] 2))]
"TARGET_68881 && flag_fast_math"
"*
@@ -7880,7 +7880,7 @@
}")
(define_insn "cosdf2"
- [(set (match_operand:DF 0 "general_operand" "=f")
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f")
(unspec:DF [(match_operand:DF 1 "general_operand" "fm")] 2))]
"TARGET_68881 && flag_fast_math"
"*
@@ -7892,7 +7892,7 @@
}")
(define_insn "cosxf2"
- [(set (match_operand:XF 0 "general_operand" "=f")
+ [(set (match_operand:XF 0 "nonimmediate_operand" "=f")
(unspec:XF [(match_operand:XF 1 "nonimmediate_operand" "fm")] 2))]
"TARGET_68881 && flag_fast_math"
"fcos%.x %1,%0")
diff --git a/gcc/config/m68k/m68kv4.h b/gcc/config/m68k/m68kv4.h
index dafe7fdedfa..9bdc4877685 100644
--- a/gcc/config/m68k/m68kv4.h
+++ b/gcc/config/m68k/m68kv4.h
@@ -27,11 +27,6 @@ Boston, MA 02111-1307, USA. */
#include "m68k/sgs.h" /* The m68k/SVR4 assembler is SGS based */
-/* The SGS assembler requires a special definition of
- ASM_IDENTIFY_GCC. We combine the m68k/sgs.h and the svr4.h
- definitions below. */
-#undef ASM_IDENTIFY_GCC
-
#include "svr4.h" /* Pick up the generic SVR4 macros */
/* See m68k.h. 7 means 68020 with 68881. */
@@ -40,19 +35,6 @@ Boston, MA 02111-1307, USA. */
#define TARGET_DEFAULT (MASK_BITFIELD|MASK_68881|MASK_68020)
#endif
-/* When using an SGS assembler, modify the name of the artificial label which
- identifies this file as having been compiled with gcc, and the macro that
- emits such a label in the assembly output, to use '%' rather than '.' */
-
-#undef ASM_IDENTIFY_GCC
-#define ASM_IDENTIFY_GCC(FILE) \
-do \
- { \
- if (write_symbols != DBX_DEBUG) \
- fputs ("gcc2_compiled%:\n", FILE); \
- } \
-while (0)
-
/* Override the definition of NO_DOLLAR_IN_LABEL in svr4.h, for special
g++ assembler names. When this is defined, g++ uses embedded '.'
characters and some m68k assemblers have problems with this. The
diff --git a/gcc/config/m68k/mot3300.h b/gcc/config/m68k/mot3300.h
index 9c9a0994426..fd914815d64 100644
--- a/gcc/config/m68k/mot3300.h
+++ b/gcc/config/m68k/mot3300.h
@@ -38,6 +38,9 @@ Boston, MA 02111-1307, USA. */
#include "m68k/m68k.h"
+/* GDB expects a slightly different marker on this target. */
+#define STABS_GCC_MARKER "gcc2_compiled%"
+
/* See m68k.h. 0407 means 68020-68040. */
#ifndef TARGET_DEFAULT
@@ -264,11 +267,6 @@ dtors_section () \
}
#endif /* USE_GAS */
-/* The sysV68 assembler does not accept dots in labels.
- Let's use percent instead */
-
-#define ASM_IDENTIFY_GCC(FILE) fputs("gcc2_compiled%:\n", FILE)
-
/* Names to predefine in the preprocessor for this target machine. */
/* ihnp4!lmayk!lgm@eddie.mit.edu says mc68000 and m68k should not be here,
on the other hand I don't care what he says. */
diff --git a/gcc/config/m68k/news.h b/gcc/config/m68k/news.h
index 5661e87ae03..25e820e772b 100644
--- a/gcc/config/m68k/news.h
+++ b/gcc/config/m68k/news.h
@@ -139,11 +139,6 @@ Boston, MA 02111-1307, USA. */
#ifdef MOTOROLA
-/* Don't try to define `gcc_compiled.' since the assembler does not
- accept symbols with periods. This is no real loss since GDB only
- really needs it for parms passed in registers. */
-#define ASM_IDENTIFY_GCC(FILE)
-
#define FUNCTION_PROLOGUE(FILE, SIZE) \
{ register int regno; \
register int mask = 0; \
diff --git a/gcc/config/m68k/sgs.h b/gcc/config/m68k/sgs.h
index 3e4bbb15329..74716cd9e6a 100644
--- a/gcc/config/m68k/sgs.h
+++ b/gcc/config/m68k/sgs.h
@@ -102,13 +102,6 @@ Boston, MA 02111-1307, USA. */
#endif /* defined SUPPORT_SUN_FPA */
-/* When using an SGS assembler, modify the name of the artificial label which
- identifies this file as having been compiled with gcc, and the macro that
- emits such a label in the assembly output, to use '%' rather than '.' */
-
-#define ASM_IDENTIFY_GCC(FILE) \
- { fprintf ((FILE), "%s:\n", "gcc2_compiled%"); }
-
/* This is how to output an assembler line defining an `int' constant. */
/* The SGS assembler doesn't understand ".word". */
diff --git a/gcc/config/m68k/t-openbsd b/gcc/config/m68k/t-openbsd
new file mode 100644
index 00000000000..24f9a43b000
--- /dev/null
+++ b/gcc/config/m68k/t-openbsd
@@ -0,0 +1,5 @@
+# gdb gets confused if pic code is linked with non pic
+# We cope by building all variants of libgcc.
+MULTILIB_OPTIONS = fpic/fPIC
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
diff --git a/gcc/config/m68k/tower-as.h b/gcc/config/m68k/tower-as.h
index 2ab94221ad3..bb03b058a82 100644
--- a/gcc/config/m68k/tower-as.h
+++ b/gcc/config/m68k/tower-as.h
@@ -67,11 +67,6 @@ Boston, MA 02111-1307, USA. */
#define SDB_DEBUGGING_INFO
-/* This is only useful if gdb is changed, but doesn't harm anyway. */
-
-#define ASM_IDENTIFY_GCC(FILE) \
- fprintf (FILE, "gcc2_compiled%%:\n")
-
/* All the ASM_OUTPUT macros need to conform to the Tower as syntax. */
#define ASM_OUTPUT_SOURCE_FILENAME(FILE, FILENAME) \
diff --git a/gcc/config/m68k/xm-m68k.h b/gcc/config/m68k/xm-m68k.h
index 757c9af67a1..b5a5420bc3f 100644
--- a/gcc/config/m68k/xm-m68k.h
+++ b/gcc/config/m68k/xm-m68k.h
@@ -18,11 +18,6 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-
-/* #defines that need visibility everywhere. */
-#define FALSE 0
-#define TRUE 1
-
/* This describes the machine the compiler is hosted on. */
#define HOST_BITS_PER_CHAR 8
#define HOST_BITS_PER_SHORT 16
diff --git a/gcc/config/m88k/m88k.c b/gcc/config/m88k/m88k.c
index beeb8fcfeb7..2e788483166 100644
--- a/gcc/config/m88k/m88k.c
+++ b/gcc/config/m88k/m88k.c
@@ -29,7 +29,6 @@ Boston, MA 02111-1307, USA. */
#include "real.h"
#include "insn-config.h"
#include "conditions.h"
-#include "insn-flags.h"
#include "output.h"
#include "insn-attr.h"
#include "tree.h"
@@ -1573,9 +1572,8 @@ output_file_start (file, f_options, f_len, W_options, W_len)
&& TARGET_SVR4)
fprintf (file, "%s\n", REQUIRES_88110_ASM_OP);
output_file_directive (file, main_input_filename);
- /* Switch to the data section so that the coffsem symbol and the
- gcc2_compiled. symbol aren't in the text section. */
- data_section ();
+ /* Switch to the data section so that the coffsem symbol
+ isn't in the text section. */
ASM_COFFSEM (file);
if (TARGET_IDENTIFY_REVISION)
diff --git a/gcc/config/m88k/xm-m88k.h b/gcc/config/m88k/xm-m88k.h
index 4568fd5f989..1c6882bd206 100644
--- a/gcc/config/m88k/xm-m88k.h
+++ b/gcc/config/m88k/xm-m88k.h
@@ -20,11 +20,6 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-
-/* #defines that need visibility everywhere. */
-#define FALSE 0
-#define TRUE 1
-
/* This describes the machine the compiler is hosted on. */
#define HOST_BITS_PER_CHAR 8
#define HOST_BITS_PER_SHORT 16
diff --git a/gcc/config/mcore/mcore-elf.h b/gcc/config/mcore/mcore-elf.h
index fce4e8b2850..6058d27dae2 100644
--- a/gcc/config/mcore/mcore-elf.h
+++ b/gcc/config/mcore/mcore-elf.h
@@ -55,20 +55,6 @@ Boston, MA 02111-1307, USA. */
#undef DBX_REGISTER_NUMBER
#define DBX_REGISTER_NUMBER(REGNO) (REGNO)
-/* When using stabs, gcc2_compiled must be a stabs entry, not an
- ordinary symbol, or gdb won't see it. The stabs entry must be
- before the N_SO in order for gdb to find it. */
-#undef ASM_IDENTIFY_GCC
-#define ASM_IDENTIFY_GCC(FILE) \
-do \
- { \
- if (write_symbols != DBX_DEBUG) \
- fputs ("gcc2_compiled.:\n", FILE); \
- else \
- fputs ("\t.stabs\t\"gcc2_compiled.\", 0x3c, 0, 0, 0\n", FILE); \
- } \
-while (0)
-
/* MCore defines .long and .short to NOT force any alignment.
This lets you misalign as much as you wish. */
#define UNALIGNED_INT_ASM_OP "\t.long\t"
diff --git a/gcc/config/mcore/mcore.c b/gcc/config/mcore/mcore.c
index c4650232fa5..9daa7fef835 100644
--- a/gcc/config/mcore/mcore.c
+++ b/gcc/config/mcore/mcore.c
@@ -30,7 +30,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "real.h"
#include "insn-config.h"
#include "conditions.h"
-#include "insn-flags.h"
#include "output.h"
#include "insn-attr.h"
#include "flags.h"
@@ -2634,8 +2633,8 @@ mcore_dependent_simplify_rtx (x, int_op0_mode, last, in_dest, general_simplify)
{
int i;
rtx cond = XEXP(x, 0);
- rtx true = XEXP(x, 1);
- rtx false = XEXP(x, 2);
+ rtx true_rtx = XEXP(x, 1);
+ rtx false_rtx = XEXP(x, 2);
enum rtx_code true_code = GET_CODE (cond);
/* On the mcore, when doing -mcmov-one, we don't want to simplify:
@@ -2648,12 +2647,12 @@ mcore_dependent_simplify_rtx (x, int_op0_mode, last, in_dest, general_simplify)
not typically help. see combine.c, line 4217. BRC */
if (true_code == NE && XEXP (cond, 1) == const0_rtx
- && false == const0_rtx && GET_CODE (true) == CONST_INT
+ && false_rtx == const0_rtx && GET_CODE (true_rtx) == CONST_INT
&& ((1 == nonzero_bits (XEXP (cond, 0), mode)
- && (i = exact_log2 (INTVAL (true))) >= 0)
+ && (i = exact_log2 (INTVAL (true_rtx))) >= 0)
|| ((num_sign_bit_copies (XEXP (cond, 0), mode)
== GET_MODE_BITSIZE (mode))
- && (i = exact_log2 (- INTVAL (true))) >= 0)))
+ && (i = exact_log2 (- INTVAL (true_rtx))) >= 0)))
{
*general_simplify = 0;
return x;
diff --git a/gcc/config/mcore/t-mcore b/gcc/config/mcore/t-mcore
index baeb9d2780a..de526942f96 100644
--- a/gcc/config/mcore/t-mcore
+++ b/gcc/config/mcore/t-mcore
@@ -38,9 +38,6 @@ TARGET_LIBGCC2_CFLAGS=-O3 -DNO_FLOATLIB_FIXUNSDFSI #-msifilter
# We have values for float.h.
CROSS_FLOAT_H = $(srcdir)/config/mcore/gfloat.h
-# let the library provider supply an <assert.h>
-INSTALL_ASSERT_H=
-
# If support for -m4align is ever re-enabled then comment out the
# following line and uncomment the mutlilib lines below.
diff --git a/gcc/config/mcore/t-mcore-pe b/gcc/config/mcore/t-mcore-pe
index 6955c9905fa..c055a711399 100644
--- a/gcc/config/mcore/t-mcore-pe
+++ b/gcc/config/mcore/t-mcore-pe
@@ -29,9 +29,6 @@ TARGET_LIBGCC2_CFLAGS=-O3 -DNO_FLOATLIB_FIXUNSDFSI #-msifilter
# We have values for float.h.
CROSS_FLOAT_H = $(srcdir)/config/mcore/gfloat.h
-# let the library provider supply an <assert.h>
-INSTALL_ASSERT_H=
-
MULTILIB_OPTIONS = mbig-endian/mlittle-endian m210/m340
MULTILIB_DIRNAMES = big little m210 m340
MULTILIB_MATCHES =
diff --git a/gcc/config/mcore/xm-mcore.h b/gcc/config/mcore/xm-mcore.h
index 46b4eff5fd0..5210ee672b8 100644
--- a/gcc/config/mcore/xm-mcore.h
+++ b/gcc/config/mcore/xm-mcore.h
@@ -17,10 +17,6 @@ You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-/* #defines that need visibility everywhere. */
-#define FALSE 0
-#define TRUE 1
-
/* This describes the machine the compiler is hosted on. */
#define HOST_BITS_PER_CHAR 8
#define HOST_BITS_PER_SHORT 16
@@ -39,4 +35,3 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Arguments to use with `exit'. */
#define SUCCESS_EXIT_CODE 0
#define FATAL_EXIT_CODE 33
-
diff --git a/gcc/config/mips/abi64.h b/gcc/config/mips/abi64.h
index 95e7d82b9fc..b260d6ffc2e 100644
--- a/gcc/config/mips/abi64.h
+++ b/gcc/config/mips/abi64.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler. 64 bit ABI support.
- Copyright (C) 1994, 1995, 1996, 1998, 1999 Free Software Foundation, Inc.
+ Copyright (C) 1994, 1995, 1996, 1998, 1999, 2001 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -86,12 +86,17 @@ Boston, MA 02111-1307, USA. */
|| GET_MODE_CLASS (MODE) == MODE_INT))) \
? downward : upward))
+/* Under the old (i.e., 32 and O64 ABIs) all BLKmode objects are
+ returned in memory. Under the new (N32 and 64-bit MIPS ABIs) small
+ structures are returned in a register. Objects with varying size
+ must still be returned in memory, of course. */
#undef RETURN_IN_MEMORY
-#define RETURN_IN_MEMORY(TYPE) \
- ((mips_abi == ABI_32 || mips_abi == ABI_O64) \
- ? TYPE_MODE (TYPE) == BLKmode \
- : (int_size_in_bytes (TYPE) \
- > (2 * UNITS_PER_WORD)))
+#define RETURN_IN_MEMORY(TYPE) \
+ ((mips_abi == ABI_32 || mips_abi == ABI_O64) \
+ ? TYPE_MODE (TYPE) == BLKmode \
+ : ((int_size_in_bytes (TYPE) \
+ > (2 * UNITS_PER_WORD)) \
+ || (int_size_in_bytes (TYPE) == -1)))
#ifdef ANSI_PROTOTYPES
union tree_node;
diff --git a/gcc/config/mips/ecoff.h b/gcc/config/mips/ecoff.h
index dcc00a4b4b8..3297d7d4321 100644
--- a/gcc/config/mips/ecoff.h
+++ b/gcc/config/mips/ecoff.h
@@ -32,4 +32,5 @@ Boston, MA 02111-1307, USA. */
/* Don't assume anything about startfiles. The linker script will load the
appropriate startfiles. */
+#undef STARTFILE_SPEC
#define STARTFILE_SPEC ""
diff --git a/gcc/config/mips/elf.h b/gcc/config/mips/elf.h
index fa2a285239d..34d26c773da 100644
--- a/gcc/config/mips/elf.h
+++ b/gcc/config/mips/elf.h
@@ -53,6 +53,7 @@ do { \
specified using the `__attribute__ ((aligned (N)))' construct. If
not defined, the default value is `BIGGEST_ALIGNMENT'. */
+#undef MAX_OFILE_ALIGNMENT
#define MAX_OFILE_ALIGNMENT (32768*8)
/* A C statement to output something to the assembler file to switch to section
@@ -60,6 +61,7 @@ do { \
NULL_TREE. Some target formats do not support arbitrary sections. Do not
define this macro in such cases. */
+#undef ASM_OUTPUT_SECTION_NAME
#define ASM_OUTPUT_SECTION_NAME(F, DECL, NAME, RELOC) \
do { \
extern FILE *asm_out_text_file; \
@@ -191,6 +193,7 @@ do { \
but until that support is generally available, the 'if' below
should serve. */
+#undef ASM_WEAKEN_LABEL
#define ASM_WEAKEN_LABEL(FILE,NAME) ASM_OUTPUT_WEAK_ALIAS(FILE,NAME,0)
#define ASM_OUTPUT_WEAK_ALIAS(FILE,NAME,VALUE) \
do { \
@@ -210,6 +213,7 @@ do { \
#define MAKE_DECL_ONE_ONLY(DECL) (DECL_WEAK (DECL) = 1)
#undef UNIQUE_SECTION_P
#define UNIQUE_SECTION_P(DECL) (DECL_ONE_ONLY (DECL))
+#undef UNIQUE_SECTION
#define UNIQUE_SECTION(DECL,RELOC) \
do { \
int len, size, sec; \
@@ -331,6 +335,7 @@ void FN () \
/* A C statement (sans semicolon) to output an element in the table of
global constructors. */
+#undef ASM_OUTPUT_CONSTRUCTOR
#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \
do { \
ctors_section (); \
@@ -342,6 +347,7 @@ void FN () \
/* A C statement (sans semicolon) to output an element in the table of
global destructors. */
+#undef ASM_OUTPUT_DESTRUCTOR
#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \
do { \
dtors_section (); \
diff --git a/gcc/config/mips/elf64.h b/gcc/config/mips/elf64.h
index f0b00372230..0636200ed4b 100644
--- a/gcc/config/mips/elf64.h
+++ b/gcc/config/mips/elf64.h
@@ -54,6 +54,7 @@ Boston, MA 02111-1307, USA. */
specified using the `__attribute__ ((aligned (N)))' construct. If
not defined, the default value is `BIGGEST_ALIGNMENT'. */
+#undef MAX_OFILE_ALIGNMENT
#define MAX_OFILE_ALIGNMENT (32768*8)
/* We need to use .esize and .etype instead of .size and .type to
@@ -77,6 +78,7 @@ do { \
NULL_TREE. Some target formats do not support arbitrary sections. Do not
define this macro in such cases. */
+#undef ASM_OUTPUT_SECTION_NAME
#define ASM_OUTPUT_SECTION_NAME(F, DECL, NAME, RELOC) \
do { \
extern FILE *asm_out_text_file; \
@@ -172,6 +174,7 @@ do { \
but until that support is generally available, the 'if' below
should serve. */
+#undef ASM_WEAKEN_LABEL
#define ASM_WEAKEN_LABEL(FILE,NAME) ASM_OUTPUT_WEAK_ALIAS(FILE,NAME,0)
#define ASM_OUTPUT_WEAK_ALIAS(FILE,NAME,VALUE) \
do { \
@@ -191,6 +194,7 @@ do { \
#define MAKE_DECL_ONE_ONLY(DECL) (DECL_WEAK (DECL) = 1)
#undef UNIQUE_SECTION_P
#define UNIQUE_SECTION_P(DECL) (DECL_ONE_ONLY (DECL))
+#undef UNIQUE_SECTION
#define UNIQUE_SECTION(DECL,RELOC) \
do { \
int len, size, sec; \
@@ -311,6 +315,7 @@ void FN () \
/* A C statement (sans semicolon) to output an element in the table of
global constructors. */
+#undef ASM_OUTPUT_CONSTRUCTOR
#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \
do { \
ctors_section (); \
@@ -322,6 +327,7 @@ void FN () \
/* A C statement (sans semicolon) to output an element in the table of
global destructors. */
+#undef ASM_OUTPUT_DESTRUCTOR
#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \
do { \
dtors_section (); \
diff --git a/gcc/config/mips/gnu.h b/gcc/config/mips/gnu.h
index 599dc805e20..293f2234155 100644
--- a/gcc/config/mips/gnu.h
+++ b/gcc/config/mips/gnu.h
@@ -39,24 +39,6 @@ Boston, MA 02111-1307, USA. */
#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (MIPS GNU/ELF)");
-/* Output at beginning of assembler file. */
-/* The .file command should always begin the output. */
-#undef ASM_FILE_START
-#define ASM_FILE_START(FILE) \
- do { \
- mips_asm_file_start (FILE); \
- fprintf (FILE, "\t.version\t\"01.01\"\n"); \
- } while (0)
-
-#undef ASM_FILE_END
-#define ASM_FILE_END(FILE) \
- do { \
- mips_asm_file_end(FILE); \
- if (!flag_no_ident) \
- fprintf ((FILE), "%s\"GCC: (GNU) %s\"\n", \
- IDENT_ASM_OP, version_string); \
- } while (0)
-
#undef ASM_OUTPUT_SOURCE_LINE
#define ASM_OUTPUT_SOURCE_LINE(FILE, LINE) \
do { \
diff --git a/gcc/config/mips/iris4.h b/gcc/config/mips/iris4.h
index abdcda59318..db50f37c6aa 100644
--- a/gcc/config/mips/iris4.h
+++ b/gcc/config/mips/iris4.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler. Iris version 4.
- Copyright (C) 1991, 1993, 1999 Free Software Foundation, Inc.
+ Copyright (C) 1991, 1993, 1999, 2001 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -30,15 +30,16 @@ Boston, MA 02111-1307, USA. */
/* Some assemblers have a bug that causes backslash escaped chars in .ascii
to be misassembled, so we just completely avoid it. */
#undef ASM_OUTPUT_ASCII
-#define ASM_OUTPUT_ASCII(FILE,PTR,LEN) \
-do { \
- const unsigned char *s; \
- int i; \
- for (i = 0, s = (const unsigned char *)(PTR); i < (LEN); s++, i++) \
- { \
- if ((i % 8) == 0) \
- fputs ("\n\t.byte\t", (FILE)); \
- fprintf ((FILE), "%s0x%x", (i%8?",":""), (unsigned)*s); \
- } \
- fputs ("\n", (FILE)); \
+#define ASM_OUTPUT_ASCII(FILE,PTR,LEN) \
+do { \
+ const unsigned char *s_ = (const unsigned char *)(PTR); \
+ unsigned len_ = (LEN); \
+ unsigned i_; \
+ for (i_ = 0; i_ < len_; s_++, i_++) \
+ { \
+ if ((i_ % 8) == 0) \
+ fputs ("\n\t.byte\t", (FILE)); \
+ fprintf ((FILE), "%s0x%x", (i_%8?",":""), *s_); \
+ } \
+ fputs ("\n", (FILE)); \
} while (0)
diff --git a/gcc/config/mips/iris5.h b/gcc/config/mips/iris5.h
index 710a2ba64c8..eab210f9d44 100644
--- a/gcc/config/mips/iris5.h
+++ b/gcc/config/mips/iris5.h
@@ -1,5 +1,6 @@
/* Definitions of target machine for GNU compiler. Iris version 5.
- Copyright (C) 1993, 1995, 1996, 1998, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1995, 1996, 1998, 2000,
+ 2001 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -51,9 +52,9 @@ Boston, MA 02111-1307, USA. */
#undef WCHAR_TYPE_SIZE
#undef MAX_WCHAR_TYPE_SIZE
-#define WCHAR_TYPE "long int"
-#define WCHAR_TYPE_SIZE LONG_TYPE_SIZE
-#define MAX_WCHAR_TYPE_SIZE MAX_LONG_TYPE_SIZE
+#define WCHAR_TYPE "int"
+#define WCHAR_TYPE_SIZE INT_TYPE_SIZE
+#define MAX_WCHAR_TYPE_SIZE MAX_INT_TYPE_SIZE
#define WORD_SWITCH_TAKES_ARG(STR) \
(DEFAULT_WORD_SWITCH_TAKES_ARG (STR) \
@@ -154,6 +155,10 @@ do { \
fputs (" .text\n", FILE); \
} while (0)
+/* To get unaligned data, we have to turn off auto alignment. */
+#define UNALIGNED_SHORT_ASM_OP "\t.align 0\n\t.half\t"
+#define UNALIGNED_INT_ASM_OP "\t.align 0\n\t.word\t"
+
/* Also do this for libcalls. */
#define ASM_OUTPUT_EXTERNAL_LIBCALL(FILE, FUN) \
mips_output_external_libcall (FILE, XSTR (FUN, 0))
@@ -165,3 +170,26 @@ do { \
tree name_tree = get_identifier (NAME); \
TREE_ASM_WRITTEN (name_tree) = 1; \
} while (0)
+
+/* This is how we tell the assembler that a symbol is weak. */
+
+#define ASM_OUTPUT_WEAK_ALIAS(FILE, NAME, VALUE) \
+ do \
+ { \
+ ASM_GLOBALIZE_LABEL (FILE, NAME); \
+ fputs ("\t.weakext\t", FILE); \
+ assemble_name (FILE, NAME); \
+ if (VALUE) \
+ { \
+ fputc (' ', FILE); \
+ assemble_name (FILE, VALUE); \
+ } \
+ fputc ('\n', FILE); \
+ } \
+ while (0)
+
+#define ASM_WEAKEN_LABEL(FILE, NAME) ASM_OUTPUT_WEAK_ALIAS(FILE, NAME, 0)
+
+/* Handle #pragma weak and #pragma pack. */
+#undef HANDLE_SYSV_PRAGMA
+#define HANDLE_SYSV_PRAGMA 1
diff --git a/gcc/config/mips/iris6.h b/gcc/config/mips/iris6.h
index b7a6f8f64e3..5f0ca6aa350 100644
--- a/gcc/config/mips/iris6.h
+++ b/gcc/config/mips/iris6.h
@@ -39,6 +39,26 @@ Boston, MA 02111-1307, USA. */
we avoid creating such labels. */
#define DWARF2_GENERATE_TEXT_SECTION_LABEL 0
+/* wchar_t is defined differently with and without -mabi=64. */
+
+#define NO_BUILTIN_WCHAR_TYPE
+
+#undef WCHAR_TYPE
+#define WCHAR_TYPE (Pmode == DImode ? "int" : "long int")
+
+#undef WCHAR_TYPE_SIZE
+#define WCHAR_TYPE_SIZE 32
+
+/* Same for wint_t. */
+
+#define NO_BUILTIN_WINT_TYPE
+
+#undef WINT_TYPE
+#define WINT_TYPE (Pmode == DImode ? "int" : "long int")
+
+#undef WINT_TYPE_SIZE
+#define WINT_TYPE_SIZE 32
+
/* For Irix 6, -mabi=64 implies TARGET_LONG64. */
/* This is handled in override_options. */
@@ -57,10 +77,12 @@ Boston, MA 02111-1307, USA. */
#undef SUBTARGET_CPP_SIZE_SPEC
#define SUBTARGET_CPP_SIZE_SPEC "\
-%{mabi=32: -D__SIZE_TYPE__=unsigned\\ int -D__PTRDIFF_TYPE__=int} \
-%{mabi=n32: -D__SIZE_TYPE__=unsigned\\ int -D__PTRDIFF_TYPE__=int} \
-%{mabi=64: -D__SIZE_TYPE__=long\\ unsigned\\ int -D__PTRDIFF_TYPE__=long\\ int} \
-%{!mabi*: -D__SIZE_TYPE__=unsigned\\ int -D__PTRDIFF_TYPE__=int}"
+%{mabi=32|mabi=n32: -D__SIZE_TYPE__=unsigned\\ int -D__PTRDIFF_TYPE__=int \
+-D__WCHAR_TYPE__=long\\ int -D__WINT_TYPE__=long\\ int} \
+%{mabi=64: -D__SIZE_TYPE__=long\\ unsigned\\ int -D__PTRDIFF_TYPE__=long\\ int \
+-D__WCHAR_TYPE__=int -D__WINT_TYPE__=int} \
+%{!mabi*: -D__SIZE_TYPE__=unsigned\\ int -D__PTRDIFF_TYPE__=int \
+-D__WCHAR_TYPE__=long\\ int -D__WINT_TYPE__=long\\ int}"
/* We must make -mips3 do what -mlong64 used to do. */
/* ??? If no mipsX option given, but a mabi=X option is, then should set
@@ -128,16 +150,13 @@ Boston, MA 02111-1307, USA. */
#undef MACHINE_TYPE
#define MACHINE_TYPE "SGI running IRIX 6.x"
-/* The Irix 6.0.1 assembler doesn't like labels in the text section, so
- just avoid emitting them. */
-#define ASM_IDENTIFY_GCC(x) ((void)0)
-#define ASM_IDENTIFY_LANGUAGE(x) ((void)0)
-
/* Irix 5 stuff that we don't need for Irix 6. */
/* ??? We do need this for the -mabi=32 switch though. */
#undef ASM_OUTPUT_UNDEF_FUNCTION
#undef ASM_OUTPUT_EXTERNAL_LIBCALL
#undef ASM_DECLARE_FUNCTION_SIZE
+#undef UNALIGNED_SHORT_ASM_OP
+#undef UNALIGNED_INT_ASM_OP
/* Stuff we need for Irix 6 that isn't in Irix 5. */
@@ -188,27 +207,14 @@ Boston, MA 02111-1307, USA. */
#define TYPE_ASM_OP "\t.type\t"
#define SIZE_ASM_OP "\t.size\t"
-/* This is how we tell the assembler that a symbol is weak. */
-
-#define ASM_OUTPUT_WEAK_ALIAS(FILE,NAME,VALUE) \
- do { \
- ASM_GLOBALIZE_LABEL (FILE, NAME); \
- fputs ("\t.weakext\t", FILE); \
- assemble_name (FILE, NAME); \
- if (VALUE) \
- { \
- fputc (' ', FILE); \
- assemble_name (FILE, VALUE); \
- } \
- fputc ('\n', FILE); \
- } while (0)
-
-#define ASM_WEAKEN_LABEL(FILE,NAME) ASM_OUTPUT_WEAK_ALIAS(FILE,NAME,0)
-
/* Irix assembler does not support the init_priority C++ attribute. */
#undef SUPPORTS_INIT_PRIORITY
#define SUPPORTS_INIT_PRIORITY 0
+/* A linker error can empirically be avoided by removing duplicate
+ library search directories. */
+#define LINK_ELIMINATE_DUPLICATE_LDIRECTORIES 1
+
#define POPSECTION_ASM_OP "\t.popsection"
#define DEBUG_INFO_SECTION ".debug_info,0x7000001e,0,0,1"
@@ -269,9 +275,12 @@ Boston, MA 02111-1307, USA. */
#if _MIPS_SZPTR == 64
#define CTORS_SECTION_ASM_OP "\t.section\t.ctors,1,2,0,8"
#define DTORS_SECTION_ASM_OP "\t.section\t.dtors,1,2,0,8"
+#define EH_FRAME_SECTION_ASM_OP "\t.section\t.eh_frame,1,2,0,8"
#else /* _MIPS_SZPTR != 64 */
#define CTORS_SECTION_ASM_OP "\t.section\t.ctors,1,2,0,4"
#define DTORS_SECTION_ASM_OP "\t.section\t.dtors,1,2,0,4"
+#define EH_FRAME_SECTION_ASM_OP "\t.section\t.eh_frame,1,2,0,4"
+
#endif /* _MIPS_SZPTR == 64 */
#else /* ! (defined (CRT_BEGIN) || defined (CRT_END)) */
@@ -281,12 +290,10 @@ Boston, MA 02111-1307, USA. */
(Pmode == DImode ? "\t.section\t.ctors,1,2,0,8" : "\t.section\t.ctors,1,2,0,4")
#define DTORS_SECTION_ASM_OP \
(Pmode == DImode ? "\t.section\t.dtors,1,2,0,8" : "\t.section\t.dtors,1,2,0,4")
+#define EH_FRAME_SECTION_ASM_OP \
+ (Pmode == DImode ? "\t.section\t.eh_frame,1,2,0,8" : "\t.section\t.eh_frame,1,2,0,4")
#endif /* defined (CRT_BEGIN) || defined (CRT_END) */
-/* dwarf2out will handle padding this data properly. We definitely don't
- want it 8-byte aligned on n32. */
-#define EH_FRAME_SECTION_ASM_OP "\t.section\t.eh_frame,1,2,0,1"
-
/* 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
diff --git a/gcc/config/mips/irix6-libc-compat.c b/gcc/config/mips/irix6-libc-compat.c
new file mode 100644
index 00000000000..cc81ab5a109
--- /dev/null
+++ b/gcc/config/mips/irix6-libc-compat.c
@@ -0,0 +1,140 @@
+/* Compensate for inconsistent structure passing conventions on IRIX 6. */
+/* Compile this one with gcc. */
+/* Copyright (C) 2001 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+In addition to the permissions in the GNU General Public License, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file into combinations with other programs,
+and to distribute those combinations without any restriction coming
+from the use of this file. (The General Public License restrictions
+do apply in other respects; for example, they cover modification of
+the file, and distribution when not linked into a combine
+executable.)
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* GCC doesn't correctly implement the structure and union passing and return
+ conventions of the N32 and N64 ABIs on IRIX 6, as described in the
+ MIPSpro N32 ABI Handbook, ch. 2, Calling Convention Implementations, p.7.
+ The ABI requires that structures (or trailing parts of structures) smaller
+ than 8 bytes (a 64-bit register) are left-justified, whereas GCC
+ right-justifies them.
+
+ While GCC is internally consistent, calling routines compiled with a
+ compiler that does implement the documented ABI (like SGIs MIPSpro C
+ compiler) doesn't work. This is primarily an issue for system libraries
+ like libc. Fortunately, there exist only very few routines that take
+ structure value arguments or return structures by value, so until the
+ underlying bug is fixed, it is possible to work around it by providing
+ wrapper functions for the few affected routines that compensate for the
+ inconsistent alignment.
+
+ These wrappers rely on the fact that e.g. libc contains weak versions of
+ those routines, and the real implementation is provided by _-prefixed
+ variants. So we can provide our own versions, which will only be linked
+ if the application uses any of the affected functions, calling the private
+ variants after shifting the arguments or results as required.
+
+ This is a rewrite of code created by Andy Polyakov. */
+
+#include "config.h"
+#include "system.h"
+
+/* This must only be used for the N32 and N64 ABIs. O32 is correct. */
+
+#if _MIPS_SIM == _ABIN32 || _MIPS_SIM == _ABI64
+
+/* The affected arguments need to be shifted by
+
+ BITS_PER_WORD - (sizeof (arg) * BITS_PER_UNIT).
+
+ Since only 32-bit args and results are involved, the shift count is
+ always 32. */
+#define SHIFT_BITS 32
+
+extern machreg_t _inet_ntoa PARAMS ((machreg_t));
+extern machreg_t _inet_lnaof PARAMS ((machreg_t));
+extern machreg_t _inet_netof PARAMS ((machreg_t));
+extern machreg_t _inet_makeaddr PARAMS ((machreg_t, machreg_t));
+
+/* <arpa/inet.h> has
+
+ char *inet_ntoa (struct in_addr);
+
+ on both IRIX 6.2 and 6.5, with struct in_addr containing a 32-bit int. */
+
+machreg_t
+inet_ntoa (machreg_t in)
+{
+ return _inet_ntoa (in << SHIFT_BITS);
+}
+
+/* <arpa/inet.h> has
+
+ unsigned long inet_lnaof (struct in_addr); (IRIX 6.2)
+ in_addr_t inet_lnaof (struct in_addr); (IRIX 6.5)
+
+ in_addr_t is a 32-bit int. */
+
+machreg_t
+inet_lnaof (machreg_t in)
+{
+ return _inet_lnaof (in << SHIFT_BITS);
+}
+
+/* <arpa/inet.h> has
+
+ unsigned long inet_netof (struct in_addr); (IRIX 6.2)
+ in_addr_t inet_netof (struct in_addr); (IRIX 6.5) */
+
+machreg_t
+inet_netof (machreg_t in)
+{
+ return _inet_netof (in << SHIFT_BITS);
+}
+
+/* <arpa/inet.h> has
+
+ struct in_addr inet_makeaddr (int, int); (IRIX 6.2)
+ struct in_addr inet_makeaddr (in_addr_t, in_addr_t); (IRIX 6.5) */
+
+machreg_t
+inet_makeaddr (machreg_t net, machreg_t lna)
+{
+ return _inet_makeaddr (net, lna) >> SHIFT_BITS;
+}
+
+#if _MIPS_SIM == _ABIN32
+extern machreg_t _semctl PARAMS ((machreg_t, machreg_t, machreg_t, machreg_t));
+
+/* <sys/sem.h> has
+
+ int semctl (int, int, int, ...);
+
+ where the variadic argument is union semun if used. union semun contains
+ an int and two pointers, so the union is already 64 bits wide under the
+ N64 ABI and alignment is not an issue. */
+
+machreg_t
+semctl (machreg_t semid, machreg_t semnum, machreg_t cmd, machreg_t arg)
+{
+ return _semctl(semid, semnum, cmd, arg << SHIFT_BITS);
+}
+#endif /* _ABIN32 */
+
+#endif /* _ABIN32 || _ABI64 */
diff --git a/gcc/config/mips/linux.h b/gcc/config/mips/linux.h
index e6dccb9d414..39adfe36dc7 100644
--- a/gcc/config/mips/linux.h
+++ b/gcc/config/mips/linux.h
@@ -28,16 +28,6 @@ Boston, MA 02111-1307, USA. */
#undef MD_EXEC_PREFIX
#undef MD_STARTFILE_PREFIX
-/* Output at beginning of assembler file. */
-/* The .file command should always begin the output. */
-#undef ASM_FILE_START
-#define ASM_FILE_START(FILE) \
- do { \
- mips_asm_file_start (FILE); \
- fprintf (FILE, "\t.version\t\"01.01\"\n"); \
- } while (0)
-
-
/* Required to keep collect2.c happy */
#undef OBJECT_FORMAT_COFF
@@ -47,6 +37,7 @@ Boston, MA 02111-1307, USA. */
/* Handle #pragma weak and #pragma pack. */
+#undef HANDLE_SYSV_PRAGMA
#define HANDLE_SYSV_PRAGMA 1
/* Use more efficient ``thunks'' to implement C++ vtables. */
@@ -118,6 +109,13 @@ Boston, MA 02111-1307, USA. */
%{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} \
%{pthread:-D_REENTRANT}"
+/* The GNU C++ standard library requires that these macros be defined. */
+#undef CPLUSPLUS_CPP_SPEC
+#define CPLUSPLUS_CPP_SPEC "\
+-D__LANGUAGE_C_PLUS_PLUS -D_LANGUAGE_C_PLUS_PLUS \
+-D_GNU_SOURCE %(cpp) \
+"
+
/* Provide a STARTFILE_SPEC appropriate for GNU/Linux. Here we add
the GNU/Linux magical crtbegin.o file (see crtstuff.c) which
provides part of the support for getting C++ file-scope static
@@ -170,3 +168,92 @@ Boston, MA 02111-1307, USA. */
%{mabi=64: -64} \
%{!fno-PIC:%{!fno-pic:-KPIC}} \
%{fno-PIC:-non_shared} %{fno-pic:-non_shared}"
+
+/* We don't need those nonsenses. */
+#undef INVOKE__main
+#undef CTOR_LIST_BEGIN
+#undef CTOR_LIST_END
+#undef DTOR_LIST_BEGIN
+#undef DTOR_LIST_END
+
+/* The MIPS assembler has different syntax for .set. We set it to
+ .dummy to trap any errors. */
+#undef SET_ASM_OP
+#define SET_ASM_OP "\t.dummy\t"
+
+#undef ASM_OUTPUT_SOURCE_LINE
+#define ASM_OUTPUT_SOURCE_LINE(FILE, LINE) \
+do \
+ { \
+ static int sym_lineno = 1; \
+ fprintf (FILE, "%sLM%d:\n\t%s 68,0,%d,%sLM%d", \
+ LOCAL_LABEL_PREFIX, sym_lineno, ASM_STABN_OP, \
+ LINE, LOCAL_LABEL_PREFIX, sym_lineno); \
+ putc ('-', FILE); \
+ assemble_name (FILE, \
+ XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0));\
+ putc ('\n', FILE); \
+ sym_lineno++; \
+ } \
+while (0)
+
+/* This is how we tell the assembler that two symbols have the
+ same value. */
+#undef ASM_OUTPUT_DEF
+#define ASM_OUTPUT_DEF(FILE,LABEL1,LABEL2) \
+ do { \
+ fprintf ((FILE), "\t"); \
+ assemble_name (FILE, LABEL1); \
+ fprintf (FILE, "="); \
+ assemble_name (FILE, LABEL2); \
+ fprintf (FILE, "\n"); \
+ } while (0)
+
+#undef ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL
+#define ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL(FILE, SY, HI, LO) \
+ do { \
+ fputc ('\t', FILE); \
+ assemble_name (FILE, SY); \
+ fputc ('=', FILE); \
+ assemble_name (FILE, HI); \
+ fputc ('-', FILE); \
+ assemble_name (FILE, LO); \
+ } while (0)
+
+#undef ASM_DECLARE_FUNCTION_NAME
+#define ASM_DECLARE_FUNCTION_NAME(STREAM, NAME, DECL) \
+ do { \
+ if (!flag_inhibit_size_directive) \
+ { \
+ fputs ("\t.ent\t", STREAM); \
+ assemble_name (STREAM, NAME); \
+ putc ('\n', STREAM); \
+ } \
+ fprintf (STREAM, "\t%s\t ", TYPE_ASM_OP); \
+ assemble_name (STREAM, NAME); \
+ putc (',', STREAM); \
+ fprintf (STREAM, TYPE_OPERAND_FMT, "function"); \
+ putc ('\n', STREAM); \
+ assemble_name (STREAM, NAME); \
+ fputs (":\n", STREAM); \
+ } while (0)
+
+#undef ASM_DECLARE_FUNCTION_SIZE
+#define ASM_DECLARE_FUNCTION_SIZE(STREAM, NAME, DECL) \
+ do { \
+ if (!flag_inhibit_size_directive) \
+ { \
+ fputs ("\t.end\t", STREAM); \
+ assemble_name (STREAM, NAME); \
+ putc ('\n', STREAM); \
+ } \
+ } while (0)
+
+/* Tell function_prologue in mips.c that we have already output the .ent/.end
+ pseudo-ops. */
+#define FUNCTION_NAME_ALREADY_DECLARED
+
+/* Output #ident as a .ident. */
+#undef ASM_OUTPUT_IDENT
+#define ASM_OUTPUT_IDENT(FILE, NAME) \
+ fprintf (FILE, "\t%s\t\"%s\"\n", IDENT_ASM_OP, NAME);
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 1f19c98028e..f98408af645 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -36,9 +36,7 @@ Boston, MA 02111-1307, USA. */
#include "real.h"
#include "insn-config.h"
#include "conditions.h"
-#include "insn-flags.h"
#include "insn-attr.h"
-#include "insn-codes.h"
#include "recog.h"
#include "toplev.h"
#include "output.h"
@@ -6279,6 +6277,20 @@ compute_frame_size (size)
}
}
+ /* We need to restore these for the handler. */
+ if (current_function_calls_eh_return)
+ {
+ int i;
+ for (i = 0; ; ++i)
+ {
+ regno = EH_RETURN_DATA_REGNO (i);
+ if (regno == INVALID_REGNUM)
+ break;
+ gp_reg_size += GET_MODE_SIZE (gpr_mode);
+ mask |= 1L << (regno - GP_REG_FIRST);
+ }
+ }
+
/* Calculate space needed for fp registers. */
if (TARGET_FLOAT64 || TARGET_SINGLE_FLOAT)
{
@@ -7115,13 +7127,22 @@ mips_expand_prologue ()
for (i = 0; i < num; i++)
{
- rtx pattern = RTVEC_ELT (adjust, i);
+ rtx insn, pattern;
+
+ pattern = RTVEC_ELT (adjust, i);
if (GET_CODE (pattern) != SET
|| GET_CODE (SET_SRC (pattern)) != ASHIFT)
abort_with_insn (pattern, "Insn is not a shift");
-
PUT_CODE (SET_SRC (pattern), ASHIFTRT);
- emit_insn (pattern);
+
+ insn = emit_insn (pattern);
+
+ /* Global life information isn't valid at this point, so we
+ can't check whether these shifts are actually used. Mark
+ them MAYBE_DEAD so that flow2 will remove them, and not
+ complain about dead code in the prologue. */
+ REG_NOTES(insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, NULL_RTX,
+ REG_NOTES (insn));
}
}
@@ -7557,13 +7578,27 @@ mips_expand_epilogue ()
if (tsize > 32767 && TARGET_MIPS16)
abort ();
+ if (current_function_calls_eh_return)
+ {
+ rtx eh_ofs = EH_RETURN_STACKADJ_RTX;
+ if (Pmode == DImode)
+ emit_insn (gen_adddi3 (eh_ofs, eh_ofs, tsize_rtx));
+ else
+ emit_insn (gen_addsi3 (eh_ofs, eh_ofs, tsize_rtx));
+ tsize_rtx = eh_ofs;
+ }
+
emit_insn (gen_blockage ());
- if (Pmode == DImode && tsize != 0)
- emit_insn (gen_adddi3 (stack_pointer_rtx, stack_pointer_rtx,
- tsize_rtx));
- else if (tsize != 0)
- emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
- tsize_rtx));
+
+ if (tsize != 0 || current_function_calls_eh_return)
+ {
+ if (Pmode == DImode)
+ emit_insn (gen_adddi3 (stack_pointer_rtx, stack_pointer_rtx,
+ tsize_rtx));
+ else
+ emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
+ tsize_rtx));
+ }
}
/* The mips16 loads the return address into $7, not $31. */
diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h
index 1510ecc445d..fba6416827b 100644
--- a/gcc/config/mips/mips.h
+++ b/gcc/config/mips/mips.h
@@ -1079,6 +1079,7 @@ while (0)
/* On Sun 4, this limit is 2048. We use 1500 to be safe,
since the length can run past this up to a continuation point. */
+#undef DBX_CONTIN_LENGTH
#define DBX_CONTIN_LENGTH 1500
/* How to renumber registers for dbx and gdb. */
@@ -1097,6 +1098,10 @@ while (0)
/* Before the prologue, RA lives in r31. */
#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (VOIDmode, GP_REG_FIRST + 31)
+/* Describe how we implement __builtin_eh_return. */
+#define EH_RETURN_DATA_REGNO(N) ((N) < 4 ? (N) + GP_ARG_FIRST : INVALID_REGNUM)
+#define EH_RETURN_STACKADJ_RTX gen_rtx_REG (Pmode, GP_REG_FIRST + 3)
+
/* Overrides for the COFF debug format. */
#define PUT_SDB_SCL(a) \
do { \
@@ -3782,6 +3787,7 @@ while (0)
declaration when the code is processed, it generates a two
instruction sequence. */
+#undef ASM_FILE_START
#define ASM_FILE_START(STREAM) mips_asm_file_start (STREAM)
/* Output to assembler file text saying following lines
@@ -4093,6 +4099,7 @@ while (0)
#define LABEL_AFTER_LOC(STREAM)
#endif
+#undef ASM_OUTPUT_SOURCE_LINE
#define ASM_OUTPUT_SOURCE_LINE(STREAM, LINE) \
mips_output_lineno (STREAM, LINE)
@@ -4133,6 +4140,7 @@ do { \
If this macro is not defined, then the variable name is defined
in the usual manner as a label (by means of `ASM_OUTPUT_LABEL'). */
+#undef ASM_DECLARE_OBJECT_NAME
#define ASM_DECLARE_OBJECT_NAME(STREAM, NAME, DECL) \
do \
{ \
@@ -4193,6 +4201,7 @@ while (0)
mips_output_external(STREAM,DECL,NAME)
/* This says what to print at the end of the assembly file */
+#undef ASM_FILE_END
#define ASM_FILE_END(STREAM) mips_asm_file_end(STREAM)
@@ -4203,6 +4212,7 @@ while (0)
Also, switch files if we are optimizing the global pointer. */
+#undef ASM_DECLARE_FUNCTION_NAME
#define ASM_DECLARE_FUNCTION_NAME(STREAM,NAME,DECL) \
{ \
extern FILE *asm_out_text_file; \
@@ -4225,6 +4235,7 @@ while (0)
/* This is how to output an internal numbered label where
PREFIX is the class of label and NUM is the number within the class. */
+#undef ASM_OUTPUT_INTERNAL_LABEL
#define ASM_OUTPUT_INTERNAL_LABEL(STREAM,PREFIX,NUM) \
fprintf (STREAM, "%s%s%d:\n", LOCAL_LABEL_PREFIX, PREFIX, NUM)
@@ -4233,6 +4244,7 @@ while (0)
PREFIX is the class of label and NUM is the number within the class.
This is suitable for output with `assemble_name'. */
+#undef ASM_GENERATE_INTERNAL_LABEL
#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
sprintf ((LABEL), "*%s%s%ld", (LOCAL_LABEL_PREFIX), (PREFIX), (long)(NUM))
@@ -4348,6 +4360,7 @@ do { \
JUMP_TABLES_IN_TEXT_SECTION, because it is not conditional.
Instead, we use ASM_OUTPUT_CASE_LABEL to switch back to the .text
section if appropriate. */
+#undef ASM_OUTPUT_CASE_LABEL
#define ASM_OUTPUT_CASE_LABEL(FILE, PREFIX, NUM, INSN) \
do { \
if (TARGET_EMBEDDED_PIC || TARGET_MIPS16) \
@@ -4365,75 +4378,77 @@ do { \
/* This is how to output an assembler line to advance the location
counter by SIZE bytes. */
+#undef ASM_OUTPUT_SKIP
#define ASM_OUTPUT_SKIP(STREAM,SIZE) \
fprintf (STREAM, "\t.space\t%u\n", (SIZE))
/* This is how to output a string. */
+#undef ASM_OUTPUT_ASCII
#define ASM_OUTPUT_ASCII(STREAM, STRING, LEN) \
do { \
- register int i, c, len = (LEN), cur_pos = 17; \
- register const unsigned char *string = \
+ register int i_, len_ = (LEN), cur_pos_ = 17; \
+ register const unsigned char *string_ = \
(const unsigned char *)(STRING); \
fprintf ((STREAM), "\t.ascii\t\""); \
- for (i = 0; i < len; i++) \
+ for (i_ = 0; i_ < len_; i_++) \
{ \
- register int c = string[i]; \
+ register int c_ = string_[i_]; \
\
- switch (c) \
+ switch (c_) \
{ \
case '\"': \
case '\\': \
putc ('\\', (STREAM)); \
- putc (c, (STREAM)); \
- cur_pos += 2; \
+ putc (c_, (STREAM)); \
+ cur_pos_ += 2; \
break; \
\
case TARGET_NEWLINE: \
fputs ("\\n", (STREAM)); \
- if (i+1 < len \
- && (((c = string[i+1]) >= '\040' && c <= '~') \
- || c == TARGET_TAB)) \
- cur_pos = 32767; /* break right here */ \
+ if (i_+1 < len_ \
+ && (((c_ = string_[i_+1]) >= '\040' && c_ <= '~') \
+ || c_ == TARGET_TAB)) \
+ cur_pos_ = 32767; /* break right here */ \
else \
- cur_pos += 2; \
+ cur_pos_ += 2; \
break; \
\
case TARGET_TAB: \
fputs ("\\t", (STREAM)); \
- cur_pos += 2; \
+ cur_pos_ += 2; \
break; \
\
case TARGET_FF: \
fputs ("\\f", (STREAM)); \
- cur_pos += 2; \
+ cur_pos_ += 2; \
break; \
\
case TARGET_BS: \
fputs ("\\b", (STREAM)); \
- cur_pos += 2; \
+ cur_pos_ += 2; \
break; \
\
case TARGET_CR: \
fputs ("\\r", (STREAM)); \
- cur_pos += 2; \
+ cur_pos_ += 2; \
break; \
\
default: \
- if (c >= ' ' && c < 0177) \
+ if (c_ >= ' ' && c_ < 0177) \
{ \
- putc (c, (STREAM)); \
- cur_pos++; \
+ putc (c_, (STREAM)); \
+ cur_pos_++; \
} \
else \
{ \
- fprintf ((STREAM), "\\%03o", c); \
- cur_pos += 4; \
+ fprintf ((STREAM), "\\%03o", c_); \
+ cur_pos_ += 4; \
} \
} \
\
- if (cur_pos > 72 && i+1 < len) \
+ if (cur_pos_ > 72 && i_+1 < len_) \
{ \
- cur_pos = 17; \
+ cur_pos_ = 17; \
fprintf ((STREAM), "\"\n\t.ascii\t\""); \
} \
} \
@@ -4444,6 +4459,7 @@ do { \
#define SCCS_DIRECTIVE
/* Output #ident as a in the read-only data section. */
+#undef ASM_OUTPUT_IDENT
#define ASM_OUTPUT_IDENT(FILE, STRING) \
{ \
const char *p = STRING; \
@@ -4462,11 +4478,13 @@ do { \
#define DATA_SECTION_ASM_OP "\t.data" /* large data */
#define SDATA_SECTION_ASM_OP "\t.sdata" /* small data */
#define RDATA_SECTION_ASM_OP "\t.rdata" /* read-only data */
+#undef READONLY_DATA_SECTION
#define READONLY_DATA_SECTION rdata_section
#define SMALL_DATA_SECTION sdata_section
/* What other sections we support other than the normal .data/.text. */
+#undef EXTRA_SECTIONS
#define EXTRA_SECTIONS in_sdata, in_rdata
/* Define the additional functions to select our additional sections. */
@@ -4479,6 +4497,7 @@ do { \
if the constant is too large for sdata, and it's readonly, it
will go into the .rdata section. */
+#undef EXTRA_SECTION_FUNCTIONS
#define EXTRA_SECTION_FUNCTIONS \
void \
sdata_section () \
@@ -4503,8 +4522,10 @@ rdata_section () \
/* Given a decl node or constant node, choose the section to output it in
and select that section. */
+#undef SELECT_RTX_SECTION
#define SELECT_RTX_SECTION(MODE,RTX) mips_select_rtx_section (MODE, RTX)
+#undef SELECT_SECTION
#define SELECT_SECTION(DECL, RELOC) mips_select_section (DECL, RELOC)
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index a37464e569f..ee0c5ddbfa3 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -26,6 +26,27 @@
;; ??? Currently does not have define_function_unit support for the R8000.
;; Must include new entries for fmadd in addition to existing entries.
+;; UNSPEC values used in mips.md
+;; Number USE
+;; 0 movsi_ul
+;; 1 movsi_us, get_fnaddr
+;; 3 eh_set_return
+;; 20 builtin_setjmp_setup
+;;
+;; UNSPEC_VOLATILE values
+;; 0 blockage
+;; 2 loadgp
+;; 3 builtin_longjmp
+;; 4 exception_receiver
+;; 10 consttable_qi
+;; 11 consttable_hi
+;; 12 consttable_si
+;; 13 consttable_di
+;; 14 consttable_sf
+;; 15 consttable_df
+;; 16 align_2
+;; 17 align_4
+;; 18 align_8
;; ....................
@@ -5087,7 +5108,7 @@ move\\t%0,%z4\\n\\
;; use a TImode scratch reg.
(define_expand "reload_outdi"
- [(set (match_operand:DI 0 "" "=b")
+ [(set (match_operand:DI 0 "general_operand" "=b")
(match_operand:DI 1 "se_register_operand" "b"))
(clobber (match_operand:TI 2 "register_operand" "=&d"))]
"TARGET_64BIT"
@@ -9468,6 +9489,93 @@ ld\\t%2,%1-%S1(%2)\;daddu\\t%2,%2,$31\;j\\t%2"
(set_attr "mode" "none")
(set_attr "length" "16")])
+;; This is used in compiling the unwind routines.
+(define_expand "eh_return"
+ [(use (match_operand 0 "general_operand" ""))
+ (use (match_operand 1 "general_operand" ""))]
+ ""
+ "
+{
+ enum machine_mode gpr_mode = TARGET_64BIT ? DImode : SImode;
+
+ if (GET_MODE (operands[1]) != gpr_mode)
+ operands[1] = convert_to_mode (gpr_mode, operands[1], 0);
+ if (TARGET_64BIT)
+ emit_insn (gen_eh_set_lr_di (operands[1]));
+ else
+ emit_insn (gen_eh_set_lr_si (operands[1]));
+
+ emit_move_insn (EH_RETURN_STACKADJ_RTX, operands[0]);
+ DONE;
+}")
+
+;; Clobber the return address on the stack. We can't expand this
+;; until we know where it will be put in the stack frame.
+
+(define_insn "eh_set_lr_si"
+ [(unspec [(match_operand:SI 0 "register_operand" "r")] 3)
+ (clobber (match_scratch:SI 1 "=&r"))]
+ "! TARGET_64BIT"
+ "#")
+
+(define_insn "eh_set_lr_di"
+ [(unspec [(match_operand:DI 0 "register_operand" "r")] 3)
+ (clobber (match_scratch:DI 1 "=&r"))]
+ "TARGET_64BIT"
+ "#")
+
+(define_split
+ [(unspec [(match_operand 0 "register_operand" "r")] 3)
+ (clobber (match_scratch 1 "=&r"))]
+ "reload_completed"
+ [(const_int 0)]
+ "
+{
+ HOST_WIDE_INT gp_offset;
+ rtx base;
+
+ compute_frame_size (get_frame_size ());
+ if (((current_frame_info.mask >> 31) & 1) == 0)
+ abort ();
+ gp_offset = current_frame_info.gp_sp_offset;
+
+ if (gp_offset < 32768)
+ base = stack_pointer_rtx;
+ else
+ {
+ base = operands[1];
+ emit_move_insn (base, GEN_INT (gp_offset));
+ if (Pmode == DImode)
+ emit_insn (gen_adddi3 (base, base, stack_pointer_rtx));
+ else
+ emit_insn (gen_addsi3 (base, base, stack_pointer_rtx));
+ gp_offset = 0;
+ }
+ emit_move_insn (gen_rtx_MEM (GET_MODE (operands[0]),
+ plus_constant (base, gp_offset)),
+ operands[0]);
+ DONE;
+}")
+
+(define_insn "exception_receiver"
+ [(unspec_volatile [(const_int 0)] 4)]
+ "TARGET_ABICALLS && (mips_abi == ABI_32 || mips_abi == ABI_O64)"
+ "*
+{
+ rtx loc;
+
+ operands[0] = pic_offset_table_rtx;
+ if (frame_pointer_needed)
+ loc = hard_frame_pointer_rtx;
+ else
+ loc = stack_pointer_rtx;
+ loc = plus_constant (loc, current_frame_info.args_size);
+ operands[1] = gen_rtx_MEM (Pmode, loc);
+
+ return mips_move_1word (operands, insn, 0);
+}"
+ [(set_attr "type" "load")
+ (set_attr "length" "8")])
;;
;; ....................
diff --git a/gcc/config/mips/osfrose.h b/gcc/config/mips/osfrose.h
index e9ab26b07c3..26fc7448dab 100644
--- a/gcc/config/mips/osfrose.h
+++ b/gcc/config/mips/osfrose.h
@@ -115,32 +115,3 @@ Boston, MA 02111-1307, USA. */
/* Generate calls to memcpy, etc., not bcopy, etc. */
#define TARGET_MEM_FUNCTIONS
-
-/* A C statement to output assembler commands which will identify
- the object file as having been compiled with GNU CC (or another
- GNU compiler).
-
- If you don't define this macro, the string `gcc2_compiled.:' is
- output. This string is calculated to define a symbol which, on
- BSD systems, will never be defined for any other reason. GDB
- checks for the presence of this symbol when reading the symbol
- table of an executable.
-
- On non-BSD systems, you must arrange communication with GDB in
- some other fashion. If GDB is not used on your system, you can
- define this macro with an empty body.
-
- On OSF/1, gcc2_compiled. confuses the kernel debugger, so don't
- put it out. */
-
-#define ASM_IDENTIFY_GCC(STREAM)
-
-/* Identify the front-end which produced this file. To keep symbol
- space down, and not confuse kdb, only do this if the language is
- not C. */
-
-#define ASM_IDENTIFY_LANGUAGE(STREAM) \
-{ \
- if (strcmp (lang_identify (), "c") != 0) \
- output_lang_identify (STREAM); \
-}
diff --git a/gcc/config/mips/sni-svr4.h b/gcc/config/mips/sni-svr4.h
index 077b96be1be..702a4e42727 100644
--- a/gcc/config/mips/sni-svr4.h
+++ b/gcc/config/mips/sni-svr4.h
@@ -68,15 +68,6 @@ Boston, MA 02111-1307, USA. */
#define NM_FLAGS "-p"
-/* wir haben ein Problem, wenn in einem Assembler-File keine .text-section
- erzeugt wird. Dann landen diese Pseudo-Labels in irgendeiner anderen
- section, z.B. .reginfo. Das macht den ld sehr ungluecklich. */
-
-#define ASM_IDENTIFY_GCC(mw_stream) \
- fprintf(mw_stream, "\t.ident \"gcc2_compiled.\"\n");
-
-#define ASM_IDENTIFY_LANGUAGE(STREAM)
-
#define ASM_LONG ".word\t"
#define ASM_GLOBAL ".rdata\n\t\t.globl\t"
diff --git a/gcc/config/mips/t-iris6 b/gcc/config/mips/t-iris6
index 6fab3fcf9ce..33a4d403e9a 100644
--- a/gcc/config/mips/t-iris6
+++ b/gcc/config/mips/t-iris6
@@ -22,10 +22,10 @@ CRTSTUFF_T_CFLAGS=-g1
# Build a shared libgcc library.
SHLIB_EXT = .so
SHLIB_LINK = $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) -shared -nodefaultlibs \
- -Wl,-soname,@shlib_base_name@.so.0 \
+ -Wl,-soname,@shlib_base_name@.so.1 \
-o @shlib_base_name@.so @multilib_flags@ @shlib_objs@ -lc && \
- rm -f @shlib_base_name@.so.0 && \
- $(LN_S) @shlib_base_name@.so @shlib_base_name@.so.0
+ rm -f @shlib_base_name@.so.1 && \
+ $(LN_S) @shlib_base_name@.so @shlib_base_name@.so.1
# ??? Irix 6.5 seems to eat the option fine (if we somehow remove the
# -hidden_symbol option, which is documented to be ignored in conjunction
# with -exports_file), but fails to actually hide any symbols.
@@ -33,9 +33,9 @@ SHLIB_LINK = $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) -shared -nodefaultlibs \
# $(slibdir) double quoted to protect it from expansion while building
# libgcc.mk. We want this delayed until actual install time.
-SHLIB_INSTALL = $(INSTALL_DATA) @shlib_base_name@.so $$(slibdir)/@shlib_base_name@.so.0; \
+SHLIB_INSTALL = $(INSTALL_DATA) @shlib_base_name@.so $$(slibdir)/@shlib_base_name@.so.1; \
rm -f $$(slibdir)/@shlib_base_name@.so; \
- $(LN_S) @shlib_base_name@.so.0 $$(slibdir)/@shlib_base_name@.so
+ $(LN_S) @shlib_base_name@.so.1 $$(slibdir)/@shlib_base_name@.so
SHLIB_MKMAP = $(srcdir)/mkmap-flat.awk
SHLIB_MAPFILES = $(srcdir)/libgcc-std.ver
@@ -53,3 +53,7 @@ fp-bit.c: $(srcdir)/config/fp-bit.c
echo '#define FLOAT' > fp-bit.c
echo '#undef US_SOFTWARE_GOFAST' >> fp-bit.c
cat $(srcdir)/config/fp-bit.c >> fp-bit.c
+
+# This is only needed in the static libgcc as a band-aid until gcc correctly
+# implements the N32/N64 ABI structure passing conventions
+LIB2FUNCS_STATIC_EXTRA = $(srcdir)/config/mips/irix6-libc-compat.c
diff --git a/gcc/config/mips/xm-mips.h b/gcc/config/mips/xm-mips.h
index ad49d7f4837..fcb31965c02 100644
--- a/gcc/config/mips/xm-mips.h
+++ b/gcc/config/mips/xm-mips.h
@@ -18,11 +18,6 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-
-/* #defines that need visibility everywhere. */
-#define FALSE 0
-#define TRUE 1
-
/* This describes the machine the compiler is hosted on. */
#define HOST_BITS_PER_CHAR 8
#define HOST_BITS_PER_SHORT 16
diff --git a/gcc/config/mn10200/mn10200.c b/gcc/config/mn10200/mn10200.c
index 9cafc33a114..1e520a84c60 100644
--- a/gcc/config/mn10200/mn10200.c
+++ b/gcc/config/mn10200/mn10200.c
@@ -28,7 +28,6 @@ Boston, MA 02111-1307, USA. */
#include "real.h"
#include "insn-config.h"
#include "conditions.h"
-#include "insn-flags.h"
#include "output.h"
#include "insn-attr.h"
#include "flags.h"
diff --git a/gcc/config/mn10200/t-mn10200 b/gcc/config/mn10200/t-mn10200
index 072d6f42b88..82f8a88439f 100644
--- a/gcc/config/mn10200/t-mn10200
+++ b/gcc/config/mn10200/t-mn10200
@@ -28,7 +28,9 @@ LIB1ASMFUNCS = _divhi3 \
_prologue \
_epilogue_a0 \
_epilogue_d0 \
- _epilogue_noreturn
+ _epilogue_noreturn \
+ _floatdisf \
+ _fixsfdi
# We do not have DF or DI types, so fake out the libgcc2 compilation.
diff --git a/gcc/config/mn10200/xm-mn10200.h b/gcc/config/mn10200/xm-mn10200.h
index 5e291d0991a..68baf3f06d2 100644
--- a/gcc/config/mn10200/xm-mn10200.h
+++ b/gcc/config/mn10200/xm-mn10200.h
@@ -19,10 +19,6 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* #defines that need visibility everywhere. */
-#define FALSE 0
-#define TRUE 1
-
/* This describes the machine the compiler is hosted on. */
#define HOST_BITS_PER_CHAR 8
#define HOST_BITS_PER_SHORT 16
diff --git a/gcc/config/mn10300/mn10300.c b/gcc/config/mn10300/mn10300.c
index bc6b1fc3c87..225c8789994 100644
--- a/gcc/config/mn10300/mn10300.c
+++ b/gcc/config/mn10300/mn10300.c
@@ -28,7 +28,6 @@ Boston, MA 02111-1307, USA. */
#include "real.h"
#include "insn-config.h"
#include "conditions.h"
-#include "insn-flags.h"
#include "output.h"
#include "insn-attr.h"
#include "flags.h"
diff --git a/gcc/config/mn10300/mn10300.h b/gcc/config/mn10300/mn10300.h
index e6425376e63..ebb6784ca70 100644
--- a/gcc/config/mn10300/mn10300.h
+++ b/gcc/config/mn10300/mn10300.h
@@ -698,7 +698,9 @@ struct cum_arg {int nbytes; };
&& INT_8_BITS (INTVAL (XEXP (XEXP (OP, 0), 1))))))
#define EXTRA_CONSTRAINT(OP, C) \
- ((C) == 'R' ? OK_FOR_R (OP) : (C) == 'S' ? GET_CODE (OP) == SYMBOL_REF : 0)
+ ((C) == 'R' ? OK_FOR_R (OP) \
+ : (C) == 'S' ? GET_CODE (OP) == SYMBOL_REF \
+ : 0)
/* Maximum number of registers that can appear in a valid memory address. */
@@ -1049,12 +1051,7 @@ do { char dstr[30]; \
#define DWARF2_ASM_LINE_DEBUG_INFO 1
-#define DBX_REGISTER_NUMBER(REGNO) \
- (REGNO_DATA_P ((REGNO)) ? (0 + (REGNO) - FIRST_DATA_REGNUM) \
- : REGNO_ADDRESS_P ((REGNO)) ? (4 + (REGNO) - FIRST_ADDRESS_REGNUM) \
- : REGNO_SP_P ((REGNO)) ? 8 \
- : REGNO_EXTENDED_P ((REGNO)) ? (15 + (REGNO) - FIRST_EXTENDED_REGNUM) \
- : -1)
+#define DBX_REGISTER_NUMBER(REGNO) (REGNO)
/* GDB always assumes the current function's frame begins at the value
of the stack pointer upon entry to the current function. Accessing
diff --git a/gcc/config/mn10300/xm-mn10300.h b/gcc/config/mn10300/xm-mn10300.h
index 84f888be488..5a210f3461c 100644
--- a/gcc/config/mn10300/xm-mn10300.h
+++ b/gcc/config/mn10300/xm-mn10300.h
@@ -19,10 +19,6 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* #defines that need visibility everywhere. */
-#define FALSE 0
-#define TRUE 1
-
/* This describes the machine the compiler is hosted on. */
#define HOST_BITS_PER_CHAR 8
#define HOST_BITS_PER_SHORT 16
diff --git a/gcc/config/nextstep.h b/gcc/config/nextstep.h
index 28deb16a3cc..76e1a3505a6 100644
--- a/gcc/config/nextstep.h
+++ b/gcc/config/nextstep.h
@@ -208,11 +208,6 @@ Boston, MA 02111-1307, USA. */
/* Define our object format type for crtstuff.c */
#define OBJECT_FORMAT_MACHO
-/* Don't use .gcc_compiled symbols to communicate with GDB;
- They interfere with numerically sorted symbol lists. */
-
-#undef ASM_IDENTIFY_GCC
-#define ASM_IDENTIFY_GCC(asm_out_file)
#undef INIT_SECTION_ASM_OP
#define INIT_SECTION_ASM_OP
#undef INVOKE__main
diff --git a/gcc/config/ns32k/ns32k.c b/gcc/config/ns32k/ns32k.c
index 42ad19d370f..3fbde5a8f16 100644
--- a/gcc/config/ns32k/ns32k.c
+++ b/gcc/config/ns32k/ns32k.c
@@ -27,7 +27,6 @@ Boston, MA 02111-1307, USA. */
#include "real.h"
#include "insn-config.h"
#include "conditions.h"
-#include "insn-flags.h"
#include "output.h"
#include "insn-attr.h"
#include "tree.h"
diff --git a/gcc/config/ns32k/xm-ns32k.h b/gcc/config/ns32k/xm-ns32k.h
index 3d1d7ac8fc1..5c912fc28a2 100644
--- a/gcc/config/ns32k/xm-ns32k.h
+++ b/gcc/config/ns32k/xm-ns32k.h
@@ -18,10 +18,6 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* #defines that need visibility everywhere. */
-#define FALSE 0
-#define TRUE 1
-
/* target machine dependencies.
tm.h is a symbolic link to the actual target specific file. */
#include "tm.h"
diff --git a/gcc/config/openbsd.h b/gcc/config/openbsd.h
index 87b3a60567f..ff1c1ad540b 100644
--- a/gcc/config/openbsd.h
+++ b/gcc/config/openbsd.h
@@ -78,12 +78,16 @@ Boston, MA 02111-1307, USA. */
since all code must be compiled with -pthread to work.
This two-stage defines makes it easy to pick that for targets that
have subspecs. */
+#ifdef CPP_CPU_SPEC
+#define OBSD_CPP_SPEC "%(cpp_cpu) %{posix:-D_POSIX_SOURCE} %{pthread:-D_POSIX_THREADS}"
+#else
#define OBSD_CPP_SPEC "%{posix:-D_POSIX_SOURCE} %{pthread:-D_POSIX_THREADS}"
+#endif
/* LIB_SPEC appropriate for OpenBSD. Select the appropriate libc,
depending on profiling and threads. Basically,
-lc(_r)?(_p)?, select _r for threads, and _p for p or pg. */
-#define OBSD_LIB_SPEC "-lc%{pthread:_r}%{p:_p}%{!p:%{pg:_p}}"
+#define OBSD_LIB_SPEC "%{!shared:-lc%{pthread:_r}%{p:_p}%{!p:%{pg:_p}}}"
#ifndef OBSD_HAS_CORRECT_SPECS
@@ -103,6 +107,7 @@ Boston, MA 02111-1307, USA. */
pic code. */
#undef ASM_SPEC
#define ASM_SPEC "%{fpic:-k} %{fPIC:-k -K} %|"
+
#else
/* Since we use gas, stdin -> - is a good idea, but we don't want to
override native specs just for that. */
@@ -116,10 +121,10 @@ Boston, MA 02111-1307, USA. */
#undef LINK_SPEC
#ifdef OBSD_NO_DYNAMIC_LIBRARIES
#define LINK_SPEC \
- "%{!nostdlib:%{!r*:%{!e*:-e start}}} -dc -dp %{assert*}"
+ "%{g:%{!nostdlib:-L/usr/lib/debug}} %{!nostdlib:%{!r*:%{!e*:-e start}}} -dc -dp %{assert*}"
#else
#define LINK_SPEC \
- "%{!shared:%{!nostdlib:%{!r*:%{!e*:-e start}}}} %{shared:-Bshareable -x} -dc -dp %{R*} %{static:-Bstatic} %{assert*}"
+ "%{g:%{!nostdlib:-L/usr/lib/debug}} %{!shared:%{!nostdlib:%{!r*:%{!e*:-e start}}}} %{shared:-Bshareable -x} -dc -dp %{R*} %{static:-Bstatic} %{assert*}"
#endif
#undef LIB_SPEC
diff --git a/gcc/config/pa/lib2funcs.asm b/gcc/config/pa/lib2funcs.asm
index d2a0f762225..bf632d5e2af 100644
--- a/gcc/config/pa/lib2funcs.asm
+++ b/gcc/config/pa/lib2funcs.asm
@@ -37,7 +37,6 @@
.SUBSPA $MILLICODE$,QUAD=0,ALIGN=8,ACCESS=44,SORT=8
.IMPORT $$dyncall,MILLICODE
-; gcc_compiled.:
.SPACE $TEXT$
.SUBSPA $CODE$
diff --git a/gcc/config/pa/long_double.h b/gcc/config/pa/long_double.h
index 92d03761e0f..e65f15f9345 100644
--- a/gcc/config/pa/long_double.h
+++ b/gcc/config/pa/long_double.h
@@ -52,6 +52,7 @@ do { long value[4]; \
we can massage its return value for PA64. */
#define FIX_TRUNCTFSI2_LIBCALL \
(TARGET_64BIT ? "__U_Qfcnvfxt_quad_to_sgl" : "_U_Qfcnvfxt_quad_to_sgl")
+#define FIXUNS_TRUNCTFSI2_LIBCALL "_U_Qfcnvfxt_quad_to_usgl"
#define FIX_TRUNCTFDI2_LIBCALL "_U_Qfcnvfxt_quad_to_dbl"
#define EQTF2_LIBCALL "_U_Qfeq"
#define NETF2_LIBCALL "_U_Qfne"
@@ -89,7 +90,7 @@ do { long value[4]; \
floatditf_libfunc = gen_rtx_SYMBOL_REF (Pmode, FLOATDITF2_LIBCALL); \
fixtfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, FIX_TRUNCTFSI2_LIBCALL);\
fixtfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, FIX_TRUNCTFDI2_LIBCALL);\
- fixunstfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, FIX_TRUNCTFSI2_LIBCALL); \
+ fixunstfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, FIXUNS_TRUNCTFSI2_LIBCALL);\
fixunstfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, FIX_TRUNCTFDI2_LIBCALL); \
eqtf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, EQTF2_LIBCALL); \
netf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, NETF2_LIBCALL); \
diff --git a/gcc/config/pa/pa-hpux10.h b/gcc/config/pa/pa-hpux10.h
index 22223e10c73..94d8a662ee7 100644
--- a/gcc/config/pa/pa-hpux10.h
+++ b/gcc/config/pa/pa-hpux10.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler, for HP PA-RISC 1.1
- Copyright (C) 1995, 1996, 1997, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996, 1997, 2000, 2001 Free Software Foundation, Inc.
Contributed by Tim Moore (moore@defmacro.cs.utah.edu)
This file is part of GNU CC.
@@ -40,6 +40,9 @@ Boston, MA 02111-1307, USA. */
%{p: -L/lib/libp/ -lc}\
%{pg: -L/lib/libp/ -lc}}"
+#undef THREAD_MODEL_SPEC
+#define THREAD_MODEL_SPEC "%{!threads:single}%{threads:dce}"
+
/* Under hpux10, the normal location of the `ld' and `as' programs is the
/usr/ccs/bin directory. */
diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
index a7a0b9ec002..47b02c52476 100644
--- a/gcc/config/pa/pa.c
+++ b/gcc/config/pa/pa.c
@@ -28,7 +28,6 @@ Boston, MA 02111-1307, USA. */
#include "real.h"
#include "insn-config.h"
#include "conditions.h"
-#include "insn-flags.h"
#include "output.h"
#include "insn-attr.h"
#include "flags.h"
@@ -183,8 +182,9 @@ override_options ()
write_symbols = NO_DEBUG;
}
- /* We always generate PIC code when in 64bit mode. */
- if (TARGET_64BIT)
+ /* We only support the "big PIC" model now. And we always generate PIC
+ code when in 64bit mode. */
+ if (flag_pic == 1 || TARGET_64BIT)
flag_pic = 2;
/* Register global variables with the garbage collector. */
@@ -377,13 +377,14 @@ move_operand (op, mode)
op = XEXP (op, 0);
- /* The LO_SUM part of a DLT reference is not considered a move_operand;
- we must reject it here since it must be accepted by memory_address_p. */
+ /* We consider a LO_SUM DLT reference a move_operand now since it has
+ been merged into the normal movsi/movdi patterns. */
if (GET_CODE (op) == LO_SUM
&& GET_CODE (XEXP (op, 0)) == REG
&& REG_OK_FOR_BASE_P (XEXP (op, 0))
- && GET_CODE (XEXP (op, 1)) == UNSPEC)
- return 0;
+ && GET_CODE (XEXP (op, 1)) == UNSPEC
+ && GET_MODE (op) == Pmode)
+ return 1;
/* Since move_operand is only used for source operands, we can always
allow scaled indexing! */
@@ -712,22 +713,15 @@ legitimize_pic_address (orig, mode, reg)
if (reg == 0)
abort ();
- if (flag_pic == 2)
- {
- emit_move_insn (reg,
- gen_rtx_PLUS (word_mode, pic_offset_table_rtx,
- gen_rtx_HIGH (word_mode, orig)));
- pic_ref
- = gen_rtx_MEM (Pmode,
- gen_rtx_LO_SUM (Pmode, reg,
- gen_rtx_UNSPEC (Pmode,
- gen_rtvec (1, orig),
- 0)));
- }
- else
- pic_ref = gen_rtx_MEM (Pmode,
- gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
- orig));
+ emit_move_insn (reg,
+ gen_rtx_PLUS (word_mode, pic_offset_table_rtx,
+ gen_rtx_HIGH (word_mode, orig)));
+ pic_ref
+ = gen_rtx_MEM (Pmode,
+ gen_rtx_LO_SUM (Pmode, reg,
+ gen_rtx_UNSPEC (Pmode,
+ gen_rtvec (1, orig),
+ 0)));
current_function_uses_pic_offset_table = 1;
RTX_UNCHANGING_P (pic_ref) = 1;
@@ -1341,8 +1335,9 @@ emit_move_sequence (operands, mode, scratch_reg)
return 1;
}
/* Handle secondary reloads for SAR. These occur when trying to load
- the SAR from memory a FP register, or with a constant. */
+ the SAR from memory, FP register, or with a constant. */
else if (GET_CODE (operand0) == REG
+ && REGNO (operand0) < FIRST_PSEUDO_REGISTER
&& REGNO_REG_CLASS (REGNO (operand0)) == SHIFT_REGS
&& (GET_CODE (operand1) == MEM
|| GET_CODE (operand1) == CONST_INT
@@ -2988,70 +2983,75 @@ hppa_expand_prologue()
/* Save RP first. The calling conventions manual states RP will
always be stored into the caller's frame at sp-20 or sp - 16
depending on which ABI is in use. */
- if ((regs_ever_live[2] || profile_flag) && TARGET_64BIT)
- store_reg (2, -16, STACK_POINTER_REGNUM);
-
- if ((regs_ever_live[2] || profile_flag) && ! TARGET_64BIT)
- store_reg (2, -20, STACK_POINTER_REGNUM);
+ if (regs_ever_live[2] || profile_flag)
+ store_reg (2, TARGET_64BIT ? -16 : -20, STACK_POINTER_REGNUM);
/* Allocate the local frame and set up the frame pointer if needed. */
- if (actual_fsize)
- {
- if (frame_pointer_needed)
- {
- /* Copy the old frame pointer temporarily into %r1. Set up the
- new stack pointer, then store away the saved old frame pointer
- into the stack at sp+actual_fsize and at the same time update
- the stack pointer by actual_fsize bytes. Two versions, first
- handles small (<8k) frames. The second handles large (>8k)
- frames. */
- emit_move_insn (tmpreg, frame_pointer_rtx);
- emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
- if (VAL_14_BITS_P (actual_fsize))
- emit_insn (gen_post_store (stack_pointer_rtx, tmpreg, size_rtx));
- else
- {
- /* It is incorrect to store the saved frame pointer at *sp,
- then increment sp (writes beyond the current stack boundary).
-
- So instead use stwm to store at *sp and post-increment the
- stack pointer as an atomic operation. Then increment sp to
- finish allocating the new frame. */
- emit_insn (gen_post_store (stack_pointer_rtx, tmpreg,
- GEN_INT (64)));
+ if (actual_fsize != 0)
+ {
+ if (frame_pointer_needed)
+ {
+ /* Copy the old frame pointer temporarily into %r1. Set up the
+ new stack pointer, then store away the saved old frame pointer
+ into the stack at sp+actual_fsize and at the same time update
+ the stack pointer by actual_fsize bytes. Two versions, first
+ handles small (<8k) frames. The second handles large (>=8k)
+ frames. */
+ emit_move_insn (tmpreg, frame_pointer_rtx);
+ emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
+ if (VAL_14_BITS_P (actual_fsize))
+ emit_insn (gen_post_store (stack_pointer_rtx, tmpreg, size_rtx));
+ else
+ {
+ /* It is incorrect to store the saved frame pointer at *sp,
+ then increment sp (writes beyond the current stack boundary).
+
+ So instead use stwm to store at *sp and post-increment the
+ stack pointer as an atomic operation. Then increment sp to
+ finish allocating the new frame. */
+ int adjust1 = 8192 - 64;
+ int adjust2 = actual_fsize - adjust1;
+ rtx delta = GEN_INT (adjust1);
+ emit_insn (gen_post_store (stack_pointer_rtx, tmpreg, delta));
+ set_reg_plus_d (STACK_POINTER_REGNUM,
+ STACK_POINTER_REGNUM,
+ adjust2);
+ }
+ /* Prevent register spills from being scheduled before the
+ stack pointer is raised. Necessary as we will be storing
+ registers using the frame pointer as a base register, and
+ we happen to set fp before raising sp. */
+ emit_insn (gen_blockage ());
+ }
+ /* no frame pointer needed. */
+ else
+ {
+ /* In some cases we can perform the first callee register save
+ and allocating the stack frame at the same time. If so, just
+ make a note of it and defer allocating the frame until saving
+ the callee registers. */
+ if (VAL_14_BITS_P (actual_fsize)
+ && local_fsize == 0
+ && ! profile_flag
+ && ! flag_pic)
+ merge_sp_adjust_with_store = 1;
+ /* Can not optimize. Adjust the stack frame by actual_fsize
+ bytes. */
+ else
set_reg_plus_d (STACK_POINTER_REGNUM,
STACK_POINTER_REGNUM,
- actual_fsize - 64);
- }
- }
- /* no frame pointer needed. */
- else
- {
- /* In some cases we can perform the first callee register save
- and allocating the stack frame at the same time. If so, just
- make a note of it and defer allocating the frame until saving
- the callee registers. */
- if (VAL_14_BITS_P (-actual_fsize)
- && local_fsize == 0
- && ! profile_flag
- && ! flag_pic)
- merge_sp_adjust_with_store = 1;
- /* Can not optimize. Adjust the stack frame by actual_fsize bytes. */
- else if (actual_fsize != 0)
- set_reg_plus_d (STACK_POINTER_REGNUM,
- STACK_POINTER_REGNUM,
- actual_fsize);
- }
- }
+ actual_fsize);
+ }
- /* The hppa calling conventions say that %r19, the pic offset
- register, is saved at sp - 32 (in this function's frame) when
- generating PIC code. FIXME: What is the correct thing to do
- for functions which make no calls and allocate no frame? Do
- we need to allocate a frame, or can we just omit the save? For
- now we'll just omit the save. */
- if (actual_fsize != 0 && flag_pic && !TARGET_64BIT)
- store_reg (PIC_OFFSET_TABLE_REGNUM, -32, STACK_POINTER_REGNUM);
+ /* The hppa calling conventions say that %r19, the pic offset
+ register, is saved at sp - 32 (in this function's frame)
+ when generating PIC code. FIXME: What is the correct thing
+ to do for functions which make no calls and allocate no
+ frame? Do we need to allocate a frame, or can we just omit
+ the save? For now we'll just omit the save. */
+ if (flag_pic && !TARGET_64BIT)
+ store_reg (PIC_OFFSET_TABLE_REGNUM, -32, STACK_POINTER_REGNUM);
+ }
/* Profiling code.
@@ -3225,8 +3225,9 @@ void
hppa_expand_epilogue ()
{
rtx tmpreg;
- int offset,i;
- int merge_sp_adjust_with_load = 0;
+ int offset, i;
+ int merge_sp_adjust_with_load = 0;
+ int ret_off = 0;
/* We will use this often. */
tmpreg = gen_rtx_REG (word_mode, 1);
@@ -3234,23 +3235,24 @@ hppa_expand_epilogue ()
/* Try to restore RP early to avoid load/use interlocks when
RP gets used in the return (bv) instruction. This appears to still
be necessary even when we schedule the prologue and epilogue. */
- if (frame_pointer_needed
- && !TARGET_64BIT
- && (regs_ever_live [2] || profile_flag))
- load_reg (2, -20, FRAME_POINTER_REGNUM);
- else if (TARGET_64BIT && frame_pointer_needed
- && (regs_ever_live[2] || profile_flag))
- load_reg (2, -16, FRAME_POINTER_REGNUM);
- else if (TARGET_64BIT
- && ! frame_pointer_needed
- && (regs_ever_live[2] || profile_flag)
- && VAL_14_BITS_P (actual_fsize + 20))
- load_reg (2, - (actual_fsize + 16), STACK_POINTER_REGNUM);
- /* No frame pointer, and stack is smaller than 8k. */
- else if (! frame_pointer_needed
- && VAL_14_BITS_P (actual_fsize + 20)
- && (regs_ever_live[2] || profile_flag))
- load_reg (2, - (actual_fsize + 20), STACK_POINTER_REGNUM);
+ if (regs_ever_live [2] || profile_flag)
+ {
+ ret_off = TARGET_64BIT ? -16 : -20;
+ if (frame_pointer_needed)
+ {
+ load_reg (2, ret_off, FRAME_POINTER_REGNUM);
+ ret_off = 0;
+ }
+ else
+ {
+ /* No frame pointer, and stack is smaller than 8k. */
+ if (VAL_14_BITS_P (ret_off - actual_fsize))
+ {
+ load_reg (2, ret_off - actual_fsize, STACK_POINTER_REGNUM);
+ ret_off = 0;
+ }
+ }
+ }
/* General register restores. */
if (frame_pointer_needed)
@@ -3271,9 +3273,9 @@ hppa_expand_epilogue ()
/* Only for the first load.
merge_sp_adjust_with_load holds the register load
with which we will merge the sp adjustment. */
- if (VAL_14_BITS_P (actual_fsize + 20)
+ if (merge_sp_adjust_with_load == 0
&& local_fsize == 0
- && ! merge_sp_adjust_with_load)
+ && VAL_14_BITS_P (-actual_fsize))
merge_sp_adjust_with_load = i;
else
load_reg (i, offset, STACK_POINTER_REGNUM);
@@ -3313,47 +3315,10 @@ hppa_expand_epilogue ()
This is necessary as we must not cut the stack back before all the
restores are finished. */
emit_insn (gen_blockage ());
- /* No frame pointer, but we have a stack greater than 8k. We restore
- %r2 very late in this case. (All other cases are restored as early
- as possible.) */
- if (! frame_pointer_needed
- && ! VAL_14_BITS_P (actual_fsize + 20)
- && ! TARGET_64BIT
- && (regs_ever_live[2] || profile_flag))
- {
- set_reg_plus_d (STACK_POINTER_REGNUM,
- STACK_POINTER_REGNUM,
- - actual_fsize);
-
- /* This used to try and be clever by not depending on the value in
- %r30 and instead use the value held in %r1 (so that the 2nd insn
- which sets %r30 could be put in the delay slot of the return insn).
-
- That won't work since if the stack is exactly 8k set_reg_plus_d
- doesn't set %r1, just %r30. */
- load_reg (2, - 20, STACK_POINTER_REGNUM);
- }
- else if (! frame_pointer_needed
- && ! VAL_14_BITS_P (actual_fsize + 20)
- && TARGET_64BIT
- && (regs_ever_live[2] || profile_flag))
- {
- set_reg_plus_d (STACK_POINTER_REGNUM,
- STACK_POINTER_REGNUM,
- - actual_fsize);
-
- /* This used to try and be clever by not depending on the value in
- %r30 and instead use the value held in %r1 (so that the 2nd insn
- which sets %r30 could be put in the delay slot of the return insn).
-
- That won't work since if the stack is exactly 8k set_reg_plus_d
- doesn't set %r1, just %r30. */
- load_reg (2, - 16, STACK_POINTER_REGNUM);
- }
/* Reset stack pointer (and possibly frame pointer). The stack
pointer is initially set to fp + 64 to avoid a race condition. */
- else if (frame_pointer_needed)
+ if (frame_pointer_needed)
{
set_reg_plus_d (STACK_POINTER_REGNUM, FRAME_POINTER_REGNUM, 64);
emit_insn (gen_pre_load (frame_pointer_rtx,
@@ -3361,14 +3326,25 @@ hppa_expand_epilogue ()
GEN_INT (-64)));
}
/* If we were deferring a callee register restore, do it now. */
- else if (! frame_pointer_needed && merge_sp_adjust_with_load)
- emit_insn (gen_pre_load (gen_rtx_REG (word_mode, merge_sp_adjust_with_load),
- stack_pointer_rtx,
- GEN_INT (- actual_fsize)));
+ else if (merge_sp_adjust_with_load)
+ {
+ rtx delta = GEN_INT (-actual_fsize);
+ emit_insn (gen_pre_load (gen_rtx_REG (word_mode,
+ merge_sp_adjust_with_load),
+ stack_pointer_rtx,
+ delta));
+ }
else if (actual_fsize != 0)
- set_reg_plus_d (STACK_POINTER_REGNUM,
- STACK_POINTER_REGNUM,
- - actual_fsize);
+ {
+ set_reg_plus_d (STACK_POINTER_REGNUM,
+ STACK_POINTER_REGNUM,
+ - actual_fsize);
+ }
+
+ /* If we haven't restored %r2 yet (no frame pointer, and a stack
+ frame greater than 8k), do so now. */
+ if (ret_off != 0)
+ load_reg (2, ret_off, STACK_POINTER_REGNUM);
}
/* Set up a callee saved register for the pic offset table register. */
@@ -3816,6 +3792,7 @@ pa_adjust_insn_length (insn, length)
/* Block move pattern. */
else if (GET_CODE (insn) == INSN
&& GET_CODE (pat) == PARALLEL
+ && GET_CODE (XVECEXP (pat, 0, 0)) == SET
&& GET_CODE (XEXP (XVECEXP (pat, 0, 0), 0)) == MEM
&& GET_CODE (XEXP (XVECEXP (pat, 0, 0), 1)) == MEM
&& GET_MODE (XEXP (XVECEXP (pat, 0, 0), 0)) == BLKmode
@@ -3901,6 +3878,17 @@ print_operand (file, x, code)
}
else
break;
+ case 'A':
+ {
+ rtx xoperands[2];
+
+ xoperands[0] = XEXP (XEXP (x, 0), 0);
+ xoperands[1] = XVECEXP (XEXP (XEXP (x, 0), 1), 0, 0);
+ output_global_address (file, xoperands[1], 0);
+ fprintf (file, "(%s)", reg_names [REGNO (xoperands[0])]);
+ return;
+ }
+
case 'C': /* Plain (C)ondition */
case 'X':
switch (GET_CODE (x))
@@ -4570,7 +4558,7 @@ secondary_reload_class (class, mode, in)
/* Trying to load a constant into a FP register during PIC code
generation will require %r1 as a scratch register. */
- if (flag_pic == 2
+ if (flag_pic
&& GET_MODE_CLASS (mode) == MODE_INT
&& FP_REG_CLASS_P (class)
&& (GET_CODE (in) == CONST_INT || GET_CODE (in) == CONST_DOUBLE))
@@ -4605,6 +4593,13 @@ secondary_reload_class (class, mode, in)
|| (class == SHIFT_REGS && (regno <= 0 || regno >= 32)))
return GENERAL_REGS;
+ /* A SAR<->FP register copy requires a secondary register (GPR) as
+ well as secondary memory. */
+ if (regno >= 0 && regno < FIRST_PSEUDO_REGISTER
+ && ((REGNO_REG_CLASS (regno) == SHIFT_REGS && FP_REG_CLASS_P (class))
+ || (class == SHIFT_REGS && FP_REG_CLASS_P (REGNO_REG_CLASS (regno)))))
+ return GENERAL_REGS;
+
if (GET_CODE (in) == HIGH)
in = XEXP (in, 0);
diff --git a/gcc/config/pa/pa.h b/gcc/config/pa/pa.h
index e20cffd729f..3faa01a4ee8 100644
--- a/gcc/config/pa/pa.h
+++ b/gcc/config/pa/pa.h
@@ -323,6 +323,17 @@ extern int target_flags;
%{!ansi: -D_HPUX_SOURCE -D_HIUX_SOURCE -D__STDC_EXT__} \
%{threads: -D_REENTRANT -D_DCE_THREADS}"
+#define CPLUSPLUS_CPP_SPEC "\
+-D_HPUX_SOURCE -D_HIUX_SOURCE -D__STDC_EXT__ \
+%{mpa-risc-1-0:%(cpp_pa10)} \
+%{mpa-risc-1-1:%(cpp_pa11)} \
+%{msnake:%(cpp_pa11)} \
+%{mpa-risc-2-0:%(cpp_pa20)} \
+%{!mpa-risc-1-0:%{!mpa-risc-1-1:%{!mpa-risc-2-0:%{!msnake:%(cpp_cpu_default)}}}} \
+%{m64bit:%(cpp_64bit)} \
+%{!m64bit:%(cpp_64bit_default)} \
+%{threads: -D_REENTRANT -D_DCE_THREADS}"
+
/* Defines for a K&R CC */
#define CC1_SPEC "%{pg:} %{p:}"
@@ -1187,8 +1198,15 @@ extern int may_call_alloca;
|| GET_CODE (XEXP (XEXP (OP, 0), 1)) == MULT)))\
: ((C) == 'U' ? \
(GET_CODE (OP) == CONST_INT && INTVAL (OP) == 63) \
+ : ((C) == 'A' ? \
+ (GET_CODE (OP) == MEM \
+ && GET_CODE (XEXP (OP, 0)) == LO_SUM \
+ && GET_CODE (XEXP (XEXP (OP, 0), 0)) == REG \
+ && REG_OK_FOR_BASE_P (XEXP (XEXP (OP, 0), 0)) \
+ && GET_CODE (XEXP (XEXP (OP, 0), 1)) == UNSPEC \
+ && GET_MODE (XEXP (OP, 0)) == Pmode) \
: ((C) == 'S' ? \
- (GET_CODE (OP) == CONST_INT && INTVAL (OP) == 31) : 0)))))
+ (GET_CODE (OP) == CONST_INT && INTVAL (OP) == 31) : 0))))))
/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
@@ -1262,16 +1280,7 @@ extern int may_call_alloca;
else if (GET_CODE (X) == PLUS) \
{ \
rtx base = 0, index = 0; \
- if (flag_pic && XEXP (X, 0) == pic_offset_table_rtx)\
- { \
- if (GET_CODE (XEXP (X, 1)) == REG \
- && REG_OK_FOR_BASE_P (XEXP (X, 1))) \
- goto ADDR; \
- else if (flag_pic == 1 \
- && GET_CODE (XEXP (X, 1)) == SYMBOL_REF)\
- goto ADDR; \
- } \
- else if (REG_P (XEXP (X, 0)) \
+ if (REG_P (XEXP (X, 0)) \
&& REG_OK_FOR_BASE_P (XEXP (X, 0))) \
base = XEXP (X, 0), index = XEXP (X, 1); \
else if (REG_P (XEXP (X, 1)) \
@@ -1333,7 +1342,11 @@ extern int may_call_alloca;
else if (GET_CODE (X) == LO_SUM \
&& GET_CODE (XEXP (X, 0)) == REG \
&& REG_OK_FOR_BASE_P (XEXP (X, 0)) \
- && GET_CODE (XEXP (X, 1)) == UNSPEC) \
+ && GET_CODE (XEXP (X, 1)) == UNSPEC \
+ && (TARGET_SOFT_FLOAT \
+ || TARGET_PA_20 \
+ || ((MODE) != SFmode \
+ && (MODE) != DFmode))) \
goto ADDR; \
}
@@ -1963,9 +1976,7 @@ while (0)
fputs ("R'", FILE); \
else if (flag_pic == 0) \
fputs ("RR'", FILE); \
- else if (flag_pic == 1) \
- abort (); \
- else if (flag_pic == 2) \
+ else \
fputs ("RT'", FILE); \
output_global_address (FILE, XEXP (addr, 1), 0); \
fputs ("(", FILE); \
diff --git a/gcc/config/pa/pa.md b/gcc/config/pa/pa.md
index ac70bfdc75a..4828da8cd67 100644
--- a/gcc/config/pa/pa.md
+++ b/gcc/config/pa/pa.md
@@ -2085,26 +2085,16 @@
DONE;
}")
-;;; pic symbol references
-
-(define_insn ""
- [(set (match_operand:SI 0 "register_operand" "=r")
- (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
- (match_operand:SI 2 "symbolic_operand" ""))))]
- "flag_pic && operands[1] == pic_offset_table_rtx"
- "ldw T'%2(%1),%0"
- [(set_attr "type" "load")
- (set_attr "length" "4")])
-
(define_insn ""
[(set (match_operand:SI 0 "reg_or_nonsymb_mem_operand"
- "=r,r,r,r,r,Q,*q,!f,f,*TR")
+ "=r,r,r,r,r,r,Q,*q,!f,f,*TR")
(match_operand:SI 1 "move_operand"
- "r,J,N,K,RQ,rM,rM,!fM,*RT,f"))]
+ "A,r,J,N,K,RQ,rM,rM,!fM,*RT,f"))]
"(register_operand (operands[0], SImode)
|| reg_or_0_operand (operands[1], SImode))
&& ! TARGET_SOFT_FLOAT"
"@
+ ldw RT'%A1,%0
copy %1,%0
ldi %1,%0
ldil L'%1,%0
@@ -2115,19 +2105,20 @@
fcpy,sgl %f1,%0
fldw%F1 %1,%0
fstw%F0 %1,%0"
- [(set_attr "type" "move,move,move,shift,load,store,move,fpalu,fpload,fpstore")
+ [(set_attr "type" "load,move,move,move,shift,load,store,move,fpalu,fpload,fpstore")
(set_attr "pa_combine_type" "addmove")
- (set_attr "length" "4,4,4,4,4,4,4,4,4,4")])
+ (set_attr "length" "4,4,4,4,4,4,4,4,4,4,4")])
(define_insn ""
[(set (match_operand:SI 0 "reg_or_nonsymb_mem_operand"
- "=r,r,r,r,r,Q,*q")
+ "=r,r,r,r,r,r,Q,*q")
(match_operand:SI 1 "move_operand"
- "r,J,N,K,RQ,rM,rM"))]
+ "A,r,J,N,K,RQ,rM,rM"))]
"(register_operand (operands[0], SImode)
|| reg_or_0_operand (operands[1], SImode))
&& TARGET_SOFT_FLOAT"
"@
+ ldw RT'%A1,%0
copy %1,%0
ldi %1,%0
ldil L'%1,%0
@@ -2135,9 +2126,9 @@
ldw%M1 %1,%0
stw%M0 %r1,%0
mtsar %r1"
- [(set_attr "type" "move,move,move,move,load,store,move")
+ [(set_attr "type" "load,move,move,move,move,load,store,move")
(set_attr "pa_combine_type" "addmove")
- (set_attr "length" "4,4,4,4,4,4,4")])
+ (set_attr "length" "4,4,4,4,4,4,4,4")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -2329,7 +2320,7 @@
(high:SI (match_operand 2 "" ""))))]
"symbolic_operand (operands[2], Pmode)
&& ! function_label_operand (operands[2], Pmode)
- && flag_pic == 2"
+ && flag_pic"
"addil LT'%G2,%1"
[(set_attr "type" "binary")
(set_attr "length" "4")])
@@ -2341,46 +2332,11 @@
"symbolic_operand (operands[2], Pmode)
&& ! function_label_operand (operands[2], Pmode)
&& TARGET_64BIT
- && flag_pic == 2"
+ && flag_pic"
"addil LT'%G2,%1"
[(set_attr "type" "binary")
(set_attr "length" "4")])
-; We need this to make sure CSE doesn't simplify a memory load with a
-; symbolic address, whose content it think it knows. For PIC, what CSE
-; think is the real value will be the address of that value.
-(define_insn ""
- [(set (match_operand:SI 0 "register_operand" "=r")
- (mem:SI
- (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
- (unspec:SI
- [(match_operand:SI 2 "symbolic_operand" "")] 0))))]
- ""
- "*
-{
- if (flag_pic != 2)
- abort ();
- return \"ldw RT'%G2(%1),%0\";
-}"
- [(set_attr "type" "load")
- (set_attr "length" "4")])
-
-(define_insn ""
- [(set (match_operand:DI 0 "register_operand" "=r")
- (mem:DI
- (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
- (unspec:DI
- [(match_operand:DI 2 "symbolic_operand" "")] 0))))]
- "TARGET_64BIT"
- "*
-{
- if (flag_pic != 2)
- abort ();
- return \"ldd RT'%G2(%1),%0\";
-}"
- [(set_attr "type" "load")
- (set_attr "length" "4")])
-
;; Always use addil rather than ldil;add sequences. This allows the
;; HP linker to eliminate the dp relocation if the symbolic operand
;; lives in the TEXT space.
@@ -3083,7 +3039,7 @@
}")
(define_expand "reload_outdi"
- [(set (match_operand:DI 0 "general_operand" "")
+ [(set (match_operand:DI 0 "non_hard_reg_operand" "")
(match_operand:DI 1 "register_operand" "Z"))
(clobber (match_operand:SI 2 "register_operand" "=&r"))]
""
@@ -3156,13 +3112,14 @@
(define_insn ""
[(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand"
- "=r,r,r,r,r,Q,*q,!f,f,*TR")
+ "=r,r,r,r,r,r,Q,*q,!f,f,*TR")
(match_operand:DI 1 "move_operand"
- "r,J,N,K,RQ,rM,rM,!fM,*RT,f"))]
+ "A,r,J,N,K,RQ,rM,rM,!fM,*RT,f"))]
"(register_operand (operands[0], DImode)
|| reg_or_0_operand (operands[1], DImode))
&& ! TARGET_SOFT_FLOAT && TARGET_64BIT"
"@
+ ldd RT'%A1,%0
copy %1,%0
ldi %1,%0
ldil L'%1,%0
@@ -3173,9 +3130,9 @@
fcpy,dbl %f1,%0
fldd%F1 %1,%0
fstd%F0 %1,%0"
- [(set_attr "type" "move,move,move,shift,load,store,move,fpalu,fpload,fpstore")
+ [(set_attr "type" "load,move,move,move,shift,load,store,move,fpalu,fpload,fpstore")
(set_attr "pa_combine_type" "addmove")
- (set_attr "length" "4,4,4,4,4,4,4,4,4,4")])
+ (set_attr "length" "4,4,4,4,4,4,4,4,4,4,4")])
(define_insn ""
[(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand"
@@ -6254,8 +6211,7 @@
;;; EH does longjmp's from and within the data section. Thus,
;;; an interspace branch is required for the longjmp implementation.
-;;; Registers r1 and r2 are not saved in the jmpbuf environment.
-;;; Thus, they can be used as scratch registers for the jump.
+;;; Registers r1 and r2 are used as scratch registers for the jump.
(define_expand "interspace_jump"
[(parallel
[(set (pc) (match_operand 0 "pmode_register_operand" "a"))
@@ -6289,8 +6245,10 @@
{
/* The elements of the buffer are, in order: */
rtx fp = gen_rtx_MEM (Pmode, operands[0]);
- rtx lab = gen_rtx_MEM (Pmode, plus_constant (operands[0], 4));
- rtx stack = gen_rtx_MEM (Pmode, plus_constant (operands[0], 8));
+ rtx lab = gen_rtx_MEM (Pmode, plus_constant (operands[0],
+ POINTER_SIZE / BITS_PER_UNIT));
+ rtx stack = gen_rtx_MEM (Pmode, plus_constant (operands[0],
+ (POINTER_SIZE * 2) / BITS_PER_UNIT));
rtx pv = gen_rtx_REG (Pmode, 1);
/* This bit is the same as expand_builtin_longjmp. */
@@ -6303,10 +6261,16 @@
where to look for it when we get back to setjmp's function for
restoring the gp. */
emit_move_insn (pv, lab);
+
+ /* Prevent the insns above from being scheduled into the delay slot
+ of the interspace jump because the space register could change. */
+ emit_insn (gen_blockage ());
+
emit_jump_insn (gen_interspace_jump (pv));
emit_barrier ();
DONE;
}")
+
;;; Hope this is only within a function...
(define_insn "indirect_jump"
[(set (pc) (match_operand 0 "register_operand" "r"))]
@@ -7172,3 +7136,18 @@
emit_insn (gen_blockage ());
DONE;
}")
+
+(define_expand "builtin_setjmp_receiver"
+ [(label_ref (match_operand 0 "" ""))]
+ "flag_pic"
+ "
+{
+ if (PIC_OFFSET_TABLE_SAVE_RTX == NULL_RTX)
+ hppa_init_pic_save ();
+
+ /* Restore the PIC register. Hopefully, this will always be from
+ a stack slot. The only registers that are valid after a
+ builtin_longjmp are the stack and frame pointers. */
+ emit_move_insn (pic_offset_table_rtx, PIC_OFFSET_TABLE_SAVE_RTX);
+ DONE;
+}")
diff --git a/gcc/config/pa/pa32-regs.h b/gcc/config/pa/pa32-regs.h
index 145a90e42a1..54d399e1b16 100644
--- a/gcc/config/pa/pa32-regs.h
+++ b/gcc/config/pa/pa32-regs.h
@@ -174,7 +174,7 @@
? GET_MODE_SIZE (MODE) <= 4 || ((REGNO) & 1) == 0 \
/* Make wide modes be in aligned registers. */ \
: (GET_MODE_SIZE (MODE) <= UNITS_PER_WORD \
- || (GET_MODE_SIZE (MODE) <= 2 * UNITS_PER_WORD && ((REGNO) & 1) == 0)))
+ || (GET_MODE_SIZE (MODE) <= 4 * UNITS_PER_WORD && ((REGNO) & 1) == 0)))
/* How to renumber registers for dbx and gdb.
diff --git a/gcc/config/pa/quadlib.c b/gcc/config/pa/quadlib.c
index 598e0c297cb..cdf3ea989db 100644
--- a/gcc/config/pa/quadlib.c
+++ b/gcc/config/pa/quadlib.c
@@ -92,3 +92,12 @@ __U_Qfcnvfxt_quad_to_sgl (long double a)
return _U_Qfcnvfxt_quad_to_sgl (a) >> 32;
}
#endif
+
+/* HP only has signed conversion in library, so need to synthesize an
+ unsigned version */
+unsigned int
+_U_Qfcnvfxt_quad_to_usgl(long double a)
+{
+ extern long long _U_Qfcnvfxt_quad_to_dbl (long double a);
+ return (unsigned int) _U_Qfcnvfxt_quad_to_dbl (a);
+}
diff --git a/gcc/config/pa/som.h b/gcc/config/pa/som.h
index 06ee54b107b..df3cb04a431 100644
--- a/gcc/config/pa/som.h
+++ b/gcc/config/pa/som.h
@@ -1,5 +1,5 @@
/* Definitions for SOM assembler support.
- Copyright (C) 1999 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2001 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -251,6 +251,13 @@ do { \
#define BSS_SECTION_ASM_OP "\t.SPACE $PRIVATE$\n\t.SUBSPA $BSS$\n"
+/* We must not have a reference to an external symbol defined in a
+ shared library in a readonly section, else the SOM linker will
+ complain.
+
+ So, we force exception information into the data section. */
+#define EXCEPTION_SECTION data_section
+
/* Define the .bss section for ASM_OUTPUT_LOCAL to use. */
#ifndef CTORS_SECTION_FUNCTION
@@ -261,34 +268,6 @@ do { \
#define EXTRA_SECTIONS in_readonly_data, in_ctors, in_dtors
#endif
-/* Switch into a generic section.
- This is currently only used to support section attributes.
-
- We make the section read-only and executable for a function decl,
- read-only for a const data decl, and writable for a non-const data decl. */
-#define ASM_OUTPUT_SECTION_NAME(FILE, DECL, NAME, RELOC) \
- if (DECL && TREE_CODE (DECL) == FUNCTION_DECL) \
- { \
- fputs ("\t.SPACE $TEXT$\n", FILE); \
- fprintf (FILE, \
- "\t.SUBSPA %s%s%s,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY,SORT=24\n",\
- TARGET_GAS ? "" : "$", NAME, TARGET_GAS ? "" : "$"); \
- } \
- else if (DECL && DECL_READONLY_SECTION (DECL, RELOC)) \
- { \
- fputs ("\t.SPACE $TEXT$\n", FILE); \
- fprintf (FILE, \
- "\t.SUBSPA %s%s%s,QUAD=0,ALIGN=8,ACCESS=44,SORT=16\n", \
- TARGET_GAS ? "" : "$", NAME, TARGET_GAS ? "" : "$"); \
- } \
- else \
- { \
- fputs ("\t.SPACE $PRIVATE$\n", FILE); \
- fprintf (FILE, \
- "\t.SUBSPA %s%s%s,QUAD=1,ALIGN=8,ACCESS=31,SORT=16\n", \
- TARGET_GAS ? "" : "$", NAME, TARGET_GAS ? "" : "$"); \
- }
-
/* FIXME: HPUX ld generates incorrect GOT entries for "T" fixups
which reference data within the $TEXT$ space (for example constant
strings in the $LIT$ subspace).
@@ -378,20 +357,6 @@ do { \
/* The .align directive in the HP assembler allows up to a 32 alignment. */
#define MAX_OFILE_ALIGNMENT 32768
-#ifdef HAVE_GAS_WEAK
-#define MAKE_DECL_ONE_ONLY(DECL) (DECL_WEAK (DECL) = 1)
-
-/* This is how we tell the assembler that a symbol is weak. */
-
-#define ASM_WEAKEN_LABEL(FILE,NAME) \
- do { fputs ("\t.weak\t", FILE); \
- assemble_name (FILE, NAME); \
- fputc ('\n', FILE); \
- if (! FUNCTION_NAME_P (NAME)) \
- { \
- fputs ("\t.EXPORT ", FILE); \
- assemble_name (FILE, NAME); \
- fputs (",DATA\n", FILE); \
- } \
- } while (0)
-#endif
+/* SOM does not support the init_priority C++ attribute. */
+#undef SUPPORTS_INIT_PRIORITY
+#define SUPPORTS_INIT_PRIORITY 0
diff --git a/gcc/config/pa/xm-linux.h b/gcc/config/pa/xm-linux.h
index e7699d8b7b2..076e935b535 100644
--- a/gcc/config/pa/xm-linux.h
+++ b/gcc/config/pa/xm-linux.h
@@ -21,10 +21,6 @@ Boston, MA 02111-1307, USA. */
extern int errno;
-/* #defines that need visibility everywhere. */
-#define FALSE 0
-#define TRUE 1
-
/* This describes the machine the compiler is hosted on. */
#define HOST_BITS_PER_CHAR 8
#define HOST_BITS_PER_SHORT 16
diff --git a/gcc/config/pa/xm-pa.h b/gcc/config/pa/xm-pa.h
index 5814a898be3..9d9b99a9257 100644
--- a/gcc/config/pa/xm-pa.h
+++ b/gcc/config/pa/xm-pa.h
@@ -21,10 +21,6 @@ Boston, MA 02111-1307, USA. */
extern int errno;
-/* #defines that need visibility everywhere. */
-#define FALSE 0
-#define TRUE 1
-
/* This describes the machine the compiler is hosted on. */
#define HOST_BITS_PER_CHAR 8
#define HOST_BITS_PER_SHORT 16
diff --git a/gcc/config/pa/xm-pa64hpux.h b/gcc/config/pa/xm-pa64hpux.h
index fc1ad27506c..563695d5a0e 100644
--- a/gcc/config/pa/xm-pa64hpux.h
+++ b/gcc/config/pa/xm-pa64hpux.h
@@ -22,11 +22,6 @@ Boston, MA 02111-1307, USA. */
/* HP-UX is a flavor of System V */
#define USG
-/* Use System V memory functions. */
-/* #defines that need visibility everywhere. */
-#define FALSE 0
-#define TRUE 1
-
/* This describes the machine the compiler is hosted on. */
#define HOST_BITS_PER_CHAR 8
#define HOST_BITS_PER_SHORT 16
diff --git a/gcc/config/pa/xm-pahpux.h b/gcc/config/pa/xm-pahpux.h
index d62210a4ab0..5a82566abd2 100644
--- a/gcc/config/pa/xm-pahpux.h
+++ b/gcc/config/pa/xm-pahpux.h
@@ -19,15 +19,9 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-
/* HP-UX is a flavor of System V */
#define USG
-/* Use System V memory functions. */
-/* #defines that need visibility everywhere. */
-#define FALSE 0
-#define TRUE 1
-
/* This describes the machine the compiler is hosted on. */
#define HOST_BITS_PER_CHAR 8
#define HOST_BITS_PER_SHORT 16
diff --git a/gcc/config/pa/xm-papro.h b/gcc/config/pa/xm-papro.h
index ad4675beba1..6d887a9f803 100644
--- a/gcc/config/pa/xm-papro.h
+++ b/gcc/config/pa/xm-papro.h
@@ -21,10 +21,6 @@ Boston, MA 02111-1307, USA. */
extern int errno;
-/* #defines that need visibility everywhere. */
-#define FALSE 0
-#define TRUE 1
-
/* This describes the machine the compiler is hosted on. */
#define HOST_BITS_PER_CHAR 8
#define HOST_BITS_PER_SHORT 16
diff --git a/gcc/config/pdp11/pdp11.c b/gcc/config/pdp11/pdp11.c
index 83f191f340d..b298ea0ebff 100644
--- a/gcc/config/pdp11/pdp11.c
+++ b/gcc/config/pdp11/pdp11.c
@@ -28,7 +28,6 @@ Boston, MA 02111-1307, USA. */
#include "real.h"
#include "insn-config.h"
#include "conditions.h"
-#include "insn-flags.h"
#include "function.h"
#include "output.h"
#include "insn-attr.h"
diff --git a/gcc/config/pdp11/pdp11.h b/gcc/config/pdp11/pdp11.h
index 39aac2ff6cf..08b7849b0d9 100644
--- a/gcc/config/pdp11/pdp11.h
+++ b/gcc/config/pdp11/pdp11.h
@@ -1245,10 +1245,6 @@ fprintf (FILE, "$help$: . = .+8 ; space for tmp moves!\n") \
fprintf (FILE, "\tmov (sp)+, %s\n", reg_names[REGNO]) \
)
-
-#define ASM_IDENTIFY_GCC(FILE) \
- fprintf(FILE, "gcc_compiled:\n")
-
/* trampoline - how should i do it in separate i+d ?
have some allocate_trampoline magic???
diff --git a/gcc/config/pj/lib1funcs.S b/gcc/config/pj/lib1funcs.S
index 004d73ae941..02390bc5740 100644
--- a/gcc/config/pj/lib1funcs.S
+++ b/gcc/config/pj/lib1funcs.S
@@ -1,19 +1,19 @@
! lib1funcs.S for picoJava.
-! Copyright (C) 2000 Free Software Foundation, Inc.
+! Copyright (C) 2000, 2001 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 2, or (at your option) any
! later version.
!
-| In addition to the permissions in the GNU General Public License, the
-| Free Software Foundation gives you unlimited permission to link the
-| compiled version of this file into combinations with other programs,
-| and to distribute those combinations without any restriction coming
-| from the use of this file. (The General Public License restrictions
-| do apply in other respects; for example, they cover modification of
-| the file, and distribution when not linked into a combine
-| executable.)
+! In addition to the permissions in the GNU General Public License, the
+! Free Software Foundation gives you unlimited permission to link the
+! compiled version of this file into combinations with other programs,
+! and to distribute those combinations without any restriction coming
+! from the use of this file. (The General Public License restrictions
+! do apply in other respects; for example, they cover modification of
+! the file, and distribution when not linked into a combine
+! executable.)
!
! This file is distributed in the hope that it will be useful, but
! WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/gcc/config/pj/pj.c b/gcc/config/pj/pj.c
index 43a3066d07c..febe2997bcf 100644
--- a/gcc/config/pj/pj.c
+++ b/gcc/config/pj/pj.c
@@ -89,7 +89,6 @@ Boston, MA 02111-1307, USA. */
#include "real.h"
#include "insn-config.h"
#include "conditions.h"
-#include "insn-flags.h"
#include "output.h"
#include "insn-attr.h"
#include "flags.h"
diff --git a/gcc/config/pj/pj.h b/gcc/config/pj/pj.h
index 39f8d797fb5..a5f5ebaa3e7 100644
--- a/gcc/config/pj/pj.h
+++ b/gcc/config/pj/pj.h
@@ -27,10 +27,10 @@ Boston, MA 02111-1307, USA. */
#undef ASM_SPEC
#ifdef TARGET_LITTLE_ENDIAN_DEFAULT
#define CPP_SPEC "%{mb:-D__BIG_ENDIAN__ }%{!mb:-D__LITTLE_ENDIAN__ }"
-#define ASM_SPEC "%{mb:-mb }%{!mb:-ml }"
+#define ASM_SPEC "%{mb:-EB }%{!mb:-EL }"
#else
#define CPP_SPEC "%{ml:-D__LITTLE_ENDIAN__ }%{!ml:-D__BIG_ENDIAN__}"
-#define ASM_SPEC "%{ml:-ml } %{!ml:-mb }"
+#define ASM_SPEC "%{ml:-EL } %{!ml:-EB }"
#endif
#ifndef CPP_PREDEFINES
@@ -234,7 +234,7 @@ enum
LAST_O_REG=OSC_REG,
LAST_R_REG=R31_REG,
LAST_I_REG=ISC_REG,
- LAST_S_REG=P7_REG,
+ LAST_S_REG=P7_REG
};
@@ -445,7 +445,7 @@ enum reg_class
SRC_REGS, /* All registers valid as a source. */
DST_REGS, /* All registers valid as a destination. */
ALL_REGS,
- LIM_REG_CLASSES,
+ LIM_REG_CLASSES
};
#define GENERAL_REGS SRC_REGS
@@ -460,7 +460,7 @@ enum reg_class
"ARG_REGS", \
"SRC_REGS", \
"DST_REGS", \
- "ALL_REGS", \
+ "ALL_REGS" \
}
/* Define which registers fit in which classes.
@@ -1159,7 +1159,7 @@ do { fputs (current_function_varargs || current_function_stdarg \
/* The prefix to add to an internally generated label. */
-#define LOCAL_LABEL_PREFIX ""
+#define LOCAL_LABEL_PREFIX "."
/* Make an internal label into a string. */
#define ASM_GENERATE_INTERNAL_LABEL(STRING, PREFIX, NUM) \
diff --git a/gcc/config/pj/xm-pj.h b/gcc/config/pj/xm-pj.h
index e635cce87c9..63bd847b3f8 100644
--- a/gcc/config/pj/xm-pj.h
+++ b/gcc/config/pj/xm-pj.h
@@ -18,10 +18,6 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* #defines that need visibility everywhere. */
-#define FALSE 0
-#define TRUE 1
-
/* This describes the machine the compiler is hosted on. */
#define HOST_BITS_PER_CHAR 8
#define HOST_BITS_PER_SHORT 16
diff --git a/gcc/config/psos.h b/gcc/config/psos.h
index cb739fe36d6..361c5bb86cf 100644
--- a/gcc/config/psos.h
+++ b/gcc/config/psos.h
@@ -67,18 +67,6 @@ Boston, MA 02111-1307, USA.
#define TARGET_MEM_FUNCTIONS
-
-/* When using stabs, gcc2_compiled must be a stabs entry, not an
- ordinary symbol, or gdb won't see it. The stabs entry must be
- before the N_SO in order for gdb to find it. */
-
-#define ASM_IDENTIFY_GCC(FILE) \
-do \
- { \
- fputs (".stabs \"gcc2_compiled.\", 0x3c, 0, 0, 0\n", FILE); \
- } \
-while (0)
-
/* This is how we tell the assembler that a symbol is weak. */
#define ASM_WEAKEN_LABEL(FILE,NAME) \
diff --git a/gcc/config/ptx4.h b/gcc/config/ptx4.h
index c7108748d49..57b04645dab 100644
--- a/gcc/config/ptx4.h
+++ b/gcc/config/ptx4.h
@@ -204,21 +204,6 @@ Boston, MA 02111-1307, USA.
#undef DBX_REGISTER_NUMBER
-/* When using stabs, gcc2_compiled must be a stabs entry, not an
- ordinary symbol, or gdb won't see it. The stabs entry must be
- before the N_SO in order for gdb to find it. */
-
-#undef ASM_IDENTIFY_GCC
-#define ASM_IDENTIFY_GCC(FILE) \
-do \
- { \
- if (write_symbols != DBX_DEBUG) \
- fputs ("gcc2_compiled.:\n", FILE); \
- else \
- fputs ("\t.stabs\t\"gcc2_compiled.\", 0x3c, 0, 0, 0\n", FILE); \
- } \
-while (0)
-
/* Like block addresses, stabs line numbers are relative to the
current function. */
diff --git a/gcc/config/romp/romp.c b/gcc/config/romp/romp.c
index 91cfeeba33b..7aedeb60024 100644
--- a/gcc/config/romp/romp.c
+++ b/gcc/config/romp/romp.c
@@ -29,7 +29,6 @@ Boston, MA 02111-1307, USA. */
#include "real.h"
#include "insn-config.h"
#include "conditions.h"
-#include "insn-flags.h"
#include "output.h"
#include "insn-attr.h"
#include "flags.h"
diff --git a/gcc/config/romp/xm-romp.h b/gcc/config/romp/xm-romp.h
index acb5b8cecb1..80a14c3c562 100644
--- a/gcc/config/romp/xm-romp.h
+++ b/gcc/config/romp/xm-romp.h
@@ -18,11 +18,6 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-
-/* #defines that need visibility everywhere. */
-#define FALSE 0
-#define TRUE 1
-
/* This describes the machine the compiler is hosted on. */
#define HOST_BITS_PER_CHAR 8
#define HOST_BITS_PER_SHORT 16
diff --git a/gcc/config/rs6000/aix.h b/gcc/config/rs6000/aix.h
index a28fe1b517f..853a5d396fb 100644
--- a/gcc/config/rs6000/aix.h
+++ b/gcc/config/rs6000/aix.h
@@ -68,7 +68,7 @@ Boston, MA 02111-1307, USA. */
/* #define ASM_OUTPUT_DESTRUCTOR(file, name) */
/* The prefix to add to user-visible assembler symbols. */
-#define USER_LABEL_PREFIX "."
+#define USER_LABEL_PREFIX ""
/* Don't turn -B into -L if the argument specifies a relative file name. */
#define RELATIVE_PREFIX_NOT_LINKDIR
@@ -402,9 +402,6 @@ toc_section () \
Also, in order to output proper .bs/.es pairs, we need at least one static
[RW] section emitted.
- We then switch back to text to force the gcc2_compiled. label and the space
- allocated after it (when profiling) into the text section.
-
Finally, declare mcount when profiling to make the assembler happy. */
#define ASM_FILE_START(FILE) \
@@ -561,48 +558,9 @@ toc_section () \
use '.long' or '.word', but that aligns to a 4-byte boundary which
is not what is required. So we define a million macros... */
-#define ASM_OUTPUT_DWARF_ADDR_VAR(FILE, LABEL, LENGTH) \
- do { fprintf ((FILE), "\t.vbyte\t%d,", LENGTH); \
- assemble_name (FILE, LABEL); \
- } while (0)
-
-#define ASM_OUTPUT_DWARF_DELTA_VAR(FILE, LABEL1, LABEL2, LENGTH) \
- do { fprintf ((FILE), "\t.vbyte\t%d,", LENGTH); \
- assemble_name (FILE, LABEL1); \
- fprintf (FILE, "-"); \
- assemble_name (FILE, LABEL2); \
- } while (0)
-
-#define ASM_OUTPUT_DWARF_DELTA2(FILE, LABEL1, LABEL2) \
- ASM_OUTPUT_DWARF_DELTA_VAR (FILE, LABEL1, LABEL2, 2)
-
-#define ASM_OUTPUT_DWARF_DELTA4(FILE, LABEL1, LABEL2) \
- ASM_OUTPUT_DWARF_DELTA_VAR (FILE, LABEL1, LABEL2, 4)
-
-#define ASM_OUTPUT_DWARF_DELTA(FILE, LABEL1, LABEL2) \
- ASM_OUTPUT_DWARF_DELTA_VAR (FILE, LABEL1, LABEL2, DWARF_OFFSET_SIZE)
-
-#define ASM_OUTPUT_DWARF_ADDR_DELTA(FILE, LABEL1, LABEL2) \
- ASM_OUTPUT_DWARF_DELTA_VAR (FILE, LABEL1, LABEL2, \
- POINTER_SIZE / BITS_PER_UNIT)
-
-#define ASM_OUTPUT_DWARF_ADDR(FILE, LABEL) \
- ASM_OUTPUT_DWARF_ADDR_VAR (FILE, LABEL, POINTER_SIZE / BITS_PER_UNIT)
-
-#define ASM_OUTPUT_DWARF_DATA4(FILE, VALUE) \
- fprintf ((FILE), "\t.vbyte\t4,0x%x", (unsigned) (VALUE))
-
-#define ASM_OUTPUT_DWARF_DATA2(FILE, VALUE) \
- fprintf ((FILE), "\t.vbyte\t2,0x%x", (unsigned) (VALUE))
-
-#define ASM_OUTPUT_DWARF_OFFSET4(FILE, LABEL) \
- ASM_OUTPUT_DWARF_ADDR_VAR (FILE, LABEL, 4)
-
-#define ASM_OUTPUT_DWARF_OFFSET(FILE, LABEL) \
- ASM_OUTPUT_DWARF_ADDR_VAR (FILE, LABEL, DWARF_OFFSET_SIZE)
-
-/* dwarf2out keys off this, but we don't have to have a real definition. */
-#define UNALIGNED_INT_ASM_OP bite_me
+#define UNALIGNED_SHORT_ASM_OP "\t.vbyte\t2,"
+#define UNALIGNED_INT_ASM_OP "\t.vbyte\t4,"
+#define UNALIGNED_DOUBLE_INT_ASM_OP "\t.vbyte\t8,"
/* Output before instructions. */
#define TEXT_SECTION_ASM_OP "\t.csect .text[PR]"
diff --git a/gcc/config/rs6000/aix43.h b/gcc/config/rs6000/aix43.h
index 3f08e771fe2..78700eaa209 100644
--- a/gcc/config/rs6000/aix43.h
+++ b/gcc/config/rs6000/aix43.h
@@ -199,6 +199,10 @@ do { \
%{pthread:%{pg:gcrt0_r%O%s}%{!pg:%{p:mcrt0_r%O%s}%{!p:crt0_r%O%s}}}\
%{!pthread:%{pg:gcrt0%O%s}%{!pg:%{p:mcrt0%O%s}%{!p:crt0%O%s}}}}}}"
+/* Since there are separate multilibs for pthreads, determine the
+ thread model based on the command-line arguments. */
+#define THREAD_MODEL_SPEC "%{pthread:posix}%{!pthread:single}"
+
/* AIX 4.3 typedefs ptrdiff_t as "long" while earlier releases used "int". */
#undef PTRDIFF_TYPE
diff --git a/gcc/config/rs6000/aix51.h b/gcc/config/rs6000/aix51.h
index fd679b9c487..ef512e8da5a 100644
--- a/gcc/config/rs6000/aix51.h
+++ b/gcc/config/rs6000/aix51.h
@@ -21,10 +21,7 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#include "rs6000/rs6000.h"
-#include "rs6000/aix.h"
-
-/* AIX V5 and above support 64-bit executables. */
+/* AIX 4.3 and above support 64-bit executables. */
#undef SUBSUBTARGET_SWITCHES
#define SUBSUBTARGET_SWITCHES \
{"aix64", MASK_64BIT | MASK_POWERPC64 | MASK_POWERPC, \
@@ -106,13 +103,13 @@ do { \
-D_AIX -D_AIX32 -D_AIX41 -D_AIX43 -D_AIX51 -Asystem=unix -Asystem=aix"
#undef CPP_SPEC
-#define CPP_SPEC "%{posix: -D_POSIX_SOURCE} \
- %{ansi: -D_ANSI_C_SOURCE} \
- %{!maix64: -D__WCHAR_TYPE__="short unsigned int"} \
- %{maix64: -D__64BIT__ -D_ARCH_PPC -D__WCHAR_TYPE__="unsigned int" \
- -D__LONG_MAX__=9223372036854775807L} \
- %{mpe: -I/usr/lpp/ppe.poe/include} \
- %{pthread: -D_THREAD_SAFE} \
+#define CPP_SPEC "%{posix: -D_POSIX_SOURCE}\
+ %{ansi: -D_ANSI_C_SOURCE}\
+ %{!maix64: -D__WCHAR_TYPE__=short\\ unsigned\\ int}\
+ %{maix64: -D__64BIT__ -D_ARCH_PPC -D__LONG_MAX__=9223372036854775807L \
+ -D__WCHAR_TYPE__=unsigned\\ int}\
+ %{mpe: -I/usr/lpp/ppe.poe/include}\
+ %{pthread: -D_THREAD_SAFE}\
%(cpp_cpu)"
/* The GNU C++ standard library requires that these macros be
@@ -123,9 +120,9 @@ do { \
-D_XOPEN_SOURCE_EXTENDED=1 \
-D_LARGE_FILE_API \
-D_ALL_SOURCE \
- %{!maix64: -D__WCHAR_TYPE__="short unsigned int"} \
- %{maix64: -D__64BIT__ -D_ARCH_PPC -D__WCHAR_TYPE__="unsigned int" \
- -D__LONG_MAX__=9223372036854775807L} \
+ %{!maix64: -D__WCHAR_TYPE__=short\\ unsigned\\ int}\
+ %{maix64: -D__64BIT__ -D_ARCH_PPC -D__LONG_MAX__=9223372036854775807L \
+ -D__WCHAR_TYPE__=unsigned\\ int}\
%{mpe: -I/usr/lpp/ppe.poe/include}\
%{pthread: -D_THREAD_SAFE}\
%(cpp_cpu)"
@@ -205,6 +202,10 @@ do { \
%{pthread:%{pg:gcrt0_r%O%s}%{!pg:%{p:mcrt0_r%O%s}%{!p:crt0_r%O%s}}}\
%{!pthread:%{pg:gcrt0%O%s}%{!pg:%{p:mcrt0%O%s}%{!p:crt0%O%s}}}}}}"
+/* Since there are separate multilibs for pthreads, determine the
+ thread model based on the command-line arguments. */
+#define THREAD_MODEL_SPEC "%{pthread:posix}%{!pthread:single}"
+
/* AIX V5 typedefs ptrdiff_t as "long" while earlier releases used "int". */
#undef PTRDIFF_TYPE
@@ -213,6 +214,7 @@ do { \
/* __WCHAR_TYPE__ is dynamic, so do not define it statically. */
#define NO_BUILTIN_WCHAR_TYPE
#undef WCHAR_TYPE
+#undef WCHAR_TYPE_SIZE
/* Width of wchar_t in bits. */
#define WCHAR_TYPE_SIZE (!TARGET_64BIT ? 16 : 32)
diff --git a/gcc/config/rs6000/linux.h b/gcc/config/rs6000/linux.h
index f0cf9d18c34..6e06ecbd781 100644
--- a/gcc/config/rs6000/linux.h
+++ b/gcc/config/rs6000/linux.h
@@ -1,6 +1,7 @@
/* Definitions of target machine for GNU compiler,
- for IBM RS/6000 running AIX version 3.1.
- Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
+ for powerpc machines running Linux.
+ Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation,
+ Inc.
Contributed by Michael Meissner (meissner@cygnus.com).
This file is part of GNU CC.
@@ -33,6 +34,12 @@ Boston, MA 02111-1307, USA. */
#undef CPP_OS_DEFAULT_SPEC
#define CPP_OS_DEFAULT_SPEC "%(cpp_os_linux)"
+/* The GNU C++ standard library currently requires _GNU_SOURCE being
+ defined on glibc-based systems. This temporary hack accomplishes this,
+ it should go away as soon as libstdc++-v3 has a real fix. */
+#undef CPLUSPLUS_CPP_SPEC
+#define CPLUSPLUS_CPP_SPEC "-D_GNU_SOURCE %(cpp)"
+
#undef LINK_SHLIB_SPEC
#define LINK_SHLIB_SPEC "%{shared:-shared} %{!shared: %{static:-static}}"
@@ -66,3 +73,58 @@ Boston, MA 02111-1307, USA. */
#ifndef USE_GNULIBC_1
#define DEFAULT_VTABLE_THUNKS 1
#endif
+
+/* Do code reading to identify a signal frame, and set the frame
+ state data appropriately. See unwind-dw2.c for the structs. */
+
+#ifdef IN_LIBGCC2
+#include <signal.h>
+#include <sys/ucontext.h>
+
+enum { SIGNAL_FRAMESIZE = 64 };
+#endif
+
+#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \
+ do { \
+ unsigned char *pc_ = (CONTEXT)->ra; \
+ struct sigcontext *sc_; \
+ long new_cfa_; \
+ int i_; \
+ \
+ /* li r0, 0x7777; sc (rt_sigreturn) */ \
+ /* li r0, 0x6666; sc (sigreturn) */ \
+ if (((*(unsigned int *) (pc_+0) == 0x38007777) \
+ || (*(unsigned int *) (pc_+0) == 0x38006666)) \
+ && (*(unsigned int *) (pc_+4) == 0x44000002)) \
+ sc_ = (CONTEXT)->cfa + SIGNAL_FRAMESIZE; \
+ else \
+ break; \
+ \
+ new_cfa_ = sc_->regs->gpr[STACK_POINTER_REGNUM]; \
+ (FS)->cfa_how = CFA_REG_OFFSET; \
+ (FS)->cfa_reg = STACK_POINTER_REGNUM; \
+ (FS)->cfa_offset = new_cfa_ - (long) (CONTEXT)->cfa; \
+ \
+ for (i_ = 0; i_ < 32; i_++) \
+ if (i_ != STACK_POINTER_REGNUM) \
+ { \
+ (FS)->regs.reg[i_].how = REG_SAVED_OFFSET; \
+ (FS)->regs.reg[i_].loc.offset \
+ = (long)&(sc_->regs->gpr[i_]) - new_cfa_; \
+ } \
+ \
+ (FS)->regs.reg[LINK_REGISTER_REGNUM].how = REG_SAVED_OFFSET; \
+ (FS)->regs.reg[LINK_REGISTER_REGNUM].loc.offset \
+ = (long)&(sc_->regs->link) - new_cfa_; \
+ \
+ /* The unwinder expects the IP to point to the following insn, \
+ whereas the kernel returns the address of the actual \
+ faulting insn. */ \
+ sc_->regs->nip += 4; \
+ (FS)->regs.reg[CR0_REGNO].how = REG_SAVED_OFFSET; \
+ (FS)->regs.reg[CR0_REGNO].loc.offset \
+ = (long)&(sc_->regs->nip) - new_cfa_; \
+ (FS)->retaddr_column = CR0_REGNO; \
+ goto SUCCESS; \
+ } while (0)
+
diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h
index 31e5716bcf8..e4e2401ab59 100644
--- a/gcc/config/rs6000/rs6000-protos.h
+++ b/gcc/config/rs6000/rs6000-protos.h
@@ -42,11 +42,14 @@ extern int reg_or_neg_short_operand PARAMS ((rtx, enum machine_mode));
extern int reg_or_u_short_operand PARAMS ((rtx, enum machine_mode));
extern int reg_or_cint_operand PARAMS ((rtx, enum machine_mode));
extern int reg_or_arith_cint_operand PARAMS ((rtx, enum machine_mode));
+extern int reg_or_add_cint64_operand PARAMS ((rtx, enum machine_mode));
+extern int reg_or_sub_cint64_operand PARAMS ((rtx, enum machine_mode));
extern int reg_or_logical_cint_operand PARAMS ((rtx, enum machine_mode));
extern int got_operand PARAMS ((rtx, enum machine_mode));
extern int got_no_const_operand PARAMS ((rtx, enum machine_mode));
extern int num_insns_constant PARAMS ((rtx, enum machine_mode));
extern int easy_fp_constant PARAMS ((rtx, enum machine_mode));
+extern int zero_fp_constant PARAMS ((rtx, enum machine_mode));
extern int volatile_mem_operand PARAMS ((rtx, enum machine_mode));
extern int offsettable_mem_operand PARAMS ((rtx, enum machine_mode));
extern int mem_or_easy_const_operand PARAMS ((rtx, enum machine_mode));
@@ -79,6 +82,7 @@ extern int scc_comparison_operator PARAMS ((rtx, enum machine_mode));
extern int trap_comparison_operator PARAMS ((rtx, enum machine_mode));
extern int boolean_operator PARAMS ((rtx, enum machine_mode));
extern int boolean_or_operator PARAMS ((rtx, enum machine_mode));
+extern int min_max_operator PARAMS ((rtx, enum machine_mode));
extern int includes_lshift_p PARAMS ((rtx, rtx));
extern int includes_rshift_p PARAMS ((rtx, rtx));
extern int includes_lshift64_p PARAMS ((rtx, rtx));
@@ -94,6 +98,8 @@ extern enum rtx_code rs6000_reverse_condition PARAMS ((enum machine_mode,
extern void rs6000_emit_sCOND PARAMS ((enum rtx_code, rtx));
extern void rs6000_emit_cbranch PARAMS ((enum rtx_code, rtx));
extern char * output_cbranch PARAMS ((rtx, const char *, int, rtx));
+extern int rs6000_emit_cmove PARAMS ((rtx, rtx, rtx, rtx));
+extern void rs6000_emit_minmax PARAMS ((rtx, enum rtx_code, rtx, rtx));
extern void output_toc PARAMS ((FILE *, rtx, int, enum machine_mode));
extern int rs6000_adjust_cost PARAMS ((rtx, rtx, rtx, int));
extern int rs6000_adjust_priority PARAMS ((rtx, int));
@@ -107,6 +113,7 @@ extern struct rtx_def *create_TOC_reference PARAMS ((rtx));
extern void rs6000_emit_eh_toc_restore PARAMS ((rtx));
extern void rs6000_emit_move PARAMS ((rtx, rtx, enum machine_mode));
extern rtx rs6000_legitimize_address PARAMS ((rtx, rtx, enum machine_mode));
+extern int rs6000_legitimate_address PARAMS ((enum machine_mode, rtx, int));
extern void rs6000_select_rtx_section PARAMS ((enum machine_mode, rtx));
extern rtx rs6000_return_addr PARAMS ((int, rtx));
extern void rs6000_output_symbol_ref PARAMS ((FILE*, rtx));
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 2640c60c120..7f1aa22f25d 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -28,7 +28,6 @@ Boston, MA 02111-1307, USA. */
#include "real.h"
#include "insn-config.h"
#include "conditions.h"
-#include "insn-flags.h"
#include "insn-attr.h"
#include "flags.h"
#include "recog.h"
@@ -38,6 +37,7 @@ Boston, MA 02111-1307, USA. */
#include "except.h"
#include "function.h"
#include "output.h"
+#include "basic-block.h"
#include "toplev.h"
#include "ggc.h"
#include "hashtab.h"
@@ -471,7 +471,8 @@ rs6000_float_const (string, mode)
const char *string;
enum machine_mode mode;
{
- REAL_VALUE_TYPE value = REAL_VALUE_ATOF (string, mode);
+ REAL_VALUE_TYPE value;
+ value = REAL_VALUE_ATOF (string, mode);
return immed_real_const_1 (value, mode);
}
@@ -673,7 +674,43 @@ reg_or_arith_cint_operand (op, mode)
|| (GET_CODE (op) == CONST_INT
#if HOST_BITS_PER_WIDE_INT != 32
&& ((unsigned HOST_WIDE_INT) (INTVAL (op) + 0x80000000)
- < 0x100000000u)
+ < 0x100000000ll)
+#endif
+ ));
+}
+
+/* Return 1 is the operand is either a non-special register or a 32-bit
+ signed constant integer valid for 64-bit addition. */
+
+int
+reg_or_add_cint64_operand (op, mode)
+ register rtx op;
+ enum machine_mode mode;
+{
+ return (gpc_reg_operand (op, mode)
+ || (GET_CODE (op) == CONST_INT
+ && INTVAL (op) < 0x7fff8000
+#if HOST_BITS_PER_WIDE_INT != 32
+ && ((unsigned HOST_WIDE_INT) (INTVAL (op) + 0x80008000)
+ < 0x100000000ll)
+#endif
+ ));
+}
+
+/* Return 1 is the operand is either a non-special register or a 32-bit
+ signed constant integer valid for 64-bit subtraction. */
+
+int
+reg_or_sub_cint64_operand (op, mode)
+ register rtx op;
+ enum machine_mode mode;
+{
+ return (gpc_reg_operand (op, mode)
+ || (GET_CODE (op) == CONST_INT
+ && (- INTVAL (op)) < 0x7fff8000
+#if HOST_BITS_PER_WIDE_INT != 32
+ && ((unsigned HOST_WIDE_INT) ((- INTVAL (op)) + 0x80008000)
+ < 0x100000000ll)
#endif
));
}
@@ -904,6 +941,15 @@ easy_fp_constant (op, mode)
abort ();
}
+/* Return 1 if the operand is 0.0. */
+int
+zero_fp_constant (op, mode)
+ register rtx op;
+ register enum machine_mode mode;
+{
+ return GET_MODE_CLASS (mode) == MODE_FLOAT && op == CONST0_RTX (mode);
+}
+
/* Return 1 if the operand is in volatile memory. Note that during the
RTL generation phase, memory_operand does not return TRUE for
volatile memory references. So this function allows us to
@@ -963,9 +1009,11 @@ add_operand (op, mode)
register rtx op;
enum machine_mode mode;
{
- return (reg_or_short_operand (op, mode)
- || (GET_CODE (op) == CONST_INT
- && CONST_OK_FOR_LETTER_P (INTVAL(op), 'L')));
+ if (GET_CODE (op) == CONST_INT)
+ return (CONST_OK_FOR_LETTER_P (INTVAL(op), 'I')
+ || CONST_OK_FOR_LETTER_P (INTVAL(op), 'L'));
+
+ return gpc_reg_operand (op, mode);
}
/* Return 1 if OP is a constant but not a valid add_operand. */
@@ -1535,6 +1583,58 @@ rs6000_legitimize_address (x, oldx, mode)
else
return NULL_RTX;
}
+
+/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
+ that is a valid memory address for an instruction.
+ The MODE argument is the machine mode for the MEM expression
+ that wants to use this address.
+
+ On the RS/6000, there are four valid address: a SYMBOL_REF that
+ refers to a constant pool entry of an address (or the sum of it
+ plus a constant), a short (16-bit signed) constant plus a register,
+ the sum of two registers, or a register indirect, possibly with an
+ auto-increment. For DFmode and DImode with an constant plus register,
+ we must ensure that both words are addressable or PowerPC64 with offset
+ word aligned.
+
+ For modes spanning multiple registers (DFmode in 32-bit GPRs,
+ 32-bit DImode, TImode), indexed addressing cannot be used because
+ adjacent memory cells are accessed by adding word-sized offsets
+ during assembly output. */
+int
+rs6000_legitimate_address (mode, x, reg_ok_strict)
+ enum machine_mode mode;
+ rtx x;
+ int reg_ok_strict;
+{
+ if (LEGITIMATE_INDIRECT_ADDRESS_P (x, reg_ok_strict))
+ return 1;
+ if ((GET_CODE (x) == PRE_INC || GET_CODE (x) == PRE_DEC)
+ && TARGET_UPDATE
+ && LEGITIMATE_INDIRECT_ADDRESS_P (XEXP (x, 0), reg_ok_strict))
+ return 1;
+ if (LEGITIMATE_SMALL_DATA_P (mode, x))
+ return 1;
+ if (LEGITIMATE_CONSTANT_POOL_ADDRESS_P (x))
+ return 1;
+ /* If not REG_OK_STRICT (before reload) let pass any stack offset. */
+ if (! reg_ok_strict
+ && GET_CODE (x) == PLUS
+ && GET_CODE (XEXP (x, 0)) == REG
+ && XEXP (x, 0) == virtual_stack_vars_rtx
+ && GET_CODE (XEXP (x, 1)) == CONST_INT)
+ return 1;
+ if (LEGITIMATE_OFFSET_ADDRESS_P (mode, x, reg_ok_strict))
+ return 1;
+ if (mode != TImode
+ && (TARGET_HARD_FLOAT || TARGET_POWERPC64 || mode != DFmode)
+ && (TARGET_POWERPC64 || mode != DImode)
+ && LEGITIMATE_INDEXED_ADDRESS_P (x, reg_ok_strict))
+ return 1;
+ if (LEGITIMATE_LO_SUM_ADDRESS_P (mode, x, reg_ok_strict))
+ return 1;
+ return 0;
+}
/* Emit a move from SOURCE to DEST in mode MODE. */
void
@@ -1913,7 +2013,7 @@ function_arg_advance (cum, mode, type, named)
{
if (mode == DFmode)
cum->words += cum->words & 1;
- cum->words += RS6000_ARG_SIZE (mode, type, 1);
+ cum->words += RS6000_ARG_SIZE (mode, type);
}
}
else
@@ -1926,7 +2026,7 @@ function_arg_advance (cum, mode, type, named)
|| mode == TFmode)
n_words = 1;
else
- n_words = RS6000_ARG_SIZE (mode, type, 1);
+ n_words = RS6000_ARG_SIZE (mode, type);
/* Long long is put in odd registers. */
if (n_words == 2 && (gregno & 1) == 0)
@@ -1961,14 +2061,10 @@ function_arg_advance (cum, mode, type, named)
{
int align = (TARGET_32BIT && (cum->words & 1) != 0
&& function_arg_boundary (mode, type) == 64) ? 1 : 0;
- cum->words += align;
+ cum->words += align + RS6000_ARG_SIZE (mode, type);
- if (named)
- {
- cum->words += RS6000_ARG_SIZE (mode, type, named);
- if (GET_MODE_CLASS (mode) == MODE_FLOAT && TARGET_HARD_FLOAT)
- cum->fregno++;
- }
+ if (GET_MODE_CLASS (mode) == MODE_FLOAT && TARGET_HARD_FLOAT)
+ cum->fregno++;
if (TARGET_DEBUG_ARG)
{
@@ -2009,7 +2105,7 @@ function_arg (cum, mode, type, named)
CUMULATIVE_ARGS *cum;
enum machine_mode mode;
tree type;
- int named;
+ int named ATTRIBUTE_UNUSED;
{
enum rs6000_abi abi = DEFAULT_ABI;
@@ -2053,7 +2149,7 @@ function_arg (cum, mode, type, named)
|| mode == TFmode)
n_words = 1;
else
- n_words = RS6000_ARG_SIZE (mode, type, 1);
+ n_words = RS6000_ARG_SIZE (mode, type);
/* Long long is put in odd registers. */
if (n_words == 2 && (gregno & 1) == 0)
@@ -2072,9 +2168,6 @@ function_arg (cum, mode, type, named)
&& function_arg_boundary (mode, type) == 64) ? 1 : 0;
int align_words = cum->words + align;
- if (! named)
- return NULL_RTX;
-
if (type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
return NULL_RTX;
@@ -2096,7 +2189,7 @@ function_arg (cum, mode, type, named)
((align_words >= GP_ARG_NUM_REG)
? NULL_RTX
: (align_words
- + RS6000_ARG_SIZE (mode, type, named)
+ + RS6000_ARG_SIZE (mode, type)
> GP_ARG_NUM_REG
/* If this is partially on the stack, then
we only include the portion actually
@@ -2126,11 +2219,8 @@ function_arg_partial_nregs (cum, mode, type, named)
CUMULATIVE_ARGS *cum;
enum machine_mode mode;
tree type;
- int named;
+ int named ATTRIBUTE_UNUSED;
{
- if (! named)
- return 0;
-
if (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS)
return 0;
@@ -2141,7 +2231,7 @@ function_arg_partial_nregs (cum, mode, type, named)
}
if (cum->words < GP_ARG_NUM_REG
- && GP_ARG_NUM_REG < (cum->words + RS6000_ARG_SIZE (mode, type, named)))
+ && GP_ARG_NUM_REG < (cum->words + RS6000_ARG_SIZE (mode, type)))
{
int ret = GP_ARG_NUM_REG - cum->words;
if (ret && TARGET_DEBUG_ARG)
@@ -2206,25 +2296,24 @@ setup_incoming_varargs (cum, mode, type, pretend_size, no_rtl)
{
CUMULATIVE_ARGS next_cum;
int reg_size = TARGET_32BIT ? 4 : 8;
- rtx save_area, mem;
+ rtx save_area = NULL_RTX, mem;
int first_reg_offset, set;
+ tree fntype;
+ int stdarg_p;
- if (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS)
- {
- tree fntype;
- int stdarg_p;
-
- fntype = TREE_TYPE (current_function_decl);
- stdarg_p = (TYPE_ARG_TYPES (fntype) != 0
- && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
- != void_type_node));
+ fntype = TREE_TYPE (current_function_decl);
+ stdarg_p = (TYPE_ARG_TYPES (fntype) != 0
+ && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
+ != void_type_node));
- /* For varargs, we do not want to skip the dummy va_dcl argument.
- For stdargs, we do want to skip the last named argument. */
- next_cum = *cum;
- if (stdarg_p)
- function_arg_advance (&next_cum, mode, type, 1);
+ /* For varargs, we do not want to skip the dummy va_dcl argument.
+ For stdargs, we do want to skip the last named argument. */
+ next_cum = *cum;
+ if (stdarg_p)
+ function_arg_advance (&next_cum, mode, type, 1);
+ if (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS)
+ {
/* Indicate to allocate space on the stack for varargs save area. */
/* ??? Does this really have to be located at a magic spot on the
stack, or can we allocate this with assign_stack_local instead. */
@@ -2237,12 +2326,12 @@ setup_incoming_varargs (cum, mode, type, pretend_size, no_rtl)
}
else
{
+ first_reg_offset = next_cum.words;
save_area = virtual_incoming_args_rtx;
cfun->machine->sysv_varargs_p = 0;
- first_reg_offset = cum->words;
if (MUST_PASS_IN_STACK (mode, type))
- first_reg_offset += RS6000_ARG_SIZE (TYPE_MODE (type), type, 1);
+ first_reg_offset += RS6000_ARG_SIZE (TYPE_MODE (type), type);
}
set = get_varargs_alias_set ();
@@ -3080,14 +3169,14 @@ lmw_operation (op, mode)
|| count != 32 - (int) dest_regno)
return 0;
- if (LEGITIMATE_INDIRECT_ADDRESS_P (src_addr))
+ if (LEGITIMATE_INDIRECT_ADDRESS_P (src_addr, 0))
{
offset = 0;
base_regno = REGNO (src_addr);
if (base_regno == 0)
return 0;
}
- else if (LEGITIMATE_OFFSET_ADDRESS_P (SImode, src_addr))
+ else if (LEGITIMATE_OFFSET_ADDRESS_P (SImode, src_addr, 0))
{
offset = INTVAL (XEXP (src_addr, 1));
base_regno = REGNO (XEXP (src_addr, 0));
@@ -3110,12 +3199,12 @@ lmw_operation (op, mode)
|| GET_MODE (SET_SRC (elt)) != SImode)
return 0;
newaddr = XEXP (SET_SRC (elt), 0);
- if (LEGITIMATE_INDIRECT_ADDRESS_P (newaddr))
+ if (LEGITIMATE_INDIRECT_ADDRESS_P (newaddr, 0))
{
newoffset = 0;
addr_reg = newaddr;
}
- else if (LEGITIMATE_OFFSET_ADDRESS_P (SImode, newaddr))
+ else if (LEGITIMATE_OFFSET_ADDRESS_P (SImode, newaddr, 0))
{
addr_reg = XEXP (newaddr, 0);
newoffset = INTVAL (XEXP (newaddr, 1));
@@ -3158,14 +3247,14 @@ stmw_operation (op, mode)
|| count != 32 - (int) src_regno)
return 0;
- if (LEGITIMATE_INDIRECT_ADDRESS_P (dest_addr))
+ if (LEGITIMATE_INDIRECT_ADDRESS_P (dest_addr, 0))
{
offset = 0;
base_regno = REGNO (dest_addr);
if (base_regno == 0)
return 0;
}
- else if (LEGITIMATE_OFFSET_ADDRESS_P (SImode, dest_addr))
+ else if (LEGITIMATE_OFFSET_ADDRESS_P (SImode, dest_addr, 0))
{
offset = INTVAL (XEXP (dest_addr, 1));
base_regno = REGNO (XEXP (dest_addr, 0));
@@ -3188,12 +3277,12 @@ stmw_operation (op, mode)
|| GET_MODE (SET_DEST (elt)) != SImode)
return 0;
newaddr = XEXP (SET_DEST (elt), 0);
- if (LEGITIMATE_INDIRECT_ADDRESS_P (newaddr))
+ if (LEGITIMATE_INDIRECT_ADDRESS_P (newaddr, 0))
{
newoffset = 0;
addr_reg = newaddr;
}
- else if (LEGITIMATE_OFFSET_ADDRESS_P (SImode, newaddr))
+ else if (LEGITIMATE_OFFSET_ADDRESS_P (SImode, newaddr, 0))
{
addr_reg = XEXP (newaddr, 0);
newoffset = INTVAL (XEXP (newaddr, 1));
@@ -3237,8 +3326,9 @@ validate_condition_mode (code, mode)
|| code == UNGE || code == UNLE))
abort();
- /* These should never be generated. */
+ /* These should never be generated except for fast_math. */
if (mode == CCFPmode
+ && ! flag_fast_math
&& (code == LE || code == GE
|| code == UNEQ || code == LTGT
|| code == UNGT || code == UNLT))
@@ -3351,6 +3441,15 @@ boolean_or_operator (op, mode)
enum rtx_code code = GET_CODE (op);
return (code == IOR || code == XOR);
}
+
+int
+min_max_operator (op, mode)
+ rtx op;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+ enum rtx_code code = GET_CODE (op);
+ return (code == SMIN || code == SMAX || code == UMIN || code == UMAX);
+}
/* Return 1 if ANDOP is a mask that has no bits on that are not in the
mask required to convert the result of a rotate insn into a shift
@@ -3985,6 +4084,7 @@ print_operand (file, x, code)
case 'p':
/* X is a CONST_INT that is a power of two. Output the logarithm. */
if (! INT_P (x)
+ || INT_LOWPART (x) < 0
|| (i = exact_log2 (INT_LOWPART (x))) < 0)
output_operand_lossage ("invalid %%p value");
else
@@ -4250,7 +4350,7 @@ print_operand (file, x, code)
case 'X':
if (GET_CODE (x) == MEM
- && LEGITIMATE_INDEXED_ADDRESS_P (XEXP (x, 0)))
+ && LEGITIMATE_INDEXED_ADDRESS_P (XEXP (x, 0), 0))
putc ('x', file);
return;
@@ -4451,8 +4551,10 @@ rs6000_generate_compare (code)
rs6000_compare_op0,
rs6000_compare_op1)));
- /* Some kinds of FP comparisons need an OR operation. */
+ /* Some kinds of FP comparisons need an OR operation;
+ except that for fast_math we don't bother. */
if (rs6000_compare_fp_p
+ && ! flag_fast_math
&& (code == LE || code == GE
|| code == UNEQ || code == LTGT
|| code == UNGT || code == UNLT))
@@ -4579,12 +4681,18 @@ output_cbranch (op, label, reversed, insn)
{
/* Not all of these are actually distinct opcodes, but
we distinguish them for clarity of the resulting assembler. */
- case NE: ccode = "ne"; break;
- case EQ: ccode = "eq"; break;
- case GE: case GEU: ccode = "ge"; break;
- case GT: case GTU: ccode = "gt"; break;
- case LE: case LEU: ccode = "le"; break;
- case LT: case LTU: ccode = "lt"; break;
+ case NE: case LTGT:
+ ccode = "ne"; break;
+ case EQ: case UNEQ:
+ ccode = "eq"; break;
+ case GE: case GEU:
+ ccode = "ge"; break;
+ case GT: case GTU: case UNGT:
+ ccode = "gt"; break;
+ case LE: case LEU:
+ ccode = "le"; break;
+ case LT: case LTU: case UNLT:
+ ccode = "lt"; break;
case UNORDERED: ccode = "un"; break;
case ORDERED: ccode = "nu"; break;
case UNGE: ccode = "nl"; break;
@@ -4634,6 +4742,181 @@ output_cbranch (op, label, reversed, insn)
return string;
}
+
+/* Emit a conditional move: move TRUE_COND to DEST if OP of the
+ operands of the last comparison is nonzero/true, FALSE_COND if it
+ is zero/false. Return 0 if the hardware has no such operation. */
+int
+rs6000_emit_cmove (dest, op, true_cond, false_cond)
+ rtx dest;
+ rtx op;
+ rtx true_cond;
+ rtx false_cond;
+{
+ enum rtx_code code = GET_CODE (op);
+ rtx op0 = rs6000_compare_op0;
+ rtx op1 = rs6000_compare_op1;
+ REAL_VALUE_TYPE c1;
+ enum machine_mode mode = GET_MODE (op0);
+ rtx temp;
+
+ /* First, work out if the hardware can do this at all, or
+ if it's too slow... */
+ /* If the comparison is an integer one, since we only have fsel
+ it'll be cheaper to use a branch. */
+ if (! rs6000_compare_fp_p)
+ return 0;
+
+ /* Eliminate half of the comparisons by switching operands, this
+ makes the remaining code simpler. */
+ if (code == UNLT || code == UNGT || code == UNORDERED || code == NE
+ || code == LTGT || code == LT)
+ {
+ code = reverse_condition_maybe_unordered (code);
+ temp = true_cond;
+ true_cond = false_cond;
+ false_cond = temp;
+ }
+
+ /* UNEQ and LTGT take four instructions for a comparison with zero,
+ it'll probably be faster to use a branch here too. */
+ if (code == UNEQ)
+ return 0;
+
+ if (GET_CODE (op1) == CONST_DOUBLE)
+ REAL_VALUE_FROM_CONST_DOUBLE (c1, op1);
+
+ /* We're going to try to implement comparions by performing
+ a subtract, then comparing against zero. Unfortunately,
+ Inf - Inf is NaN which is not zero, and so if we don't
+ know that the the operand is finite and the comparison
+ would treat EQ different to UNORDERED, we can't do it. */
+ if (! flag_fast_math
+ && code != GT && code != UNGE
+ && (GET_CODE (op1) != CONST_DOUBLE || target_isinf (c1))
+ /* Constructs of the form (a OP b ? a : b) are safe. */
+ && ((! rtx_equal_p (op0, false_cond) && ! rtx_equal_p (op1, false_cond))
+ || (! rtx_equal_p (op0, true_cond)
+ && ! rtx_equal_p (op1, true_cond))))
+ return 0;
+ /* At this point we know we can use fsel. */
+
+ /* Reduce the comparison to a comparison against zero. */
+ temp = gen_reg_rtx (mode);
+ emit_insn (gen_rtx_SET (VOIDmode, temp,
+ gen_rtx_MINUS (mode, op0, op1)));
+ op0 = temp;
+ op1 = CONST0_RTX (mode);
+
+ /* If we don't care about NaNs we can reduce some of the comparisons
+ down to faster ones. */
+ if (flag_fast_math)
+ switch (code)
+ {
+ case GT:
+ code = LE;
+ temp = true_cond;
+ true_cond = false_cond;
+ false_cond = temp;
+ break;
+ case UNGE:
+ code = GE;
+ break;
+ case UNEQ:
+ code = EQ;
+ break;
+ default:
+ break;
+ }
+
+ /* Now, reduce everything down to a GE. */
+ switch (code)
+ {
+ case GE:
+ break;
+
+ case LE:
+ temp = gen_reg_rtx (mode);
+ emit_insn (gen_rtx_SET (VOIDmode, temp, gen_rtx_NEG (mode, op0)));
+ op0 = temp;
+ break;
+
+ case ORDERED:
+ temp = gen_reg_rtx (mode);
+ emit_insn (gen_rtx_SET (VOIDmode, temp, gen_rtx_ABS (mode, op0)));
+ op0 = temp;
+ break;
+
+ case EQ:
+ temp = gen_reg_rtx (mode);
+ emit_insn (gen_rtx_SET (VOIDmode, temp,
+ gen_rtx_NEG (mode,
+ gen_rtx_ABS (mode, op0))));
+ op0 = temp;
+ break;
+
+ case UNGE:
+ temp = gen_reg_rtx (mode);
+ emit_insn (gen_rtx_SET (VOIDmode, temp,
+ gen_rtx_IF_THEN_ELSE (mode,
+ gen_rtx_GE (VOIDmode,
+ op0, op1),
+ true_cond, false_cond)));
+ false_cond = temp;
+ true_cond = false_cond;
+
+ temp = gen_reg_rtx (mode);
+ emit_insn (gen_rtx_SET (VOIDmode, temp, gen_rtx_NEG (mode, op0)));
+ op0 = temp;
+ break;
+
+ case GT:
+ temp = gen_reg_rtx (mode);
+ emit_insn (gen_rtx_SET (VOIDmode, temp,
+ gen_rtx_IF_THEN_ELSE (mode,
+ gen_rtx_GE (VOIDmode,
+ op0, op1),
+ true_cond, false_cond)));
+ true_cond = temp;
+ false_cond = true_cond;
+
+ temp = gen_reg_rtx (mode);
+ emit_insn (gen_rtx_SET (VOIDmode, temp, gen_rtx_NEG (mode, op0)));
+ op0 = temp;
+ break;
+
+ default:
+ abort ();
+ }
+
+ emit_insn (gen_rtx_SET (VOIDmode, dest,
+ gen_rtx_IF_THEN_ELSE (mode,
+ gen_rtx_GE (VOIDmode,
+ op0, op1),
+ true_cond, false_cond)));
+ return 1;
+}
+
+void
+rs6000_emit_minmax (dest, code, op0, op1)
+ rtx dest;
+ enum rtx_code code;
+ rtx op0;
+ rtx op1;
+{
+ enum machine_mode mode = GET_MODE (op0);
+ rtx target;
+ if (code == SMAX || code == UMAX)
+ target = emit_conditional_move (dest, GE, op0, op1, mode,
+ op0, op1, mode, 0);
+ else
+ target = emit_conditional_move (dest, GE, op0, op1, mode,
+ op1, op0, mode, 0);
+ if (target == NULL_RTX)
+ abort ();
+ if (target != dest)
+ emit_move_insn (dest, target);
+}
/* This page contains routines that are used to determine what the function
prologue and epilogue code will do and write them out. */
@@ -4804,6 +5087,7 @@ rs6000_stack_info ()
rs6000_stack_t *info_ptr = &info;
int reg_size = TARGET_POWERPC64 ? 8 : 4;
enum rs6000_abi abi;
+ int ehrd_size;
int total_raw_size;
/* Zero all fields portably */
@@ -4856,6 +5140,19 @@ rs6000_stack_info ()
info_ptr->cr_size = reg_size;
}
+ /* If the current function calls __builtin_eh_return, then we need
+ to allocate stack space for registers that will hold data for
+ the exception handler. */
+ if (current_function_calls_eh_return)
+ {
+ unsigned int i;
+ for (i = 0; EH_RETURN_DATA_REGNO (i) != INVALID_REGNUM; ++i)
+ continue;
+ ehrd_size = i * UNITS_PER_WORD;
+ }
+ else
+ ehrd_size = 0;
+
/* Determine various sizes */
info_ptr->reg_size = reg_size;
info_ptr->fixed_size = RS6000_SAVE_AREA;
@@ -4864,6 +5161,7 @@ rs6000_stack_info ()
info_ptr->parm_size = RS6000_ALIGN (current_function_outgoing_args_size, 8);
info_ptr->save_size = RS6000_ALIGN (info_ptr->fp_size
+ info_ptr->gp_size
+ + ehrd_size
+ info_ptr->cr_size
+ info_ptr->lr_size
+ info_ptr->toc_size, 8);
@@ -4879,6 +5177,7 @@ rs6000_stack_info ()
case ABI_AIX_NODESC:
info_ptr->fp_save_offset = - info_ptr->fp_size;
info_ptr->gp_save_offset = info_ptr->fp_save_offset - info_ptr->gp_size;
+ info_ptr->ehrd_offset = info_ptr->gp_save_offset - ehrd_size;
info_ptr->cr_save_offset = reg_size; /* first word when 64-bit. */
info_ptr->lr_save_offset = 2*reg_size;
break;
@@ -4889,6 +5188,7 @@ rs6000_stack_info ()
info_ptr->gp_save_offset = info_ptr->fp_save_offset - info_ptr->gp_size;
info_ptr->cr_save_offset = info_ptr->gp_save_offset - info_ptr->cr_size;
info_ptr->toc_save_offset = info_ptr->cr_save_offset - info_ptr->toc_size;
+ info_ptr->ehrd_offset = info_ptr->toc_save_offset - ehrd_size;
info_ptr->lr_save_offset = reg_size;
break;
}
@@ -5581,7 +5881,7 @@ rs6000_frame_related (insn, reg, val, reg2, rreg)
/* Emit function prologue as insns. */
void
-rs6000_emit_prologue()
+rs6000_emit_prologue ()
{
rs6000_stack_t *info = rs6000_stack_info ();
enum machine_mode reg_mode = TARGET_POWERPC64 ? DImode : SImode;
@@ -5737,6 +6037,31 @@ rs6000_emit_prologue()
}
}
+ /* ??? There's no need to emit actual instructions here, but it's the
+ easiest way to get the frame unwind information emitted. */
+ if (current_function_calls_eh_return)
+ {
+ unsigned int i, regno;
+ for (i = 0; ; ++i)
+ {
+ rtx addr, reg, mem;
+
+ regno = EH_RETURN_DATA_REGNO (i);
+ if (regno == INVALID_REGNUM)
+ break;
+
+ reg = gen_rtx_REG (reg_mode, regno);
+ addr = plus_constant (frame_reg_rtx,
+ info->ehrd_offset + sp_offset + reg_size * i);
+ mem = gen_rtx_MEM (reg_mode, addr);
+ MEM_ALIAS_SET (mem) = rs6000_sr_alias_set;
+
+ insn = emit_move_insn (mem, reg);
+ rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
+ NULL_RTX, NULL_RTX);
+ }
+ }
+
/* Save lr if we used it. */
if (info->lr_save_p)
{
@@ -5800,8 +6125,9 @@ rs6000_emit_prologue()
it. We use R11 for this purpose because emit_load_toc_table
can use register 0. This allows us to use a plain 'blr' to return
from the procedure more often. */
- int save_LR_around_toc_setup = (TARGET_ELF && flag_pic != 0 &&
- ! info->lr_save_p);
+ int save_LR_around_toc_setup = (TARGET_ELF && flag_pic != 0
+ && ! info->lr_save_p
+ && EXIT_BLOCK_PTR->pred != NULL);
if (save_LR_around_toc_setup)
emit_move_insn (gen_rtx_REG (Pmode, 11),
gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM));
@@ -5872,7 +6198,7 @@ output_prolog (file, size)
need special notes to explain where r11 is in relation to the stack. */
void
-rs6000_emit_epilogue(sibcall)
+rs6000_emit_epilogue (sibcall)
int sibcall;
{
rs6000_stack_t *info;
@@ -5891,6 +6217,7 @@ rs6000_emit_epilogue(sibcall)
using_load_multiple = (TARGET_MULTIPLE && ! TARGET_POWERPC64
&& info->first_gp_reg_save < 31);
restoring_FPRs_inline = (sibcall
+ || current_function_calls_eh_return
|| info->first_fp_reg_save == 64
|| FP_SAVE_INLINE (info->first_fp_reg_save));
use_backchain_to_restore_sp = (frame_pointer_needed
@@ -5956,6 +6283,26 @@ rs6000_emit_epilogue(sibcall)
emit_move_insn (gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM),
gen_rtx_REG (Pmode, 0));
+ /* Load exception handler data registers, if needed. */
+ if (current_function_calls_eh_return)
+ {
+ unsigned int i, regno;
+ for (i = 0; ; ++i)
+ {
+ rtx addr, mem;
+
+ regno = EH_RETURN_DATA_REGNO (i);
+ if (regno == INVALID_REGNUM)
+ break;
+
+ addr = plus_constant (frame_reg_rtx,
+ info->ehrd_offset + sp_offset + reg_size * i);
+ mem = gen_rtx_MEM (reg_mode, addr);
+ MEM_ALIAS_SET (mem) = rs6000_sr_alias_set;
+
+ emit_move_insn (gen_rtx_REG (reg_mode, regno), mem);
+ }
+ }
/* Restore GPRs. This is done as a PARALLEL if we are using
the load-multiple instructions. */
@@ -6091,6 +6438,14 @@ rs6000_emit_epilogue(sibcall)
}
}
+ if (current_function_calls_eh_return)
+ {
+ rtx sa = EH_RETURN_STACKADJ_RTX;
+ emit_insn (Pmode == SImode
+ ? gen_addsi3 (sp_reg_rtx, sp_reg_rtx, sa)
+ : gen_adddi3 (sp_reg_rtx, sp_reg_rtx, sa));
+ }
+
if (!sibcall)
{
rtvec p;
@@ -7160,9 +7515,6 @@ output_function_profiler (file, labelno)
FILE *file;
int labelno;
{
- /* The last used parameter register. */
- int last_parm_reg;
- int i, j;
char buf[100];
ASM_GENERATE_INTERNAL_LABEL (buf, "LP", labelno);
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index fc70c506c3a..5b4c70ea7d8 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -1044,7 +1044,7 @@ enum reg_class
`K' is a constant with only the low-order 16 bits non-zero
`L' is a signed 16-bit constant shifted left 16 bits
`M' is a constant that is greater than 31
- `N' is a constant that is an exact power of two
+ `N' is a positive constant that is an exact power of two
`O' is the constant zero
`P' is a constant whose negation is a signed 16-bit constant */
@@ -1055,7 +1055,7 @@ enum reg_class
: (C) == 'L' ? (((VALUE) & 0xffff) == 0 \
&& ((VALUE) >> 31 == -1 || (VALUE) >> 31 == 0)) \
: (C) == 'M' ? (VALUE) > 31 \
- : (C) == 'N' ? exact_log2 (VALUE) >= 0 \
+ : (C) == 'N' ? (VALUE) > 0 && exact_log2 (VALUE) >= 0 \
: (C) == 'O' ? (VALUE) == 0 \
: (C) == 'P' ? (unsigned HOST_WIDE_INT) ((- (VALUE)) + 0x8000) < 0x10000 \
: 0)
@@ -1180,6 +1180,7 @@ typedef struct rs6000_stack {
int cr_save_offset; /* offset to save CR from initial SP */
int toc_save_offset; /* offset to save the TOC pointer */
int varargs_save_offset; /* offset to save the varargs registers */
+ int ehrd_offset; /* offset to EH return data */
int reg_size; /* register size (4 or 8) */
int varargs_size; /* size to hold V.4 args passed in regs */
int vars_size; /* variable save area size */
@@ -1422,9 +1423,8 @@ typedef struct rs6000_args
/* Define intermediate macro to compute the size (in registers) of an argument
for the RS/6000. */
-#define RS6000_ARG_SIZE(MODE, TYPE, NAMED) \
-(! (NAMED) ? 0 \
- : (MODE) != BLKmode \
+#define RS6000_ARG_SIZE(MODE, TYPE) \
+((MODE) != BLKmode \
? (GET_MODE_SIZE (MODE) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD \
: ((unsigned HOST_WIDE_INT) int_size_in_bytes (TYPE) \
+ (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)
@@ -1540,6 +1540,10 @@ typedef struct rs6000_args
#define EXPAND_BUILTIN_VA_ARG(valist, type) \
rs6000_va_arg (valist, type)
+/* Define this macro to be a nonzero value if the location where a function
+ argument is passed depends on whether or not it is a named argument. */
+#define STRICT_ARGUMENT_NAMING 1
+
/* This macro generates the assembly code for function entry.
FILE is a stdio stream to output the code to.
SIZE is an int: how many units of temporary storage to allocate.
@@ -1569,8 +1573,11 @@ typedef struct rs6000_args
and frame pointer registers are already be assumed to be used as
needed. */
-#define EPILOGUE_USES(REGNO) \
- (reload_completed && (REGNO) == LINK_REGISTER_REGNUM)
+#define EPILOGUE_USES(REGNO) \
+ ((reload_completed && (REGNO) == LINK_REGISTER_REGNUM) \
+ || (current_function_calls_eh_return \
+ && TARGET_AIX \
+ && (REGNO) == TOC_REGISTER))
/* This macro generates the assembly code for function exit,
on machines that need it. If FUNCTION_EPILOGUE is not defined
@@ -1772,26 +1779,28 @@ typedef struct rs6000_args
After reload, it makes no difference, since pseudo regs have
been eliminated by then. */
-#ifndef REG_OK_STRICT
+#ifdef REG_OK_STRICT
+# define REG_OK_STRICT_FLAG 1
+#else
+# define REG_OK_STRICT_FLAG 0
+#endif
/* Nonzero if X is a hard reg that can be used as an index
- or if it is a pseudo reg. */
-#define REG_OK_FOR_INDEX_P(X) \
- (REGNO (X) <= 31 || REGNO (X) == 67 || REGNO (X) >= FIRST_PSEUDO_REGISTER)
+ or if it is a pseudo reg in the non-strict case. */
+#define INT_REG_OK_FOR_INDEX_P(X, STRICT) \
+ ((! (STRICT) \
+ && (REGNO (X) <= 31 \
+ || REGNO (X) == ARG_POINTER_REGNUM \
+ || REGNO (X) >= FIRST_PSEUDO_REGISTER)) \
+ || ((STRICT) && REGNO_OK_FOR_INDEX_P (REGNO (X))))
/* Nonzero if X is a hard reg that can be used as a base reg
- or if it is a pseudo reg. */
-#define REG_OK_FOR_BASE_P(X) \
- (REGNO (X) > 0 && REG_OK_FOR_INDEX_P (X))
-
-#else
-
-/* Nonzero if X is a hard reg that can be used as an index. */
-#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X))
-/* Nonzero if X is a hard reg that can be used as a base reg. */
-#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
+ or if it is a pseudo reg in the non-strict case. */
+#define INT_REG_OK_FOR_BASE_P(X, STRICT) \
+ (REGNO (X) > 0 && INT_REG_OK_FOR_INDEX_P (X, (STRICT)))
-#endif
+#define REG_OK_FOR_INDEX_P(X) INT_REG_OK_FOR_INDEX_P (X, REG_OK_STRICT_FLAG)
+#define REG_OK_FOR_BASE_P(X) INT_REG_OK_FOR_BASE_P (X, REG_OK_STRICT_FLAG)
/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
that is a valid memory address for an instruction.
@@ -1828,68 +1837,51 @@ typedef struct rs6000_args
&& (GET_CODE (X) == SYMBOL_REF || GET_CODE (X) == CONST) \
&& small_data_operand (X, MODE))
-#define LEGITIMATE_ADDRESS_INTEGER_P(X,OFFSET) \
+#define LEGITIMATE_ADDRESS_INTEGER_P(X, OFFSET) \
(GET_CODE (X) == CONST_INT \
&& (unsigned HOST_WIDE_INT) (INTVAL (X) + (OFFSET) + 0x8000) < 0x10000)
-#define LEGITIMATE_OFFSET_ADDRESS_P(MODE,X) \
- (GET_CODE (X) == PLUS \
- && GET_CODE (XEXP (X, 0)) == REG \
- && REG_OK_FOR_BASE_P (XEXP (X, 0)) \
- && LEGITIMATE_ADDRESS_INTEGER_P (XEXP (X, 1), 0) \
- && (((MODE) != DFmode && (MODE) != DImode) \
- || (TARGET_32BIT \
- ? LEGITIMATE_ADDRESS_INTEGER_P (XEXP (X, 1), 4) \
- : ! (INTVAL (XEXP (X, 1)) & 3))) \
- && ((MODE) != TImode \
- || (TARGET_32BIT \
- ? LEGITIMATE_ADDRESS_INTEGER_P (XEXP (X, 1), 12) \
- : (LEGITIMATE_ADDRESS_INTEGER_P (XEXP (X, 1), 8) \
+#define LEGITIMATE_OFFSET_ADDRESS_P(MODE, X, STRICT) \
+ (GET_CODE (X) == PLUS \
+ && GET_CODE (XEXP (X, 0)) == REG \
+ && INT_REG_OK_FOR_BASE_P (XEXP (X, 0), (STRICT)) \
+ && LEGITIMATE_ADDRESS_INTEGER_P (XEXP (X, 1), 0) \
+ && (((MODE) != DFmode && (MODE) != DImode) \
+ || (TARGET_32BIT \
+ ? LEGITIMATE_ADDRESS_INTEGER_P (XEXP (X, 1), 4) \
+ : ! (INTVAL (XEXP (X, 1)) & 3))) \
+ && ((MODE) != TImode \
+ || (TARGET_32BIT \
+ ? LEGITIMATE_ADDRESS_INTEGER_P (XEXP (X, 1), 12) \
+ : (LEGITIMATE_ADDRESS_INTEGER_P (XEXP (X, 1), 8) \
&& ! (INTVAL (XEXP (X, 1)) & 3)))))
-#define LEGITIMATE_INDEXED_ADDRESS_P(X) \
- (GET_CODE (X) == PLUS \
- && GET_CODE (XEXP (X, 0)) == REG \
- && GET_CODE (XEXP (X, 1)) == REG \
- && ((REG_OK_FOR_BASE_P (XEXP (X, 0)) \
- && REG_OK_FOR_INDEX_P (XEXP (X, 1))) \
- || (REG_OK_FOR_BASE_P (XEXP (X, 1)) \
- && REG_OK_FOR_INDEX_P (XEXP (X, 0)))))
-
-#define LEGITIMATE_INDIRECT_ADDRESS_P(X) \
- (GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X))
-
-#define LEGITIMATE_LO_SUM_ADDRESS_P(MODE, X) \
- (TARGET_ELF \
- && ! flag_pic && ! TARGET_TOC \
- && (MODE) != DImode \
- && (MODE) != TImode \
- && (TARGET_HARD_FLOAT || (MODE) != DFmode) \
- && GET_CODE (X) == LO_SUM \
- && GET_CODE (XEXP (X, 0)) == REG \
- && REG_OK_FOR_BASE_P (XEXP (X, 0)) \
+#define LEGITIMATE_INDEXED_ADDRESS_P(X, STRICT) \
+ (GET_CODE (X) == PLUS \
+ && GET_CODE (XEXP (X, 0)) == REG \
+ && GET_CODE (XEXP (X, 1)) == REG \
+ && ((INT_REG_OK_FOR_BASE_P (XEXP (X, 0), (STRICT)) \
+ && INT_REG_OK_FOR_INDEX_P (XEXP (X, 1), (STRICT))) \
+ || (INT_REG_OK_FOR_BASE_P (XEXP (X, 1), (STRICT)) \
+ && INT_REG_OK_FOR_INDEX_P (XEXP (X, 0), (STRICT)))))
+
+#define LEGITIMATE_INDIRECT_ADDRESS_P(X, STRICT) \
+ (GET_CODE (X) == REG && INT_REG_OK_FOR_BASE_P (X, (STRICT)))
+
+#define LEGITIMATE_LO_SUM_ADDRESS_P(MODE, X, STRICT) \
+ (TARGET_ELF \
+ && ! flag_pic && ! TARGET_TOC \
+ && (MODE) != DImode \
+ && (MODE) != TImode \
+ && (TARGET_HARD_FLOAT || (MODE) != DFmode) \
+ && GET_CODE (X) == LO_SUM \
+ && GET_CODE (XEXP (X, 0)) == REG \
+ && INT_REG_OK_FOR_BASE_P (XEXP (X, 0), (STRICT)) \
&& CONSTANT_P (XEXP (X, 1)))
-#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
-{ if (LEGITIMATE_INDIRECT_ADDRESS_P (X)) \
- goto ADDR; \
- if ((GET_CODE (X) == PRE_INC || GET_CODE (X) == PRE_DEC) \
- && TARGET_UPDATE \
- && LEGITIMATE_INDIRECT_ADDRESS_P (XEXP (X, 0))) \
- goto ADDR; \
- if (LEGITIMATE_SMALL_DATA_P (MODE, X)) \
- goto ADDR; \
- if (LEGITIMATE_CONSTANT_POOL_ADDRESS_P (X)) \
- goto ADDR; \
- if (LEGITIMATE_OFFSET_ADDRESS_P (MODE, X)) \
- goto ADDR; \
- if ((MODE) != TImode \
- && (TARGET_HARD_FLOAT || TARGET_POWERPC64 || (MODE) != DFmode) \
- && (TARGET_POWERPC64 || (MODE) != DImode) \
- && LEGITIMATE_INDEXED_ADDRESS_P (X)) \
- goto ADDR; \
- if (LEGITIMATE_LO_SUM_ADDRESS_P (MODE, X)) \
- goto ADDR; \
+#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
+{ if (rs6000_legitimate_address (MODE, X, REG_OK_STRICT_FLAG)) \
+ goto ADDR; \
}
/* Try machine-dependent ways of modifying an illegitimate address
@@ -2641,6 +2633,10 @@ do { \
#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM)
#define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGNUM (LINK_REGISTER_REGNUM)
+/* Describe how we implement __builtin_eh_return. */
+#define EH_RETURN_DATA_REGNO(N) ((N) < 4 ? (N) + 3 : INVALID_REGNUM)
+#define EH_RETURN_STACKADJ_RTX gen_rtx_REG (Pmode, 10)
+
/* Define results of standard character escape sequences. */
#define TARGET_BELL 007
#define TARGET_BS 010
@@ -2679,10 +2675,13 @@ do { \
{"reg_or_u_short_operand", {SUBREG, REG, CONST_INT}}, \
{"reg_or_cint_operand", {SUBREG, REG, CONST_INT}}, \
{"reg_or_arith_cint_operand", {SUBREG, REG, CONST_INT}}, \
+ {"reg_or_add_cint64_operand", {SUBREG, REG, CONST_INT}}, \
+ {"reg_or_sub_cint64_operand", {SUBREG, REG, CONST_INT}}, \
{"reg_or_logical_cint_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE}}, \
{"got_operand", {SYMBOL_REF, CONST, LABEL_REF}}, \
{"got_no_const_operand", {SYMBOL_REF, LABEL_REF}}, \
{"easy_fp_constant", {CONST_DOUBLE}}, \
+ {"zero_fp_constant", {CONST_DOUBLE}}, \
{"reg_or_mem_operand", {SUBREG, MEM, REG}}, \
{"lwa_operand", {SUBREG, MEM, REG}}, \
{"volatile_mem_operand", {MEM}}, \
@@ -2718,7 +2717,8 @@ do { \
{"trap_comparison_operator", {EQ, NE, LE, LT, GE, \
GT, LEU, LTU, GEU, GTU}}, \
{"boolean_operator", {AND, IOR, XOR}}, \
- {"boolean_or_operator", {IOR, XOR}},
+ {"boolean_or_operator", {IOR, XOR}}, \
+ {"min_max_operator", {SMIN, SMAX, UMIN, UMAX}},
/* uncomment for disabling the corresponding default options */
/* #define MACHINE_no_sched_interblock */
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 9df70cf3eaf..d1a995157b6 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -1422,16 +1422,14 @@
rtx tmp = ((no_new_pseudos || rtx_equal_p (operands[0], operands[1]))
? operands[0] : gen_reg_rtx (SImode));
- HOST_WIDE_INT low = INTVAL (operands[2]) & 0xffff;
- HOST_WIDE_INT high = INTVAL (operands[2]) & (~ (HOST_WIDE_INT) 0xffff);
-
- if (low & 0x8000)
- high += 0x10000, low |= ((HOST_WIDE_INT) -1) << 16;
+ HOST_WIDE_INT val = INTVAL (operands[2]);
+ HOST_WIDE_INT low = (val & 0xffff) - 2 * (val & 0x8000);
+ HOST_WIDE_INT rest = trunc_int_for_mode (val - low, SImode);
/* The ordering here is important for the prolog expander.
When space is allocated from the stack, adding 'low' first may
produce a temporary deallocation (which would be bad). */
- emit_insn (gen_addsi3 (tmp, operands[1], GEN_INT (high)));
+ emit_insn (gen_addsi3 (tmp, operands[1], GEN_INT (rest)));
emit_insn (gen_addsi3 (operands[0], tmp, GEN_INT (low)));
DONE;
}
@@ -1525,13 +1523,11 @@
(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 4)))]
"
{
- HOST_WIDE_INT low = INTVAL (operands[2]) & 0xffff;
- HOST_WIDE_INT high = INTVAL (operands[2]) & (~ (HOST_WIDE_INT) 0xffff);
-
- if (low & 0x8000)
- high += 0x10000, low |= ((HOST_WIDE_INT) -1) << 16;
+ HOST_WIDE_INT val = INTVAL (operands[2]);
+ HOST_WIDE_INT low = (val & 0xffff) - 2 * (val & 0x8000);
+ HOST_WIDE_INT rest = trunc_int_for_mode (val - low, SImode);
- operands[3] = GEN_INT (high);
+ operands[3] = GEN_INT (rest);
operands[4] = GEN_INT (low);
}")
@@ -2263,6 +2259,7 @@
"
{
if (GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) > 0
&& exact_log2 (INTVAL (operands[2])) >= 0)
;
else if (TARGET_POWERPC)
@@ -2314,12 +2311,9 @@
rtx temp1;
rtx temp2;
- if (GET_CODE (operands[2]) != CONST_INT)
- FAIL;
-
- i = exact_log2 (INTVAL (operands[2]));
-
- if (i < 0)
+ if (GET_CODE (operands[2]) != CONST_INT
+ || INTVAL (operands[2]) < 0
+ || (i = exact_log2 (INTVAL (operands[2]))) < 0)
FAIL;
temp1 = gen_reg_rtx (SImode);
@@ -2335,7 +2329,7 @@
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(div:SI (match_operand:SI 1 "gpc_reg_operand" "r")
(match_operand:SI 2 "const_int_operand" "N")))]
- "exact_log2 (INTVAL (operands[2])) >= 0"
+ "INTVAL (operands[2]) > 0 && exact_log2 (INTVAL (operands[2])) >= 0"
"{srai|srawi} %0,%1,%p2\;{aze|addze} %0,%0"
[(set_attr "length" "8")])
@@ -2345,7 +2339,7 @@
(match_operand:SI 2 "const_int_operand" "N,N"))
(const_int 0)))
(clobber (match_scratch:SI 3 "=r,r"))]
- "exact_log2 (INTVAL (operands[2])) >= 0"
+ "INTVAL (operands[2]) > 0 && exact_log2 (INTVAL (operands[2])) >= 0"
"@
{srai|srawi} %3,%1,%p2\;{aze.|addze.} %3,%3
#"
@@ -2358,7 +2352,8 @@
(match_operand:SI 2 "const_int_operand" ""))
(const_int 0)))
(clobber (match_scratch:SI 3 ""))]
- "exact_log2 (INTVAL (operands[2])) >= 0 && reload_completed"
+ "INTVAL (operands[2]) > 0 && exact_log2 (INTVAL (operands[2])) >= 0
+ && reload_completed"
[(set (match_dup 3)
(div:SI (match_dup 1) (match_dup 2)))
(set (match_dup 0)
@@ -2373,7 +2368,7 @@
(const_int 0)))
(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
(div:SI (match_dup 1) (match_dup 2)))]
- "exact_log2 (INTVAL (operands[2])) >= 0"
+ "INTVAL (operands[2]) > 0 && exact_log2 (INTVAL (operands[2])) >= 0"
"@
{srai|srawi} %0,%1,%p2\;{aze.|addze.} %0,%0
#"
@@ -2387,7 +2382,8 @@
(const_int 0)))
(set (match_operand:SI 0 "gpc_reg_operand" "")
(div:SI (match_dup 1) (match_dup 2)))]
- "exact_log2 (INTVAL (operands[2])) >= 0 && reload_completed"
+ "INTVAL (operands[2]) > 0 && exact_log2 (INTVAL (operands[2])) >= 0
+ && reload_completed"
[(set (match_dup 0)
(div:SI (match_dup 1) (match_dup 2)))
(set (match_dup 3)
@@ -4808,60 +4804,35 @@
;; single DEFINE_INSN for fsel and the define_splits to make them if made by
;; combine.
(define_expand "maxsf3"
- [(set (match_dup 3)
- (minus:SF (match_operand:SF 1 "gpc_reg_operand" "")
- (match_operand:SF 2 "gpc_reg_operand" "")))
- (set (match_operand:SF 0 "gpc_reg_operand" "")
- (if_then_else:SF (ge (match_dup 3)
- (const_int 0))
- (match_dup 1)
- (match_dup 2)))]
- "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT"
- "
-{ operands[3] = gen_reg_rtx (SFmode); }")
-
-(define_split
[(set (match_operand:SF 0 "gpc_reg_operand" "")
- (smax:SF (match_operand:SF 1 "gpc_reg_operand" "")
- (match_operand:SF 2 "gpc_reg_operand" "")))
- (clobber (match_operand:SF 3 "gpc_reg_operand" ""))]
- "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT"
- [(set (match_dup 3)
- (minus:SF (match_dup 1) (match_dup 2)))
- (set (match_dup 0)
- (if_then_else:SF (ge (match_dup 3)
- (const_int 0))
+ (if_then_else:SF (ge (match_operand:SF 1 "gpc_reg_operand" "")
+ (match_operand:SF 2 "gpc_reg_operand" ""))
(match_dup 1)
(match_dup 2)))]
- "")
+ "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT"
+ "{ rs6000_emit_minmax (operands[0], SMAX, operands[1], operands[2]); DONE;}")
(define_expand "minsf3"
- [(set (match_dup 3)
- (minus:SF (match_operand:SF 2 "gpc_reg_operand" "")
- (match_operand:SF 1 "gpc_reg_operand" "")))
- (set (match_operand:SF 0 "gpc_reg_operand" "")
- (if_then_else:SF (ge (match_dup 3)
- (const_int 0))
- (match_dup 1)
- (match_dup 2)))]
+ [(set (match_operand:SF 0 "gpc_reg_operand" "")
+ (if_then_else:SF (ge (match_operand:SF 1 "gpc_reg_operand" "")
+ (match_operand:SF 2 "gpc_reg_operand" ""))
+ (match_dup 2)
+ (match_dup 1)))]
"TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT"
- "
-{ operands[3] = gen_reg_rtx (SFmode); }")
+ "{ rs6000_emit_minmax (operands[0], SMIN, operands[1], operands[2]); DONE;}")
(define_split
[(set (match_operand:SF 0 "gpc_reg_operand" "")
- (smin:SF (match_operand:SF 1 "gpc_reg_operand" "")
- (match_operand:SF 2 "gpc_reg_operand" "")))
- (clobber (match_operand:SF 3 "gpc_reg_operand" ""))]
+ (match_operator:SF 3 "min_max_operator"
+ [(match_operand:SF 1 "gpc_reg_operand" "")
+ (match_operand:SF 2 "gpc_reg_operand" "")]))]
"TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT"
- [(set (match_dup 3)
- (minus:SF (match_dup 2) (match_dup 1)))
- (set (match_dup 0)
- (if_then_else:SF (ge (match_dup 3)
- (const_int 0))
- (match_dup 1)
- (match_dup 2)))]
- "")
+ [(const_int 0)]
+ "
+{ rs6000_emit_minmax (operands[0], GET_CODE (operands[3]),
+ operands[1], operands[2]);
+ DONE;
+}")
(define_expand "movsfcc"
[(set (match_operand:SF 0 "gpc_reg_operand" "")
@@ -4871,82 +4842,26 @@
"TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT"
"
{
- rtx temp, op0, op1;
- enum rtx_code code = GET_CODE (operands[1]);
- if (! rs6000_compare_fp_p)
- FAIL;
- switch (code)
- {
- case GE: case EQ: case NE:
- op0 = rs6000_compare_op0;
- op1 = rs6000_compare_op1;
- break;
- case GT:
- op0 = rs6000_compare_op1;
- op1 = rs6000_compare_op0;
- temp = operands[2]; operands[2] = operands[3]; operands[3] = temp;
- break;
- case LE:
- op0 = rs6000_compare_op1;
- op1 = rs6000_compare_op0;
- break;
- case LT:
- op0 = rs6000_compare_op0;
- op1 = rs6000_compare_op1;
- temp = operands[2]; operands[2] = operands[3]; operands[3] = temp;
- break;
- default:
- FAIL;
- }
- if (GET_MODE (rs6000_compare_op0) == DFmode)
- {
- temp = gen_reg_rtx (DFmode);
- emit_insn (gen_subdf3 (temp, op0, op1));
- emit_insn (gen_fseldfsf4 (operands[0], temp, operands[2], operands[3]));
- if (code == EQ)
- {
- emit_insn (gen_negdf2 (temp, temp));
- emit_insn (gen_fseldfsf4 (operands[0], temp, operands[0], operands[3]));
- }
- else if (code == NE)
- {
- emit_insn (gen_negdf2 (temp, temp));
- emit_insn (gen_fseldfsf4 (operands[0], temp, operands[3], operands[0]));
- }
- }
+ if (rs6000_emit_cmove (operands[0], operands[1], operands[2], operands[3]))
+ DONE;
else
- {
- temp = gen_reg_rtx (SFmode);
- emit_insn (gen_subsf3 (temp, op0, op1));
- emit_insn (gen_fselsfsf4 (operands[0], temp, operands[2], operands[3]));
- if (code == EQ)
- {
- emit_insn (gen_negsf2 (temp, temp));
- emit_insn (gen_fselsfsf4 (operands[0], temp, operands[0], operands[3]));
- }
- else if (code == NE)
- {
- emit_insn (gen_negsf2 (temp, temp));
- emit_insn (gen_fselsfsf4 (operands[0], temp, operands[3], operands[0]));
- }
- }
- DONE;
+ FAIL;
}")
-(define_insn "fselsfsf4"
+(define_insn "*fselsfsf4"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(if_then_else:SF (ge (match_operand:SF 1 "gpc_reg_operand" "f")
- (const_int 0))
+ (match_operand:SF 4 "zero_fp_constant" "F"))
(match_operand:SF 2 "gpc_reg_operand" "f")
(match_operand:SF 3 "gpc_reg_operand" "f")))]
"TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT"
"fsel %0,%1,%2,%3"
[(set_attr "type" "fp")])
-(define_insn "fseldfsf4"
+(define_insn "*fseldfsf4"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(if_then_else:SF (ge (match_operand:DF 1 "gpc_reg_operand" "f")
- (const_int 0))
+ (match_operand:DF 4 "zero_fp_constant" "F"))
(match_operand:SF 2 "gpc_reg_operand" "f")
(match_operand:SF 3 "gpc_reg_operand" "f")))]
"TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT"
@@ -5049,66 +4964,39 @@
"fsqrt %0,%1"
[(set_attr "type" "dsqrt")])
-;; For MIN, MAX, and conditional move, we use DEFINE_EXPAND's that involve a
-;; fsel instruction and some auxiliary computations. Then we just have a
-;; single DEFINE_INSN for fsel and the define_splits to make them if made by
-;; combine.
+;; The conditional move instructions allow us to perform max and min
+;; operations even when
(define_expand "maxdf3"
- [(set (match_dup 3)
- (minus:DF (match_operand:DF 1 "gpc_reg_operand" "")
- (match_operand:DF 2 "gpc_reg_operand" "")))
- (set (match_operand:DF 0 "gpc_reg_operand" "")
- (if_then_else:DF (ge (match_dup 3)
- (const_int 0))
- (match_dup 1)
- (match_dup 2)))]
- "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT"
- "
-{ operands[3] = gen_reg_rtx (DFmode); }")
-
-(define_split
[(set (match_operand:DF 0 "gpc_reg_operand" "")
- (smax:DF (match_operand:DF 1 "gpc_reg_operand" "")
- (match_operand:DF 2 "gpc_reg_operand" "")))
- (clobber (match_operand:DF 3 "gpc_reg_operand" ""))]
- "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT"
- [(set (match_dup 3)
- (minus:DF (match_dup 1) (match_dup 2)))
- (set (match_dup 0)
- (if_then_else:DF (ge (match_dup 3)
- (const_int 0))
+ (if_then_else:DF (ge (match_operand:DF 1 "gpc_reg_operand" "")
+ (match_operand:DF 2 "gpc_reg_operand" ""))
(match_dup 1)
(match_dup 2)))]
- "")
+ "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT"
+ "{ rs6000_emit_minmax (operands[0], SMAX, operands[1], operands[2]); DONE;}")
(define_expand "mindf3"
- [(set (match_dup 3)
- (minus:DF (match_operand:DF 2 "gpc_reg_operand" "")
- (match_operand:DF 1 "gpc_reg_operand" "")))
- (set (match_operand:DF 0 "gpc_reg_operand" "")
- (if_then_else:DF (ge (match_dup 3)
- (const_int 0))
- (match_dup 1)
- (match_dup 2)))]
+ [(set (match_operand:DF 0 "gpc_reg_operand" "")
+ (if_then_else:DF (ge (match_operand:DF 1 "gpc_reg_operand" "")
+ (match_operand:DF 2 "gpc_reg_operand" ""))
+ (match_dup 2)
+ (match_dup 1)))]
"TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT"
- "
-{ operands[3] = gen_reg_rtx (DFmode); }")
+ "{ rs6000_emit_minmax (operands[0], SMIN, operands[1], operands[2]); DONE;}")
(define_split
[(set (match_operand:DF 0 "gpc_reg_operand" "")
- (smin:DF (match_operand:DF 1 "gpc_reg_operand" "")
- (match_operand:DF 2 "gpc_reg_operand" "")))
- (clobber (match_operand:DF 3 "gpc_reg_operand" ""))]
+ (match_operator:DF 3 "min_max_operator"
+ [(match_operand:DF 1 "gpc_reg_operand" "")
+ (match_operand:DF 2 "gpc_reg_operand" "")]))]
"TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT"
- [(set (match_dup 3)
- (minus:DF (match_dup 2) (match_dup 1)))
- (set (match_dup 0)
- (if_then_else:DF (ge (match_dup 3)
- (const_int 0))
- (match_dup 1)
- (match_dup 2)))]
- "")
+ [(const_int 0)]
+ "
+{ rs6000_emit_minmax (operands[0], GET_CODE (operands[3]),
+ operands[1], operands[2]);
+ DONE;
+}")
(define_expand "movdfcc"
[(set (match_operand:DF 0 "gpc_reg_operand" "")
@@ -5118,82 +5006,26 @@
"TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT"
"
{
- rtx temp, op0, op1;
- enum rtx_code code = GET_CODE (operands[1]);
- if (! rs6000_compare_fp_p)
- FAIL;
- switch (code)
- {
- case GE: case EQ: case NE:
- op0 = rs6000_compare_op0;
- op1 = rs6000_compare_op1;
- break;
- case GT:
- op0 = rs6000_compare_op1;
- op1 = rs6000_compare_op0;
- temp = operands[2]; operands[2] = operands[3]; operands[3] = temp;
- break;
- case LE:
- op0 = rs6000_compare_op1;
- op1 = rs6000_compare_op0;
- break;
- case LT:
- op0 = rs6000_compare_op0;
- op1 = rs6000_compare_op1;
- temp = operands[2]; operands[2] = operands[3]; operands[3] = temp;
- break;
- default:
- FAIL;
- }
- if (GET_MODE (rs6000_compare_op0) == DFmode)
- {
- temp = gen_reg_rtx (DFmode);
- emit_insn (gen_subdf3 (temp, op0, op1));
- emit_insn (gen_fseldfdf4 (operands[0], temp, operands[2], operands[3]));
- if (code == EQ)
- {
- emit_insn (gen_negdf2 (temp, temp));
- emit_insn (gen_fseldfdf4 (operands[0], temp, operands[0], operands[3]));
- }
- else if (code == NE)
- {
- emit_insn (gen_negdf2 (temp, temp));
- emit_insn (gen_fseldfdf4 (operands[0], temp, operands[3], operands[0]));
- }
- }
+ if (rs6000_emit_cmove (operands[0], operands[1], operands[2], operands[3]))
+ DONE;
else
- {
- temp = gen_reg_rtx (SFmode);
- emit_insn (gen_subsf3 (temp, op0, op1));
- emit_insn (gen_fselsfdf4 (operands[0], temp, operands[2], operands[3]));
- if (code == EQ)
- {
- emit_insn (gen_negsf2 (temp, temp));
- emit_insn (gen_fselsfdf4 (operands[0], temp, operands[0], operands[3]));
- }
- else if (code == NE)
- {
- emit_insn (gen_negsf2 (temp, temp));
- emit_insn (gen_fselsfdf4 (operands[0], temp, operands[3], operands[0]));
- }
- }
- DONE;
+ FAIL;
}")
-(define_insn "fseldfdf4"
+(define_insn "*fseldfdf4"
[(set (match_operand:DF 0 "gpc_reg_operand" "=f")
(if_then_else:DF (ge (match_operand:DF 1 "gpc_reg_operand" "f")
- (const_int 0))
+ (match_operand:DF 4 "zero_fp_constant" "F"))
(match_operand:DF 2 "gpc_reg_operand" "f")
(match_operand:DF 3 "gpc_reg_operand" "f")))]
"TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT"
"fsel %0,%1,%2,%3"
[(set_attr "type" "fp")])
-(define_insn "fselsfdf4"
+(define_insn "*fselsfdf4"
[(set (match_operand:DF 0 "gpc_reg_operand" "=f")
(if_then_else:DF (ge (match_operand:SF 1 "gpc_reg_operand" "f")
- (const_int 0))
+ (match_operand:SF 4 "zero_fp_constant" "F"))
(match_operand:DF 2 "gpc_reg_operand" "f")
(match_operand:DF 3 "gpc_reg_operand" "f")))]
"TARGET_PPC_GFXOPT"
@@ -5739,7 +5571,7 @@
(define_expand "adddi3"
[(set (match_operand:DI 0 "gpc_reg_operand" "")
(plus:DI (match_operand:DI 1 "gpc_reg_operand" "")
- (match_operand:DI 2 "reg_or_arith_cint_operand" "")))]
+ (match_operand:DI 2 "reg_or_add_cint64_operand" "")))]
""
"
{
@@ -5755,13 +5587,17 @@
rtx tmp = ((no_new_pseudos || rtx_equal_p (operands[0], operands[1]))
? operands[0] : gen_reg_rtx (DImode));
- HOST_WIDE_INT low = INTVAL (operands[2]) & 0xffff;
- HOST_WIDE_INT high = INTVAL (operands[2]) & (~ (HOST_WIDE_INT) 0xffff);
+ HOST_WIDE_INT val = INTVAL (operands[2]);
+ HOST_WIDE_INT low = (val & 0xffff) - 2 * (val & 0x8000);
+ HOST_WIDE_INT rest = trunc_int_for_mode (val - low, DImode);
- if (low & 0x8000)
- high += 0x10000, low |= ((HOST_WIDE_INT) -1) << 16;
+ if (!CONST_OK_FOR_LETTER_P (rest, 'L'))
+ FAIL;
- emit_insn (gen_adddi3 (tmp, operands[1], GEN_INT (high)));
+ /* The ordering here is important for the prolog expander.
+ When space is allocated from the stack, adding 'low' first may
+ produce a temporary deallocation (which would be bad). */
+ emit_insn (gen_adddi3 (tmp, operands[1], GEN_INT (rest)));
emit_insn (gen_adddi3 (operands[0], tmp, GEN_INT (low)));
DONE;
}
@@ -5854,14 +5690,22 @@
(set (match_dup 0) (plus:DI (match_dup 0) (match_dup 4)))]
"
{
- HOST_WIDE_INT low = INTVAL (operands[2]) & 0xffff;
- HOST_WIDE_INT high = INTVAL (operands[2]) & (~ (HOST_WIDE_INT) 0xffff);
+ HOST_WIDE_INT val = INTVAL (operands[2]);
+ HOST_WIDE_INT low = (val & 0xffff) - 2 * (val & 0x8000);
+ HOST_WIDE_INT rest = trunc_int_for_mode (val - low, DImode);
- if (low & 0x8000)
- high+=0x10000, low |= ((HOST_WIDE_INT) -1) << 16;
-
- operands[3] = GEN_INT (high);
operands[4] = GEN_INT (low);
+ if (CONST_OK_FOR_LETTER_P (rest, 'L'))
+ operands[3] = GEN_INT (rest);
+ else if (! no_new_pseudos)
+ {
+ operands[3] = gen_reg_rtx (DImode);
+ emit_move_insn (operands[3], operands[2]);
+ emit_insn (gen_adddi3 (operands[0], operands[1], operands[3]));
+ DONE;
+ }
+ else
+ FAIL;
}")
(define_insn "one_cmpldi2"
@@ -5990,7 +5834,7 @@
(define_expand "subdi3"
[(set (match_operand:DI 0 "gpc_reg_operand" "")
(minus:DI (match_operand:DI 1 "reg_or_short_operand" "")
- (match_operand:DI 2 "reg_or_arith_cint_operand" "")))]
+ (match_operand:DI 2 "reg_or_sub_cint64_operand" "")))]
""
"
{
@@ -6149,6 +5993,7 @@
"
{
if (GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) > 0
&& exact_log2 (INTVAL (operands[2])) >= 0)
;
else
@@ -6162,11 +6007,13 @@
"TARGET_POWERPC64"
"
{
- int i = exact_log2 (INTVAL (operands[2]));
+ int i;
rtx temp1;
rtx temp2;
- if (GET_CODE (operands[2]) != CONST_INT || i < 0)
+ if (GET_CODE (operands[2]) != CONST_INT
+ || INTVAL (operands[2]) <= 0
+ || (i = exact_log2 (INTVAL (operands[2]))) < 0)
FAIL;
temp1 = gen_reg_rtx (DImode);
@@ -6182,7 +6029,8 @@
[(set (match_operand:DI 0 "gpc_reg_operand" "=r")
(div:DI (match_operand:DI 1 "gpc_reg_operand" "r")
(match_operand:DI 2 "const_int_operand" "N")))]
- "TARGET_POWERPC64 && exact_log2 (INTVAL (operands[2])) >= 0"
+ "TARGET_POWERPC64 && INTVAL (operands[2]) > 0
+ && exact_log2 (INTVAL (operands[2])) >= 0"
"sradi %0,%1,%p2\;addze %0,%0"
[(set_attr "length" "8")])
@@ -6192,7 +6040,8 @@
(match_operand:DI 2 "const_int_operand" "N,N"))
(const_int 0)))
(clobber (match_scratch:DI 3 "=r,r"))]
- "TARGET_POWERPC64 && exact_log2 (INTVAL (operands[2])) >= 0"
+ "TARGET_POWERPC64 && INTVAL (operands[2]) > 0
+ && exact_log2 (INTVAL (operands[2])) >= 0"
"@
sradi %3,%1,%p2\;addze. %3,%3
#"
@@ -6205,7 +6054,8 @@
(match_operand:DI 2 "const_int_operand" ""))
(const_int 0)))
(clobber (match_scratch:DI 3 ""))]
- "TARGET_POWERPC64 && exact_log2 (INTVAL (operands[2])) >= 0 && reload_completed"
+ "TARGET_POWERPC64 && INTVAL (operands[2]) > 0
+ && exact_log2 (INTVAL (operands[2])) >= 0 && reload_completed"
[(set (match_dup 3)
(div:DI (match_dup 1) (match_dup 2)))
(set (match_dup 0)
@@ -6220,7 +6070,8 @@
(const_int 0)))
(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
(div:DI (match_dup 1) (match_dup 2)))]
- "TARGET_POWERPC64 && exact_log2 (INTVAL (operands[2])) >= 0"
+ "TARGET_POWERPC64 && INTVAL (operands[2]) > 0
+ && exact_log2 (INTVAL (operands[2])) >= 0"
"@
sradi %0,%1,%p2\;addze. %0,%0
#"
@@ -6234,7 +6085,8 @@
(const_int 0)))
(set (match_operand:DI 0 "gpc_reg_operand" "")
(div:DI (match_dup 1) (match_dup 2)))]
- "TARGET_POWERPC64 && exact_log2 (INTVAL (operands[2])) >= 0 && reload_completed"
+ "TARGET_POWERPC64 && INTVAL (operands[2]) > 0
+ && exact_log2 (INTVAL (operands[2])) >= 0 && reload_completed"
[(set (match_dup 0)
(div:DI (match_dup 1) (match_dup 2)))
(set (match_dup 3)
@@ -6707,7 +6559,7 @@
(and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "r")
(match_operand:SI 2 "const_int_operand" "i"))
(match_operand:DI 3 "rldic_operand" "n")))]
- "includes_lshift64_p (operands[2], operands[3])"
+ "TARGET_POWERPC64 && includes_lshift64_p (operands[2], operands[3])"
"rldic %0,%1,%H2,%W3")
(define_insn "ashldi3_internal5"
@@ -6718,7 +6570,7 @@
(match_operand:DI 3 "rldic_operand" "n,n"))
(const_int 0)))
(clobber (match_scratch:DI 4 "=r,r"))]
- "includes_lshift64_p (operands[2], operands[3])"
+ "TARGET_POWERPC64 && includes_lshift64_p (operands[2], operands[3])"
"@
rldic. %4,%1,%H2,%W3
#"
@@ -6733,7 +6585,7 @@
(match_operand:DI 3 "rldic_operand" ""))
(const_int 0)))
(clobber (match_scratch:DI 4 ""))]
- "includes_lshift64_p (operands[2], operands[3]) && reload_completed"
+ "TARGET_POWERPC64 && includes_lshift64_p (operands[2], operands[3]) && reload_completed"
[(set (match_dup 4)
(and:DI (ashift:DI (match_dup 1) (match_dup 2))
(match_dup 3)))
@@ -6751,7 +6603,7 @@
(const_int 0)))
(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
(and:DI (ashift:DI (match_dup 1) (match_dup 2)) (match_dup 3)))]
- "includes_lshift64_p (operands[2], operands[3])"
+ "TARGET_POWERPC64 && includes_lshift64_p (operands[2], operands[3])"
"@
rldic. %0,%1,%H2,%W3
#"
@@ -6767,7 +6619,7 @@
(const_int 0)))
(set (match_operand:DI 0 "gpc_reg_operand" "")
(and:DI (ashift:DI (match_dup 1) (match_dup 2)) (match_dup 3)))]
- "includes_lshift64_p (operands[2], operands[3]) && reload_completed"
+ "TARGET_POWERPC64 && includes_lshift64_p (operands[2], operands[3]) && reload_completed"
[(set (match_dup 0)
(and:DI (ashift:DI (match_dup 1) (match_dup 2))
(match_dup 3)))
@@ -12575,7 +12427,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
(const_int 0)])
(const_int 0)))]
""
- "crnot %E0,%j1"
+ "{crnor %E0,%j1,%j1|crnot %E0,%j1}"
[(set_attr "type" "cr_logical")])
;; If we are comparing the result of two comparisons, this can be done
@@ -12622,7 +12474,14 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
operands[4]);
if (positive_1 == positive_2)
- operands[1] = gen_rtx_NOT (SImode, operands[1]);
+ {
+ operands[1] = gen_rtx_NOT (SImode, operands[1]);
+ operands[5] = constm1_rtx;
+ }
+ else
+ {
+ operands[5] = const1_rtx;
+ }
}")
;; Unconditional branch and return.
@@ -12807,7 +12666,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
{
if (which_alternative != 0)
return \"#\";
- else if (get_attr_length (insn) == 8)
+ else if (get_attr_length (insn) == 4)
return \"{bdn|bdnz} %l0\";
else
return \"bdz %$+8\;b %l0\";
@@ -12831,7 +12690,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
{
if (which_alternative != 0)
return \"#\";
- else if (get_attr_length (insn) == 8)
+ else if (get_attr_length (insn) == 4)
return \"bdz %l0\";
else
return \"{bdn|bdnz} %$+8\;b %l0\";
@@ -12855,7 +12714,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
{
if (which_alternative != 0)
return \"#\";
- else if (get_attr_length (insn) == 8)
+ else if (get_attr_length (insn) == 4)
return \"{bdn|bdnz} %l0\";
else
return \"bdz %$+8\;b %l0\";
@@ -12879,7 +12738,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
{
if (which_alternative != 0)
return \"#\";
- else if (get_attr_length (insn) == 8)
+ else if (get_attr_length (insn) == 4)
return \"bdz %l0\";
else
return \"{bdn|bdnz} %$+8\;b %l0\";
@@ -12905,7 +12764,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
{
if (which_alternative != 0)
return \"#\";
- else if (get_attr_length (insn) == 8)
+ else if (get_attr_length (insn) == 4)
return \"{bdn|bdnz} %l0\";
else
return \"bdz %$+8\;b %l0\";
@@ -12929,7 +12788,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
{
if (which_alternative != 0)
return \"#\";
- else if (get_attr_length (insn) == 8)
+ else if (get_attr_length (insn) == 4)
return \"bdz %l0\";
else
return \"{bdn|bdnz} %$+8\;b %l0\";
@@ -12953,7 +12812,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
{
if (which_alternative != 0)
return \"#\";
- else if (get_attr_length (insn) == 8)
+ else if (get_attr_length (insn) == 4)
return \"{bdn|bdnz} %l0\";
else
return \"bdz %$+8\;b %l0\";
@@ -12977,7 +12836,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
{
if (which_alternative != 0)
return \"#\";
- else if (get_attr_length (insn) == 8)
+ else if (get_attr_length (insn) == 4)
return \"bdz %l0\";
else
return \"{bdn|bdnz} %$+8\;b %l0\";
@@ -13003,7 +12862,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
{
if (which_alternative != 0)
return \"#\";
- else if (get_attr_length (insn) == 8)
+ else if (get_attr_length (insn) == 4)
return \"bdz %l0\";
else
return \"{bdn|bdnz} %$+8\;b %l0\";
@@ -13027,7 +12886,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
{
if (which_alternative != 0)
return \"#\";
- else if (get_attr_length (insn) == 8)
+ else if (get_attr_length (insn) == 4)
return \"{bdn|bdnz} %l0\";
else
return \"bdz %$+8\;b %l0\";
@@ -13051,7 +12910,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
{
if (which_alternative != 0)
return \"#\";
- else if (get_attr_length (insn) == 8)
+ else if (get_attr_length (insn) == 4)
return \"bdz %l0\";
else
return \"{bdn|bdnz} %$+8\;b %l0\";
@@ -13075,7 +12934,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
{
if (which_alternative != 0)
return \"#\";
- else if (get_attr_length (insn) == 8)
+ else if (get_attr_length (insn) == 4)
return \"{bdn|bdnz} %l0\";
else
return \"bdz %$+8\;b %l0\";
@@ -13374,118 +13233,67 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
"TARGET_64BIT"
"b %z2")
-; This is used in compiling the routines __throw and __rethrow.
-; It's a little different to the usual definition...
-
-(define_expand "eh_epilogue"
- [(use (match_operand 0 "general_operand" "r"))
- (use (match_operand 1 "general_operand" "r"))
- (use (match_operand 2 "general_operand" "c"))]
+; This is used in compiling the unwind routines.
+(define_expand "eh_return"
+ [(use (match_operand 0 "general_operand" ""))
+ (use (match_operand 1 "general_operand" ""))]
""
"
{
- rtx stack_reg = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
- rtx insn;
-
- /* This is required for binary compatibility. If it's wrong,
- it probably means that eh_regs() in except.c is broken. */
- if (GET_CODE (operands[0]) != REG || REGNO (operands[0]) != 3)
- abort();
-
- /* These can be anything that doesn't interfere with the epilogue. */
- if (GET_CODE (operands[1]) != REG || REGNO (operands[1]) != 4)
- {
- rtx r = gen_rtx_REG (Pmode, 4);
- emit_move_insn (r, operands[1]);
- operands[1] = r;
- }
-
- if (GET_CODE (operands[2]) != REG
- || REGNO (operands[2]) != COUNT_REGISTER_REGNUM)
- {
- rtx r = gen_rtx_REG (Pmode, COUNT_REGISTER_REGNUM);
- emit_move_insn (r, operands[2]);
- operands[2] = r;
- }
-
#if TARGET_AIX
- rs6000_emit_eh_toc_restore (operands[1]);
+ rs6000_emit_eh_toc_restore (operands[0]);
#endif
-
- emit_insn (gen_eh_reg_restore ());
-
- if (Pmode == SImode)
- emit_insn (gen_addsi3 (stack_reg, stack_reg, operands[1]));
- else
- emit_insn (gen_adddi3 (stack_reg, stack_reg, operands[1]));
-
- if (Pmode == SImode)
- insn = emit_jump_insn (gen_return_eh_si (operands[2]));
+ if (TARGET_32BIT)
+ emit_insn (gen_eh_set_lr_si (operands[1]));
else
- insn = emit_jump_insn (gen_return_eh_di (operands[2]));
- emit_barrier_after (insn);
-
+ emit_insn (gen_eh_set_lr_di (operands[1]));
+ emit_move_insn (EH_RETURN_STACKADJ_RTX, operands[0]);
DONE;
}")
-; We can't expand this before we know which registers are restored,
-; but we do want to expand it before flow2 because that way flow2 can
-; remove the redundant loads of the link register.
-(define_expand "eh_reg_restore"
- [(unspec_volatile [(const_int 0)] 9)]
- ""
- "")
+; We can't expand this before we know where the link register is stored.
+(define_insn "eh_set_lr_si"
+ [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] 9)
+ (clobber (match_scratch:SI 1 "=&r"))]
+ "TARGET_32BIT"
+ "#")
+
+(define_insn "eh_set_lr_di"
+ [(unspec_volatile [(match_operand:DI 0 "register_operand" "r")] 9)
+ (clobber (match_scratch:DI 1 "=&r"))]
+ "TARGET_64BIT"
+ "#")
(define_split
- [(unspec_volatile [(const_int 0)] 9)]
- "reload_completed && TARGET_SCHED_PROLOG"
- [(unspec_volatile [(const_int 0)] 9)]
+ [(unspec_volatile [(match_operand 0 "register_operand" "")] 9)
+ (clobber (match_scratch 1 ""))]
+ "reload_completed"
+ [(const_int 0)]
"
{
- rs6000_emit_epilogue (TRUE);
- DONE;
-}")
-
-(define_insn ""
- [(unspec_volatile [(const_int 0)] 9)]
- ""
- "*
-{
- if (TARGET_SCHED_PROLOG)
- return \"#\";
-
- /* This is slightly ugly, but at least we don't have multiple
- copies of the epilogue-emitting code. */
- start_sequence ();
-
- /* A NOTE_INSN_DELETED is supposed to be at the start
- and end of the \"toplevel\" insn chain. */
- emit_note (0, NOTE_INSN_DELETED);
- rs6000_emit_epilogue (TRUE);
- emit_note (0, NOTE_INSN_DELETED);
-
- if (TARGET_DEBUG_STACK)
- debug_rtx_list (get_insns(), 100);
- final (get_insns(), asm_out_file, FALSE, FALSE);
- end_sequence ();
- return \"\";
-}")
+ rs6000_stack_t *info = rs6000_stack_info ();
+ if (info->lr_save_p)
+ {
+ rtx frame_rtx = stack_pointer_rtx;
+ int sp_offset = 0;
+ rtx tmp;
-(define_insn "return_eh_si"
- [(return)
- (use (match_operand:SI 0 "register_operand" "lc"))
- (use (reg:SI 2))
- (use (reg:SI 3))]
- "TARGET_32BIT"
- "b%T0"
- [(set_attr "type" "jmpreg")])
+ if (frame_pointer_needed
+ || current_function_calls_alloca
+ || info->total_size > 32767)
+ {
+ emit_move_insn (operands[1], gen_rtx_MEM (Pmode, frame_rtx));
+ frame_rtx = operands[1];
+ }
+ else if (info->push_p)
+ sp_offset = info->total_size;
-(define_insn "return_eh_di"
- [(return)
- (use (match_operand:DI 0 "register_operand" "lc"))
- (use (reg:DI 2))
- (use (reg:DI 3))]
- "TARGET_64BIT"
- "b%T0"
- [(set_attr "type" "jmpreg")])
+ tmp = plus_constant (frame_rtx, info->lr_save_offset + sp_offset);
+ tmp = gen_rtx_MEM (Pmode, tmp);
+ emit_move_insn (tmp, operands[0]);
+ }
+ else
+ emit_move_insn (gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM), operands[0]);
+ DONE;
+}")
diff --git a/gcc/config/rs6000/rtems.h b/gcc/config/rs6000/rtems.h
index 6810d38a6b4..104610d9339 100644
--- a/gcc/config/rs6000/rtems.h
+++ b/gcc/config/rs6000/rtems.h
@@ -31,4 +31,10 @@ Boston, MA 02111-1307, USA. */
#endif
#undef STARTFILE_DEFAULT_SPEC
-#define STARTFILE_DEFAULT_SPEC "crt0.o%s"
+#define STARTFILE_DEFAULT_SPEC "ecrti.o%s crt0.o%s"
+
+#undef ENDFILE_DEFAULT_SPEC
+#define ENDFILE_DEFAULT_SPEC "ecrtn.o%s"
+
+/* Get machine-independent configuration parameters for RTEMS. */
+#include <rtems.h>
diff --git a/gcc/config/rs6000/sysv4.h b/gcc/config/rs6000/sysv4.h
index da2f0b7313a..34c11348cb1 100644
--- a/gcc/config/rs6000/sysv4.h
+++ b/gcc/config/rs6000/sysv4.h
@@ -856,36 +856,6 @@ do { \
} \
} while (0)
-/* This is how to output an assembler line defining an address
- constant for the dwarf call unwinding information.
- For -mrelocatable, we mark all addresses that need to be fixed up
- in the .fixup section. */
-
-#define ASM_OUTPUT_DWARF_ADDR(FILE,LABEL) \
-do { \
- if (TARGET_RELOCATABLE) \
- { \
- char buf[256]; \
- \
- ASM_GENERATE_INTERNAL_LABEL (buf, "LCP", fixuplabelno); \
- fixuplabelno++; \
- ASM_OUTPUT_LABEL (FILE, buf); \
- fprintf (FILE, "\t.%dbyte\t", POINTER_SIZE / BITS_PER_UNIT); \
- assemble_name (FILE, LABEL); \
- fprintf (FILE, "\n"); \
- fprintf (FILE, "\t.section \".fixup\",\"aw\"\n"); \
- ASM_OUTPUT_ALIGN (FILE, 2); \
- fprintf (FILE, "\t.long\t"); \
- assemble_name (FILE, buf); \
- fprintf (FILE, "\n\t.previous\n"); \
- } \
- else \
- { \
- fprintf (FILE, "\t.%dbyte\t", POINTER_SIZE / BITS_PER_UNIT); \
- assemble_name (FILE, LABEL); \
- } \
-} while (0)
-
/* This is the end of what might become sysv4.h. */
/* Allow stabs and dwarf, for now, make stabs the default debugging type,
diff --git a/gcc/config/rs6000/t-ppccomm b/gcc/config/rs6000/t-ppccomm
index 3a1f106ad21..7d500c36894 100644
--- a/gcc/config/rs6000/t-ppccomm
+++ b/gcc/config/rs6000/t-ppccomm
@@ -6,7 +6,10 @@ CROSS_LIBGCC1 =
# These are really part of libgcc1, but this will cause them to be
# built correctly, so... [taken from t-sparclite]
-LIB2FUNCS_EXTRA = eabi.S tramp.S
+LIB2FUNCS_EXTRA = tramp.S
+
+# This one can't end up in shared libgcc
+LIB2FUNCS_STATIC_EXTRA = eabi.S
# We want fine grained libraries, so use the new code to build the
# floating point emulation libraries.
diff --git a/gcc/config/rs6000/xm-beos.h b/gcc/config/rs6000/xm-beos.h
index 3660a696ed1..f4e6b570aac 100644
--- a/gcc/config/rs6000/xm-beos.h
+++ b/gcc/config/rs6000/xm-beos.h
@@ -21,12 +21,6 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-
-/* #defines that need visibility everywhere. */
-
-#define FALSE 0
-#define TRUE 1
-
/* This describes the machine the compiler is hosted on. */
#define HOST_BITS_PER_CHAR 8
@@ -83,4 +77,3 @@ extern void *alloca ();
/* SYSTEM_INCLUDE_DIR is the location for system specific, non-POSIX headers. */
#define SYSTEM_INCLUDE_DIR "/boot/develop/headers/be"
-
diff --git a/gcc/config/rs6000/xm-rs6000.h b/gcc/config/rs6000/xm-rs6000.h
index 1ad9da9a6ee..9e4658bc82c 100644
--- a/gcc/config/rs6000/xm-rs6000.h
+++ b/gcc/config/rs6000/xm-rs6000.h
@@ -19,11 +19,6 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-
-/* #defines that need visibility everywhere. */
-#define FALSE 0
-#define TRUE 1
-
/* This describes the machine the compiler is hosted on. */
#define HOST_BITS_PER_CHAR 8
#define HOST_BITS_PER_SHORT 16
diff --git a/gcc/config/rs6000/xm-sysv4.h b/gcc/config/rs6000/xm-sysv4.h
index 46d1ddd8e54..4c0ade6dd38 100644
--- a/gcc/config/rs6000/xm-sysv4.h
+++ b/gcc/config/rs6000/xm-sysv4.h
@@ -19,11 +19,6 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-
-/* #defines that need visibility everywhere. */
-#define FALSE 0
-#define TRUE 1
-
/* This describes the machine the compiler is hosted on. */
#define HOST_BITS_PER_CHAR 8
#define HOST_BITS_PER_SHORT 16
diff --git a/gcc/config/s390/fixdfdi.h b/gcc/config/s390/fixdfdi.h
new file mode 100644
index 00000000000..4f1fb352f1b
--- /dev/null
+++ b/gcc/config/s390/fixdfdi.h
@@ -0,0 +1,301 @@
+/* Definitions of target machine for GNU compiler, for IBM S/390
+ Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
+ Contributed by Hartmut Penner (hpenner@de.ibm.com) and
+ Ulrich Weigand (uweigand@de.ibm.com).
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#ifdef L_fixunsdfdi
+#define EXPD(fp) (((fp.l.upper) >> 20) & 0x7FF)
+#define EXCESSD 1022
+#define SIGNBIT 0x80000000
+#define SIGND(fp) ((fp.l.upper) & SIGNBIT)
+#define MANTD_LL(fp) ((fp.ll & (HIDDEND_LL-1)) | HIDDEND_LL)
+#define FRACD_LL(fp) (fp.ll & (HIDDEND_LL-1))
+#define HIDDEND_LL ((UDItype_x)1 << 52)
+
+typedef int DItype_x __attribute__ ((mode (DI)));
+typedef unsigned int UDItype_x __attribute__ ((mode (DI)));
+typedef int SItype_x __attribute__ ((mode (SI)));
+typedef unsigned int USItype_x __attribute__ ((mode (SI)));
+
+union double_long {
+ double d;
+ struct {
+ SItype_x upper;
+ USItype_x lower;
+ } l;
+ UDItype_x ll;
+};
+
+
+/* convert double to unsigned int */
+UDItype_x
+__fixunsdfdi (double a1)
+{
+ register union double_long dl1;
+ register int exp;
+ register UDItype_x l;
+
+ dl1.d = a1;
+
+ /* +/- 0, denormalized, negativ */
+
+ if (!EXPD (dl1) || SIGND(dl1))
+ return 0;
+
+ exp = EXPD (dl1) - EXCESSD - 53;
+
+ /* number < 1 */
+
+ if (exp < -53)
+ return 0;
+
+ /* NaN */
+
+ if ((EXPD(dl1) == 0x7ff) && (FRACD_LL(dl1) != 0)) /* NaN */
+ return 0x0ULL;
+
+ /* Number big number & + inf */
+
+ if (exp >= 12) {
+ return 0xFFFFFFFFFFFFFFFFULL;
+ }
+
+ l = MANTD_LL(dl1);
+
+ /* shift down until exp < 12 or l = 0 */
+ if (exp > 0)
+ l <<= exp;
+ else
+ l >>= -exp;
+
+ return l;
+}
+#define __fixunsdfdi ___fixunsdfdi
+#endif
+#undef L_fixunsdfdi
+
+#ifdef L_fixdfdi
+#define EXPD(fp) (((fp.l.upper) >> 20) & 0x7FF)
+#define EXCESSD 1022
+#define SIGNBIT 0x80000000
+#define SIGND(fp) ((fp.l.upper) & SIGNBIT)
+#define MANTD_LL(fp) ((fp.ll & (HIDDEND_LL-1)) | HIDDEND_LL)
+#define FRACD_LL(fp) (fp.ll & (HIDDEND_LL-1))
+#define HIDDEND_LL ((UDItype_x)1 << 52)
+
+typedef int DItype_x __attribute__ ((mode (DI)));
+typedef unsigned int UDItype_x __attribute__ ((mode (DI)));
+typedef int SItype_x __attribute__ ((mode (SI)));
+typedef unsigned int USItype_x __attribute__ ((mode (SI)));
+
+union double_long {
+ double d;
+ struct {
+ SItype_x upper;
+ USItype_x lower;
+ } l;
+ UDItype_x ll;
+};
+
+/* convert double to int */
+DItype_x
+__fixdfdi (double a1)
+{
+ register union double_long dl1;
+ register int exp;
+ register DItype_x l;
+
+ dl1.d = a1;
+
+ /* +/- 0, denormalized */
+
+ if (!EXPD (dl1))
+ return 0;
+
+ exp = EXPD (dl1) - EXCESSD - 53;
+
+ /* number < 1 */
+
+ if (exp < -53)
+ return 0;
+
+ /* NaN */
+
+ if ((EXPD(dl1) == 0x7ff) && (FRACD_LL(dl1) != 0)) /* NaN */
+ return 0x8000000000000000ULL;
+
+ /* Number big number & +/- inf */
+
+ if (exp >= 11) {
+ l = (long long)1<<63;
+ if (!SIGND(dl1))
+ l--;
+ return l;
+ }
+
+ l = MANTD_LL(dl1);
+
+ /* shift down until exp < 12 or l = 0 */
+ if (exp > 0)
+ l <<= exp;
+ else
+ l >>= -exp;
+
+ return (SIGND (dl1) ? -l : l);
+}
+#define __fixdfdi ___fixdfdi
+#endif
+#undef L_fixdfdi
+
+#ifdef L_fixunssfdi
+#define EXP(fp) (((fp.l) >> 23) & 0xFF)
+#define EXCESS 126
+#define SIGNBIT 0x80000000
+#define SIGN(fp) ((fp.l) & SIGNBIT)
+#define HIDDEN (1 << 23)
+#define MANT(fp) (((fp.l) & 0x7FFFFF) | HIDDEN)
+#define FRAC(fp) ((fp.l) & 0x7FFFFF)
+
+typedef int DItype_x __attribute__ ((mode (DI)));
+typedef unsigned int UDItype_x __attribute__ ((mode (DI)));
+typedef int SItype_x __attribute__ ((mode (SI)));
+typedef unsigned int USItype_x __attribute__ ((mode (SI)));
+
+union float_long
+ {
+ float f;
+ USItype_x l;
+ };
+
+/* convert float to unsigned int */
+UDItype_x
+__fixunssfdi (float a1)
+{
+ register union float_long fl1;
+ register int exp;
+ register UDItype_x l;
+
+ fl1.f = a1;
+
+ /* +/- 0, denormalized, negativ */
+
+ if (!EXP (fl1) || SIGN(fl1))
+ return 0;
+
+ exp = EXP (fl1) - EXCESS - 24;
+
+ /* number < 1 */
+
+ if (exp < -24)
+ return 0;
+
+ /* NaN */
+
+ if ((EXP(fl1) == 0xff) && (FRAC(fl1) != 0)) /* NaN */
+ return 0x0ULL;
+
+ /* Number big number & + inf */
+
+ if (exp >= 41) {
+ return 0xFFFFFFFFFFFFFFFFULL;
+ }
+
+ l = MANT(fl1);
+
+ if (exp > 0)
+ l <<= exp;
+ else
+ l >>= -exp;
+
+ return l;
+}
+#define __fixunssfdi ___fixunssfdi
+#endif
+#undef L_fixunssfdi
+
+#ifdef L_fixsfdi
+#define EXP(fp) (((fp.l) >> 23) & 0xFF)
+#define EXCESS 126
+#define SIGNBIT 0x80000000
+#define SIGN(fp) ((fp.l) & SIGNBIT)
+#define HIDDEN (1 << 23)
+#define MANT(fp) (((fp.l) & 0x7FFFFF) | HIDDEN)
+#define FRAC(fp) ((fp.l) & 0x7FFFFF)
+
+typedef int DItype_x __attribute__ ((mode (DI)));
+typedef unsigned int UDItype_x __attribute__ ((mode (DI)));
+typedef int SItype_x __attribute__ ((mode (SI)));
+typedef unsigned int USItype_x __attribute__ ((mode (SI)));
+
+union float_long
+ {
+ float f;
+ USItype_x l;
+ };
+
+/* convert double to int */
+DItype_x
+__fixsfdi (float a1)
+{
+ register union float_long fl1;
+ register int exp;
+ register DItype_x l;
+
+ fl1.f = a1;
+
+ /* +/- 0, denormalized */
+
+ if (!EXP (fl1))
+ return 0;
+
+ exp = EXP (fl1) - EXCESS - 24;
+
+ /* number < 1 */
+
+ if (exp < -24)
+ return 0;
+
+ /* NaN */
+
+ if ((EXP(fl1) == 0xff) && (FRAC(fl1) != 0)) /* NaN */
+ return 0x8000000000000000ULL;
+
+ /* Number big number & +/- inf */
+
+ if (exp >= 40) {
+ l = (long long)1<<63;
+ if (!SIGN(fl1))
+ l--;
+ return l;
+ }
+
+ l = MANT(fl1);
+
+ if (exp > 0)
+ l <<= exp;
+ else
+ l >>= -exp;
+
+ return (SIGN (fl1) ? -l : l);
+}
+#define __fixsfdi ___fixsfdi
+#endif
+#undef L_fixsfdi
+
diff --git a/gcc/config/s390/linux.h b/gcc/config/s390/linux.h
new file mode 100644
index 00000000000..6136412c9c5
--- /dev/null
+++ b/gcc/config/s390/linux.h
@@ -0,0 +1,381 @@
+/* Definitions for Linux for S/390.
+ Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
+ Contributed by Hartmut Penner (hpenner@de.ibm.com) and
+ Ulrich Weigand (uweigand@de.ibm.com).
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#ifndef _LINUX_H
+#define _LINUX_H
+
+#undef SIZE_TYPE /* use default */
+
+#undef TARGET_VERSION
+#define TARGET_VERSION fprintf (stderr, " (Linux for S/390)");
+
+/* Names to predefine in the preprocessor for this target machine. */
+
+#define CPP_PREDEFINES "-Dlinux -Asystem(linux) -Acpu(s390) -Amachine(s390) -D__s390__ -Asystem(unix) -Dunix -D__ELF__"
+
+/*
+ * Caller save not (always) working in gcc-2.95.2
+ */
+
+#undef CC1_SPEC
+#define CC1_SPEC "-fno-caller-saves"
+#define CC1PLUS_SPEC "-fno-caller-saves"
+
+#undef LINK_SPEC
+#ifdef CROSS_COMPILE
+#define LINK_SPEC "-m elf_s390 %{shared:-shared} \
+ %{!shared: \
+ %{!ibcs: \
+ %{!static: \
+ %{rdynamic:-export-dynamic} \
+ %{!dynamic-linker:-dynamic-linker /lib/ld.so.1 \
+ -rpath-link=/usr/local/s390-ibm-linux/lib}} \
+ %{static:-static}}}"
+#else
+#define LINK_SPEC "-m elf_s390 %{shared:-shared} \
+ %{!shared: \
+ %{!ibcs: \
+ %{!static: \
+ %{rdynamic:-export-dynamic} \
+ %{!dynamic-linker:-dynamic-linker /lib/ld.so.1}} \
+ %{static:-static}}}"
+#endif
+
+/* Need to define this. Otherwise define to BITS_PER_WORD in cexp.c.
+ But BITS_PER_WORD depends on target flags, which are not defined in
+ cexpc.c. */
+
+#undef WCHAR_TYPE
+#define WCHAR_TYPE "int"
+#undef WCHAR_TYPE_SIZE
+#define WCHAR_TYPE_SIZE 32
+#define MAX_LONG_TYPE_SIZE 64
+
+/* Character to start a comment. */
+
+#define ASM_COMMENT_START "#"
+
+
+/* Assembler pseudos to introduce constants of various size. */
+
+#define ASM_SHORT "\t.word"
+#define ASM_LONG "\t.long"
+#define ASM_QUAD "\t.quad"
+#define ASM_DOUBLE "\t.double"
+
+
+/* Prefix for internally generated assembler labels. */
+#define LPREFIX ".L"
+
+#define ASM_OUTPUT_LABELREF(FILE, NAME) \
+ fprintf (FILE, "%s", NAME);
+
+
+/* This is how to output the definition of a user-level label named NAME,
+ such as the label on a static function or variable NAME. */
+
+#undef ASM_OUTPUT_LABEL
+#define ASM_OUTPUT_LABEL(FILE, NAME) \
+ (assemble_name (FILE, NAME), fputs (":\n", FILE))
+
+/* This is how to output an assembler line defining a `double' constant. */
+
+
+/* This is how to output an assembler line defining a `double' constant. */
+
+#undef ASM_OUTPUT_DOUBLE
+#define ASM_OUTPUT_DOUBLE(FILE, VALUE) \
+ { \
+ long t[2]; \
+ REAL_VALUE_TO_TARGET_DOUBLE ((VALUE), t); \
+ fprintf (FILE, "\t.long 0x%lx\n\t.long 0x%lx\n", \
+ t[0] & 0xffffffff, t[1] & 0xffffffff); \
+ }
+
+/* This is how to output an assembler line defining a `float' constant. */
+
+#undef ASM_OUTPUT_FLOAT
+#define ASM_OUTPUT_FLOAT(FILE, VALUE) \
+ { \
+ long t; \
+ REAL_VALUE_TO_TARGET_SINGLE ((VALUE), t); \
+ fprintf (FILE, "\t.long 0x%lx\n", t & 0xffffffff); \
+ }
+
+/* Store in OUTPUT a string (made with alloca) containing
+ an assembler-name for a local static variable named NAME.
+ LABELNO is an integer which is different for each call. */
+
+#undef ASM_FORMAT_PRIVATE_NAME
+#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \
+( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \
+ sprintf ((OUTPUT), "%s.%d", (NAME), (LABELNO)))
+
+
+#define ASM_OUTPUT_DOUBLE_INT(FILE, VALUE) \
+do { fprintf (FILE, "%s\t", ASM_QUAD); \
+ output_addr_const (FILE, (VALUE)); \
+ putc ('\n',FILE); \
+ } while (0)
+
+
+/* This is how to output an assembler line defining an `int' constant. */
+
+#undef ASM_OUTPUT_INT
+#define ASM_OUTPUT_INT(FILE, VALUE) \
+do { fprintf (FILE, "%s\t", ASM_LONG); \
+ output_addr_const (FILE, (VALUE)); \
+ putc ('\n',FILE); \
+ } while (0)
+
+/* Likewise for `char' and `short' constants.
+ is this supposed to do align too?? */
+
+#define ASM_OUTPUT_SHORT(FILE, VALUE) \
+( fprintf (FILE, "%s ", ASM_SHORT), \
+ output_addr_const (FILE, (VALUE)), \
+ putc ('\n',FILE))
+
+#define ASM_OUTPUT_CHAR(FILE, VALUE) \
+( fprintf (FILE, "%s ", ASM_BYTE_OP), \
+ output_addr_const (FILE, (VALUE)), \
+ putc ('\n', FILE))
+
+/* This is how to output an assembler line for a numeric constant byte. */
+
+#define ASM_OUTPUT_BYTE(FILE, VALUE) \
+ fprintf ((FILE), "%s 0x%x\n", ASM_BYTE_OP, (VALUE))
+
+ /* internal macro to output long */
+#define _ASM_OUTPUT_LONG(FILE, VALUE) \
+ fprintf (FILE, "\t.long\t0x%lX\n", VALUE);
+
+
+/* This is how to output an element of a case-vector that is absolute. */
+
+#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
+ fprintf (FILE, "%s\t%s%d\n", TARGET_64BIT?ASM_QUAD:ASM_LONG, \
+ LPREFIX, VALUE)
+
+/* This is how to output an element of a case-vector that is relative. */
+
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
+ fprintf (FILE, "%s\t%s%d-%s%d\n", TARGET_64BIT?ASM_QUAD:ASM_LONG, \
+ LPREFIX, VALUE, LPREFIX, REL)
+
+
+/* Define the parentheses used to group arithmetic operations
+ in assembler code. */
+
+#undef ASM_OPEN_PAREN
+#undef ASM_CLOSE_PAREN
+#define ASM_OPEN_PAREN ""
+#define ASM_CLOSE_PAREN ""
+
+
+
+/* This is how to output an assembler line
+ that says to advance the location counter
+ to a multiple of 2**LOG bytes. */
+
+#define ASM_OUTPUT_ALIGN(FILE, LOG) \
+ if ((LOG)!=0) fprintf ((FILE), "\t.align %d\n", 1<<(LOG))
+
+/* This is how to output an assembler line
+ that says to advance the location counter by SIZE bytes. */
+
+#undef ASM_OUTPUT_SKIP
+#define ASM_OUTPUT_SKIP(FILE, SIZE) \
+ fprintf ((FILE), "\t.set .,.+%u\n", (SIZE))
+
+/* This is how to output an assembler line
+ that says to advance the location counter
+ to a multiple of 2**LOG bytes. */
+
+#define ASM_OUTPUT_ALIGN(FILE, LOG) \
+ if ((LOG)!=0) fprintf ((FILE), "\t.align %d\n", 1<<(LOG))
+
+/* This is how to output an assembler line
+ that says to advance the location counter by SIZE bytes. */
+
+#define ASM_OUTPUT_SKIP(FILE, SIZE) \
+ fprintf ((FILE), "\t.set .,.+%u\n", (SIZE))
+
+/* The routine used to output sequences of byte values. We use a special
+ version of this for most svr4 targets because doing so makes the
+ generated assembly code more compact (and thus faster to assemble)
+ as well as more readable. Note that if we find subparts of the
+ character sequence which end with NUL (and which are shorter than
+ STRING_LIMIT) we output those using ASM_OUTPUT_LIMITED_STRING. */
+
+#undef ASM_OUTPUT_ASCII
+#define ASM_OUTPUT_ASCII(FILE, STR, LENGTH) \
+do { \
+ register unsigned char *_ascii_bytes = (unsigned char *) (STR); \
+ register unsigned char *limit = _ascii_bytes + (LENGTH); \
+ register unsigned bytes_in_chunk = 0; \
+ for (; _ascii_bytes < limit; _ascii_bytes++) \
+ { \
+ register unsigned char *p; \
+ if (bytes_in_chunk >= 64) \
+ { \
+ fputc ('\n', (FILE)); \
+ bytes_in_chunk = 0; \
+ } \
+ for (p = _ascii_bytes; p < limit && *p != '\0'; p++) \
+ continue; \
+ if (p < limit && (p - _ascii_bytes) <= STRING_LIMIT) \
+ { \
+ if (bytes_in_chunk > 0) \
+ { \
+ fputc ('\n', (FILE)); \
+ bytes_in_chunk = 0; \
+ } \
+ ASM_OUTPUT_LIMITED_STRING ((FILE), _ascii_bytes); \
+ _ascii_bytes = p; \
+ } \
+ else \
+ { \
+ if (bytes_in_chunk == 0) \
+ fprintf ((FILE), "%s\t", ASM_BYTE_OP); \
+ else \
+ fputc (',', (FILE)); \
+ fprintf ((FILE), "0x%02x", *_ascii_bytes); \
+ bytes_in_chunk += 5; \
+ } \
+ } \
+ if (bytes_in_chunk > 0) \
+ fprintf ((FILE), "\n"); \
+} while (0)
+
+/* Output before read-only data. */
+
+#define TEXT_SECTION_ASM_OP ".text"
+
+/* Output before writable (initialized) data. */
+
+#define DATA_SECTION_ASM_OP ".data"
+
+/* Output before writable (uninitialized) data. */
+
+#define BSS_SECTION_ASM_OP ".bss"
+
+/* This is how to output a command to make the user-level label named NAME
+ defined for reference from other files. */
+
+#define ASM_GLOBALIZE_LABEL(FILE, NAME) \
+ (fputs (".globl ", FILE), assemble_name (FILE, NAME), fputs ("\n", FILE))
+
+#define DBX_REGISTER_NUMBER(REGNO) (REGNO)
+
+/*
+ * This macro generates the assembly code for function entry.
+ */
+
+#define FUNCTION_PROLOGUE(FILE, LSIZE) s390_function_prologue (FILE, LSIZE)
+
+/* This macro generates the assembly code for function exit, on machines
+ that need it. If FUNCTION_EPILOGUE is not defined then individual
+ return instructions are generated for each return statement. Args are
+ same as for FUNCTION_PROLOGUE.
+
+ The function epilogue should not depend on the current stack pointer!
+ It should use the frame pointer only. This is mandatory because
+ of alloca; we also take advantage of it to omit stack adjustments
+ before returning. */
+
+#define FUNCTION_EPILOGUE(FILE, LSIZE) s390_function_epilogue(FILE, LSIZE)
+
+/* Select section for constant in constant pool.
+ We are in the right section.
+ undef for 64 bit mode (linux64.h).
+ */
+
+#undef SELECT_RTX_SECTION
+#define SELECT_RTX_SECTION(MODE, X)
+
+
+/* Output code to add DELTA to the first argument, and then jump to FUNCTION.
+ Used for C++ multiple inheritance. */
+#define ASM_OUTPUT_MI_THUNK(FILE, THUNK_FNDECL, DELTA, FUNCTION) \
+do { \
+ if (TARGET_64BIT) \
+ { \
+ if (flag_pic) \
+ { \
+ fprintf (FILE, "\tlarl 1,0f\n"); \
+ fprintf (FILE, "\tagf %d,0(1)\n", \
+ aggregate_value_p (TREE_TYPE \
+ (TREE_TYPE (FUNCTION))) ? 3 :2 ); \
+ fprintf (FILE, "\tlarl 1,"); \
+ assemble_name (FILE, XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0)); \
+ fprintf (FILE, "@GOTENT\n"); \
+ fprintf (FILE, "\tlg 1,0(1)\n"); \
+ fprintf (FILE, "\tbr 1\n"); \
+ fprintf (FILE, "0:\t.long %d\n",DELTA); \
+ } \
+ else \
+ { \
+ fprintf (FILE, "\tlarl 1,0f\n"); \
+ fprintf (FILE, "\tagf %d,0(1)\n", \
+ aggregate_value_p (TREE_TYPE \
+ (TREE_TYPE (FUNCTION))) ? 3 :2 ); \
+ fprintf (FILE, "\tjg "); \
+ assemble_name (FILE, XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0)); \
+ fprintf (FILE, "\n"); \
+ fprintf (FILE, "0:\t.long %d\n",DELTA); \
+ } \
+ } \
+ else \
+ { \
+ if (flag_pic) \
+ { \
+ fprintf (FILE, "\tbras 1,0f\n"); \
+ fprintf (FILE, "\t.long _GLOBAL_OFFSET_TABLE_-.\n"); \
+ fprintf (FILE, "\t.long "); \
+ assemble_name (FILE, XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0)); \
+ fprintf (FILE, "@GOT\n"); \
+ fprintf (FILE, "\t.long %d\n",DELTA); \
+ fprintf (FILE, "0:\tal %d,8(1)\n", \
+ aggregate_value_p (TREE_TYPE \
+ (TREE_TYPE (FUNCTION))) ? 3 : 2 ); \
+ fprintf (FILE, "\tl 0,4(1)\n"); \
+ fprintf (FILE, "\tal 1,0(1)\n"); \
+ fprintf (FILE, "\talr 1,0\n"); \
+ fprintf (FILE, "\tl 1,0(1)\n"); \
+ fprintf (FILE, "\tbr 1\n"); \
+ } else { \
+ fprintf (FILE, "\tbras 1,0f\n"); \
+ fprintf (FILE, "\t.long "); \
+ assemble_name (FILE, XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0)); \
+ fprintf (FILE, "-.\n"); \
+ fprintf (FILE, "\t.long %d\n",DELTA); \
+ fprintf (FILE, "0:\tal %d,4(1)\n", \
+ aggregate_value_p (TREE_TYPE \
+ (TREE_TYPE (FUNCTION))) ? 3 : 2 ); \
+ fprintf (FILE, "\tal 1,0(1)\n"); \
+ fprintf (FILE, "\tbr 1\n"); \
+ } \
+ } \
+} while (0)
+
+#endif
diff --git a/gcc/config/s390/linux64.h b/gcc/config/s390/linux64.h
new file mode 100644
index 00000000000..1a86715f3d2
--- /dev/null
+++ b/gcc/config/s390/linux64.h
@@ -0,0 +1,80 @@
+/* Definitions for Linux for S/390 64bit.
+ Copyright (C) 2000 Free Software Foundation, Inc.
+ Contributed by Hartmut Penner <hpenner@de.ibm.com>
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#ifndef _LINUX64_H
+#define _LINUX64_H
+
+#undef PTRDIFF_TYPE
+#define PTRDIFF_TYPE "long int"
+
+#undef TARGET_DEFAULT
+#define TARGET_DEFAULT 0x13
+
+#undef TARGET_VERSION
+#define TARGET_VERSION fprintf (stderr, " (Linux for S/390 zSeries 64 bit)");
+
+/* Names to predefine in the preprocessor for this target machine. */
+
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES "-Dlinux -Asystem(linux) -Acpu(s390) -Amachine(s390) -D__s390__ -D__s390x__ -Asystem(unix) -Dunix -D__ELF__"
+
+
+#undef LINK_SPEC
+#ifdef CROSS_COMPILE
+#define LINK_SPEC "-m elf64_s390 %{shared:-shared} \
+ %{!shared: \
+ %{!ibcs: \
+ %{!static: \
+ %{rdynamic:-export-dynamic} \
+ %{!dynamic-linker:-dynamic-linker /lib/ld64.so.1 \
+ -rpath-link=/usr/local/s390x-ibm-linux/lib}} \
+ %{static:-static}}}"
+#else
+#define LINK_SPEC "-m elf64_s390 %{shared:-shared} \
+ %{!shared: \
+ %{!ibcs: \
+ %{!static: \
+ %{rdynamic:-export-dynamic} \
+ %{!dynamic-linker:-dynamic-linker /lib/ld64.so.1}} \
+ %{static:-static}}}"
+#endif
+
+#undef INT_ASM_OP
+#define INT_ASM_OP "\t.quad\t"
+
+#undef PROMOTE_PROTOTYPES
+#undef MASK_RETURN_ADDR
+#undef SELECT_SECTION
+
+/* With 64 bit new linkage for floating point registers. */
+#undef CALL_USED_REGISTERS
+#define CALL_USED_REGISTERS \
+{ 1, 1, 1, 1, \
+ 1, 1, 0, 0, \
+ 0, 0, 0, 0, \
+ 0, 1, 1, 1, \
+ 1, 1, 1, 1, \
+ 1, 1, 1, 1, \
+ 0, 0, 0, 0, \
+ 0, 0, 0, 0, \
+ 1, 1 }
+
+#endif
diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h
new file mode 100644
index 00000000000..b90c20e51d4
--- /dev/null
+++ b/gcc/config/s390/s390-protos.h
@@ -0,0 +1,85 @@
+/* Definitions of target machine for GNU compiler, for IBM S/390.
+ Copyright (C) 2000 Free Software Foundation, Inc.
+ Contributed by Hartmut Penner (hpenner@de.ibm.com)
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* Declare functions in s390.c and linux.c */
+
+#ifdef RTX_CODE
+
+#ifdef TREE_CODE
+extern void init_cumulative_args PARAMS ((CUMULATIVE_ARGS *, tree, rtx, int));
+extern void s390_va_start PARAMS ((int, tree, rtx));
+
+#endif /* TREE_CODE */
+
+extern int fp_operand PARAMS ((rtx, enum machine_mode));
+extern int s_operand PARAMS ((rtx, enum machine_mode));
+extern int r_or_im8_operand PARAMS ((rtx, enum machine_mode));
+extern int r_or_s_operand PARAMS ((rtx, enum machine_mode));
+extern int r_or_s_or_im8_operand PARAMS ((rtx, enum machine_mode));
+extern int r_or_x_or_im16_operand PARAMS ((rtx, enum machine_mode));
+extern int bras_sym_operand PARAMS ((rtx, enum machine_mode));
+extern int dead_p PARAMS ((rtx, rtx));
+extern void print_operand PARAMS ((FILE *, rtx, char));
+extern void print_operand_address PARAMS ((FILE *, rtx));
+extern int legitimate_pic_operand_p PARAMS ((rtx));
+extern int legitimate_constant_p PARAMS ((rtx));
+
+extern int unsigned_comparison_operator PARAMS ((rtx));
+extern int unsigned_jump_follows_p PARAMS ((rtx));
+
+extern void update_cc PARAMS ((rtx, rtx));
+
+extern void s390_initialize_trampoline PARAMS ((rtx, rtx, rtx));
+extern void s390_output_symbolic_const PARAMS ((FILE *, rtx));
+extern int s390_adjust_cost PARAMS ((rtx, rtx, rtx, int));
+
+extern int s390_stop_dump_lit_p PARAMS ((rtx));
+extern void s390_dump_literal_pool PARAMS ((rtx, rtx));
+extern void s390_expand_eh_epilogue PARAMS ((rtx, rtx, rtx));
+extern void s390_asm_output_external_libcall PARAMS ((FILE *, rtx));
+
+#endif /* RTX_CODE */
+
+#ifdef TREE_CODE
+extern void s390_function_arg_advance PARAMS ((CUMULATIVE_ARGS *,
+ enum machine_mode,
+ tree, int));
+extern struct rtx_def *s390_function_arg PARAMS ((CUMULATIVE_ARGS *,
+ enum machine_mode, tree, int));
+extern int s390_function_arg_partial_nregs PARAMS ((CUMULATIVE_ARGS *,
+ enum machine_mode, tree, int));
+extern int s390_function_arg_pass_by_reference PARAMS ((enum machine_mode, tree));
+extern void setup_incoming_varargs PARAMS ((CUMULATIVE_ARGS *,
+ enum machine_mode, tree,
+ int *, int));
+extern struct rtx_def *s390_va_arg PARAMS ((tree, tree));
+extern union tree_node *s390_build_va_list PARAMS ((void));
+extern void s390_asm_output_pool_prologue PARAMS ((FILE *, char *, tree, int));
+extern void encode_section_info PARAMS ((tree));
+
+#endif /* TREE_CODE */
+
+
+extern void s390_trampoline_template PARAMS ((FILE *));
+extern int s390_function_prologue PARAMS ((FILE *, int));
+extern int s390_function_epilogue PARAMS ((FILE *, int));
+extern void s390_final_chunkify PARAMS ((int));
+extern int s390_arg_frame_offset PARAMS ((void));
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
new file mode 100644
index 00000000000..95ace863907
--- /dev/null
+++ b/gcc/config/s390/s390.c
@@ -0,0 +1,3118 @@
+/* Subroutines used for code generation on IBM S/390 and zSeries
+ Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
+ Contributed by Hartmut Penner (hpenner@de.ibm.com) and
+ Ulrich Weigand (uweigand@de.ibm.com).
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "rtl.h"
+#include "expr.h"
+#include "tree.h"
+#include "regs.h"
+#include "hard-reg-set.h"
+#include "real.h"
+#include "insn-config.h"
+#include "conditions.h"
+#include "insn-flags.h"
+#include "output.h"
+#include "insn-attr.h"
+#include "flags.h"
+#include "recog.h"
+#include "math.h"
+#include "obstack.h"
+#include "except.h"
+#include "function.h"
+#include "toplev.h"
+
+#include "tm_p.h"
+
+extern int reload_completed;
+
+/* Function count for creating unique internal labels in a compile unit. */
+int s390_function_count = 0;
+
+/* Save information from a "cmpxx" operation until the branch or scc is
+ emitted. */
+rtx s390_compare_op0, s390_compare_op1;
+
+/* Return TRUE or FALSE depending on whether every SET in INSN that
+ set the CC register has source and destination with matching CC modes,
+ and that the CC mode is at least as constrained as REQ_MODE. */
+
+static int
+s390_match_ccmode_set (set, req_mode)
+ rtx set;
+ int req_mode;
+{
+ int set_mode;
+
+ if (GET_CODE (set) != SET)
+ abort ();
+
+ if (GET_CODE (SET_DEST (set)) != REG || !CC_REGNO_P (REGNO (SET_DEST (set))))
+ return 1;
+
+ set_mode = GET_MODE (SET_DEST (set));
+ switch (set_mode)
+ {
+ case CCmode:
+ return 0;
+
+ case CCSmode:
+ if (req_mode != CCSmode)
+ return 0;
+ break;
+ case CCUmode:
+ if (req_mode != CCUmode)
+ return 0;
+ break;
+ case CCZmode:
+ if (req_mode != CCSmode && req_mode != CCUmode && req_mode != CCTmode)
+ return 0;
+ break;
+
+ default:
+ abort ();
+ }
+
+ return (GET_MODE (SET_SRC (set)) == set_mode);
+}
+
+int
+s390_match_ccmode (insn, req_mode)
+ rtx insn;
+ int req_mode;
+{
+ int i;
+
+ if (GET_CODE (PATTERN (insn)) == SET)
+ return s390_match_ccmode_set (PATTERN (insn), req_mode);
+
+ if (GET_CODE (PATTERN (insn)) == PARALLEL)
+ for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
+ {
+ rtx set = XVECEXP (PATTERN (insn), 0, i);
+ if (GET_CODE (set) == SET)
+ if (!s390_match_ccmode_set (set, req_mode))
+ return 0;
+ }
+
+ return 1;
+}
+
+
+void
+optimization_options (level, size)
+ int level;
+ int size ATTRIBUTE_UNUSED;
+{
+#ifdef HAVE_decrement_and_branch_on_count
+ /* When optimizing, enable use of BRCT instruction. */
+ if (level >= 1)
+ flag_branch_on_count_reg = 1;
+#endif
+}
+
+
+/* Map for smallest class containing reg regno. */
+
+enum reg_class regclass_map[FIRST_PSEUDO_REGISTER] =
+{ GENERAL_REGS, ADDR_REGS, ADDR_REGS, ADDR_REGS,
+ ADDR_REGS, ADDR_REGS, ADDR_REGS, ADDR_REGS,
+ ADDR_REGS, ADDR_REGS, ADDR_REGS, ADDR_REGS,
+ ADDR_REGS, ADDR_REGS, ADDR_REGS, ADDR_REGS,
+ FP_REGS, FP_REGS, FP_REGS, FP_REGS,
+ FP_REGS, FP_REGS, FP_REGS, FP_REGS,
+ FP_REGS, FP_REGS, FP_REGS, FP_REGS,
+ FP_REGS, FP_REGS, FP_REGS, FP_REGS,
+ ADDR_REGS, NO_REGS
+};
+
+
+/* Match exactly zero. */
+
+int
+const0_operand (op, mode)
+ register rtx op;
+ enum machine_mode mode;
+{
+ return op == CONST0_RTX (mode);
+}
+
+/* Match exactly one. */
+
+int
+const1_operand (op, mode)
+ register rtx op;
+ enum machine_mode mode;
+{
+ return op == CONST1_RTX (mode);
+}
+
+
+/* Return 1 if OP needs base and index register. */
+
+static int
+base_n_index_p (rtx op)
+{
+ if ((GET_CODE (op) == PLUS) &&
+ (GET_CODE (XEXP (op, 0)) == PLUS ||
+ GET_CODE (XEXP (op, 1)) == PLUS ||
+ GET_CODE (XEXP (op, 1)) == REG ))
+ return 1;
+ return 0;
+}
+
+/* Check mode and mode of op, set it to mode of op, if VOIDmode. */
+
+static int
+check_mode (op, mode)
+ register rtx op;
+ enum machine_mode *mode;
+{
+ if (*mode == VOIDmode)
+ *mode = GET_MODE (op);
+ else
+ {
+ if (GET_MODE (op) != VOIDmode && GET_MODE (op) != *mode)
+ return 0;
+ }
+ return 1;
+}
+
+
+/* Return 1 if OP a valid operand for the LARL instruction.
+ OP is the current operation.
+ MODE is the current operation mode. */
+
+int
+larl_operand (op, mode)
+ register rtx op;
+ enum machine_mode mode;
+{
+ rtx sym;
+ register enum rtx_code code = GET_CODE (op);
+
+ if (! check_mode (op, &mode))
+ return 0;
+
+ /* Allow labels and local symbols. */
+ if (GET_CODE (op) == LABEL_REF)
+ return 1;
+ if (GET_CODE (op) == SYMBOL_REF
+ && (!flag_pic || SYMBOL_REF_FLAG (op)
+ || CONSTANT_POOL_ADDRESS_P (op)))
+ return 1;
+
+ /* Everything else must have a CONST, so strip it. */
+ if (GET_CODE (op) != CONST)
+ return 0;
+ op = XEXP (op, 0);
+
+ /* Allow adding *even* constants. */
+ if (GET_CODE (op) == PLUS)
+ {
+ if (GET_CODE (XEXP (op, 1)) != CONST_INT
+ || (INTVAL (XEXP (op, 1)) & 1) != 0)
+ return 0;
+ op = XEXP (op, 0);
+ }
+
+ /* Labels and local symbols allowed here as well. */
+ if (GET_CODE (op) == LABEL_REF)
+ return 1;
+ if (GET_CODE (op) == SYMBOL_REF
+ && (!flag_pic || SYMBOL_REF_FLAG (op)
+ || CONSTANT_POOL_ADDRESS_P (op)))
+ return 1;
+
+ /* Now we must have a @GOTENT offset or @PLT stub. */
+ if (GET_CODE (op) == UNSPEC
+ && XINT (op, 1) == 111)
+ return 1;
+ if (GET_CODE (op) == UNSPEC
+ && XINT (op, 1) == 113)
+ return 1;
+
+ return 0;
+}
+
+/* Return 1 if OP is a valid FP-Register.
+ OP is the current operation.
+ MODE is the current operation mode. */
+
+int
+fp_operand (op, mode)
+ register rtx op;
+ enum machine_mode mode;
+{
+ register enum rtx_code code = GET_CODE (op);
+ if (! check_mode (op, &mode))
+ return 0;
+ if (code == REG && REGNO_OK_FOR_FP_P (REGNO (op)))
+ return 1;
+ else
+ return 0;
+}
+
+/* Return 1 if OP is a valid S operand for an RS, SI or SS type instruction. */
+
+int
+s_operand (op, mode)
+ register rtx op;
+ enum machine_mode mode;
+{
+ register enum rtx_code code = GET_CODE (op);
+
+ if (! check_mode (op,&mode))
+ return 0;
+
+ if (code == MEM) {
+ if (base_n_index_p (XEXP (op, 0)))
+ return 0;
+ }
+
+ return memory_operand (op, mode);
+}
+
+/* Return 1 if OP is a valid R or S operand for an RS, SI or SS type
+ instruction. */
+
+int
+r_or_s_operand (op, mode)
+ register rtx op;
+ enum machine_mode mode;
+{
+ register enum rtx_code code = GET_CODE (op);
+
+ if (!general_operand (op, mode))
+ return 0;
+
+ if (code == MEM) {
+ if (base_n_index_p (XEXP (op, 0)))
+ return 0;
+ else
+ return memory_operand (op, mode);
+ }
+ return register_operand (op, mode);
+}
+
+/* Return 1 if OP is a valid R or S or immediate operand for
+ RS, SI or SS type instruction. */
+
+int
+r_or_s_or_im8_operand (op, mode)
+ register rtx op;
+ enum machine_mode mode;
+{
+ register enum rtx_code code = GET_CODE (op);
+
+ if (!general_operand (op, mode))
+ return 0;
+
+ if (code == MEM) {
+ if (base_n_index_p (XEXP (op, 0)))
+ return 0;
+ else
+ return memory_operand (op, mode);
+ }
+ return register_operand (op, mode) || immediate_operand (op, mode);
+}
+
+/* Return 1 if OP is a valid R or X or 16 bit immediate operand for
+ RX, RR or RI type instruction. */
+
+int
+r_or_x_or_im16_operand (op, mode)
+ register rtx op;
+ enum machine_mode mode;
+{
+
+ if (! general_operand (op, mode))
+ return 0;
+
+ if (GET_CODE (op) == CONST_INT)
+ return (CONST_OK_FOR_LETTER_P (INTVAL (op), 'K'));
+ return register_operand (op, mode) || memory_operand (op, mode);
+}
+
+/* Return 1 if OP is a valid R or 8 bit immediate operand for
+ !!!!!!! type instruction. */
+
+int
+r_or_im8_operand (op, mode)
+ register rtx op;
+ enum machine_mode mode;
+{
+
+ if (!general_operand (op, mode))
+ return 0;
+
+ if (GET_CODE (op) == CONST_INT)
+ return (CONST_OK_FOR_LETTER_P (INTVAL (op), 'J'));
+ return register_operand (op, mode) || memory_operand (op, mode);
+}
+
+/* Return 1 if OP is a valid operand for the 'test under mask'
+ instruction with 16 bit immediate.
+ The value should only have set bits in one halfword. */
+
+int
+tmxx_operand (op, mode)
+ register rtx op;
+ enum machine_mode mode;
+{
+ rtx con;
+ if (GET_CODE (op) == CONST_INT)
+ return (CONST_OK_FOR_LETTER_P (INTVAL (op), 'L'));
+ if (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == SYMBOL_REF &&
+ CONSTANT_POOL_ADDRESS_P (XEXP (op, 0)))
+ {
+ con = get_pool_constant (XEXP (op, 0));
+
+ if (GET_CODE (con) == CONST_INT)
+ {
+ unsigned HOST_WIDEST_INT c;
+
+ c = (unsigned HOST_WIDEST_INT) INTVAL (con);
+
+ return ((c & 0xffff) ? ((c & 0xffffffffffff0000ULL)==0) :
+ (c & 0xffff0000) ? ((c & 0xffffffff0000ffffULL)==0) :
+ (c & 0xffff00000000ULL) ? ((c & 0xffff0000ffffffffULL)==0) :
+ (c & 0xffff000000000000ULL) ? ((c & 0xffffffffffffULL)==0) : 1);
+
+ }
+ }
+ return 0;
+}
+
+
+/* Return 1 if valid operand for BRAS
+ OP is the current operation.
+ MODE is the current operation mode. */
+
+int
+bras_sym_operand (op, mode)
+ register rtx op;
+ enum machine_mode mode;
+{
+ register enum rtx_code code = GET_CODE (op);
+
+ /* Allow SYMBOL_REFs. */
+ if (code == SYMBOL_REF)
+ return 1;
+
+ /* Allow @PLT stubs. */
+ if (code == CONST
+ && GET_CODE (XEXP (op, 0)) == UNSPEC
+ && XINT (XEXP (op, 0), 1) == 113)
+ return 1;
+ return 0;
+}
+
+
+/* Return 1 if OP is a load multiple operation. It is known to be a
+ PARALLEL and the first section will be tested. */
+
+int
+load_multiple_operation (op, mode)
+ rtx op;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+ int count = XVECLEN (op, 0);
+ unsigned int dest_regno;
+ rtx src_addr;
+ int i;
+
+
+ /* Perform a quick check so we don't blow up below. */
+ if (count <= 1
+ || GET_CODE (XVECEXP (op, 0, 0)) != SET
+ || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != REG
+ || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != MEM)
+ return 0;
+
+ dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, 0)));
+ src_addr = XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0);
+
+ for (i = 1; i < count; i++)
+ {
+ rtx elt = XVECEXP (op, 0, i);
+
+ if (GET_CODE (elt) != SET
+ || GET_CODE (SET_DEST (elt)) != REG
+ || GET_MODE (SET_DEST (elt)) != Pmode
+ || REGNO (SET_DEST (elt)) != dest_regno + i
+ || GET_CODE (SET_SRC (elt)) != MEM
+ || GET_MODE (SET_SRC (elt)) != Pmode
+ || GET_CODE (XEXP (SET_SRC (elt), 0)) != PLUS
+ || ! rtx_equal_p (XEXP (XEXP (SET_SRC (elt), 0), 0), src_addr)
+ || GET_CODE (XEXP (XEXP (SET_SRC (elt), 0), 1)) != CONST_INT
+ || INTVAL (XEXP (XEXP (SET_SRC (elt), 0), 1)) != i * 4)
+ return 0;
+ }
+
+ return 1;
+}
+
+/* Similar, but tests for store multiple. */
+
+int
+store_multiple_operation (op, mode)
+ rtx op;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+ int count = XVECLEN (op, 0) - 1;
+ unsigned int src_regno;
+ rtx dest_addr;
+ int i;
+
+ /* Perform a quick check so we don't blow up below. */
+ if (count <= 1
+ || GET_CODE (XVECEXP (op, 0, 0)) != SET
+ || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != MEM
+ || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != REG)
+ return 0;
+
+ src_regno = REGNO (SET_SRC (XVECEXP (op, 0, 0)));
+ dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, 0)), 0);
+
+ for (i = 1; i < count; i++)
+ {
+ rtx elt = XVECEXP (op, 0, i);
+
+ if (GET_CODE (elt) != SET
+ || GET_CODE (SET_SRC (elt)) != REG
+ || GET_MODE (SET_SRC (elt)) != Pmode
+ || REGNO (SET_SRC (elt)) != src_regno + i
+ || GET_CODE (SET_DEST (elt)) != MEM
+ || GET_MODE (SET_DEST (elt)) != Pmode
+ || GET_CODE (XEXP (SET_DEST (elt), 0)) != PLUS
+ || ! rtx_equal_p (XEXP (XEXP (SET_DEST (elt), 0), 0), dest_addr)
+ || GET_CODE (XEXP (XEXP (SET_DEST (elt), 0), 1)) != CONST_INT
+ || INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1)) != i * 4)
+ return 0;
+ }
+ return 1;
+}
+
+
+/* Returns 1 if OP contains a symbol reference */
+
+int
+symbolic_reference_mentioned_p (op)
+ rtx op;
+{
+ register char *fmt;
+ register int i;
+
+ if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF)
+ return 1;
+
+ fmt = GET_RTX_FORMAT (GET_CODE (op));
+ for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
+ {
+ if (fmt[i] == 'E')
+ {
+ register int j;
+
+ for (j = XVECLEN (op, i) - 1; j >= 0; j--)
+ if (symbolic_reference_mentioned_p (XVECEXP (op, i, j)))
+ return 1;
+ }
+
+ else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i)))
+ return 1;
+ }
+
+ return 0;
+}
+
+
+/* Returns 1 if OP is a legitimate general operand when
+ generating PIC code. It is given that flag_pic is on
+ and that OP satisfies CONSTANT_P or is a CONST_DOUBLE. */
+
+int
+legitimate_pic_operand_p (op)
+ register rtx op;
+{
+ /* All non-symbolic constants that made it
+ up to here are fine. */
+ if (!SYMBOLIC_CONST (op))
+ return 1;
+
+ /* Accept immediate LARL operands. */
+ if (TARGET_64BIT)
+ return larl_operand (op, VOIDmode);
+
+ /* Reject everything else; must be handled
+ via emit_pic_move. */
+ return 0;
+}
+
+/* Returns 1 if the constant value OP is a legitimate general operand.
+ It is given that OP satisfies CONSTANT_P or is a CONST_DOUBLE. */
+
+int
+legitimate_constant_p (op)
+ register rtx op;
+{
+ /* Reject doubles and integers out of range. */
+ if (GET_CODE (op) == CONST_DOUBLE ||
+ (GET_CODE (op) == CONST_INT &&
+ (INTVAL (op) < -32768 || INTVAL (op) > 32767)))
+ return 0;
+
+ /* Accept all other non-symbolic constants. */
+ if (!SYMBOLIC_CONST (op))
+ return 1;
+
+ /* In the PIC case, symbolic constants must *not* be
+ forced into the literal pool. We accept them here,
+ so that they will be handled by emit_pic_move. */
+ if (flag_pic)
+ return 1;
+
+ /* Even in the non-PIC case, we can accept immediate
+ LARL operands here. */
+ if (TARGET_64BIT)
+ return larl_operand (op, VOIDmode);
+
+ /* All remaining non-PIC symbolic constants are
+ forced into the literal pool. */
+ return 0;
+}
+
+
+/* Structure used to hold the components of a S/390 memory
+ address. A legitimate address on S/390 is of the general
+ form
+ base + index + displacement
+ where any of the components is optional.
+
+ base and index are registers of the class ADDR_REGS,
+ displacement is an unsigned 12-bit immediate constant. */
+
+struct s390_address
+{
+ rtx base;
+ rtx indx;
+ rtx disp;
+};
+
+/* Decompose a RTL expression ADDR for a memory address into
+ its components, returned in OUT. The boolean STRICT
+ specifies whether strict register checking applies.
+ Returns 0 if ADDR is not a valid memory address, nonzero
+ otherwise. If OUT is NULL, don't return the components,
+ but check for validity only.
+
+ Note: Only addresses in canonical form are recognized.
+ LEGITIMIZE_ADDRESS should convert non-canonical forms to the
+ canonical form so that they will be recognized. */
+
+static int
+s390_decompose_address (addr, out, strict)
+ register rtx addr;
+ struct s390_address *out;
+ int strict;
+{
+ rtx base = NULL_RTX;
+ rtx indx = NULL_RTX;
+ rtx disp = NULL_RTX;
+
+ /* Decompose address into base + index + displacement. */
+
+ if (GET_CODE (addr) == REG || GET_CODE (addr) == UNSPEC)
+ base = addr;
+
+ else if (GET_CODE (addr) == PLUS)
+ {
+ rtx op0 = XEXP (addr, 0);
+ rtx op1 = XEXP (addr, 1);
+ enum rtx_code code0 = GET_CODE (op0);
+ enum rtx_code code1 = GET_CODE (op1);
+
+ if (code0 == REG || code0 == UNSPEC)
+ {
+ if (code1 == REG || code1 == UNSPEC)
+ {
+ indx = op0; /* index + base */
+ base = op1;
+ }
+
+ else
+ {
+ base = op0; /* base + displacement */
+ disp = op1;
+ }
+ }
+
+ else if (code0 == PLUS)
+ {
+ indx = XEXP (op0, 0); /* index + base + disp */
+ base = XEXP (op0, 1);
+ disp = op1;
+ }
+
+ else
+ {
+ return FALSE;
+ }
+ }
+
+ else
+ disp = addr; /* displacement */
+
+
+ /* Validate base register. */
+ if (base)
+ {
+ if (GET_CODE (base) == UNSPEC)
+ {
+ if (XVECLEN (base, 0) != 1 || XINT (base, 1) != 101)
+ return FALSE;
+ base = XVECEXP (base, 0, 0);
+ }
+
+ if (GET_CODE (base) != REG || GET_MODE (base) != Pmode)
+ return FALSE;
+
+ if ((strict && ! REG_OK_FOR_BASE_STRICT_P (base))
+ || (! strict && ! REG_OK_FOR_BASE_NONSTRICT_P (base)))
+ return FALSE;
+ }
+
+ /* Validate index register. */
+ if (indx)
+ {
+ if (GET_CODE (indx) == UNSPEC)
+ {
+ if (XVECLEN (indx, 0) != 1 || XINT (indx, 1) != 101)
+ return FALSE;
+ indx = XVECEXP (indx, 0, 0);
+ }
+
+ if (GET_CODE (indx) != REG || GET_MODE (indx) != Pmode)
+ return FALSE;
+
+ if ((strict && ! REG_OK_FOR_BASE_STRICT_P (indx))
+ || (! strict && ! REG_OK_FOR_BASE_NONSTRICT_P (indx)))
+ return FALSE;
+ }
+
+ /* Validate displacement. */
+ if (disp)
+ {
+ /* Allow integer constant in range. */
+ if (GET_CODE (disp) == CONST_INT)
+ {
+ if (INTVAL (disp) < 0 || INTVAL (disp) >= 4096)
+ return FALSE;
+ }
+
+ /* In the small-PIC case, the linker converts @GOT12
+ offsets to possible displacements. */
+ else if (GET_CODE (disp) == CONST
+ && GET_CODE (XEXP (disp, 0)) == UNSPEC
+ && XINT (XEXP (disp, 0), 1) == 110)
+ {
+ if (flag_pic != 1)
+ return FALSE;
+ }
+
+ /* We can convert literal pool addresses to
+ displacements by basing them off the base register. */
+ else
+ {
+ /* In some cases, we can accept an additional
+ small constant offset. Split these off here. */
+
+ int offset = 0;
+
+ if (GET_CODE (disp) == CONST
+ && GET_CODE (XEXP (disp, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (disp, 0), 1)) == CONST_INT)
+ {
+ offset = INTVAL (XEXP (XEXP (disp, 0), 1));
+ disp = XEXP (XEXP (disp, 0), 0);
+ }
+
+ /* Now we must have a literal pool address. */
+ if (GET_CODE (disp) != SYMBOL_REF
+ || !CONSTANT_POOL_ADDRESS_P (disp))
+ return FALSE;
+
+ /* In 64-bit PIC mode we cannot accept symbolic
+ constants in the constant pool. */
+ if (TARGET_64BIT && flag_pic
+ && SYMBOLIC_CONST (get_pool_constant (disp)))
+ return FALSE;
+
+ /* If we have an offset, make sure it does not
+ exceed the size of the constant pool entry. */
+ if (offset && offset >= GET_MODE_SIZE (get_pool_mode (disp)))
+ return FALSE;
+
+ /* Either base or index must be free to
+ hold the base register. */
+ if (base && indx)
+ return FALSE;
+
+ /* Convert the address. */
+ if (base)
+ indx = gen_rtx_REG (Pmode, BASE_REGISTER);
+ else
+ base = gen_rtx_REG (Pmode, BASE_REGISTER);
+
+ disp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, disp), 100);
+ disp = gen_rtx_CONST (Pmode, disp);
+
+ if (offset)
+ disp = plus_constant (disp, offset);
+ }
+ }
+
+ if (out)
+ {
+ out->base = base;
+ out->indx = indx;
+ out->disp = disp;
+ }
+
+ return TRUE;
+}
+
+/* Returns nonzero if ADDR is a valid memory address.
+ STRICT specifies whether strict register checking applies. */
+
+int
+legitimate_address_p (mode, addr, strict)
+ enum machine_mode mode;
+ register rtx addr;
+ int strict;
+{
+ return s390_decompose_address (addr, NULL, strict);
+}
+
+/* Return a legitimate reference for ORIG (an address) using the
+ register REG. If REG is 0, a new pseudo is generated.
+
+ There are two types of references that must be handled:
+
+ 1. Global data references must load the address from the GOT, via
+ the PIC reg. An insn is emitted to do this load, and the reg is
+ returned.
+
+ 2. Static data references, constant pool addresses, and code labels
+ compute the address as an offset from the GOT, whose base is in
+ the PIC reg. Static data objects have SYMBOL_REF_FLAG set to
+ differentiate them from global data objects. The returned
+ address is the PIC reg + an unspec constant.
+
+ GO_IF_LEGITIMATE_ADDRESS rejects symbolic references unless the PIC
+ reg also appears in the address. */
+
+rtx
+legitimize_pic_address (orig, reg)
+ rtx orig;
+ rtx reg;
+{
+ rtx addr = orig;
+ rtx new = orig;
+ rtx base;
+
+ if (GET_CODE (addr) == LABEL_REF
+ || (GET_CODE (addr) == SYMBOL_REF
+ && (SYMBOL_REF_FLAG (addr)
+ || CONSTANT_POOL_ADDRESS_P (addr))))
+ {
+ /* This is a local symbol. */
+ if (TARGET_64BIT)
+ {
+ /* Access local symbols PC-relative via LARL.
+ This is the same as in the non-PIC case, so it is
+ handled automatically ... */
+ }
+ else
+ {
+ /* Access local symbols relative to the literal pool. */
+
+ rtx temp = reg? reg : gen_reg_rtx (Pmode);
+
+ addr = gen_rtx_UNSPEC (SImode, gen_rtvec (1, addr), 100);
+ addr = gen_rtx_CONST (SImode, addr);
+ addr = force_const_mem (SImode, addr);
+ emit_move_insn (temp, addr);
+
+ base = gen_rtx_REG (Pmode, BASE_REGISTER);
+ base = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, base), 101);
+ new = gen_rtx_PLUS (Pmode, base, temp);
+
+ if (reg != 0)
+ {
+ emit_move_insn (reg, new);
+ new = reg;
+ }
+ }
+ }
+ else if (GET_CODE (addr) == SYMBOL_REF)
+ {
+ if (reg == 0)
+ reg = gen_reg_rtx (Pmode);
+
+ if (flag_pic == 1)
+ {
+ /* Assume GOT offset < 4k. This is handled the same way
+ in both 31- and 64-bit code (@GOT12). */
+
+ current_function_uses_pic_offset_table = 1;
+
+ new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), 110);
+ new = gen_rtx_CONST (Pmode, new);
+ new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new);
+ new = gen_rtx_MEM (Pmode, new);
+ RTX_UNCHANGING_P (new) = 1;
+ emit_move_insn (reg, new);
+ new = reg;
+ }
+ else if (TARGET_64BIT)
+ {
+ /* If the GOT offset might be >= 4k, we determine the position
+ of the GOT entry via a PC-relative LARL (@GOTENT). */
+
+ rtx temp = gen_reg_rtx (Pmode);
+
+ new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), 111);
+ new = gen_rtx_CONST (Pmode, new);
+ emit_move_insn (temp, new);
+
+ new = gen_rtx_MEM (Pmode, temp);
+ RTX_UNCHANGING_P (new) = 1;
+ emit_move_insn (reg, new);
+ new = reg;
+ }
+ else
+ {
+ /* If the GOT offset might be >= 4k, we have to load it
+ from the literal pool (@GOT). */
+
+ rtx temp = gen_reg_rtx (Pmode);
+
+ current_function_uses_pic_offset_table = 1;
+
+ addr = gen_rtx_UNSPEC (SImode, gen_rtvec (1, addr), 112);
+ addr = gen_rtx_CONST (SImode, addr);
+ addr = force_const_mem (SImode, addr);
+ emit_move_insn (temp, addr);
+
+ new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, temp);
+ new = gen_rtx_MEM (Pmode, new);
+ RTX_UNCHANGING_P (new) = 1;
+ emit_move_insn (reg, new);
+ new = reg;
+ }
+ }
+ else
+ {
+ if (GET_CODE (addr) == CONST)
+ {
+ addr = XEXP (addr, 0);
+ if (GET_CODE (addr) == UNSPEC)
+ {
+ if (XVECLEN (addr, 0) != 1)
+ abort ();
+ switch (XINT (addr, 1))
+ {
+ /* If someone moved an @GOT or lt-relative UNSPEC
+ out of the literal pool, force them back in. */
+ case 100:
+ case 112:
+ case 114:
+ new = force_const_mem (SImode, orig);
+ break;
+
+ /* @GOTENT is OK as is. */
+ case 111:
+ break;
+
+ /* @PLT is OK as is on 64-bit, must be converted to
+ lt-relative PLT on 31-bit. */
+ case 113:
+ if (!TARGET_64BIT)
+ {
+ rtx temp = reg? reg : gen_reg_rtx (Pmode);
+
+ addr = XVECEXP (addr, 0, 0);
+ addr = gen_rtx_UNSPEC (SImode, gen_rtvec (1, addr), 114);
+ addr = gen_rtx_CONST (SImode, addr);
+ addr = force_const_mem (SImode, addr);
+ emit_move_insn (temp, addr);
+
+ base = gen_rtx_REG (Pmode, BASE_REGISTER);
+ base = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, base), 101);
+ new = gen_rtx_PLUS (Pmode, base, temp);
+
+ if (reg != 0)
+ {
+ emit_move_insn (reg, new);
+ new = reg;
+ }
+ }
+ break;
+
+ /* Everything else cannot happen. */
+ default:
+ abort ();
+ }
+ }
+ else if (GET_CODE (addr) != PLUS)
+ abort ();
+ }
+ if (GET_CODE (addr) == PLUS)
+ {
+ rtx op0 = XEXP (addr, 0), op1 = XEXP (addr, 1);
+ /* Check first to see if this is a constant offset
+ from a local symbol reference. */
+ if ((GET_CODE (op0) == LABEL_REF
+ || (GET_CODE (op0) == SYMBOL_REF
+ && (SYMBOL_REF_FLAG (op0)
+ || CONSTANT_POOL_ADDRESS_P (op0))))
+ && GET_CODE (op1) == CONST_INT)
+ {
+ if (TARGET_64BIT)
+ {
+ if (INTVAL (op1) & 1)
+ {
+ /* LARL can't handle odd offsets, so emit a
+ pair of LARL and LA. */
+ rtx temp = reg? reg : gen_reg_rtx (Pmode);
+
+ if (INTVAL (op1) < 0 || INTVAL (op1) >= 4096)
+ {
+ int even = INTVAL (op1) - 1;
+ op0 = gen_rtx_PLUS (Pmode, op0, GEN_INT (even));
+ op1 = GEN_INT (1);
+ }
+
+ emit_move_insn (temp, op0);
+ new = gen_rtx_PLUS (Pmode, temp, op1);
+
+ if (reg != 0)
+ {
+ emit_move_insn (reg, new);
+ new = reg;
+ }
+ }
+ else
+ {
+ /* If the offset is even, we can just use LARL.
+ This will happen automatically. */
+ }
+ }
+ else
+ {
+ /* Access local symbols relative to the literal pool. */
+
+ rtx temp = reg? reg : gen_reg_rtx (Pmode);
+
+ addr = gen_rtx_UNSPEC (SImode, gen_rtvec (1, op0), 100);
+ addr = gen_rtx_PLUS (SImode, addr, op1);
+ addr = gen_rtx_CONST (SImode, addr);
+ addr = force_const_mem (SImode, addr);
+ emit_move_insn (temp, addr);
+
+ base = gen_rtx_REG (Pmode, BASE_REGISTER);
+ base = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, base), 101);
+ new = gen_rtx_PLUS (Pmode, base, temp);
+
+ if (reg != 0)
+ {
+ emit_move_insn (reg, new);
+ new = reg;
+ }
+ }
+ }
+
+ /* Now, check whether it is an LT-relative symbol plus offset
+ that was pulled out of the literal pool. Force it back in. */
+
+ else if (GET_CODE (op0) == UNSPEC
+ && GET_CODE (op1) == CONST_INT)
+ {
+ if (XVECLEN (op0, 0) != 1)
+ abort ();
+ if (XINT (op0, 1) != 100)
+ abort ();
+
+ new = force_const_mem (SImode, orig);
+ }
+
+ /* Otherwise, compute the sum. */
+ else
+ {
+ base = legitimize_pic_address (XEXP (addr, 0), reg);
+ new = legitimize_pic_address (XEXP (addr, 1),
+ base == reg ? NULL_RTX : reg);
+ if (GET_CODE (new) == CONST_INT)
+ new = plus_constant (base, INTVAL (new));
+ else
+ {
+ if (GET_CODE (new) == PLUS && CONSTANT_P (XEXP (new, 1)))
+ {
+ base = gen_rtx_PLUS (Pmode, base, XEXP (new, 0));
+ new = XEXP (new, 1);
+ }
+ new = gen_rtx_PLUS (Pmode, base, new);
+ }
+
+ if (GET_CODE (new) == CONST)
+ new = XEXP (new, 0);
+ new = force_operand (new, 0);
+ }
+ }
+ }
+ return new;
+}
+
+/* Emit insns to move operands[1] into operands[0]. */
+
+void
+emit_pic_move (operands, mode)
+ rtx *operands;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+ rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
+
+ if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1]))
+ operands[1] = force_reg (Pmode, operands[1]);
+ else
+ operands[1] = legitimize_pic_address (operands[1], temp);
+}
+
+/* Try machine-dependent ways of modifying an illegitimate address
+ to be legitimate. If we find one, return the new, valid address.
+ This macro is used in only one place: `memory_address' in explow.c.
+
+ OLDX is the address as it was before break_out_memory_refs was called.
+ In some cases it is useful to look at this to decide what needs to be done.
+
+ MODE and WIN are passed so that this macro can use
+ GO_IF_LEGITIMATE_ADDRESS.
+
+ It is always safe for this macro to do nothing. It exists to recognize
+ opportunities to optimize the output.
+
+ When -fpic is used, special handling is needed for symbolic references.
+ See comments by legitimize_pic_address for details. */
+
+rtx
+legitimize_address (x, oldx, mode)
+ register rtx x;
+ register rtx oldx ATTRIBUTE_UNUSED;
+ enum machine_mode mode;
+{
+ if (flag_pic && SYMBOLIC_CONST (x))
+ return legitimize_pic_address (x, 0);
+
+ return x;
+}
+
+
+/* Output branch condition code of RTX code in assembler
+ syntax to stdio stream FILE. */
+
+static void
+output_branch_condition (FILE *file, rtx code)
+{
+ switch (GET_CODE (code))
+ {
+ case EQ:
+ fprintf (file, "e");
+ break;
+ case NE:
+ fprintf (file, "ne");
+ break;
+ case GT:
+ case GTU:
+ fprintf (file, "h");
+ break;
+ case LT:
+ case LTU:
+ fprintf (file, "l");
+ break;
+ case GE:
+ case GEU:
+ fprintf (file, "he");
+ break;
+ case LE:
+ case LEU:
+ fprintf (file, "le");
+ break;
+ default:
+ fatal_insn ("Unknown CC code", code);
+ }
+}
+
+/* Output the inverse of the branch condition code of RTX code
+ in assembler syntax to stdio stream FILE. */
+
+static void
+output_inverse_branch_condition (FILE *file, rtx code)
+{
+ switch (GET_CODE (code))
+ {
+ case EQ:
+ fprintf (file, "ne");
+ break;
+ case NE:
+ fprintf (file, "e");
+ break;
+ case GT:
+ case GTU:
+ fprintf (file, "nh");
+ break;
+ case LT:
+ case LTU:
+ fprintf (file, "nl");
+ break;
+ case GE:
+ case GEU:
+ fprintf (file, "nhe");
+ break;
+ case LE:
+ case LEU:
+ fprintf (file, "nle");
+ break;
+ default:
+ fatal_insn ("Unknown CC code", code);
+ }
+}
+
+/* Output symbolic constant X in assembler syntax to
+ stdio stream FILE. */
+
+void
+s390_output_symbolic_const (FILE *file, rtx x)
+{
+ switch (GET_CODE (x))
+ {
+ case CONST:
+ case ZERO_EXTEND:
+ case SIGN_EXTEND:
+ s390_output_symbolic_const (file, XEXP (x, 0));
+ break;
+
+ case PLUS:
+ s390_output_symbolic_const (file, XEXP (x, 0));
+ fprintf (file, "+");
+ s390_output_symbolic_const (file, XEXP (x, 1));
+ break;
+
+ case MINUS:
+ s390_output_symbolic_const (file, XEXP (x, 0));
+ fprintf (file, "-");
+ s390_output_symbolic_const (file, XEXP (x, 1));
+ break;
+
+ case CONST_INT:
+ output_addr_const (file, x);
+ break;
+
+ case LABEL_REF:
+ case CODE_LABEL:
+ output_addr_const (file, x);
+ break;
+
+ case SYMBOL_REF:
+ output_addr_const (file, x);
+ if (CONSTANT_POOL_ADDRESS_P (x) && s390_pool_count != 0)
+ fprintf (file, "_%X", s390_pool_count);
+ break;
+
+ case UNSPEC:
+ if (XVECLEN (x, 0) != 1)
+ output_operand_lossage ("invalid UNSPEC as operand (1)");
+ switch (XINT (x, 1))
+ {
+ case 100:
+ s390_output_symbolic_const (file, XVECEXP (x, 0, 0));
+ fprintf (file, "-.LT%X_%X",
+ s390_function_count, s390_pool_count);
+ break;
+ case 110:
+ s390_output_symbolic_const (file, XVECEXP (x, 0, 0));
+ fprintf (file, "@GOT12");
+ break;
+ case 111:
+ s390_output_symbolic_const (file, XVECEXP (x, 0, 0));
+ fprintf (file, "@GOTENT");
+ break;
+ case 112:
+ s390_output_symbolic_const (file, XVECEXP (x, 0, 0));
+ fprintf (file, "@GOT");
+ break;
+ case 113:
+ s390_output_symbolic_const (file, XVECEXP (x, 0, 0));
+ fprintf (file, "@PLT");
+ break;
+ case 114:
+ s390_output_symbolic_const (file, XVECEXP (x, 0, 0));
+ fprintf (file, "@PLT-.LT%X_%X",
+ s390_function_count, s390_pool_count);
+ break;
+ default:
+ output_operand_lossage ("invalid UNSPEC as operand (2)");
+ break;
+ }
+ break;
+
+ default:
+ fatal_insn ("UNKNOWN in s390_output_symbolic_const !?", x);
+ break;
+ }
+}
+
+/* Output address operand ADDR in assembler syntax to
+ stdio stream FILE. */
+
+void
+print_operand_address (FILE *file, rtx addr)
+{
+ struct s390_address ad;
+
+ if (!s390_decompose_address (addr, &ad, TRUE))
+ output_operand_lossage ("Cannot decompose address.\n");
+
+ if (ad.disp)
+ s390_output_symbolic_const (file, ad.disp);
+ else
+ fprintf (file, "0");
+
+ if (ad.base && ad.indx)
+ fprintf (file, "(%s,%s)", reg_names[REGNO (ad.indx)],
+ reg_names[REGNO (ad.base)]);
+ else if (ad.base)
+ fprintf (file, "(%s)", reg_names[REGNO (ad.base)]);
+}
+
+/* Output operand X in assembler syntax to stdio stream FILE.
+ The following format flags are recognized as CODE:
+
+ 'C': print opcode suffix for branch condition.
+ 'D': print opcode suffix for inverse branch condition.
+ 'Y': print current constant pool address (pc-relative).
+ 'y': print current constant pool address (absolute).
+ 'O': print only the displacement of a memory reference.
+ 'R': print only the base register of a memory reference.
+ 'N': print the second word of a DImode operand.
+ 'M': print the second word of a TImode operand.
+
+ 'b': print integer X as if it's a unsigned byte.
+ 'x': print integer X as if it's a unsigned word.
+ 'h': print integer X as if it's a signed word. */
+
+void
+print_operand (FILE *file, rtx x, char code)
+{
+ switch (code)
+ {
+ case 'C':
+ output_branch_condition (file, x);
+ return;
+
+ case 'D':
+ output_inverse_branch_condition (file, x);
+ return;
+
+ case 'Y':
+ fprintf (file, ".LT%X_%X-.", s390_function_count, s390_pool_count);
+ return;
+
+ case 'y':
+ fprintf (file, ".LT%X_%X", s390_function_count, s390_pool_count);
+ return;
+
+ case 'O':
+ {
+ struct s390_address ad;
+
+ if (GET_CODE (x) != MEM
+ || !s390_decompose_address (XEXP (x, 0), &ad, TRUE)
+ || ad.indx)
+ abort ();
+
+ if (ad.disp)
+ s390_output_symbolic_const (file, ad.disp);
+ else
+ fprintf (file, "0");
+ }
+ return;
+
+ case 'R':
+ {
+ struct s390_address ad;
+
+ if (GET_CODE (x) != MEM
+ || !s390_decompose_address (XEXP (x, 0), &ad, TRUE)
+ || ad.indx)
+ abort ();
+
+ if (ad.base)
+ fprintf (file, "%s", reg_names[REGNO (ad.base)]);
+ else
+ fprintf (file, "0");
+ }
+ return;
+
+ case 'N':
+ if (GET_CODE (x) == REG)
+ x = gen_rtx_REG (GET_MODE (x), REGNO (x) + 1);
+ else if (GET_CODE (x) == MEM)
+ x = change_address (x, VOIDmode, plus_constant (XEXP (x, 0), 4));
+ else
+ abort ();
+ break;
+
+ case 'M':
+ if (GET_CODE (x) == REG)
+ x = gen_rtx_REG (GET_MODE (x), REGNO (x) + 1);
+ else if (GET_CODE (x) == MEM)
+ x = change_address (x, VOIDmode, plus_constant (XEXP (x, 0), 8));
+ else
+ abort ();
+ break;
+ }
+
+ switch (GET_CODE (x))
+ {
+ case REG:
+ fprintf (file, "%s", reg_names[REGNO (x)]);
+ break;
+
+ case MEM:
+ output_address (XEXP (x, 0));
+ break;
+
+ case CONST:
+ case CODE_LABEL:
+ case LABEL_REF:
+ case SYMBOL_REF:
+ s390_output_symbolic_const (file, x);
+ break;
+
+ case CONST_INT:
+ if (code == 'b')
+ fprintf (file, "%d", INTVAL (x) & 0xff);
+ else if (code == 'X')
+ fprintf (file, "%d", INTVAL (x) & 0xff);
+ else if (code == 'x')
+ fprintf (file, "0x%x", INTVAL (x) & 0xffff);
+ else if (code == 'h')
+ fprintf (file, "%d", (INTVAL (x) << 16) >> 16);
+ else
+ fprintf (file, "%d", INTVAL (x));
+ break;
+
+ default:
+ fatal_insn ("UNKNOWN in print_operand !?", x);
+ break;
+ }
+}
+
+#define DEBUG_SCHED 0
+
+/* Returns true if register REGNO is used for forming
+ a memory address in expression X. */
+
+static int
+reg_used_in_mem_p (int regno, rtx x)
+{
+ enum rtx_code code = GET_CODE (x);
+ int i, j;
+ const char *fmt;
+
+ if (code == MEM)
+ {
+ if (refers_to_regno_p (regno, regno+1,
+ XEXP (x, 0), 0))
+ return 1;
+ }
+
+ fmt = GET_RTX_FORMAT (code);
+ for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+ {
+ if (fmt[i] == 'e'
+ && reg_used_in_mem_p (regno, XEXP (x, i)))
+ return 1;
+
+ else if (fmt[i] == 'E')
+ for (j = 0; j < XVECLEN (x, i); j++)
+ if (reg_used_in_mem_p (regno, XVECEXP (x, i, j)))
+ return 1;
+ }
+ return 0;
+}
+
+/* Returns true if expression DEP_RTX sets a address register
+ used by instruction INSN to address memory. */
+
+static int
+addr_generation_dependency_p (rtx dep_rtx, rtx insn)
+{
+ rtx target;
+
+ if (GET_CODE (dep_rtx) == SET)
+ {
+ target = SET_DEST (dep_rtx);
+
+ if (GET_CODE (target) == REG)
+ {
+ int regno = REGNO (target);
+
+ if (get_attr_type (insn) == TYPE_LA)
+ return refers_to_regno_p (regno, regno+1,
+ SET_SRC (PATTERN (insn)), 0);
+ else if (get_attr_atype (insn) == ATYPE_MEM)
+ return reg_used_in_mem_p (regno, PATTERN (insn));
+ }
+ }
+ return 0;
+}
+
+
+/* Data dependencies are all handled without delay. But if an register
+ is changed for a memory access, at least 4 cycle need to be put
+ between the set of the register and the use. Because of that,
+ the delays specified in the .md file needs to check and adjust
+ to the right cost. */
+
+int
+s390_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
+{
+ rtx dep_rtx, dest, x;
+ int i;
+
+ /* If the dependence is an anti-dependence, there is no cost. For an
+ output dependence, there is sometimes a cost, but it doesn't seem
+ worth handling those few cases. */
+
+ if (REG_NOTE_KIND (link) != 0)
+ return 0;
+
+ /* If we can't recognize the insns, we can't really do anything. */
+ if (recog_memoized (insn) < 0 || recog_memoized (dep_insn) < 0)
+ return cost;
+
+ /* If cost equal 1 nothing needs to be checked. */
+
+ if (cost == 1)
+ {
+ return cost;
+ }
+
+ dep_rtx = PATTERN (dep_insn);
+
+ if (GET_CODE (dep_rtx) == SET)
+ {
+ if (addr_generation_dependency_p (dep_rtx, insn))
+ {
+ if (DEBUG_SCHED)
+ {
+ fprintf (stderr, "\n\nAddress dependency detected: cost %d\n",
+ cost);
+ debug_rtx (dep_insn);
+ debug_rtx (insn);
+ }
+ return cost;
+ }
+ }
+
+ else if (GET_CODE (dep_rtx) == PARALLEL)
+ {
+ for (i = 0; i < XVECLEN (dep_rtx, 0); i++)
+ {
+ if (addr_generation_dependency_p (XVECEXP (dep_rtx, 0, i),
+ insn))
+ {
+ if (DEBUG_SCHED)
+ {
+ fprintf (stderr, "\n\nAddress dependency detected: cost %d\n"
+ ,cost);
+ debug_rtx (dep_insn);
+ debug_rtx (insn);
+ }
+ return cost;
+ }
+ }
+ }
+
+ /* default cost. */
+ return 1;
+}
+
+/* Pool concept for Linux 390:
+ - Function prologue saves used register
+ - literal pool is dumped in prologue and jump across with bras
+ - If function has more than 4 k literals, at about every
+ S390_CHUNK_MAX offset in the function a literal pool will be
+ dumped
+ - in this case, a branch from one chunk to other chunk needs
+ a reload of base register at the code label branched to. */
+
+rtx s390_pool_start_insn = NULL_RTX;
+
+/* Count of actual pool in function (-1 -> before function). */
+
+int s390_pool_count = -1;
+
+static int pool_stop_uid;
+
+/* Called from the ASM_OUTPUT_POOL_PROLOGUE macro to
+ prepare for printing a literal pool chunk. */
+
+void
+s390_asm_output_pool_prologue (FILE *file, char *fname, tree fndecl, int size)
+{
+
+ if (s390_pool_count>0) {
+ /*
+ * We are in an internal pool, branch over
+ */
+ if (TARGET_64BIT)
+ {
+ fprintf (file, "\tlarl\t%s,.LT%X_%X\n",
+ reg_names[BASE_REGISTER],
+ s390_function_count, s390_pool_count);
+ readonly_data_section ();
+ ASM_OUTPUT_ALIGN (file, floor_log2 (3));
+ fprintf (file, ".LT%X_%X:\t# Pool %d\n",
+ s390_function_count, s390_pool_count, s390_pool_count);
+ }
+ else
+ fprintf (file,"\t.align 4\n\tbras\t%s,0f\n.LT%X_%X:\t# Pool %d \n",
+ reg_names[BASE_REGISTER],
+ s390_function_count, s390_pool_count, s390_pool_count);
+ }
+ if (!TARGET_64BIT)
+ function_section (fndecl);
+}
+
+/* Return 1 if OTHER_ADDR is in different chunk than MY_ADDR.
+ LTORG points to a list of all literal pools inserted
+ into the current function. */
+
+static int
+other_chunk (int *ltorg, int my_addr, int other_addr)
+{
+ int ad, i=0, j=0;
+
+ while ((ad = ltorg[i++])) {
+ if (INSN_ADDRESSES (ad) >= my_addr)
+ break;
+ }
+
+ while ((ad = ltorg[j++])) {
+ if (INSN_ADDRESSES (ad) > other_addr)
+ break;
+ }
+
+ if (i==j)
+ return 0;
+
+ return 1;
+}
+
+/* Return 1 if OTHER_ADDR is too far away from MY_ADDR
+ to use a relative branch instruction. */
+
+static int
+far_away (int my_addr, int other_addr)
+{
+ /* In 64 bit mode we can jump +- 4GB. */
+ if (TARGET_64BIT)
+ return 0;
+ if (abs (my_addr - other_addr) > S390_REL_MAX)
+ return 1;
+ return 0;
+}
+
+/* Go through all insns in the current function (starting
+ at INSN), replacing branch insn if necessary. A branch
+ needs to be modified if either the distance to the
+ target is too far to use a relative branch, or if the
+ target uses a different literal pool than the origin.
+ LTORG_UIDS points to a list of all literal pool insns
+ that have been inserted. */
+
+static rtx
+check_and_change_labels (rtx insn, int *ltorg_uids)
+{
+ rtx temp_reg = gen_rtx_REG (Pmode, RETURN_REGNUM);
+ rtx target, jump;
+ rtx pattern, tmp, body, label1;
+ int addr0, addr1;
+
+ if (GET_CODE (insn) != JUMP_INSN)
+ return insn;
+
+ pattern = PATTERN (insn);
+
+ addr0 = INSN_ADDRESSES (INSN_UID (insn));
+ if (GET_CODE (pattern) == SET)
+ {
+ body = XEXP (pattern, 1);
+ if (GET_CODE (body) == LABEL_REF)
+ {
+ addr1 = INSN_ADDRESSES (INSN_UID (XEXP (body, 0)));
+
+ if (other_chunk (ltorg_uids, addr0, addr1))
+ {
+ SYMBOL_REF_USED (XEXP (body, 0)) = 1;
+ }
+ if (far_away (addr0, addr1))
+ {
+ if (flag_pic)
+ {
+ target = gen_rtx_UNSPEC (SImode, gen_rtvec (1, body), 100);
+ target = gen_rtx_CONST (SImode, target);
+ target = force_const_mem (SImode, target);
+ jump = gen_rtx_REG (Pmode, BASE_REGISTER);
+ jump = gen_rtx_PLUS (Pmode, jump, temp_reg);
+ }
+ else
+ {
+ target = force_const_mem (Pmode, body);
+ jump = temp_reg;
+ }
+
+ emit_insn_before (gen_movsi (temp_reg, target), insn);
+ tmp = emit_jump_insn_before (gen_indirect_jump (jump), insn);
+ remove_insn (insn);
+ INSN_ADDRESSES_NEW (tmp, -1);
+ return tmp;
+ }
+ }
+ else if (GET_CODE (body) == IF_THEN_ELSE)
+ {
+ if (GET_CODE (XEXP (body, 1)) == LABEL_REF)
+ {
+ addr1 = INSN_ADDRESSES (INSN_UID (XEXP (XEXP (body, 1), 0)));
+
+ if (other_chunk (ltorg_uids, addr0, addr1))
+ {
+ SYMBOL_REF_USED (XEXP (XEXP (body, 1), 0)) = 1;
+ }
+
+ if (far_away (addr0, addr1))
+ {
+ if (flag_pic)
+ {
+ target = gen_rtx_UNSPEC (SImode, gen_rtvec (1, XEXP (body, 1)), 100);
+ target = gen_rtx_CONST (SImode, target);
+ target = force_const_mem (SImode, target);
+ jump = gen_rtx_REG (Pmode, BASE_REGISTER);
+ jump = gen_rtx_PLUS (Pmode, jump, temp_reg);
+ }
+ else
+ {
+ target = force_const_mem (Pmode, XEXP (body, 1));
+ jump = temp_reg;
+ }
+
+ label1 = gen_label_rtx ();
+ emit_jump_insn_before (gen_icjump (label1, XEXP (body, 0)), insn);
+ emit_insn_before (gen_movsi (temp_reg, target), insn);
+ tmp = emit_jump_insn_before (gen_indirect_jump (jump), insn);
+ INSN_ADDRESSES_NEW (emit_label_before (label1, insn), -1);
+ remove_insn (insn);
+ return tmp;
+ }
+ }
+ else if (GET_CODE (XEXP (body, 2)) == LABEL_REF)
+ {
+ addr1 = INSN_ADDRESSES (INSN_UID (XEXP (XEXP (body, 2), 0)));
+
+ if (other_chunk (ltorg_uids, addr0, addr1))
+ {
+ SYMBOL_REF_USED (XEXP (XEXP (body, 2), 0)) = 1;
+ }
+
+ if (far_away (addr0, addr1))
+ {
+ if (flag_pic)
+ {
+ target = gen_rtx_UNSPEC (SImode, gen_rtvec (1, XEXP (body, 2)), 100);
+ target = gen_rtx_CONST (SImode, target);
+ target = force_const_mem (SImode, target);
+ jump = gen_rtx_REG (Pmode, BASE_REGISTER);
+ jump = gen_rtx_PLUS (Pmode, jump, temp_reg);
+ }
+ else
+ {
+ target = force_const_mem (Pmode, XEXP (body, 2));
+ jump = temp_reg;
+ }
+
+ label1 = gen_label_rtx ();
+ emit_jump_insn_before (gen_cjump (label1, XEXP (body, 0)), insn);
+ emit_insn_before (gen_movsi (temp_reg, target), insn);
+ tmp = emit_jump_insn_before (gen_indirect_jump (jump), insn);
+ INSN_ADDRESSES_NEW (emit_label_before (label1, insn), -1);
+ remove_insn (insn);
+ return tmp;
+ }
+ }
+ }
+ }
+ else if (GET_CODE (pattern) == ADDR_VEC ||
+ GET_CODE (pattern) == ADDR_DIFF_VEC)
+ {
+ int i, diff_vec_p = GET_CODE (pattern) == ADDR_DIFF_VEC;
+ int len = XVECLEN (pattern, diff_vec_p);
+
+ for (i = 0; i < len; i++)
+ {
+ addr1 = INSN_ADDRESSES (INSN_UID (XEXP (XVECEXP (pattern, diff_vec_p, i), 0)));
+ if (other_chunk (ltorg_uids, addr0, addr1))
+ {
+ SYMBOL_REF_USED (XEXP (XVECEXP (pattern, diff_vec_p, i), 0)) = 1;
+ }
+ }
+ }
+ return insn;
+}
+
+static int chunk_max=0;
+
+
+/* Called from s390_function_prologue to make final adjustments
+ before outputting code. CHUNKIFY specifies whether we need
+ to use multiple literal pools (because the total size of the
+ literals exceeds 4K). */
+
+void
+s390_final_chunkify (int chunkify)
+{
+ rtx insn, ninsn, tmp;
+ int addr, naddr, uids;
+
+ const char *asms;
+
+ int size = insn_current_address;
+
+ int *ltorg_uids;
+ int max_ltorg=0;
+
+ ltorg_uids = alloca (size / 1024 + 1024);
+ memset (ltorg_uids, 0, size / 1024 + 1024);
+
+ if (chunkify == 1)
+ {
+ chunk_max = size * 2048 / get_pool_size ();
+ chunk_max = chunk_max > S390_CHUNK_MAX
+ ? S390_CHUNK_MAX : chunk_max;
+ }
+
+ for (insn=get_insns (); insn;insn = next_real_insn (insn))
+ {
+ if (GET_RTX_CLASS (GET_CODE (insn)) != 'i')
+ continue;
+
+ addr = INSN_ADDRESSES (INSN_UID (insn));
+ if ((ninsn = next_real_insn (insn)))
+ {
+ naddr = INSN_ADDRESSES (INSN_UID (ninsn));
+ }
+
+ if (chunkify && (addr / chunk_max != naddr / chunk_max))
+ {
+ for (tmp = insn; tmp; tmp = NEXT_INSN (tmp))
+ {
+ if (GET_CODE (tmp) == CODE_LABEL &&
+ GET_CODE (NEXT_INSN (tmp)) != JUMP_INSN)
+ {
+ ltorg_uids[max_ltorg++] = INSN_UID (prev_real_insn (tmp));
+ break;
+ }
+ if (GET_CODE (tmp) == CALL_INSN)
+ {
+ ltorg_uids[max_ltorg++] = INSN_UID (tmp);
+ break;
+ }
+ if (INSN_ADDRESSES (INSN_UID (tmp)) - naddr > S390_CHUNK_OV)
+ {
+ debug_rtx (insn);
+ debug_rtx (tmp);
+ fprintf (stderr, "s390 multiple literalpool support:"
+ "\n No code label between this insn %X %X",
+ naddr, INSN_ADDRESSES (INSN_UID (tmp)));
+ abort ();
+ }
+ }
+ if (tmp == NULL)
+ {
+ warning ("no code label found");
+ }
+ }
+ else if (GET_CODE (PATTERN (insn)) == ASM_INPUT && !TARGET_64BIT)
+ {
+ asms = XSTR (PATTERN (insn),0);
+
+ if ((memcmp (asms,".section",8) == 0) ||
+ (memcmp (asms,".text",5) == 0) ||
+ (memcmp (asms,"\t.section",9) == 0) ||
+ (memcmp (asms,"\t.text",6) == 0)) {
+ ltorg_uids[max_ltorg++] = INSN_UID (insn);
+ INSN_ADDRESSES_NEW (emit_insn_before (gen_rtx_ASM_INPUT (VOIDmode,
+ ".align 4"), insn), -1);
+ }
+ }
+ }
+ ltorg_uids[max_ltorg] = 0;
+ for (insn=get_insns (),uids=0; insn;insn = next_real_insn (insn))
+ {
+ if (GET_RTX_CLASS (GET_CODE (insn)) != 'i')
+ continue;
+ if (INSN_UID (insn) == ltorg_uids[uids])
+ {
+ INSN_ADDRESSES_NEW (emit_insn_after (gen_ltorg (
+ gen_rtx_CONST_INT (Pmode, ltorg_uids[++uids])),
+ insn), -1);
+ }
+ if (GET_CODE (insn) == JUMP_INSN)
+ {
+ insn = check_and_change_labels (insn, ltorg_uids);
+ }
+ }
+ if (chunkify)
+ {
+ for (insn=get_insns (); insn;insn = next_insn (insn))
+ {
+ if (GET_CODE (insn) == CODE_LABEL)
+ {
+ if (SYMBOL_REF_USED (insn))
+ {
+ INSN_ADDRESSES_NEW (emit_insn_after (gen_reload_base (
+ gen_rtx_LABEL_REF (Pmode, XEXP (insn, 0))), insn), -1);
+ }
+ }
+ }
+ }
+ pool_stop_uid = ltorg_uids[0];
+}
+
+/* Return 1 if next literal pool is reached (check for ltorg insn)
+ maybe should use unspec insn. */
+
+int
+s390_stop_dump_lit_p (rtx insn)
+{
+ rtx body=PATTERN (insn);
+ if (GET_CODE (body) == PARALLEL
+ && GET_CODE (XVECEXP (body, 0, 0)) == SET
+ && GET_CODE (XVECEXP (body, 0, 1)) == USE
+ && GET_CODE (XEXP ((XVECEXP (body, 0, 1)),0)) == CONST_INT
+ && GET_CODE (SET_DEST (XVECEXP (body, 0, 0))) == REG
+ && REGNO (SET_DEST (XVECEXP (body, 0, 0))) == BASE_REGISTER
+ && SET_SRC (XVECEXP (body, 0, 0)) == pc_rtx) {
+ return 1;
+ }
+ else
+ return 0;
+}
+
+/* Output literal pool chunk to be used for insns
+ between ACT_INSN and STOP. */
+
+void
+s390_dump_literal_pool (rtx act_insn, rtx stop)
+{
+ s390_pool_start_insn = act_insn;
+ pool_stop_uid = INTVAL (stop);
+ s390_pool_count++;
+ output_constant_pool (current_function_name, current_function_decl);
+ function_section (current_function_decl);
+}
+
+
+#ifdef DWARF2_DEBUGGING_INFO
+extern char *dwarf2out_cfi_label PARAMS ((void));
+#endif
+
+/* Flag set in prologue, used in epilog to know
+ if stack is allocated or not. */
+
+static int leaf_function_flag;
+rtx s390_got_label;
+rtx s390_profile[10];
+int s390_nr_constants;
+
+/* Returns 1 if floating point registers need to be saved. */
+
+static int
+save_fprs_p ()
+{
+ int i;
+ if (!TARGET_64BIT)
+ return 0;
+ for (i=24; i<=31; i++)
+ {
+ if (regs_ever_live[i] == 1)
+ return 1;
+ }
+ return 0;
+}
+
+/* Current function is a leaf function, without automatics,
+ alloca or vararg stuff. */
+
+static int
+cur_is_leaf_function ()
+{
+ int lsize = get_frame_size () + current_function_outgoing_args_size
+ + save_fprs_p () * 64;
+
+ if (leaf_function_p () && ((lsize) == 0) &&
+ ! (current_function_calls_alloca) &&
+ ! (current_function_stdarg) && ! (current_function_varargs))
+ return 1;
+ return 0;
+}
+
+/* Calculate offset between argument pointer and frame pointer
+ initialy after prologue. */
+
+int
+s390_arg_frame_offset ()
+{
+ int lsize = get_frame_size () + current_function_outgoing_args_size
+ + save_fprs_p () * 64;
+
+ if (cur_is_leaf_function ())
+ return STACK_POINTER_OFFSET;
+ else
+ return 2*STACK_POINTER_OFFSET + lsize;
+}
+
+/* Output code to stdio stream FILE to save floating point
+ registers on current stack, at offset OFFSET to the frame
+ pointer register FP. */
+
+static int
+save_fprs (FILE *file, long offset, int fp)
+{
+ int i;
+
+ if (!TARGET_64BIT)
+ return 0;
+
+ for (i=24; i<=31; i++)
+ {
+ if (regs_ever_live[i] == 1)
+ {
+ fprintf (file, "\tstd\t%s,%d(%s)\n", reg_names[i],
+ (i-24) * 8 + offset, reg_names[fp]);
+ }
+ }
+}
+
+/* Output code to stdio stream FILE to restore floating point
+ registers from current stack, at offset OFFSET to the frame
+ pointer register FP. */
+
+static int
+restore_fprs (FILE *file, long offset, int fp)
+{
+ int i;
+
+ if (!TARGET_64BIT)
+ return 0;
+
+ if (!save_fprs_p ())
+ return 0;
+
+ if (offset < 0)
+ {
+ fp = 1;
+ offset = 0;
+ fprintf (file, "\tlgr\t%s,%s\n", reg_names[fp],
+ reg_names[STACK_POINTER_REGNUM]);
+ fprintf (file, "\taghi\t%s,-64\n", reg_names[fp]);
+ }
+
+ for (i=24; i<=31; i++)
+ {
+ if (regs_ever_live[i] == 1)
+ {
+ fprintf (file, "\tld\t%s,%d(%s)\n", reg_names[i],
+ (i-24) * 8 + offset, reg_names[fp]);
+ }
+ }
+}
+
+/* Output constant pool in function prologue (31 bit) or in readonly section. */
+
+static int
+s390_output_constant_pool (FILE* file)
+{
+ /* Output constant pool. */
+ if (s390_nr_constants || regs_ever_live[BASE_REGISTER])
+ {
+ s390_pool_count = 0;
+ if (TARGET_64BIT)
+ {
+ fprintf (file, "\tlarl\t%s,.LT%X_%X\n", reg_names[BASE_REGISTER],
+ s390_function_count, s390_pool_count);
+ readonly_data_section ();
+ ASM_OUTPUT_ALIGN (file, floor_log2 (3));
+ }
+ else
+ {
+ fprintf (file, "\tbras\t%s,.LTN%X_%X\n", reg_names[BASE_REGISTER],
+ s390_function_count, s390_pool_count);
+ }
+ fprintf (file, ".LT%X_%X:\n", s390_function_count, s390_pool_count);
+ output_constant_pool (current_function_name, current_function_decl);
+ fprintf (file, ".LTN%X_%X:\n", s390_function_count,
+ s390_pool_count);
+ if (TARGET_64BIT)
+ function_section (current_function_decl);
+
+ regs_ever_live[BASE_REGISTER] = 1;
+ }
+}
+
+/* Add constant CTX to the constant pool at a late time
+ (after the initial pass to count the number of constants
+ was already done). Returns the resulting constant
+ pool reference. */
+
+static rtx
+s390_force_const_mem_late (rtx cst)
+{
+ cst = force_const_mem (Pmode, cst);
+
+ s390_nr_constants++;
+ regs_ever_live[BASE_REGISTER] = 1;
+
+ emit_insn_before (gen_rtx (USE, Pmode, cst), get_insns ());
+
+ return cst;
+}
+
+/* Add a reference to the symbol NAME to the constant pool.
+ FUNC specifies whether NAME refers to a function, while
+ GLOBAL specifies whether NAME is a global symbol. Depending
+ on these flags, the appopriate PLT or GOT references are
+ generated. Returns the constant pool reference. */
+
+static rtx
+s390_force_const_mem_symbol (char *name, int func, int global)
+{
+ rtx symbol;
+
+ if (TARGET_64BIT)
+ abort ();
+
+ symbol = gen_rtx (SYMBOL_REF, Pmode, name);
+ SYMBOL_REF_FLAG (symbol) = !global;
+
+ if (flag_pic)
+ {
+ if (global)
+ {
+ current_function_uses_pic_offset_table = 1;
+ symbol = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, symbol), func? 114 : 112);
+ symbol = gen_rtx_CONST (VOIDmode, symbol);
+ }
+ else
+ {
+ symbol = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, symbol), 100);
+ symbol = gen_rtx_CONST (VOIDmode, symbol);
+ }
+ }
+
+ return s390_force_const_mem_late (symbol);
+}
+
+/* Output the function prologue assembly code to the
+ stdio stream FILE. The local frame size is passed
+ in LSIZE. */
+
+int
+s390_function_prologue (FILE * file, int lsize)
+{
+ extern int profile_label_no;
+ int i, j;
+ long frame_size;
+ rtx stack_label = 0, got_label = 0, tmp;
+ char *l;
+ char b64[2] = " ";
+ b64[0] = TARGET_64BIT ? 'g' : '\0';
+
+ /* Check for too large size of local variables */
+
+ if (lsize > 0x7fff0000)
+ fatal_error ("Total size of local variables exceeds architecture limit.");
+ /* Profile code (-p, -a, -ax needs some literals). */
+
+ if (profile_block_flag && !TARGET_64BIT)
+ {
+ s390_profile[0] = s390_force_const_mem_symbol ("__bb_init_func", 1, 1);
+ s390_profile[1] = s390_force_const_mem_symbol ("__bb_init_trace_func", 1, 1);
+ s390_profile[2] = s390_force_const_mem_symbol ("__bb_trace_func", 1, 1);
+ s390_profile[3] = s390_force_const_mem_symbol ("__bb_trace_ret", 1, 1);
+ s390_profile[5] = s390_force_const_mem_symbol ("__bb", 0, 1);
+ s390_profile[6] = s390_force_const_mem_symbol (".LPBX0", 0, 0);
+ s390_profile[7] = s390_force_const_mem_symbol (".LPBX2", 0, 0);
+ }
+
+ if (profile_flag && !TARGET_64BIT)
+ {
+ static char label[128];
+ sprintf (label, "%sP%d", LPREFIX, profile_label_no);
+
+ s390_profile[4] = s390_force_const_mem_symbol ("_mcount", 1, 1);
+ s390_profile[9] = s390_force_const_mem_symbol (label, 0, 0);
+ }
+
+ if (get_pool_size () > S390_POOL_MAX)
+ s390_final_chunkify (1);
+ else
+ s390_final_chunkify (0);
+
+ if (current_function_uses_pic_offset_table)
+ regs_ever_live[12] = 1;
+
+ if (!TARGET_64BIT && current_function_uses_pic_offset_table)
+ {
+ got_label = s390_force_const_mem_symbol ("_GLOBAL_OFFSET_TABLE_", 0, 0);
+ }
+
+ if ((frame_size =
+ STARTING_FRAME_OFFSET + lsize + save_fprs_p () * 64) > 0x7fff)
+ {
+ stack_label = s390_force_const_mem_late (GEN_INT (frame_size));
+ }
+
+ if (!optimize)
+ {
+ /* Stupid register allocation is stupid ...
+ It does not always recognize the base register is used. */
+
+ regs_ever_live[BASE_REGISTER] = 1;
+ }
+
+ if (cur_is_leaf_function ())
+ {
+ leaf_function_flag = 1;
+ fprintf (file, "%s\tleaf function\n", ASM_COMMENT_START);
+ fprintf (file, "%s\thas varargs %d\n", ASM_COMMENT_START,
+ current_function_stdarg);
+ fprintf (file, "%s\tincoming args (stack) %d\n", ASM_COMMENT_START,
+ current_function_args_size);
+ fprintf (file, "%s\tfunction length %d\n", ASM_COMMENT_START,
+ insn_current_address);
+ fprintf (file, "%s\tregister live ", ASM_COMMENT_START);
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ fprintf (file, "%d", regs_ever_live[i]);
+ fputc ('\n',file);
+
+ /* Save gprs 6 - 15 and fprs 4 and 6. */
+ for (i = 6; i < 13 && (regs_ever_live[i] == 0); i++);
+
+ if (s390_nr_constants || regs_ever_live[13] || i != 13)
+ {
+ fprintf (file, "\tstm%s\t%s,%s,%d(%s)\n",
+ b64, reg_names[i], reg_names[13],
+ i * UNITS_PER_WORD,
+ reg_names[STACK_POINTER_REGNUM]);
+#ifdef INCOMING_RETURN_ADDR_RTX
+ if (dwarf2out_do_frame ())
+ {
+ l = dwarf2out_cfi_label ();
+ dwarf2out_def_cfa (l, STACK_POINTER_REGNUM,
+ STACK_POINTER_OFFSET);
+ for (j = i; j <= 14; j++)
+ dwarf2out_reg_save (l, j, (TARGET_64BIT ? (j-20) : (j-24))
+ * UNITS_PER_WORD);
+ if (regs_ever_live[18])
+ dwarf2out_reg_save (l, 18, -16);
+ if (regs_ever_live[19])
+ dwarf2out_reg_save (l, 19, -8);
+ }
+#endif
+ }
+
+ s390_output_constant_pool (file);
+
+ /* Save fprs. */
+
+ if (!TARGET_64BIT)
+ {
+ if (regs_ever_live[18])
+ fprintf (file, "\tstd\t4,80(%s)\n", reg_names[STACK_POINTER_REGNUM]);
+ if (regs_ever_live[19])
+ fprintf (file, "\tstd\t6,88(%s)\n", reg_names[STACK_POINTER_REGNUM]);
+ }
+ }
+ else
+ { /* No leaf function. */
+ fprintf (file, "%s\tleaf function %d\n", ASM_COMMENT_START,
+ leaf_function_p ());
+ fprintf (file, "%s\tautomatics %d\n", ASM_COMMENT_START,
+ lsize);
+ fprintf (file, "%s\toutgoing args %d\n", ASM_COMMENT_START,
+ current_function_outgoing_args_size);
+ fprintf (file, "%s\tneed frame pointer %d\n", ASM_COMMENT_START,
+ frame_pointer_needed);
+ fprintf (file, "%s\tcall alloca %d\n", ASM_COMMENT_START,
+ current_function_calls_alloca);
+ fprintf (file, "%s\thas varargs %d\n", ASM_COMMENT_START,
+ current_function_stdarg || current_function_varargs);
+ fprintf (file, "%s\tincoming args (stack) %d\n", ASM_COMMENT_START,
+ current_function_args_size);
+ fprintf (file, "%s\tfunction length %d\n", ASM_COMMENT_START,
+ insn_current_address);
+ fprintf (file, "%s\tregister live ", ASM_COMMENT_START);
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ fprintf (file, "%d", regs_ever_live[i]);
+ fputc ('\n',file);
+
+ /* Save gprs 6 - 15 and fprs 4 and 6. */
+
+ if (current_function_stdarg || current_function_varargs)
+ {
+ i = 2;
+ }
+ else
+ {
+ for (i = 6; i < 13 && (regs_ever_live[i] == 0); i++);
+ }
+
+ fprintf (file, "\tstm%s\t%s,%s,%d(%s)\n",
+ b64, reg_names[i], reg_names[15], i * UNITS_PER_WORD,
+ reg_names[STACK_POINTER_REGNUM]);
+
+#ifdef INCOMING_RETURN_ADDR_RTX
+ if (dwarf2out_do_frame ())
+ {
+ l = dwarf2out_cfi_label ();
+ dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, STACK_POINTER_OFFSET);
+ for (j = i; j <= 15; j++)
+ dwarf2out_reg_save (l, j, (TARGET_64BIT ? (j-20) : (j-24)) *
+ UNITS_PER_WORD);
+ if (regs_ever_live[18])
+ dwarf2out_reg_save (l, 18, -16);
+ if (regs_ever_live[19])
+ dwarf2out_reg_save (l, 19, -8);
+ }
+#endif
+
+ s390_output_constant_pool (file);
+
+ /* Save fprs. */
+
+ if (current_function_stdarg || current_function_varargs)
+ {
+ fprintf (file, "\tstd\t%s,%d(%s)\n",
+ reg_names[16],
+ STACK_POINTER_OFFSET-32,
+ reg_names[STACK_POINTER_REGNUM]);
+ fprintf (file, "\tstd\t%s,%d(%s)\n",
+ reg_names[17],
+ STACK_POINTER_OFFSET-24,
+ reg_names[STACK_POINTER_REGNUM]);
+ if (TARGET_64BIT)
+ {
+ fprintf (file, "\tstd\t%s,%d(%s)\n",
+ reg_names[18],
+ STACK_POINTER_OFFSET-16,
+ reg_names[STACK_POINTER_REGNUM]);
+ fprintf (file, "\tstd\t%s,%d(%s)\n",
+ reg_names[19],
+ STACK_POINTER_OFFSET-8,
+ reg_names[STACK_POINTER_REGNUM]);
+ }
+ }
+ if (!TARGET_64BIT)
+ {
+ if (regs_ever_live[18])
+ fprintf (file, "\tstd\t%s,%d(%s)\n",
+ reg_names[18],
+ STACK_POINTER_OFFSET-16,
+ reg_names[STACK_POINTER_REGNUM]);
+ if (regs_ever_live[19])
+ fprintf (file, "\tstd\t%s,%d(%s)\n",
+ reg_names[19],
+ STACK_POINTER_OFFSET-8,
+ reg_names[STACK_POINTER_REGNUM]);
+ }
+
+
+ if (save_fprs_p () && frame_size > 4095)
+ {
+ int fp = 1;
+ int offset = 0;
+ fprintf (file, "\tlgr\t%s,%s\n", reg_names[fp],
+ reg_names[STACK_POINTER_REGNUM]);
+ fprintf (file, "\taghi\t%s,-64\n", reg_names[fp]);
+ save_fprs (file, 0, fp);
+ }
+
+ /* Decrement stack. */
+
+ if (TARGET_BACKCHAIN || (STARTING_FRAME_OFFSET +
+ lsize + STACK_POINTER_OFFSET > 4095
+ || frame_pointer_needed
+ || current_function_calls_alloca))
+ {
+
+ fprintf (file, "\tl%sr\t%s,%s\n", b64,
+ reg_names[1], reg_names[STACK_POINTER_REGNUM]);
+ }
+
+ if (stack_label)
+ {
+ rtx operands[2];
+
+ operands[0] = stack_pointer_rtx;
+ operands[1] = stack_label;
+ if (TARGET_64BIT)
+ output_asm_insn ("sg\t%0,%1", operands);
+ else
+ output_asm_insn ("s\t%0,%1", operands);
+ }
+ else
+ {
+ fprintf (file, "\ta%shi\t%s,-%d\n",b64,
+ reg_names[STACK_POINTER_REGNUM], frame_size);
+ }
+#ifdef INCOMING_RETURN_ADDR_RTX
+ if (dwarf2out_do_frame ())
+ {
+ if (frame_pointer_needed)
+ dwarf2out_def_cfa ("", HARD_FRAME_POINTER_REGNUM,
+ STACK_POINTER_OFFSET+frame_size);
+ else
+ dwarf2out_def_cfa ("", STACK_POINTER_REGNUM,
+ STACK_POINTER_OFFSET+frame_size);
+ }
+#endif
+
+
+ /* Generate backchain. */
+
+ if (TARGET_BACKCHAIN || (STARTING_FRAME_OFFSET +
+ lsize + STACK_POINTER_OFFSET > 4095
+ || frame_pointer_needed
+ || current_function_calls_alloca))
+ {
+ fprintf (file, "\tst%s\t%s,0(%s)\n",
+ b64, reg_names[1], reg_names[STACK_POINTER_REGNUM]);
+ }
+ }
+
+ if (frame_pointer_needed)
+ {
+ fprintf (file, "\tl%sr\t%s,%s\n", b64,
+ reg_names[FRAME_POINTER_REGNUM],
+ reg_names[STACK_POINTER_REGNUM]);
+ }
+
+ /* Load GOT if used and emit use insn that optimizer does not
+ erase literal pool entry. */
+
+ if (current_function_uses_pic_offset_table)
+ {
+ rtx operands[3];
+ if (TARGET_64BIT)
+ {
+ fprintf (file, "\tlarl\t%s,_GLOBAL_OFFSET_TABLE_\n",
+ reg_names[PIC_OFFSET_TABLE_REGNUM]);
+ }
+ else
+ {
+ operands[0] = gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM);
+ operands[1] = got_label;
+ operands[2] = gen_rtx (REG, Pmode, BASE_REGISTER);
+ output_asm_insn ("l\t%0,%1\n\tar\t%0,%2", operands);
+ }
+ }
+ /* Save FPRs below save area. */
+
+ if (frame_size <= 4095)
+ save_fprs (file, frame_size - 64, STACK_POINTER_REGNUM);
+
+ return 0;
+}
+
+/* Output the function epilogue assembly code to the
+ stdio stream FILE. The local frame size is passed
+ in LSIZE. */
+
+int
+s390_function_epilogue (FILE * file, int lsize)
+{
+/* Register is call clobbered and not used for eh or return. */
+#define FREE_REG 4
+
+ int i;
+ long frame_size;
+ int return_reg = RETURN_REGNUM;
+ int fp, offset;
+ char b64[2] = " ";
+
+ b64[0] = TARGET_64BIT ? 'g' : '\0';
+ frame_size = STARTING_FRAME_OFFSET + lsize + save_fprs_p () * 64;
+
+ if (current_function_uses_pic_offset_table)
+ regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
+
+ if (leaf_function_flag)
+ {
+ for (i = 6; i < 13 && (regs_ever_live[i] == 0); i++);
+
+ if (s390_nr_constants || regs_ever_live[13] || i != 13)
+ {
+ fprintf (file, "\tlm%s\t%s,%s,%d(%s)\n", b64,
+ reg_names[i], reg_names[13],
+ UNITS_PER_WORD * i,
+ reg_names[STACK_POINTER_REGNUM]);
+ }
+ if (!TARGET_64BIT)
+ {
+ if (regs_ever_live[18])
+ fprintf (file, "\tld\t%s,%d(%s)\n",
+ reg_names[18],
+ STACK_POINTER_OFFSET-16,
+ reg_names[STACK_POINTER_REGNUM]);
+ if (regs_ever_live[19])
+ fprintf (file, "\tld\t%s,%d(%s)\n",
+ reg_names[19],
+ STACK_POINTER_OFFSET-8,
+ reg_names[STACK_POINTER_REGNUM]);
+ }
+ }
+ else
+ {
+ for (i = 6; i < 13 && (regs_ever_live[i] == 0); i++);
+
+ if (frame_size + STACK_POINTER_OFFSET > 4095)
+ {
+ offset = 0;
+ fp = STACK_POINTER_REGNUM;
+ }
+ else if (frame_pointer_needed || current_function_calls_alloca)
+ {
+ offset = frame_size;
+ fp = FRAME_POINTER_REGNUM;
+ }
+ else
+ {
+ offset = frame_size;
+ fp = STACK_POINTER_REGNUM;
+ }
+
+ /* Restore from offset below save area. */
+
+ if (offset == 0)
+ fprintf (file, "\tl%s\t%s,0(%s)\n", b64,
+ reg_names[fp], reg_names[fp]);
+ restore_fprs (file, offset-64, fp);
+ return_reg = FREE_REG;
+ fprintf (file, "\tl%s\t%s,%d(%s)\n", b64, reg_names[return_reg],
+ UNITS_PER_WORD*RETURN_REGNUM+offset, reg_names[fp]);
+ if (!TARGET_64BIT)
+ {
+ if (regs_ever_live[18])
+ fprintf (file, "\tld\t%s,%d(%s)\n",
+ reg_names[18],
+ offset+STACK_POINTER_OFFSET-16, reg_names[fp]);
+ if (regs_ever_live[19])
+ fprintf (file, "\tld\t%s,%d(%s)\n",
+ reg_names[19],
+ offset+STACK_POINTER_OFFSET-8, reg_names[fp]);
+ }
+ fprintf (file, "\tlm%s\t%s,%s,%d(%s)\n", b64,
+ reg_names[i], reg_names[15],
+ (UNITS_PER_WORD * i) + offset, reg_names[fp]);
+ }
+
+ fprintf (file, "\tbr\t%s\n", reg_names[return_reg]);
+
+ current_function_uses_pic_offset_table = 0;
+ leaf_function_flag = 0;
+ s390_pool_start_insn = NULL_RTX;
+ s390_pool_count = -1;
+ s390_function_count++;
+ return 0;
+}
+
+/* This is epilogue code, maybe should use generic in except.c. */
+
+void
+s390_expand_eh_epilogue (rtx reg1, rtx reg2, rtx reg3)
+{
+ abort ();
+}
+
+
+/* Return the size in bytes of a function argument of
+ type TYPE and/or mode MODE. At least one of TYPE or
+ MODE must be specified. */
+
+static int
+s390_function_arg_size (enum machine_mode mode, tree type)
+{
+ if (type)
+ return int_size_in_bytes (type);
+
+ /* No type info available for some library calls ... */
+ if (mode != BLKmode)
+ return GET_MODE_SIZE (mode);
+
+ /* If we have neither type nor mode, abort */
+ abort ();
+}
+
+/* Return 1 if a function argument of type TYPE and mode MODE
+ is to be passed by reference. The ABI specifies that only
+ structures of size 1, 2, 4, or 8 bytes are passed by value,
+ all other structures (and complex numbers) are passed by
+ reference. */
+
+int
+s390_function_arg_pass_by_reference (enum machine_mode mode, tree type)
+{
+ int size = s390_function_arg_size (mode, type);
+
+ if (type)
+ {
+ if (AGGREGATE_TYPE_P (type) &&
+ size != 1 && size != 2 && size != 4 && size != 8)
+ return 1;
+
+ if (TREE_CODE (type) == COMPLEX_TYPE)
+ return 1;
+ }
+ return 0;
+
+}
+
+/* Update the data in CUM to advance over an argument of mode MODE and
+ data type TYPE. (TYPE is null for libcalls where that information
+ may not be available.). */
+
+void
+s390_function_arg_advance (CUMULATIVE_ARGS * cum,
+ enum machine_mode mode, tree type, int named)
+{
+ if (! TARGET_SOFT_FLOAT && (mode == DFmode || mode == SFmode))
+ {
+ cum->fprs++;
+ }
+ else if (s390_function_arg_pass_by_reference (mode, type))
+ {
+ cum->gprs += 1;
+ }
+ else
+ {
+ int size = s390_function_arg_size (mode, type);
+ cum->gprs += ((size + UNITS_PER_WORD-1) / UNITS_PER_WORD);
+ }
+}
+
+/* Define where to put the arguments to a function.
+ Value is zero to push the argument on the stack,
+ or a hard register in which to store the argument.
+
+ MODE is the argument's machine mode.
+ TYPE is the data type of the argument (as a tree).
+ This is null for libcalls where that information may
+ not be available.
+ CUM is a variable of type CUMULATIVE_ARGS which gives info about
+ the preceding args and about the function being called.
+ NAMED is nonzero if this argument is a named parameter
+ (otherwise it is an extra parameter matching an ellipsis).
+
+ On S/390, we use general purpose registers 2 through 6 to
+ pass integer, pointer, and certain structure arguments, and
+ floating point registers 0 and 2 (0, 2, 4, and 6 on 64-bit)
+ to pass floating point arguments. All remaining arguments
+ are pushed to the stack. */
+
+rtx
+s390_function_arg (CUMULATIVE_ARGS * cum,
+ enum machine_mode mode, tree type, int named)
+{
+ if (s390_function_arg_pass_by_reference (mode, type))
+ return 0;
+
+ if (! TARGET_SOFT_FLOAT && (mode == DFmode || mode == SFmode))
+ {
+ if (cum->fprs + 1 > (TARGET_64BIT? 4 : 2))
+ return 0;
+ else
+ return gen_rtx (REG, mode, cum->fprs + 16);
+ }
+ else
+ {
+ int size = s390_function_arg_size (mode, type);
+ int n_gprs = (size + UNITS_PER_WORD-1) / UNITS_PER_WORD;
+
+ if (cum->gprs + n_gprs > 5)
+ return 0;
+ else
+ return gen_rtx (REG, mode, cum->gprs + 2);
+ }
+}
+
+
+/* Create the va_list datatype.
+
+ On S/390, va_list is a structure of four elements:
+
+ __gpr: number of general purpose registers used for arguments
+ __fpr: number of floating point registers used for arguments
+ __overflow_arg_area:
+ address of area holding arguments that are not
+ passed in a register
+ __reg_save_area:
+ address of register save area; the function prologue
+ saves all registers used for argument passing into this
+ area, if the function uses variable arguments. */
+
+tree
+s390_build_va_list ()
+{
+ tree f_gpr, f_fpr, f_ovf, f_sav, record, type_decl;
+
+ record = make_lang_type (RECORD_TYPE);
+
+ type_decl =
+ build_decl (TYPE_DECL, get_identifier ("__va_list_tag"), record);
+
+ f_gpr = build_decl (FIELD_DECL, get_identifier ("__gpr"),
+ long_integer_type_node);
+ f_fpr = build_decl (FIELD_DECL, get_identifier ("__fpr"),
+ long_integer_type_node);
+ f_ovf = build_decl (FIELD_DECL, get_identifier ("__overflow_arg_area"),
+ ptr_type_node);
+ f_sav = build_decl (FIELD_DECL, get_identifier ("__reg_save_area"),
+ ptr_type_node);
+
+ DECL_FIELD_CONTEXT (f_gpr) = record;
+ DECL_FIELD_CONTEXT (f_fpr) = record;
+ DECL_FIELD_CONTEXT (f_ovf) = record;
+ DECL_FIELD_CONTEXT (f_sav) = record;
+
+ TREE_CHAIN (record) = type_decl;
+ TYPE_NAME (record) = type_decl;
+ TYPE_FIELDS (record) = f_gpr;
+ TREE_CHAIN (f_gpr) = f_fpr;
+ TREE_CHAIN (f_fpr) = f_ovf;
+ TREE_CHAIN (f_ovf) = f_sav;
+
+ layout_type (record);
+
+ /* The correct type is an array type of one element. */
+ return build_array_type (record, build_index_type (size_zero_node));
+}
+
+/* Implement va_start.
+
+ The following global variables are used to initalize
+ the va_list structure:
+
+ current_function_args_info:
+ holds number of gprs and fprs used for arguments.
+ current_function_arg_offset_rtx:
+ holds the offset to the overflow argument area on the stack
+ (relative to the virtual arg pointer). */
+
+void
+s390_va_start (int stdarg_p, tree valist, rtx nextarg)
+{
+ HOST_WIDE_INT n_gpr, n_fpr;
+ int off;
+ tree f_gpr, f_fpr, f_ovf, f_sav;
+ tree gpr, fpr, ovf, sav, t;
+
+ f_gpr = TYPE_FIELDS (TREE_TYPE (va_list_type_node));
+ f_fpr = TREE_CHAIN (f_gpr);
+ f_ovf = TREE_CHAIN (f_fpr);
+ f_sav = TREE_CHAIN (f_ovf);
+
+ valist = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (valist)), valist);
+ gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr);
+ fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr);
+ ovf = build (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf);
+ sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav);
+
+ /* Count number of gp and fp argument registers used. */
+
+ n_gpr = current_function_args_info.gprs;
+ n_fpr = current_function_args_info.fprs;
+
+ t = build (MODIFY_EXPR, TREE_TYPE (gpr), gpr, build_int_2 (n_gpr, 0));
+ TREE_SIDE_EFFECTS (t) = 1;
+ expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+
+ t = build (MODIFY_EXPR, TREE_TYPE (fpr), fpr, build_int_2 (n_fpr, 0));
+ TREE_SIDE_EFFECTS (t) = 1;
+ expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+
+ /* Find the overflow area. */
+ t = make_tree (TREE_TYPE (ovf), virtual_incoming_args_rtx);
+
+ off = INTVAL (current_function_arg_offset_rtx);
+ off = off < 0 ? 0 : off;
+ if (! stdarg_p)
+ off = off > 0 ? off - UNITS_PER_WORD : off;
+ if (TARGET_DEBUG_ARG)
+ fprintf (stderr, "va_start: n_gpr = %d, n_fpr = %d off %d\n",
+ n_gpr, n_fpr, off);
+
+ t = build (PLUS_EXPR, TREE_TYPE (ovf), t, build_int_2 (off, 0));
+
+ t = build (MODIFY_EXPR, TREE_TYPE (ovf), ovf, t);
+ TREE_SIDE_EFFECTS (t) = 1;
+ expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+
+ /* Find the register save area. */
+ t = make_tree (TREE_TYPE (sav), virtual_incoming_args_rtx);
+ t = build (PLUS_EXPR, TREE_TYPE (sav), t,
+ build_int_2 (-STACK_POINTER_OFFSET, -1));
+ t = build (MODIFY_EXPR, TREE_TYPE (sav), sav, t);
+ TREE_SIDE_EFFECTS (t) = 1;
+ expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+}
+
+/* Implement va_arg.
+
+ Generates code equivalent to:
+
+ if (integral value) {
+ if (size <= 4 && args.gpr < 5 ||
+ size > 4 && args.gpr < 4 )
+ ret = args.reg_save_area[args.gpr+8]
+ else
+ ret = *args.overflow_arg_area++;
+ } else if (float value) {
+ if (args.fgpr < 2)
+ ret = args.reg_save_area[args.fpr+64]
+ else
+ ret = *args.overflow_arg_area++;
+ } else if (aggregate value) {
+ if (args.gpr < 5)
+ ret = *args.reg_save_area[args.gpr]
+ else
+ ret = **args.overflow_arg_area++;
+ } */
+
+rtx
+s390_va_arg (tree valist, tree type)
+{
+ tree f_gpr, f_fpr, f_ovf, f_sav;
+ tree gpr, fpr, ovf, sav, reg, t, u;
+ int indirect_p, size, n_reg, sav_ofs, sav_scale, max_reg;
+ rtx lab_false, lab_over, addr_rtx, r;
+
+ f_gpr = TYPE_FIELDS (TREE_TYPE (va_list_type_node));
+ f_fpr = TREE_CHAIN (f_gpr);
+ f_ovf = TREE_CHAIN (f_fpr);
+ f_sav = TREE_CHAIN (f_ovf);
+
+ valist = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (valist)), valist);
+ gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr);
+ fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr);
+ ovf = build (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf);
+ sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav);
+
+ size = int_size_in_bytes (type);
+
+ if (s390_function_arg_pass_by_reference (TYPE_MODE (type), type))
+ {
+ if (TARGET_DEBUG_ARG)
+ {
+ fprintf (stderr, "va_arg: aggregate type");
+ debug_tree (type);
+ }
+
+ /* Aggregates are passed by reference. */
+ indirect_p = 1;
+ reg = gpr;
+ n_reg = 1;
+ sav_ofs = 2 * UNITS_PER_WORD;
+ sav_scale = UNITS_PER_WORD;
+ size = UNITS_PER_WORD;
+ max_reg = 4;
+ }
+ else if (FLOAT_TYPE_P (type) && ! TARGET_SOFT_FLOAT)
+ {
+ if (TARGET_DEBUG_ARG)
+ {
+ fprintf (stderr, "va_arg: float type");
+ debug_tree (type);
+ }
+
+ /* FP args go in FP registers, if present. */
+ indirect_p = 0;
+ reg = fpr;
+ n_reg = 1;
+ sav_ofs = 16 * UNITS_PER_WORD;
+ sav_scale = 8;
+ /* TARGET_64BIT has up to 4 parameter in fprs */
+ max_reg = TARGET_64BIT ? 3 : 1;
+ }
+ else
+ {
+ if (TARGET_DEBUG_ARG)
+ {
+ fprintf (stderr, "va_arg: other type");
+ debug_tree (type);
+ }
+
+ /* Otherwise into GP registers. */
+ indirect_p = 0;
+ reg = gpr;
+ n_reg = (size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
+ sav_ofs = 2 * UNITS_PER_WORD;
+ if (TARGET_64BIT)
+ sav_ofs += TYPE_MODE (type) == SImode ? 4 :
+ TYPE_MODE (type) == HImode ? 6 :
+ TYPE_MODE (type) == QImode ? 7 : 0;
+ else
+ sav_ofs += TYPE_MODE (type) == HImode ? 2 :
+ TYPE_MODE (type) == QImode ? 3 : 0;
+
+ sav_scale = UNITS_PER_WORD;
+ if (n_reg > 1)
+ max_reg = 3;
+ else
+ max_reg = 4;
+ }
+
+ /* Pull the value out of the saved registers ... */
+
+ lab_false = gen_label_rtx ();
+ lab_over = gen_label_rtx ();
+ addr_rtx = gen_reg_rtx (Pmode);
+
+ emit_cmp_and_jump_insns (expand_expr (reg, NULL_RTX, Pmode, EXPAND_NORMAL),
+ GEN_INT (max_reg),
+ GT, const1_rtx, Pmode, 0, 1, lab_false);
+
+ if (sav_ofs)
+ t = build (PLUS_EXPR, ptr_type_node, sav, build_int_2 (sav_ofs, 0));
+ else
+ t = sav;
+
+ u = build (MULT_EXPR, long_integer_type_node,
+ reg, build_int_2 (sav_scale, 0));
+ TREE_SIDE_EFFECTS (u) = 1;
+
+ t = build (PLUS_EXPR, ptr_type_node, t, u);
+ TREE_SIDE_EFFECTS (t) = 1;
+
+ r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL);
+ if (r != addr_rtx)
+ emit_move_insn (addr_rtx, r);
+
+
+ emit_jump_insn (gen_jump (lab_over));
+ emit_barrier ();
+ emit_label (lab_false);
+
+ /* ... Otherwise out of the overflow area. */
+
+ t = save_expr (ovf);
+
+
+ /* In 64 BIT for each argument on stack, a full 64 bit slot is allocated. */
+ if (size < UNITS_PER_WORD)
+ {
+ t = build (PLUS_EXPR, TREE_TYPE (t), t, build_int_2 (UNITS_PER_WORD-size, 0));
+ t = build (MODIFY_EXPR, TREE_TYPE (ovf), ovf, t);
+ TREE_SIDE_EFFECTS (t) = 1;
+ expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+
+ t = save_expr (ovf);
+ }
+
+ r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL);
+ if (r != addr_rtx)
+ emit_move_insn (addr_rtx, r);
+
+ t = build (PLUS_EXPR, TREE_TYPE (t), t, build_int_2 (size, 0));
+ t = build (MODIFY_EXPR, TREE_TYPE (ovf), ovf, t);
+ TREE_SIDE_EFFECTS (t) = 1;
+ expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+
+ emit_label (lab_over);
+
+ /* If less than max_regs a registers are retrieved out
+ of register save area, increment. */
+
+ u = build (PREINCREMENT_EXPR, TREE_TYPE (reg), reg,
+ build_int_2 (n_reg, 0));
+ TREE_SIDE_EFFECTS (u) = 1;
+ expand_expr (u, const0_rtx, VOIDmode, EXPAND_NORMAL);
+
+ if (indirect_p)
+ {
+ r = gen_rtx_MEM (Pmode, addr_rtx);
+ MEM_ALIAS_SET (r) = get_varargs_alias_set ();
+ emit_move_insn (addr_rtx, r);
+ }
+
+
+ return addr_rtx;
+}
+
+/* Do what is necessary for `va_start'. The argument is ignored;
+ we look at the current function to determine if stdarg or varargs
+ is used. */
+
+rtx
+s390_builtin_saveregs (arglist)
+ tree arglist ATTRIBUTE_UNUSED;
+{
+ rtx off, block, dest, tmp;
+ tree fntype = TREE_TYPE (current_function_decl);
+
+ int stdarg = (TYPE_ARG_TYPES (fntype) != 0
+ && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
+ != void_type_node));
+
+ /* Allocate the va_list block. */
+
+ block = assign_stack_local (BLKmode, 4 * UNITS_PER_WORD, BITS_PER_WORD);
+ RTX_UNCHANGING_P (block) = 1;
+ RTX_UNCHANGING_P (XEXP (block, 0)) = 1;
+
+ /* Store the # of named gpr and fpr in 1st and 2nd word of va_list. */
+
+ dest = change_address (block, ptr_mode,
+ plus_constant (XEXP (block, 0), 0));
+ emit_move_insn (dest, GEN_INT (current_function_args_info.gprs));
+ dest = change_address (block, ptr_mode,
+ plus_constant (XEXP (block, 0), UNITS_PER_WORD));
+ emit_move_insn (dest, GEN_INT (current_function_args_info.fprs));
+
+ /* Store the address of the overflow area in 3rd word of va_list. */
+
+ if (stdarg)
+ off = current_function_arg_offset_rtx;
+ else
+ {
+ if (GET_CODE (current_function_arg_offset_rtx) != CONST_INT)
+ {
+ debug_rtx (current_function_arg_offset_rtx);
+ abort ();
+ }
+
+ if (INTVAL (current_function_arg_offset_rtx) != 0)
+ off = gen_rtx_CONST_INT (Pmode,
+ INTVAL (current_function_arg_offset_rtx)-
+ UNITS_PER_WORD);
+ else
+ off = current_function_arg_offset_rtx;
+ }
+
+ dest = change_address (block, ptr_mode,
+ plus_constant (XEXP (block, 0),
+ 2 * UNITS_PER_WORD));
+
+ tmp = expand_binop (Pmode, add_optab, virtual_incoming_args_rtx,
+ off,
+ dest, 0, OPTAB_WIDEN);
+ if (tmp != dest)
+ emit_move_insn (dest, tmp);
+
+ /* Store the address of the register save area in 4th word of va_list. */
+
+ dest = change_address (block, ptr_mode,
+ plus_constant (XEXP (block, 0),
+ 3 * UNITS_PER_WORD));
+
+ tmp = expand_binop (Pmode, add_optab, virtual_incoming_args_rtx,
+ GEN_INT (-STACK_POINTER_OFFSET),
+ dest, 0, OPTAB_WIDEN);
+ if (tmp != dest)
+ emit_move_insn (dest, tmp);
+
+ /* Return the address of the va_list block. */
+
+ return XEXP (block, 0);
+}
+
+
+/* Output assembly code for the trampoline template to
+ stdio stream FILE.
+
+ On S/390, we use gpr 1 internally in the trampoline code;
+ gpr 0 is used to hold the static chain. */
+
+void
+s390_trampoline_template (FILE * file)
+{
+ if (TARGET_64BIT)
+ {
+ fprintf (file, "larl\t%s,0f\n", reg_names[1]);
+ fprintf (file, "lg\t%s,0(%s)\n", reg_names[0], reg_names[1]);
+ fprintf (file, "lg\t%s,8(%s)\n", reg_names[1], reg_names[1]);
+ fprintf (file, "br\t%s\n", reg_names[1]);
+ fprintf (file, "0:\t.quad\t0\n");
+ fprintf (file, ".quad\t0\n");
+ }
+ else
+ {
+ fprintf (file, "basr\t%s,0\n", reg_names[1]);
+ fprintf (file, "l\t%s,10(%s)\n", reg_names[0], reg_names[1]);
+ fprintf (file, "l\t%s,14(%s)\n", reg_names[1], reg_names[1]);
+ fprintf (file, "br\t%s\n", reg_names[1]);
+ fprintf (file, ".long\t0\n");
+ fprintf (file, ".long\t0\n");
+ }
+}
+
+/* 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
+s390_initialize_trampoline (addr, fnaddr, cxt)
+ rtx addr;
+ rtx fnaddr;
+ rtx cxt;
+{
+ emit_move_insn (gen_rtx
+ (MEM, Pmode,
+ memory_address (Pmode,
+ plus_constant (addr, (TARGET_64BIT ? 20 : 12) ))), cxt);
+ emit_move_insn (gen_rtx
+ (MEM, Pmode,
+ memory_address (Pmode,
+ plus_constant (addr, (TARGET_64BIT ? 28 : 16) ))), fnaddr);
+}
diff --git a/gcc/config/s390/s390.h b/gcc/config/s390/s390.h
new file mode 100644
index 00000000000..721bcb1412c
--- /dev/null
+++ b/gcc/config/s390/s390.h
@@ -0,0 +1,1881 @@
+/* Definitions of target machine for GNU compiler, for IBM S/390
+ Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
+ Contributed by Hartmut Penner (hpenner@de.ibm.com) and
+ Ulrich Weigand (uweigand@de.ibm.com).
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#ifndef _S390_H
+#define _S390_H
+
+#define TARGET_VERSION fprintf (stderr, " (S/390)");
+
+extern int flag_pic;
+
+/* Run-time compilation parameters selecting different hardware subsets. */
+
+extern int target_flags;
+
+/* Target macros checked at runtime of compiler. */
+
+#define TARGET_HARD_FLOAT (target_flags & 1)
+#define TARGET_BACKCHAIN (target_flags & 2)
+#define TARGET_SMALL_EXEC (target_flags & 4)
+#define TARGET_DEBUG_ARG (target_flags & 8)
+#define TARGET_64BIT (target_flags & 16)
+#define TARGET_MVCLE (target_flags & 32)
+
+#define TARGET_DEFAULT 0x3
+#define TARGET_SOFT_FLOAT (!(target_flags & 1))
+
+/* Macro to define tables used to set the flags. This is a list in braces
+ of pairs in braces, each pair being { "NAME", VALUE }
+ where VALUE is the bits to set or minus the bits to clear.
+ An empty string NAME is used to identify the default VALUE. */
+
+#define TARGET_SWITCHES \
+{ { "hard-float", 1, N_("Use hardware fp")}, \
+ { "soft-float", -1, N_("Don't use hardware fp")}, \
+ { "backchain", 2, N_("Set backchain")}, \
+ { "no-backchain", -2, N_("Don't set backchain (faster, but debug harder")}, \
+ { "small-exec", 4, N_("Use bras for execucable < 64k")}, \
+ { "no-small-exec",-4, N_("Don't use bras")}, \
+ { "debug", 8, N_("Additional debug prints")}, \
+ { "no-debug", -8, N_("Don't print additional debug prints")}, \
+ { "64", 16, N_("64 bit mode")}, \
+ { "31", -16, N_("31 bit mode")}, \
+ { "mvcle", 32, N_("mvcle use")}, \
+ { "no-mvcle", -32, N_("mvc&ex")}, \
+ { "", TARGET_DEFAULT, 0 } }
+
+/* Define this to change the optimizations performed by default. */
+#define OPTIMIZATION_OPTIONS(LEVEL, SIZE) optimization_options(LEVEL, SIZE)
+
+/* Defines for REAL_ARITHMETIC. */
+#define IEEE_FLOAT 1
+#define TARGET_IBM_FLOAT 0
+#define TARGET_IEEE_FLOAT 1
+
+/* The current function count for create unique internal labels. */
+
+extern int s390_function_count;
+
+/* The amount of space used for outgoing arguments. */
+
+extern int current_function_outgoing_args_size;
+
+/* Target machine storage layout. */
+
+/* Define this if most significant bit is lowest numbered in instructions
+ that operate on numbered bit-fields. */
+
+#define BITS_BIG_ENDIAN 1
+
+/* Define this if most significant byte of a word is the lowest numbered. */
+
+#define BYTES_BIG_ENDIAN 1
+
+/* Define this if MS word of a multiword is the lowest numbered. */
+
+#define WORDS_BIG_ENDIAN 1
+
+/* Number of bits in an addressable storage unit. */
+
+#define BITS_PER_UNIT 8
+
+/* Width in bits of a "word", which is the contents of a machine register. */
+
+#define BITS_PER_WORD (TARGET_64BIT ? 64 : 32)
+#define MAX_BITS_PER_WORD 64
+
+/* Width of a word, in units (bytes). */
+
+#define UNITS_PER_WORD (TARGET_64BIT ? 8 : 4)
+#define MIN_UNITS_PER_WORD 4
+
+/* Width in bits of a pointer. See also the macro `Pmode' defined below. */
+
+#define POINTER_SIZE (TARGET_64BIT ? 64 : 32)
+
+/* A C expression for the size in bits of the type `short' on the
+ target machine. If you don't define this, the default is half a
+ word. (If this would be less than one storage unit, it is
+ rounded up to one unit.) */
+#define SHORT_TYPE_SIZE 16
+
+/* A C expression for the size in bits of the type `int' on the
+ target machine. If you don't define this, the default is one
+ word. */
+#define INT_TYPE_SIZE 32
+
+/* A C expression for the size in bits of the type `long' on the
+ target machine. If you don't define this, the default is one
+ word. */
+#define LONG_TYPE_SIZE (TARGET_64BIT ? 64 : 32)
+#define MAX_LONG_TYPE_SIZE 64
+
+/* A C expression for the size in bits of the type `long long' on the
+ target machine. If you don't define this, the default is two
+ words. */
+#define LONG_LONG_TYPE_SIZE 64
+
+/* Right now we only support two floating point formats, the
+ 32 and 64 bit ieee formats. */
+
+#define FLOAT_TYPE_SIZE 32
+#define DOUBLE_TYPE_SIZE 64
+#define LONG_DOUBLE_TYPE_SIZE 64
+
+/* 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 (INTEGRAL_MODE_P (MODE) && \
+ GET_MODE_SIZE (MODE) < UNITS_PER_WORD) { \
+ (MODE) = Pmode; \
+ }
+
+/* Defining PROMOTE_FUNCTION_ARGS eliminates some unnecessary zero/sign
+ extensions applied to char/short functions arguments. Defining
+ PROMOTE_FUNCTION_RETURN does the same for function returns. */
+
+#define PROMOTE_FUNCTION_ARGS
+#define PROMOTE_FUNCTION_RETURN
+#define PROMOTE_FOR_CALL_ONLY
+
+/* Allocation boundary (in *bits*) for storing pointers in memory. */
+
+#define POINTER_BOUNDARY 32
+
+/* Allocation boundary (in *bits*) for storing arguments in argument list. */
+
+#define PARM_BOUNDARY (TARGET_64BIT ? 64 : 32)
+
+/* Boundary (in *bits*) on which stack pointer should be aligned. */
+
+#define STACK_BOUNDARY 64
+
+/* Allocation boundary (in *bits*) for the code of a function. */
+
+#define FUNCTION_BOUNDARY 32
+
+/* There is no point aligning anything to a rounder boundary than this. */
+
+#define BIGGEST_ALIGNMENT 64
+
+/* Alignment of field after `int : 0' in a structure. */
+
+#define EMPTY_FIELD_BOUNDARY 32
+
+/* Alignment on even adresses for LARL instruction. */
+
+#define CONSTANT_ALIGNMENT(EXP, ALIGN) (ALIGN) < 16 ? 16 : (ALIGN)
+
+#define DATA_ALIGNMENT(TYPE, ALIGN) (ALIGN) < 16 ? 16 : (ALIGN)
+
+/* Define this if move instructions will actually fail to work when given
+ unaligned data. */
+
+#define STRICT_ALIGNMENT 0
+
+/* real arithmetic */
+
+#define REAL_ARITHMETIC
+
+/* Define target floating point format. */
+
+#undef TARGET_FLOAT_FORMAT
+#ifdef IEEE_FLOAT
+#define TARGET_FLOAT_FORMAT IEEE_FLOAT_FORMAT
+#else
+#define TARGET_FLOAT_FORMAT IBM_FLOAT_FORMAT
+#endif
+
+/* Define if special allocation order desired. */
+
+#define REG_ALLOC_ORDER \
+{ 1, 2, 3, 4, 5, 0, 14, 13, 12, 11, 10, 9, 8, 7, 6, \
+ 16, 17, 18, 19, 20, 21, 22, 23, \
+ 24, 25, 26, 27, 28, 29, 30, 31, \
+ 15, 32, 33 }
+
+/* Standard register usage. */
+
+#define INT_REGNO_P(N) ( (N) >= 0 && (N) < 16 )
+#ifdef IEEE_FLOAT
+#define FLOAT_REGNO_P(N) ( (N) >= 16 && (N) < 32 )
+#else
+#define FLOAT_REGNO_P(N) ( (N) >= 16 && (N) < 20 )
+#endif
+#define CC_REGNO_P(N) ( (N) == 33 )
+
+/* Number of actual hardware registers. The hardware registers are
+ assigned numbers for the compiler from 0 to just below
+ FIRST_PSEUDO_REGISTER.
+ All registers that the compiler knows about must be given numbers,
+ even those that are not normally considered general registers.
+ For the 390, we give the data registers numbers 0-15,
+ and the floating point registers numbers 16-19.
+ G5 and following have 16 IEEE floating point register,
+ which get numbers 16-31. */
+
+#define FIRST_PSEUDO_REGISTER 34
+
+/* The following register have a fix usage
+ GPR 12: GOT register points to the GOT, setup in prologue,
+ GOT contains pointer to variables in shared libraries
+ GPR 13: Base register setup in prologue to point to the
+ literal table of each function
+ GPR 14: Return registers holds the return address
+ GPR 15: Stack pointer */
+
+#define PIC_OFFSET_TABLE_REGNUM 12
+#define BASE_REGISTER 13
+#define RETURN_REGNUM 14
+#define STACK_POINTER_REGNUM 15
+
+#define FIXED_REGISTERS \
+{ 0, 0, 0, 0, \
+ 0, 0, 0, 0, \
+ 0, 0, 0, 0, \
+ 0, 1, 1, 1, \
+ 0, 0, 0, 0, \
+ 0, 0, 0, 0, \
+ 0, 0, 0, 0, \
+ 0, 0, 0, 0, \
+ 1, 1 }
+
+/* 1 for registers not available across function calls. These must include
+ the FIXED_REGISTERS and also any registers that can be used without being
+ saved.
+ The latter must include the registers where values are returned
+ and the register where structure-value addresses are passed. */
+
+#define CALL_USED_REGISTERS \
+{ 1, 1, 1, 1, \
+ 1, 1, 0, 0, \
+ 0, 0, 0, 0, \
+ 0, 1, 1, 1, \
+ 1, 1, 0, 0, \
+ 1, 1, 1, 1, \
+ 1, 1, 1, 1, \
+ 1, 1, 1, 1, \
+ 1, 1 }
+
+/* If not pic code, gpr 12 can be used. */
+
+#define CONDITIONAL_REGISTER_USAGE \
+do \
+ { \
+ if (flag_pic) \
+ { \
+ fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1; \
+ call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1; \
+ } \
+ } while (0)
+
+/* The following register have a special usage
+ GPR 11: Frame pointer if needed to point to automatic variables.
+ GPR 32: In functions with more the 5 args this register
+ points to that arguments, it is always eliminated
+ with stack- or frame-pointer.
+ GPR 33: Condition code 'register' */
+
+#define FRAME_POINTER_REGNUM 11
+
+#define ARG_POINTER_REGNUM 32
+
+#define CC_REGNUM 33
+
+/* We use the register %r0 to pass the static chain to a nested function.
+
+ Note: It is assumed that this register is call-clobbered!
+ We can't use any of the function-argument registers either,
+ and register 1 is needed by the trampoline code, so we have
+ no other choice but using this one ... */
+
+#define STATIC_CHAIN_REGNUM 0
+
+/* 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) \
+ (FLOAT_REGNO_P(REGNO)? \
+ (GET_MODE_CLASS(MODE) == MODE_COMPLEX_FLOAT ? 2 : 1) : \
+ INT_REGNO_P(REGNO)? \
+ ((GET_MODE_SIZE(MODE)+UNITS_PER_WORD-1) / UNITS_PER_WORD) : \
+ 1)
+
+/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
+ The gprs can hold QI, HI, SI, SF, DF, SC and DC.
+ Even gprs can hold DI.
+ The floating point registers can hold DF, SF, DC and SC. */
+
+#define HARD_REGNO_MODE_OK(REGNO, MODE) \
+ (FLOAT_REGNO_P(REGNO)? \
+ (GET_MODE_CLASS(MODE) == MODE_FLOAT || \
+ GET_MODE_CLASS(MODE) == MODE_COMPLEX_FLOAT) : \
+ INT_REGNO_P(REGNO)? \
+ (HARD_REGNO_NREGS(REGNO, MODE) == 1 || !((REGNO) & 1)) : \
+ CC_REGNO_P(REGNO)? \
+ GET_MODE_CLASS (MODE) == MODE_CC : \
+ 0)
+
+/* Value is 1 if it is a good idea to tie two pseudo registers when one has
+ mode MODE1 and one has mode MODE2.
+ If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2,
+ for any hard reg, then this must be 0 for correct output. */
+
+#define MODES_TIEABLE_P(MODE1, MODE2) \
+ (((MODE1) == SFmode || (MODE1) == DFmode) \
+ == ((MODE2) == SFmode || (MODE2) == DFmode))
+
+
+/* Define this macro if references to a symbol must be treated
+ differently depending on something about the variable or
+ function named by the symbol (such as what section it is in).
+
+ On s390, if using PIC, mark a SYMBOL_REF for a non-global symbol
+ so that we may access it directly in the GOT. */
+
+#define ENCODE_SECTION_INFO(DECL) \
+do \
+ { \
+ if (flag_pic) \
+ { \
+ rtx rtl = (TREE_CODE_CLASS (TREE_CODE (DECL)) != 'd' \
+ ? TREE_CST_RTL (DECL) : DECL_RTL (DECL)); \
+ \
+ if (GET_CODE (rtl) == MEM) \
+ { \
+ SYMBOL_REF_FLAG (XEXP (rtl, 0)) \
+ = (TREE_CODE_CLASS (TREE_CODE (DECL)) != 'd' \
+ || ! TREE_PUBLIC (DECL)); \
+ } \
+ } \
+ } \
+while (0)
+
+
+/* This is an array of structures. Each structure initializes one pair
+ of eliminable registers. The "from" register number is given first,
+ followed by "to". Eliminations of the same "from" register are listed
+ in order of preference. */
+
+#define ELIMINABLE_REGS \
+{{ FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
+ { ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
+ { ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}}
+
+#define CAN_ELIMINATE(FROM, TO) (1)
+
+#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
+{ if ((FROM) == FRAME_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM) \
+ { (OFFSET) = 0; } \
+ else if ((FROM) == ARG_POINTER_REGNUM && (TO) == FRAME_POINTER_REGNUM) \
+ { (OFFSET) = s390_arg_frame_offset (); } \
+ else if ((FROM) == ARG_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM) \
+ { (OFFSET) = s390_arg_frame_offset (); } \
+}
+
+#define CAN_DEBUG_WITHOUT_FP
+
+/* Value should be nonzero if functions must have frame pointers.
+ Zero means the frame pointer need not be set up (and parms may be
+ accessed via the stack pointer) in functions that seem suitable.
+ This is computed in `reload', in reload1.c. */
+
+#define FRAME_POINTER_REQUIRED 0
+
+/* 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. */
+
+/*#define SMALL_REGISTER_CLASSES 1*/
+
+enum reg_class
+{
+ NO_REGS, ADDR_REGS, GENERAL_REGS,
+ FP_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","ADDR_REGS", "GENERAL_REGS", "FP_REGS", "ALL_REGS" }
+
+/* Define which registers fit in which classes. This is an initializer for
+ a vector of HARD_REG_SET of length N_REG_CLASSES.
+ G5 and latter have 16 register and support IEEE floating point operations. */
+
+#define REG_CLASS_CONTENTS \
+{ \
+ { 0x00000000, 0x00000000 }, /* NO_REGS */ \
+ { 0x0000fffe, 0x00000001 }, /* ADDR_REGS */ \
+ { 0x0000ffff, 0x00000001 }, /* GENERAL_REGS */ \
+ { 0xffff0000, 0x00000000 }, /* FP_REGS */ \
+ { 0xffffffff, 0x00000003 }, /* ALL_REGS */ \
+}
+
+
+/* The same information, inverted:
+ Return the class number of the smallest class containing
+ reg number REGNO. This could be a conditional expression
+ or could index an array. */
+
+#define REGNO_REG_CLASS(REGNO) (regclass_map[REGNO])
+
+extern enum reg_class regclass_map[]; /* smalled class containing REGNO */
+
+/* The class value for index registers, and the one for base regs. */
+
+#define INDEX_REG_CLASS ADDR_REGS
+#define BASE_REG_CLASS ADDR_REGS
+
+/* Get reg_class from a letter such as appears in the machine description. */
+
+#define REG_CLASS_FROM_LETTER(C) \
+ ((C) == 'a' ? ADDR_REGS : \
+ (C) == 'd' ? GENERAL_REGS : \
+ (C) == 'f' ? FP_REGS : NO_REGS)
+
+/* The letters I, J, K, L and M in a register constraint string can be used
+ to stand for particular ranges of immediate operands.
+ This macro defines what the ranges are.
+ C is the letter, and VALUE is a constant value.
+ Return 1 if VALUE is in the range specified by C. */
+
+#define CONST_OK_FOR_LETTER_P(VALUE, C) \
+ ((C) == 'I' ? (unsigned long) (VALUE) < 256 : \
+ (C) == 'J' ? (unsigned long) (VALUE) < 4096 : \
+ (C) == 'K' ? (VALUE) >= -32768 && (VALUE) < 32768 : \
+ (C) == 'L' ? (unsigned long) (VALUE) < 65536 : 0)
+
+/* Similar, but for floating constants, and defining letters G and H.
+ Here VALUE is the CONST_DOUBLE rtx itself. */
+
+#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) 1
+
+/* 'Q' means a memory-reference for a S-type operand. */
+
+#define EXTRA_CONSTRAINT(OP, C) \
+ ((C) == 'Q' ? s_operand (OP, GET_MODE (OP)) : \
+ (C) == 'S' ? larl_operand (OP, GET_MODE (OP)) : 0)
+
+/* Given an rtx X being reloaded into a reg required to be in class CLASS,
+ return the class of reg to actually use. In general this is just CLASS;
+ but on some machines in some cases it is preferable to use a more
+ restrictive class. */
+
+#define PREFERRED_RELOAD_CLASS(X, CLASS) \
+ (GET_CODE (X) == CONST_DOUBLE ? \
+ (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT ? FP_REGS : ADDR_REGS) :\
+ (GET_CODE (X) == CONST_INT ? \
+ (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT ? FP_REGS : ADDR_REGS) :\
+ GET_CODE (X) == PLUS || \
+ GET_CODE (X) == LABEL_REF || \
+ GET_CODE (X) == SYMBOL_REF || \
+ GET_CODE (X) == CONST ? ADDR_REGS : (CLASS)))
+
+/* Return the maximum number of consecutive registers needed to represent
+ mode MODE in a register of class CLASS. */
+
+#define CLASS_MAX_NREGS(CLASS, MODE) \
+ ((CLASS) == FP_REGS ? \
+ (GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT ? 2 : 1) : \
+ (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
+
+/* If we are copying between FP registers and anything else, we need a memory
+ location. */
+
+#define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) \
+ ((CLASS1) != (CLASS2) && ((CLASS1) == FP_REGS || (CLASS2) == FP_REGS))
+
+/* Get_secondary_mem widens its argument to BITS_PER_WORD which loses on 64bit
+ because the movsi and movsf patterns don't handle r/f moves. */
+
+#define SECONDARY_MEMORY_NEEDED_MODE(MODE) \
+ (GET_MODE_BITSIZE (MODE) < 32 \
+ ? mode_for_size (32, GET_MODE_CLASS (MODE), 0) \
+ : MODE)
+
+
+/* A C expression whose value is nonzero if pseudos that have been
+ assigned to registers of class CLASS would likely be spilled
+ because registers of CLASS are needed for spill registers.
+
+ The default value of this macro returns 1 if CLASS has exactly one
+ register and zero otherwise. On most machines, this default
+ should be used. Only define this macro to some other expression
+ if pseudo allocated by `local-alloc.c' end up in memory because
+ their hard registers were needed for spill registers. If this
+ macro returns nonzero for those classes, those pseudos will only
+ be allocated by `global.c', which knows how to reallocate the
+ pseudo to another register. If there would not be another
+ register available for reallocation, you should not change the
+ definition of this macro since the only effect of such a
+ definition would be to slow down register allocation. */
+
+/* Stack layout; function entry, exit and calling. */
+
+/* The current return address is on Offset 56 of the current frame
+ if we are in an leaf_function. Otherwise we have to go one stack
+ back.
+ The return address of anything farther back is accessed normally
+ at an offset of 56 from the frame pointer.
+
+ FIXME: builtin_return_addr does not work correctly in a leaf
+ function, we need to find way to find out, if we
+ are in a leaf function
+ */
+
+#define _RETURN_ADDR_OFFSET (TARGET_64BIT ? 112 : 56)
+
+#define RETURN_ADDR_RTX(count, frame) \
+ gen_rtx (MEM, Pmode, \
+ memory_address (Pmode, \
+ plus_constant ( \
+ copy_to_reg (gen_rtx (MEM, Pmode, \
+ memory_address (Pmode, frame))), \
+ _RETURN_ADDR_OFFSET)));
+
+/* The following macros will turn on dwarf2 exception hndling
+ Other code location for this exception handling are
+ in s390.md (eh_return insn) and in linux.c in the prologue. */
+
+#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (Pmode, RETURN_REGNUM)
+
+/* We have 31 bit mode. */
+
+#define MASK_RETURN_ADDR (GEN_INT (0x7fffffff))
+
+/* Location, from where return address to load. */
+
+#define DWARF_FRAME_RETURN_COLUMN 14
+
+/* Describe how we implement __builtin_eh_return. */
+#define EH_RETURN_DATA_REGNO(N) ((N) < 4 ? (N) + 6 : INVALID_REGNUM)
+#define EH_RETURN_STACKADJ_RTX gen_rtx_REG (Pmode, 10)
+#define EH_RETURN_HANDLER_RTX \
+ gen_rtx_MEM (Pmode, plus_constant (arg_pointer_rtx, \
+ TARGET_64BIT? -48 : -40))
+
+/* Define this if pushing a word on the stack makes the stack pointer a
+ smaller address. */
+
+#define STACK_GROWS_DOWNWARD
+
+/* Define this if the nominal address of the stack frame is at the
+ high-address end of the local variables; that is, each additional local
+ variable allocated goes at a more negative offset in the frame. */
+
+/* #define FRAME_GROWS_DOWNWARD */
+
+/* Offset from stack-pointer to first location of outgoing args. */
+
+#define STACK_POINTER_OFFSET (TARGET_64BIT ? 160 : 96)
+
+/* Offset within stack frame to start allocating local variables at.
+ If FRAME_GROWS_DOWNWARD, this is the offset to the END of the
+ first local allocated. Otherwise, it is the offset to the BEGINNING
+ of the first local allocated. */
+
+#define STARTING_FRAME_OFFSET \
+ (STACK_POINTER_OFFSET + current_function_outgoing_args_size)
+
+#define INITIAL_FRAME_POINTER_OFFSET(DEPTH) (DEPTH) = 0
+
+/* If we generate an insn to push BYTES bytes, this says how many the stack
+ pointer really advances by. On S/390, we have no push instruction. */
+
+/* #define PUSH_ROUNDING(BYTES) */
+
+/* Accumulate the outgoing argument count so we can request the right
+ DSA size and determine stack offset. */
+
+#define ACCUMULATE_OUTGOING_ARGS 1
+
+/* Offset from the stack pointer register to an item dynamically
+ allocated on the stack, e.g., by `alloca'.
+
+ The default value for this macro is `STACK_POINTER_OFFSET' plus the
+ length of the outgoing arguments. The default is correct for most
+ machines. See `function.c' for details. */
+#define STACK_DYNAMIC_OFFSET(FUNDECL) (STARTING_FRAME_OFFSET)
+
+/* Offset of first parameter from the argument pointer register value.
+ On the S/390, we define the argument pointer to the start of the fixed
+ area. */
+#define FIRST_PARM_OFFSET(FNDECL) 0
+
+/* Define this if stack space is still allocated for a parameter passed
+ in a register. The value is the number of bytes allocated to this
+ area. */
+/* #define REG_PARM_STACK_SPACE(FNDECL) 32 */
+
+/* Define this if the above stack space is to be considered part of the
+ space allocated by the caller. */
+/* #define OUTGOING_REG_PARM_STACK_SPACE */
+
+/* 1 if N is a possible register number for function argument passing.
+ On S390, general registers 2 - 6 and floating point register 0 and 2
+ are used in this way. */
+
+#define FUNCTION_ARG_REGNO_P(N) (((N) >=2 && (N) <7) || \
+ (N) == 16 || (N) == 17)
+
+/* 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 s390_arg_structure
+{
+ int gprs; /* gpr so far */
+ int fprs; /* fpr so far */
+}
+CUMULATIVE_ARGS;
+
+
+/* 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, NN) \
+ ((CUM).gprs=0, (CUM).fprs=0)
+
+/* Update the data in CUM to advance over an argument of mode MODE and
+ data type TYPE. (TYPE is null for libcalls where that information
+ may not be available.) */
+
+#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
+ s390_function_arg_advance (&CUM, MODE, TYPE, NAMED)
+
+/* Define where to put the arguments to a function. Value is zero to push
+ the argument on the stack, or a hard register in which to store the
+ argument. */
+
+#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
+ s390_function_arg (&CUM, MODE, TYPE, NAMED)
+
+/* Define where to expect the arguments of a function. Value is zero, if
+ the argument is on the stack, or a hard register in which the argument
+ is stored. It is the same like FUNCTION_ARG, except for unnamed args
+ That means, that all in case of varargs used, the arguments are expected
+ from the stack.
+ S/390 has already space on the stack for args coming in registers,
+ they are pushed in prologue, if needed. */
+
+
+/* Define the `__builtin_va_list' type. */
+
+#define BUILD_VA_LIST_TYPE(VALIST) \
+ (VALIST) = s390_build_va_list ()
+
+/* Implement `va_start' for varargs and stdarg. */
+
+#define EXPAND_BUILTIN_VA_START(stdarg, valist, nextarg) \
+ s390_va_start (stdarg, valist, nextarg)
+
+/* Implement `va_arg'. */
+
+#define EXPAND_BUILTIN_VA_ARG(valist, type) \
+ s390_va_arg (valist, type)
+
+/* For an arg passed partly in registers and partly in memory, this is the
+ number of registers used. For args passed entirely in registers or
+ entirely in memory, zero. */
+
+#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) 0
+
+
+/* Define if returning from a function call automatically pops the
+ arguments described by the number-of-args field in the call. */
+
+#define RETURN_POPS_ARGS(FUNDECL, FUNTYPE, SIZE) 0
+
+
+/* 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 15. */
+
+#define RET_REG(MODE) ((GET_MODE_CLASS (MODE) == MODE_INT \
+ || TARGET_SOFT_FLOAT ) ? 2 : 16)
+
+
+/* for structs the address is passed, and the Callee makes a
+ copy, only if needed */
+
+#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \
+ s390_function_arg_pass_by_reference (MODE, TYPE)
+
+
+/* Register 2 (and 3) for integral values
+ or floating point register 0 (and 2) for fp values are used. */
+
+#define FUNCTION_VALUE(VALTYPE, FUNC) \
+ gen_rtx_REG ((INTEGRAL_TYPE_P (VALTYPE) \
+ && TYPE_PRECISION (VALTYPE) < BITS_PER_WORD) \
+ || POINTER_TYPE_P (VALTYPE) \
+ ? word_mode : TYPE_MODE (VALTYPE), \
+ TREE_CODE (VALTYPE) == REAL_TYPE && TARGET_HARD_FLOAT ? 16 : 2)
+
+/* Define how to find the value returned by a library function assuming
+ the value has mode MODE. */
+
+#define LIBCALL_VALUE(MODE) gen_rtx (REG, MODE, RET_REG (MODE))
+
+/* 1 if N is a possible register number for a function value. */
+
+#define FUNCTION_VALUE_REGNO_P(N) ((N) == 2 || (N) == 16)
+
+/* The definition of this macro implies that there are cases where
+ a scalar value cannot be returned in registers. */
+
+#define RETURN_IN_MEMORY(type) \
+ (TYPE_MODE (type) == BLKmode || \
+ GET_MODE_CLASS (TYPE_MODE (type)) == MODE_COMPLEX_INT || \
+ GET_MODE_CLASS (TYPE_MODE (type)) == MODE_COMPLEX_FLOAT)
+
+/* Mode of stack savearea.
+ FUNCTION is VOIDmode because calling convention maintains SP.
+ BLOCK needs Pmode for SP.
+ NONLOCAL needs twice Pmode to maintain both backchain and SP. */
+
+#define STACK_SAVEAREA_MODE(LEVEL) \
+ (LEVEL == SAVE_FUNCTION ? VOIDmode \
+ : LEVEL == SAVE_NONLOCAL ? (TARGET_64BIT ? TImode : DImode) : Pmode)
+
+/* Structure value address is passed as invisible first argument (gpr 2). */
+
+#define STRUCT_VALUE 0
+
+/* This macro definition sets up a default value for `main' to return. */
+
+#define DEFAULT_MAIN_RETURN c_expand_return (integer_zero_node)
+
+/* Length in units of the trampoline for entering a nested function. */
+
+#define TRAMPOLINE_SIZE (TARGET_64BIT ? 36 : 20)
+
+/* Initialize the dynamic part of trampoline. */
+
+#define INITIALIZE_TRAMPOLINE(ADDR, FNADDR, CXT) \
+ s390_initialize_trampoline ((ADDR), (FNADDR), (CXT))
+
+/* Template for constant part of trampoline. */
+
+#define TRAMPOLINE_TEMPLATE(FILE) \
+ s390_trampoline_template (FILE)
+
+/* Output assembler code to FILE to increment profiler label # LABELNO
+ for profiling a function entry. */
+
+#define FUNCTION_PROFILER(FILE, LABELNO) \
+do { \
+ extern rtx s390_profile[]; \
+ extern s390_pool_count; \
+ rtx tmp; \
+ static char label[128]; \
+ fprintf (FILE, "# function profiler \n"); \
+ if (TARGET_64BIT) \
+ { \
+ rtx tmp[1]; \
+ output_asm_insn ("stg\t14,8(15)", tmp); \
+ sprintf (label, "%sP%d", LPREFIX, LABELNO); \
+ tmp[0] = gen_rtx_SYMBOL_REF (Pmode, label); \
+ SYMBOL_REF_FLAG (tmp[0]) = 1; \
+ output_asm_insn ("larl\t1,%0", tmp); \
+ tmp[0] = gen_rtx_SYMBOL_REF (Pmode, "_mcount"); \
+ if (flag_pic) \
+ { \
+ tmp[0] = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, tmp[0]), 113); \
+ tmp[0] = gen_rtx_CONST (Pmode, tmp[0]); \
+ } \
+ output_asm_insn ("brasl\t14,%0", tmp); \
+ output_asm_insn ("lg\t14,8(15)", tmp); \
+ } \
+ else \
+ { \
+ output_asm_insn ("l 14,4(15)", s390_profile); \
+ s390_pool_count = 0; \
+ output_asm_insn ("st 14,4(15)", s390_profile); \
+ output_asm_insn ("l 14,%4", s390_profile); \
+ output_asm_insn ("l 1,%9", s390_profile); \
+ if (flag_pic) \
+ { \
+ output_asm_insn ("ar 1,13", s390_profile); \
+ output_asm_insn ("bas 14,0(14,13)", s390_profile); \
+ } \
+ else \
+ { \
+ output_asm_insn ("basr 14,14", s390_profile); \
+ } \
+ output_asm_insn ("l 14,4(15)", s390_profile); \
+ } \
+} while (0)
+
+/* #define PROFILE_BEFORE_PROLOGUE */
+
+/* There are three profiling modes for basic blocks available.
+ The modes are selected at compile time by using the options
+ -a or -ax of the gnu compiler.
+ The variable `profile_block_flag' will be set according to the
+ selected option.
+
+ profile_block_flag == 0, no option used:
+
+ No profiling done.
+
+ profile_block_flag == 1, -a option used.
+
+ Count frequency of execution of every basic block.
+
+ profile_block_flag == 2, -ax option used.
+
+ Generate code to allow several different profiling modes at run time.
+ Available modes are:
+ Produce a trace of all basic blocks.
+ Count frequency of jump instructions executed.
+ In every mode it is possible to start profiling upon entering
+ certain functions and to disable profiling of some other functions.
+
+ The result of basic-block profiling will be written to a file `bb.out'.
+ If the -ax option is used parameters for the profiling will be read
+ from file `bb.in'.
+
+*/
+
+/* The following macro shall output assembler code to FILE
+ to initialize basic-block profiling.
+
+ If profile_block_flag == 2
+
+ Output code to call the subroutine `__bb_init_trace_func'
+ and pass two parameters to it. The first parameter is
+ the address of a block allocated in the object module.
+ The second parameter is the number of the first basic block
+ of the function.
+
+ The name of the block is a local symbol made with this statement:
+
+ ASM_GENERATE_INTERNAL_LABEL (BUFFER, "LPBX", 0);
+
+ Of course, since you are writing the definition of
+ `ASM_GENERATE_INTERNAL_LABEL' as well as that of this macro, you
+ can take a short cut in the definition of this macro and use the
+ name that you know will result.
+
+ The number of the first basic block of the function is
+ passed to the macro in BLOCK_OR_LABEL.
+
+ If described in a virtual assembler language the code to be
+ output looks like:
+
+ parameter1 <- LPBX0
+ parameter2 <- BLOCK_OR_LABEL
+ call __bb_init_trace_func
+
+ else if profile_block_flag != 0
+
+ Output code to call the subroutine `__bb_init_func'
+ and pass one single parameter to it, which is the same
+ as the first parameter to `__bb_init_trace_func'.
+
+ The first word of this parameter is a flag which will be nonzero if
+ the object module has already been initialized. So test this word
+ first, and do not call `__bb_init_func' if the flag is nonzero.
+ Note: When profile_block_flag == 2 the test need not be done
+ but `__bb_init_trace_func' *must* be called.
+
+ BLOCK_OR_LABEL may be used to generate a label number as a
+ branch destination in case `__bb_init_func' will not be called.
+
+ If described in a virtual assembler language the code to be
+ output looks like:
+
+ cmp (LPBX0),0
+ jne local_label
+ parameter1 <- LPBX0
+ call __bb_init_func
+local_label:
+
+*/
+
+#undef FUNCTION_BLOCK_PROFILER
+#define FUNCTION_BLOCK_PROFILER(FILE, BLOCK_OR_LABEL) \
+do \
+ { \
+ if (TARGET_64BIT) \
+ { \
+ rtx tmp[1]; \
+ fprintf (FILE, "# function block profiler %d \n", profile_block_flag); \
+ output_asm_insn ("ipm 0", tmp); \
+ output_asm_insn ("aghi 15,-224", tmp); \
+ output_asm_insn ("stmg 14,5,160(15)", tmp); \
+ output_asm_insn ("larl 2,.LPBX0", tmp); \
+ switch (profile_block_flag) \
+ { \
+ case 2: \
+ if (BLOCK_OR_LABEL < 0x10000) { \
+ tmp[0] = gen_rtx_CONST_INT (Pmode, (BLOCK_OR_LABEL)); \
+ output_asm_insn ("llill 3,%x0", tmp); \
+ } else { \
+ int bo = BLOCK_OR_LABEL; \
+ tmp[0] = gen_rtx_CONST_INT (Pmode, bo&0x7fff); \
+ output_asm_insn ("llill 3,%x0", tmp); \
+ tmp[0] = gen_rtx_CONST_INT (Pmode, (bo&0xffff0000)>>16); \
+ output_asm_insn ("iilh 3,%x0", tmp); \
+ } \
+ tmp[0] = gen_rtx_SYMBOL_REF (Pmode, "__bb_init_trace_func"); \
+ if (flag_pic) \
+ { \
+ tmp[0] = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, tmp[0]), 113); \
+ tmp[0] = gen_rtx_CONST (Pmode, tmp[0]); \
+ } \
+ output_asm_insn ("brasl\t14,%0", tmp); \
+ break; \
+ default: \
+ output_asm_insn ("cli 7(2),0", tmp); \
+ output_asm_insn ("jne 2f", tmp); \
+ tmp[0] = gen_rtx_SYMBOL_REF (Pmode, "__bb_init_func"); \
+ if (flag_pic) \
+ { \
+ tmp[0] = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, tmp[0]), 113); \
+ tmp[0] = gen_rtx_CONST (Pmode, tmp[0]); \
+ } \
+ output_asm_insn ("brasl\t14,%0", tmp); \
+ break; \
+ } \
+ output_asm_insn ("2:", tmp); \
+ output_asm_insn ("lmg 14,5,160(15)", tmp); \
+ output_asm_insn ("aghi 15,224", tmp); \
+ output_asm_insn ("spm 0", tmp); \
+ } \
+ else \
+ { \
+ extern rtx s390_profile[]; \
+ fprintf (FILE, "# function block profiler %d \n", profile_block_flag); \
+ output_asm_insn ("ipm 0", s390_profile); \
+ output_asm_insn ("ahi 15,-128", s390_profile); \
+ output_asm_insn ("stm 14,5,96(15)", s390_profile); \
+ output_asm_insn ("l 2,%6", s390_profile); \
+ if (flag_pic) \
+ output_asm_insn ("ar 2,13", s390_profile); \
+ switch (profile_block_flag) \
+ { \
+ case 2: \
+ output_asm_insn ("l 4,%1", s390_profile); \
+ if (BLOCK_OR_LABEL < 0x8000) { \
+ s390_profile[8] = gen_rtx_CONST_INT (Pmode, (BLOCK_OR_LABEL)); \
+ output_asm_insn ("lhi 3,%8", s390_profile); \
+ } else { \
+ int bo = BLOCK_OR_LABEL; \
+ s390_profile[8] = gen_rtx_CONST_INT (Pmode, (bo&0xffff8000)>>15); \
+ output_asm_insn ("lhi 3,%8", s390_profile); \
+ output_asm_insn ("sll 3,15", s390_profile); \
+ s390_profile[8] = gen_rtx_CONST_INT (Pmode, bo&0x7fff); \
+ output_asm_insn ("ahi 3,%8", s390_profile); \
+ } \
+ break; \
+ default: \
+ output_asm_insn ("l 4,%0", s390_profile); \
+ output_asm_insn ("cli 3(2),0", s390_profile); \
+ output_asm_insn ("jne 2f", s390_profile); \
+ break; \
+ } \
+ if (flag_pic) \
+ output_asm_insn ("bas 14,0(4,13)", s390_profile); \
+ else \
+ output_asm_insn ("basr 14,4", s390_profile); \
+ output_asm_insn ("2:", s390_profile); \
+ output_asm_insn ("lm 14,5,96(15)", s390_profile); \
+ output_asm_insn ("ahi 15,128", s390_profile); \
+ output_asm_insn ("spm 0", s390_profile); \
+ } \
+ } while (0)
+
+/* The following macro shall output assembler code to FILE
+ to increment a counter associated with basic block number BLOCKNO.
+
+ If profile_block_flag == 2
+
+ Output code to initialize the global structure `__bb' and
+ call the function `__bb_trace_func' which will increment the
+ counter.
+
+ `__bb' consists of two words. In the first word the number
+ of the basic block has to be stored. In the second word
+ the address of a block allocated in the object module
+ has to be stored.
+
+ The basic block number is given by BLOCKNO.
+
+ The address of the block is given by the label created with
+
+ ASM_GENERATE_INTERNAL_LABEL (BUFFER, "LPBX", 0);
+
+ by FUNCTION_BLOCK_PROFILER.
+
+ Of course, since you are writing the definition of
+ `ASM_GENERATE_INTERNAL_LABEL' as well as that of this macro, you
+ can take a short cut in the definition of this macro and use the
+ name that you know will result.
+
+ If described in a virtual assembler language the code to be
+ output looks like:
+
+ move BLOCKNO -> (__bb)
+ move LPBX0 -> (__bb+4)
+ call __bb_trace_func
+
+ Note that function `__bb_trace_func' must not change the
+ machine state, especially the flag register. To grant
+ this, you must output code to save and restore registers
+ either in this macro or in the macros MACHINE_STATE_SAVE
+ and MACHINE_STATE_RESTORE. The last two macros will be
+ used in the function `__bb_trace_func', so you must make
+ sure that the function prologue does not change any
+ register prior to saving it with MACHINE_STATE_SAVE.
+
+ else if profile_block_flag != 0
+
+ Output code to increment the counter directly.
+ Basic blocks are numbered separately from zero within each
+ compiled object module. The count associated with block number
+ BLOCKNO is at index BLOCKNO in an array of words; the name of
+ this array is a local symbol made with this statement:
+
+ ASM_GENERATE_INTERNAL_LABEL (BUFFER, "LPBX", 2);
+
+ Of course, since you are writing the definition of
+ `ASM_GENERATE_INTERNAL_LABEL' as well as that of this macro, you
+ can take a short cut in the definition of this macro and use the
+ name that you know will result.
+
+ If described in a virtual assembler language the code to be
+ output looks like:
+
+ inc (LPBX2+4*BLOCKNO)
+
+*/
+
+#define BLOCK_PROFILER(FILE, BLOCKNO) \
+do \
+ { \
+ if (TARGET_64BIT) \
+ { \
+ rtx tmp[1]; \
+ fprintf (FILE, "# block profiler %d block %d \n", \
+ profile_block_flag, BLOCKNO); \
+ output_asm_insn ("ipm 14", tmp); \
+ output_asm_insn ("aghi 15,-224", tmp); \
+ output_asm_insn ("stmg 14,5,160(15)", tmp); \
+ output_asm_insn ("larl 2,_bb", tmp); \
+ if ((BLOCKNO*8) < 0x10000) { \
+ tmp[0] = gen_rtx_CONST_INT (Pmode, (BLOCKNO*8)); \
+ output_asm_insn ("llill 3,%x0", tmp); \
+ } else { \
+ int bo = BLOCKNO*8; \
+ tmp[0] = gen_rtx_CONST_INT (Pmode, bo&0xffff); \
+ output_asm_insn ("llill 3,%x0", tmp); \
+ tmp[0] = gen_rtx_CONST_INT (Pmode, (bo&0xffff0000)>>16); \
+ output_asm_insn ("iilh 3,%x0", tmp); \
+ } \
+ switch (profile_block_flag) \
+ { \
+ case 2: \
+ output_asm_insn ("stg 3,0(2)", tmp); \
+ output_asm_insn ("larl 3,.LPBX0", tmp); \
+ output_asm_insn ("stg 3,0(2)", tmp); \
+ tmp[0] = gen_rtx_SYMBOL_REF (Pmode, "__bb_trace_func"); \
+ if (flag_pic) \
+ { \
+ tmp[0] = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, tmp[0]), 113); \
+ tmp[0] = gen_rtx_CONST (Pmode, tmp[0]); \
+ } \
+ output_asm_insn ("brasl\t14,%0", tmp); \
+ break; \
+ default: \
+ output_asm_insn ("larl 2,.LPBX2", tmp); \
+ output_asm_insn ("la 2,0(2,3)", tmp); \
+ output_asm_insn ("lg 3,0(2)", tmp); \
+ output_asm_insn ("aghi 3,1", tmp); \
+ output_asm_insn ("stg 3,0(2)", tmp); \
+ break; \
+ } \
+ output_asm_insn ("lmg 14,5,160(15)", tmp); \
+ output_asm_insn ("ahi 15,224", tmp); \
+ output_asm_insn ("spm 14", tmp); \
+ } \
+ else \
+ { \
+ extern rtx s390_profile[]; \
+ fprintf (FILE, "# block profiler %d block %d \n", \
+ profile_block_flag,BLOCKNO); \
+ output_asm_insn ("ipm 14", s390_profile); \
+ output_asm_insn ("ahi 15,-128", s390_profile); \
+ output_asm_insn ("stm 14,5,96(15)", s390_profile); \
+ switch (profile_block_flag) \
+ { \
+ case 2: \
+ output_asm_insn ("l 4,%2", s390_profile); \
+ output_asm_insn ("l 2,%5", s390_profile); \
+ if (flag_pic) \
+ output_asm_insn ("ar 2,13", s390_profile); \
+ if (BLOCKNO < 0x8000) { \
+ s390_profile[7] = gen_rtx_CONST_INT (Pmode, (BLOCKNO)*4); \
+ output_asm_insn ("lhi 3,%8", s390_profile); \
+ } else { \
+ int bo = BLOCKNO; \
+ s390_profile[8] = gen_rtx_CONST_INT (Pmode, (bo&0xffff8000)>>15); \
+ output_asm_insn ("lhi 3,%8", s390_profile); \
+ output_asm_insn ("sll 3,15", s390_profile); \
+ s390_profile[8] = gen_rtx_CONST_INT (Pmode, bo&0x7fff); \
+ output_asm_insn ("ahi 3,%7", s390_profile); \
+ } \
+ output_asm_insn ("st 3,0(2)", s390_profile); \
+ output_asm_insn ("mvc 0(4,2),%5", s390_profile); \
+ if (flag_pic) \
+ output_asm_insn ("bas 14,0(4,13)", s390_profile); \
+ else \
+ output_asm_insn ("basr 14,4", s390_profile); \
+ break; \
+ default: \
+ if (BLOCKNO < 0x2000) { \
+ s390_profile[8] = gen_rtx_CONST_INT (Pmode, (BLOCKNO)*4); \
+ output_asm_insn ("lhi 2,%8", s390_profile); \
+ } else { \
+ int bo = BLOCKNO*4; \
+ s390_profile[8] = gen_rtx_CONST_INT (Pmode, (bo&0xffff8000)>>15); \
+ output_asm_insn ("lhi 2,%8", s390_profile); \
+ output_asm_insn ("sll 2,15", s390_profile); \
+ s390_profile[8] = gen_rtx_CONST_INT (Pmode, bo&0x7fff); \
+ output_asm_insn ("ahi 2,%8", s390_profile); \
+ } \
+ output_asm_insn ("a 2,%7", s390_profile); \
+ if (flag_pic) \
+ output_asm_insn ("l 3,0(2,13)", s390_profile); \
+ else \
+ output_asm_insn ("l 3,0(2)", s390_profile); \
+ output_asm_insn ("ahi 3,1", s390_profile); \
+ if (flag_pic) \
+ output_asm_insn ("st 3,0(2,13)", s390_profile); \
+ else \
+ output_asm_insn ("st 3,0(2)", s390_profile); \
+ break; \
+ } \
+ output_asm_insn ("lm 14,5,96(15)", s390_profile); \
+ output_asm_insn ("ahi 15,128", s390_profile); \
+ output_asm_insn ("spm 14", s390_profile); \
+ } \
+ } while (0)
+
+
+/* The following macro shall output assembler code to FILE
+ to indicate a return from function during basic-block profiling.
+
+ If profiling_block_flag == 2:
+
+ Output assembler code to call function `__bb_trace_ret'.
+
+ Note that function `__bb_trace_ret' must not change the
+ machine state, especially the flag register. To grant
+ this, you must output code to save and restore registers
+ either in this macro or in the macros MACHINE_STATE_SAVE_RET
+ and MACHINE_STATE_RESTORE_RET. The last two macros will be
+ used in the function `__bb_trace_ret', so you must make
+ sure that the function prologue does not change any
+ register prior to saving it with MACHINE_STATE_SAVE_RET.
+
+ else if profiling_block_flag != 0:
+
+ The macro will not be used, so it need not distinguish
+ these cases.
+*/
+
+#define FUNCTION_BLOCK_PROFILER_EXIT(FILE) \
+do { \
+ if (TARGET_64BIT) \
+ { \
+ rtx tmp[1]; \
+ fprintf (FILE, "# block profiler exit \n"); \
+ output_asm_insn ("ipm 14", tmp); \
+ output_asm_insn ("aghi 15,-224", tmp); \
+ output_asm_insn ("stmg 14,5,160(15)", tmp); \
+ tmp[0] = gen_rtx_SYMBOL_REF (Pmode, "__bb_trace_ret"); \
+ if (flag_pic) \
+ { \
+ tmp[0] = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, tmp[0]), 113); \
+ tmp[0] = gen_rtx_CONST (Pmode, tmp[0]); \
+ } \
+ output_asm_insn ("brasl 14,%0", tmp); \
+ output_asm_insn ("lmg 14,5,160(15)", tmp); \
+ output_asm_insn ("aghi 15,224", tmp); \
+ output_asm_insn ("spm 14", tmp); \
+ } \
+ else \
+ { \
+ extern rtx s390_profile[]; \
+ fprintf (FILE, "# block profiler exit \n"); \
+ output_asm_insn ("ipm 14", s390_profile); \
+ output_asm_insn ("ahi 15,-128", s390_profile); \
+ output_asm_insn ("stm 14,5,96(15)", s390_profile); \
+ output_asm_insn ("l 4,%3", s390_profile); \
+ if (flag_pic) \
+ output_asm_insn ("bas 14,0(4,13)", s390_profile); \
+ else \
+ output_asm_insn ("basr 14,4", s390_profile); \
+ output_asm_insn ("lm 14,5,96(15)", s390_profile); \
+ output_asm_insn ("ahi 15,128", s390_profile); \
+ output_asm_insn ("spm 14", s390_profile); \
+ } \
+ } while (0)
+
+/* The function `__bb_trace_func' is called in every basic block
+ and is not allowed to change the machine state. Saving (restoring)
+ the state can either be done in the BLOCK_PROFILER macro,
+ before calling function (rsp. after returning from function)
+ `__bb_trace_func', or it can be done inside the function by
+ defining the macros:
+
+ MACHINE_STATE_SAVE(ID)
+ MACHINE_STATE_RESTORE(ID)
+
+ In the latter case care must be taken, that the prologue code
+ of function `__bb_trace_func' does not already change the
+ state prior to saving it with MACHINE_STATE_SAVE.
+
+ The parameter `ID' is a string identifying a unique macro use.
+
+ On the s390 all save/restore is done in macros above
+*/
+
+/*
+#define MACHINE_STATE_SAVE(ID) \
+ fprintf (FILE, "\tahi 15,-128 # save state\n"); \
+ fprintf (FILE, "\tstm 14,5,96(15)\n"); \
+
+#define MACHINE_STATE_RESTORE(ID) \
+ fprintf (FILE, "\tlm 14,5,96(15) # restore state\n"); \
+ fprintf (FILE, "\tahi 15,128\n"); \
+*/
+
+
+/* Define EXIT_IGNORE_STACK if, when returning from a function, the stack
+ pointer does not matter (provided there is a frame pointer). */
+
+#define EXIT_IGNORE_STACK 1
+
+/* Addressing modes, and classification of registers for them. */
+
+/* #define HAVE_POST_INCREMENT */
+/* #define HAVE_POST_DECREMENT */
+
+/* #define HAVE_PRE_DECREMENT */
+/* #define HAVE_PRE_INCREMENT */
+
+/* These assume that REGNO is a hard or pseudo reg number. They give
+ nonzero only if REGNO is a hard reg of the suitable class or a pseudo
+ reg currently allocated to a suitable hard reg.
+ These definitions are NOT overridden anywhere. */
+
+#define REGNO_OK_FOR_INDEX_P(REGNO) \
+ (((REGNO) > 0 && (REGNO) < 16) || (REGNO) == ARG_POINTER_REGNUM \
+ /* || (REGNO) == FRAME_POINTER_REGNUM */ \
+ || (reg_renumber[REGNO] > 0 && reg_renumber[REGNO] < 16))
+
+#define REGNO_OK_FOR_BASE_P(REGNO) REGNO_OK_FOR_INDEX_P (REGNO)
+
+#define REGNO_OK_FOR_DATA_P(REGNO) \
+ ((REGNO) < 16 || (unsigned) reg_renumber[REGNO] < 16)
+
+#define REGNO_OK_FOR_FP_P(REGNO) \
+ FLOAT_REGNO_P (REGNO)
+
+/* Now macros that check whether X is a register and also,
+ strictly, whether it is in a specified class. */
+
+/* 1 if X is a data register. */
+
+#define DATA_REG_P(X) (REG_P (X) && REGNO_OK_FOR_DATA_P (REGNO (X)))
+
+/* 1 if X is an fp register. */
+
+#define FP_REG_P(X) (REG_P (X) && REGNO_OK_FOR_FP_P (REGNO (X)))
+
+/* 1 if X is an address register. */
+
+#define ADDRESS_REG_P(X) (REG_P (X) && REGNO_OK_FOR_BASE_P (REGNO (X)))
+
+/* Maximum number of registers that can appear in a valid memory address. */
+
+#define MAX_REGS_PER_ADDRESS 2
+
+/* Recognize any constant value that is a valid address. */
+
+#define CONSTANT_ADDRESS_P(X) 0
+
+#define SYMBOLIC_CONST(X) \
+(GET_CODE (X) == SYMBOL_REF \
+ || GET_CODE (X) == LABEL_REF \
+ || (GET_CODE (X) == CONST && symbolic_reference_mentioned_p (X)))
+
+/* General operand is everything except SYMBOL_REF, CONST and CONST_DOUBLE
+ they have to be forced to constant pool
+ CONST_INT have to be forced into constant pool, if greater than
+ 64k. Depending on the insn they have to be force into constant pool
+ for smaller value; in this case we have to work with nonimmediate operand. */
+
+#define LEGITIMATE_PIC_OPERAND_P(X) \
+ legitimate_pic_operand_p (X)
+
+/* 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) \
+ legitimate_constant_p (X)
+
+/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx and check
+ its validity for a certain class. We have two alternate definitions
+ for each of them. The usual definition accepts all pseudo regs; the
+ other rejects them all. The symbol REG_OK_STRICT causes the latter
+ definition to be used.
+
+ Most source files want to accept pseudo regs in the hope that they will
+ get allocated to the class that the insn wants them to be in.
+ Some source files that are used after register allocation
+ need to be strict. */
+
+/*
+ * 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_NONSTRICT_P(X) \
+((GET_MODE (X) == Pmode) && \
+ ((REGNO (X) > 0 && REGNO (X) < 16) || \
+ (REGNO (X) == ARG_POINTER_REGNUM) || \
+ (REGNO (X) >= FIRST_PSEUDO_REGISTER)))
+
+/* Nonzero if X is a hard reg that can be used as a base reg or if it is
+ a pseudo reg. */
+
+#define REG_OK_FOR_BASE_NONSTRICT_P(X) REG_OK_FOR_INDEX_NONSTRICT_P (X)
+
+/* Nonzero if X is a hard reg that can be used as an index. */
+
+#define REG_OK_FOR_INDEX_STRICT_P(X) \
+((GET_MODE (X) == Pmode) && (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_STRICT_P(X) \
+((GET_MODE (X) == Pmode) && (REGNO_OK_FOR_BASE_P (REGNO (X))))
+
+
+#ifndef REG_OK_STRICT
+#define REG_OK_FOR_INDEX_P(X) REG_OK_FOR_INDEX_NONSTRICT_P(X)
+#define REG_OK_FOR_BASE_P(X) REG_OK_FOR_BASE_NONSTRICT_P(X)
+#else
+#define REG_OK_FOR_INDEX_P(X) REG_OK_FOR_INDEX_STRICT_P(X)
+#define REG_OK_FOR_BASE_P(X) REG_OK_FOR_BASE_STRICT_P(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 other macros defined here are used only in GO_IF_LEGITIMATE_ADDRESS,
+ except for CONSTANT_ADDRESS_P which is actually machine-independent. */
+
+#ifdef REG_OK_STRICT
+#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
+{ \
+ if (legitimate_address_p (MODE, X, 1)) \
+ goto ADDR; \
+}
+#else
+#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
+{ \
+ if (legitimate_address_p (MODE, X, 0)) \
+ goto ADDR; \
+}
+#endif
+
+
+/* S/390 has no mode dependent addresses. */
+
+#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL)
+
+/* Try machine-dependent ways of modifying an illegitimate address
+ to be legitimate. If we find one, return the new, valid address.
+ This macro is used in only one place: `memory_address' in explow.c. */
+
+#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \
+{ \
+ (X) = legitimize_address (X, OLDX, MODE); \
+ if (memory_address_p (MODE, X)) \
+ goto WIN; \
+}
+
+/* Specify the machine mode that this machine uses for the index in the
+ tablejump instruction. */
+
+#define CASE_VECTOR_MODE (TARGET_64BIT ? DImode : SImode)
+
+/* Define this if the tablejump instruction expects the table to contain
+ offsets from the address of the table.
+ Do not define this if the table should contain absolute addresses. */
+
+/* #define CASE_VECTOR_PC_RELATIVE */
+
+/* Load from integral MODE < SI from memory into register makes sign_extend
+ or zero_extend
+ In our case sign_extension happens for Halfwords, other no extension. */
+
+#define LOAD_EXTEND_OP(MODE) \
+(TARGET_64BIT ? ((MODE) == QImode ? ZERO_EXTEND : \
+ (MODE) == HImode ? SIGN_EXTEND : NIL) \
+ : ((MODE) == HImode ? SIGN_EXTEND : NIL))
+
+/* Specify the tree operation to be used to convert reals to integers. */
+
+#define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR
+
+/* Define this if fixuns_trunc is the same as fix_trunc. */
+
+/* #define FIXUNS_TRUNC_LIKE_FIX_TRUNC */
+
+/* We use "unsigned char" as default. */
+
+#define DEFAULT_SIGNED_CHAR 0
+
+/* This is the kind of divide that is easiest to do in the general case. */
+
+#define EASY_DIV_EXPR TRUNC_DIV_EXPR
+
+/* Max number of bytes we can move from memory to memory in one reasonably
+ fast instruction. */
+
+#define MOVE_MAX 256
+
+/* Define this if zero-extension is slow (more than one real instruction). */
+
+#define SLOW_ZERO_EXTEND
+
+/* Nonzero if access to memory by bytes is slow and undesirable. */
+
+#define SLOW_BYTE_ACCESS 1
+
+/* Define if shifts truncate the shift count which implies one can omit
+ a sign-extension or zero-extension of a shift count. */
+
+/* #define SHIFT_COUNT_TRUNCATED */
+
+/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
+ is done just by pretending it is already truncated. */
+
+#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
+
+/* We assume that the store-condition-codes instructions store 0 for false
+ and some other value for true. This is the value stored for true. */
+
+/* #define STORE_FLAG_VALUE -1 */
+
+/* When a prototype says `char' or `short', really pass an `int'. */
+
+#define PROMOTE_PROTOTYPES 1
+
+/* Don't perform CSE on function addresses. */
+
+#define NO_FUNCTION_CSE
+
+/* Specify the machine mode that pointers have.
+ After generation of rtl, the compiler makes no further distinction
+ between pointers and any other objects of this machine mode. */
+
+#define Pmode (TARGET_64BIT ? DImode : SImode)
+
+/* A function address in a call instruction is a byte address (for
+ indexing purposes) so give the MEM rtx a byte's mode. */
+
+#define FUNCTION_MODE QImode
+
+
+/* A part of a C `switch' statement that describes the relative costs
+ of constant RTL expressions. It must contain `case' labels for
+ expression codes `const_int', `const', `symbol_ref', `label_ref'
+ and `const_double'. Each case must ultimately reach a `return'
+ statement to return the relative cost of the use of that kind of
+ constant value in an expression. The cost may depend on the
+ precise value of the constant, which is available for examination
+ in X, and the rtx code of the expression in which it is contained,
+ found in OUTER_CODE.
+
+ CODE is the expression code--redundant, since it can be obtained
+ with `GET_CODE (X)'. */
+/* Force_const_mem does not work out of reload, because the saveable_obstack
+ is set to reload_obstack, which does not live long enough.
+ Because of this we cannot use force_const_mem in addsi3.
+ This leads to problems with gen_add2_insn with a constant greater
+ than a short. Because of that we give a addition of greater
+ constants a cost of 3 (reload1.c 10096). */
+
+
+#define CONST_COSTS(RTX, CODE, OUTER_CODE) \
+ case CONST: \
+ if ((GET_CODE (XEXP (RTX, 0)) == MINUS) && \
+ (GET_CODE (XEXP (XEXP (RTX, 0), 1)) != CONST_INT)) \
+ return 1000; \
+ case CONST_INT: \
+ if ((OUTER_CODE == PLUS) && \
+ ((INTVAL (RTX) > 32767) || \
+ (INTVAL (RTX) < -32768))) \
+ return COSTS_N_INSNS (3); \
+ case LABEL_REF: \
+ case SYMBOL_REF: \
+ case CONST_DOUBLE: \
+ return 0; \
+
+
+/* Like `CONST_COSTS' but applies to nonconstant RTL expressions.
+ This can be used, for example, to indicate how costly a multiply
+ instruction is. In writing this macro, you can use the construct
+ `COSTS_N_INSNS (N)' to specify a cost equal to N fast
+ instructions. OUTER_CODE is the code of the expression in which X
+ is contained.
+
+ This macro is optional; do not define it if the default cost
+ assumptions are adequate for the target machine. */
+
+#define RTX_COSTS(X, CODE, OUTER_CODE) \
+ case ASHIFT: \
+ case ASHIFTRT: \
+ case LSHIFTRT: \
+ case PLUS: \
+ case AND: \
+ case IOR: \
+ case XOR: \
+ case MINUS: \
+ case NEG: \
+ case NOT: \
+ return 1; \
+ case MULT: \
+ if (GET_MODE (XEXP (X, 0)) == DImode) \
+ return 40; \
+ else \
+ return 7; \
+ case DIV: \
+ case UDIV: \
+ case MOD: \
+ case UMOD: \
+ return 33;
+
+
+/* An expression giving the cost of an addressing mode that contains
+ ADDRESS. If not defined, the cost is computed from the ADDRESS
+ expression and the `CONST_COSTS' values.
+
+ For most CISC machines, the default cost is a good approximation
+ of the true cost of the addressing mode. However, on RISC
+ machines, all instructions normally have the same length and
+ execution time. Hence all addresses will have equal costs.
+
+ In cases where more than one form of an address is known, the form
+ with the lowest cost will be used. If multiple forms have the
+ same, lowest, cost, the one that is the most complex will be used.
+
+ For example, suppose an address that is equal to the sum of a
+ register and a constant is used twice in the same basic block.
+ When this macro is not defined, the address will be computed in a
+ register and memory references will be indirect through that
+ register. On machines where the cost of the addressing mode
+ containing the sum is no higher than that of a simple indirect
+ reference, this will produce an additional instruction and
+ possibly require an additional register. Proper specification of
+ this macro eliminates this overhead for such machines.
+
+ Similar use of this macro is made in strength reduction of loops.
+
+ ADDRESS need not be valid as an address. In such a case, the cost
+ is not relevant and can be any value; invalid addresses need not be
+ assigned a different cost.
+
+ On machines where an address involving more than one register is as
+ cheap as an address computation involving only one register,
+ defining `ADDRESS_COST' to reflect this can cause two registers to
+ be live over a region of code where only one would have been if
+ `ADDRESS_COST' were not defined in that manner. This effect should
+ be considered in the definition of this macro. Equivalent costs
+ should probably only be given to addresses with different numbers
+ of registers on machines with lots of registers.
+
+ This macro will normally either not be defined or be defined as a
+ constant.
+
+ On s390 symbols are expensive if compiled with fpic
+ lifetimes. */
+
+#define ADDRESS_COST(RTX) \
+ ((flag_pic && GET_CODE (RTX) == SYMBOL_REF) ? 2 : 1)
+
+/* On s390, copy between fprs and gprs is expensive. */
+
+#define REGISTER_MOVE_COST(MODE, CLASS1, CLASS2) \
+ (((CLASS1 != CLASS2) && \
+ (CLASS1 == FP_REGS || CLASS2 == FP_REGS)) ? 10 : 1)
+
+
+/* A C expression for the cost of moving data of mode M between a
+ register and memory. A value of 2 is the default; this cost is
+ relative to those in `REGISTER_MOVE_COST'.
+
+ If moving between registers and memory is more expensive than
+ between two registers, you should define this macro to express the
+ relative cost. */
+
+#define MEMORY_MOVE_COST(M, C, I) 1
+
+/* A C expression for the cost of a branch instruction. A value of 1
+ is the default; other values are interpreted relative to that. */
+
+#define BRANCH_COST 1
+
+/* Add any extra modes needed to represent the condition code. */
+#define EXTRA_CC_MODES \
+ CC (CCZmode, "CCZ") \
+ CC (CCAmode, "CCA") \
+ CC (CCUmode, "CCU") \
+ CC (CCSmode, "CCS") \
+ CC (CCTmode, "CCT")
+
+/* 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) \
+ ( (OP) == EQ || (OP) == NE ? CCZmode \
+ : (OP) == LE || (OP) == LT || \
+ (OP) == GE || (OP) == GT ? CCSmode \
+ : (OP) == LEU || (OP) == LTU || \
+ (OP) == GEU || (OP) == GTU ? CCUmode \
+ : CCmode )
+
+
+/* Define the information needed to generate branch and scc insns. This is
+ stored from the compare operation. Note that we can't use "rtx" here
+ since it hasn't been defined! */
+
+extern struct rtx_def *s390_compare_op0, *s390_compare_op1;
+
+extern int s390_match_ccmode PARAMS ((struct rtx_def *, int));
+
+
+/* How to refer to registers in assembler output. This sequence is
+ indexed by compiler's hard-register-number (see above). */
+
+#define REGISTER_NAMES \
+{ "%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7", \
+ "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", \
+ "%f0", "%f2", "%f4", "%f6", "%f1", "%f3", "%f5", "%f7", \
+ "%f8", "%f10", "%f12", "%f14", "%f9", "%f11", "%f13", "%f15", \
+ "%ap", "%cc" \
+}
+
+/* implicit call of memcpy, not bcopy */
+
+#define TARGET_MEM_FUNCTIONS
+
+
+/* Define results of standard character escape sequences. */
+
+#define TARGET_BELL (0x07)
+#define TARGET_BS (0x08)
+#define TARGET_TAB (0x09)
+#define TARGET_NEWLINE (0x0A)
+#define TARGET_VT 11
+#define TARGET_FF 12
+#define TARGET_CR 13
+
+/* 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) print_operand (FILE, X, CODE)
+
+#define PRINT_OPERAND_ADDRESS(FILE, ADDR) print_operand_address (FILE, ADDR)
+
+
+/* Define the codes that are matched by predicates in aux-output.c. */
+
+#define PREDICATE_CODES \
+ {"s_operand", { MEM }}, \
+ {"bras_sym_operand",{ SYMBOL_REF, CONST }}, \
+ {"r_or_s_operand", { MEM, SUBREG, REG }}, \
+ {"r_or_im8_operand", { CONST_INT, SUBREG, REG }}, \
+ {"r_or_s_or_im8_operand", { MEM, SUBREG, REG, CONST_INT }}, \
+ {"r_or_x_or_im16_operand", { MEM, SUBREG, REG, CONST_INT }}, \
+ {"const0_operand", { CONST_INT, CONST_DOUBLE }}, \
+ {"const1_operand", { CONST_INT, CONST_DOUBLE }}, \
+ {"tmxx_operand", { CONST_INT, MEM }},
+
+
+/* A C statement (sans semicolon) to update the integer variable COST
+ based on the relationship between INSN that is dependent on
+ DEP_INSN through the dependence LINK. The default is to make no
+ adjustment to COST. This can be used for example to specify to
+ the scheduler that an output- or anti-dependence does not incur
+ the same cost as a data-dependence. */
+
+#define ADJUST_COST(insn, link, dep_insn, cost) \
+ (cost) = s390_adjust_cost (insn, link, dep_insn, cost)
+
+
+/* Constant Pool for all symbols operands which are changed with
+ force_const_mem during insn generation (expand_insn). */
+
+extern struct rtx_def *s390_pool_start_insn;
+extern int s390_pool_count;
+extern int s390_nr_constants;
+
+/* Function is splitted in chunk, if literal pool could overflow
+ Value need to be lowered, if problems with displacement overflow. */
+
+#define S390_REL_MAX 55000
+#define S390_CHUNK_MAX 0x2000
+#define S390_CHUNK_OV 0x8000
+#define S390_POOL_MAX 0xe00
+
+#define ASM_OUTPUT_POOL_PROLOGUE(FILE, FUNNAME, fndecl, size) \
+{ \
+ register rtx insn; \
+ struct pool_constant *pool; \
+ \
+ if (s390_pool_count == -1) \
+ { \
+ s390_nr_constants = 0; \
+ for (pool = first_pool; pool; pool = pool->next) \
+ if (pool->mark) s390_nr_constants++; \
+ return; \
+ } \
+ if (first_pool == 0) { \
+ s390_asm_output_pool_prologue (FILE, FUNNAME, fndecl, size); \
+ return; \
+ } \
+ for (pool = first_pool; pool; pool = pool->next) \
+ pool->mark = 0; \
+ \
+ insn = s390_pool_start_insn; \
+ \
+ if (insn==NULL_RTX) \
+ insn = get_insns (); \
+ else \
+ insn = NEXT_INSN (insn); \
+ for (; insn; insn = NEXT_INSN (insn)) { \
+ if (GET_RTX_CLASS (GET_CODE (insn)) == 'i') { \
+ if (s390_stop_dump_lit_p (insn)) { \
+ mark_constants (PATTERN (insn)); \
+ break; \
+ } else \
+ mark_constants (PATTERN (insn)); \
+ } \
+ } \
+ \
+ /* Mark entries referenced by other entries */ \
+ for (pool = first_pool; pool; pool = pool->next) \
+ if (pool->mark) \
+ mark_constants (pool->constant); \
+ \
+ s390_asm_output_pool_prologue (FILE, FUNNAME, fndecl, size); \
+}
+
+/* We need to return, because otherwise the pool is deleted of the
+ constant pool after the first output. */
+
+#define ASM_OUTPUT_POOL_EPILOGUE(FILE, FUNNAME, fndecl, size) return;
+
+#define ASM_OUTPUT_SPECIAL_POOL_ENTRY(FILE, EXP, MODE, ALIGN, LABELNO, WIN) \
+{ \
+ if ((s390_pool_count == 0) || (s390_pool_count > 0 && LABELNO >= 0)) \
+ { \
+ fprintf (FILE, ".LC%d:\n", LABELNO); \
+ LABELNO = ~LABELNO; \
+ } \
+ if (s390_pool_count > 0) \
+ { \
+ fprintf (FILE, ".LC%d_%X:\n", ~LABELNO, s390_pool_count); \
+ } \
+ \
+ /* Output the value of the constant itself. */ \
+ switch (GET_MODE_CLASS (pool->mode)) \
+ { \
+ case MODE_FLOAT: \
+ if (GET_CODE (x) != CONST_DOUBLE) \
+ abort (); \
+ \
+ memcpy ((char *) &u, (char *) &CONST_DOUBLE_LOW (x), sizeof u); \
+ assemble_real (u.d, pool->mode); \
+ break; \
+ \
+ case MODE_INT: \
+ case MODE_PARTIAL_INT: \
+ if (flag_pic && (GET_CODE (x) == CONST || \
+ GET_CODE (x) == SYMBOL_REF || \
+ GET_CODE (x) == LABEL_REF )) \
+ { \
+ fprintf (FILE, "%s\t",TARGET_64BIT ? ASM_QUAD : ASM_LONG); \
+ s390_output_symbolic_const (FILE, x); \
+ fputc ('\n', (FILE)); \
+ } \
+ else \
+ assemble_integer (x, GET_MODE_SIZE (pool->mode), 1); \
+ break; \
+ \
+ default: \
+ abort (); \
+ } \
+ goto WIN; \
+}
+
+#endif
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
new file mode 100644
index 00000000000..a5bf0faea4c
--- /dev/null
+++ b/gcc/config/s390/s390.md
@@ -0,0 +1,5882 @@
+;;- Machine description for GNU compiler -- S/390 / zSeries version.
+;; Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
+;; Contributed by Hartmut Penner (hpenner@de.ibm.com) and
+;; Ulrich Weigand (uweigand@de.ibm.com).
+;; This file is part of GNU CC.
+
+;; GNU CC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU CC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU CC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;
+;; Special constraints for s/390 machine description:
+;;
+;; a -- Any address register from 1 to 15.
+;; d -- Any register from 0 to 15.
+;; I -- An 8-bit constant (0..255).
+;; J -- A 12-bit constant (0..4095).
+;; K -- A 16-bit constant (-32768..32767).
+;; Q -- A memory reference without index-register.
+;; S -- Valid operand for the LARL instruction.
+;;
+;; Special formats used for outputting 390 instructions.
+;;
+;; %b -- Print a constant byte integer. xy
+;; %h -- Print a signed 16-bit. wxyz
+;; %N -- Print next register (second word of a DImode reg) or next word.
+;; %M -- Print next register (second word of a TImode reg) or next word.
+;; %O -- Print the offset of a memory reference (PLUS (REG) (CONST_INT)).
+;; %R -- Print the register of a memory reference (PLUS (REG) (CONST_INT)).
+;;
+;; We have a special constraint for pattern matching.
+;;
+;; s_operand -- Matches a valid S operand in a RS, SI or SS type instruction.
+;;
+;; r_or_s_operand -- Matches a register or a valid S operand in a RS, SI
+;; or SS type instruction or a register
+;;
+
+;; Insn type. Used to default other attribute values.
+
+;
+; Insn are devide in two classes:
+; mem: Use of base and/or index register for address generation
+; reg: Use of second and third register not for address generation
+;
+
+(define_attr "atype" "mem,reg" (const_string "reg"))
+
+;
+; Insn may take 1,2,3 or many cycles
+; For the scheduling it does not matter, if a instruction has
+; a issue_delay from 4 or more cycles, since the address dependency
+; between two insns needs at least 4 cycles.
+;
+
+(define_attr "cycle" "1,2,3,n" (const_string "1"))
+
+;
+; There are three classes of insns:
+; set: instruction setting a (potential) address relevant register
+; xset: instruction setting no address relevant register
+; la: instruction setting a (potential) address relevant register,
+; but behave 'better' on the pipeline
+;
+
+(define_attr "type" "set,xset,la" (const_string "xset"))
+
+;
+; Set operations changing a target register, which could be used for
+; address generation. Adjust cost will check, if realy applicable.
+;
+
+(define_function_unit "memory" 1 0
+ (and (eq_attr "type" "set")
+ (eq_attr "cycle" "1"))
+ 5 1 [(eq_attr "atype" "mem")] )
+
+(define_function_unit "memory" 1 0
+ (and (eq_attr "type" "set")
+ (eq_attr "cycle" "2")) 5 2)
+
+(define_function_unit "memory" 1 0
+ (and (eq_attr "type" "set")
+ (eq_attr "cycle" "3")) 5 3)
+
+(define_function_unit "memory" 1 0
+ (and (eq_attr "type" "set")
+ (eq_attr "cycle" "n")) 5 4)
+
+(define_function_unit "memory" 1 0
+ (eq_attr "type" "la") 2 1)
+
+;
+; xset insns, which don't set any valid address register.
+; Only the issue delay matters.
+;
+
+(define_function_unit "memory" 1 0
+ (and (eq_attr "type" "xset")
+ (eq_attr "cycle" "1")) 1 1)
+
+(define_function_unit "memory" 1 0
+ (and (eq_attr "type" "xset")
+ (eq_attr "cycle" "2")) 1 2)
+
+(define_function_unit "memory" 1 0
+ (and (eq_attr "type" "xset")
+ (eq_attr "cycle" "3")) 1 3)
+
+(define_function_unit "memory" 1 0
+ (and (eq_attr "type" "xset")
+ (eq_attr "cycle" "n")) 1 4)
+
+; Operand type. Used to default length attribute values
+
+(define_attr "op_type"
+ "NN,E,RR,RRE,RX,RS,RSI,RI,SI,S,SS,SSE,RXE,RSE,RIL,RIE"
+ (const_string "RX"))
+
+;; Length in bytes.
+
+(define_attr "length" ""
+(cond [ (eq_attr "op_type" "E") (const_int 2)
+ (eq_attr "op_type" "RR") (const_int 2)
+ (eq_attr "op_type" "RX") (const_int 4)
+ (eq_attr "op_type" "RI") (const_int 4)
+ (eq_attr "op_type" "RRE") (const_int 4)
+ (eq_attr "op_type" "RS") (const_int 4)
+ (eq_attr "op_type" "RSI") (const_int 4)
+ (eq_attr "op_type" "RX") (const_int 4)
+ (eq_attr "op_type" "S") (const_int 4)
+ (eq_attr "op_type" "SI") (const_int 4)
+ (eq_attr "op_type" "SS") (const_int 6)
+ (eq_attr "op_type" "SSE") (const_int 6)
+ (eq_attr "op_type" "RXE") (const_int 6)
+ (eq_attr "op_type" "RSE") (const_int 6)
+ (eq_attr "op_type" "RIL") (const_int 6)]
+ (const_int 4)))
+
+;; Define attributes for `asm' insns.
+
+(define_asm_attributes [(set_attr "type" "xset")
+ (set_attr "op_type" "NN")])
+
+;;
+;; Condition Codes
+;;
+;
+; CCL: Zero Nonzero Zero Nonzero (AL, ALR, SL, SLR, N, NC, NI, NR, O, OC, OI, OR, X, XC, XI, XR)
+; CCA: Zero <Zero >Zero Overflow (A, AR, AH, AHI, S, SR, SH, SHI, LTR, LCR, LNR, LPR, SLA, SLDA, SLA, SRDA)
+; CCU: Equal ULess UGreater -- (CL, CLR, CLI, CLM)
+; CCS: Equal SLess SGreater -- (C, CR, CH, CHI, ICM)
+; CCT: Zero Mixed Mixed Ones (TM, TMH, TML)
+
+; CCZ -> CCL / CCZ1
+; CCZ1 -> CCA/CCU/CCS/CCT
+; CCS -> CCA
+
+; String: CLC, CLCL, CLCLE, CLST, CUSE, MVCL, MVCLE, MVPG, MVST, SRST
+; Clobber: CKSM, CFC, CS, CDS, CUUTF, CUTFU, PLO, SPM, STCK, STCKE, TS, TRT, TRE, UPT
+
+
+;;
+;;- Compare instructions.
+;;
+
+(define_expand "cmpdi"
+ [(set (reg:CC 33)
+ (compare:CC (match_operand:DI 0 "register_operand" "")
+ (match_operand:DI 1 "general_operand" "")))]
+ "TARGET_64BIT"
+ "
+{
+ s390_compare_op0 = operands[0];
+ s390_compare_op1 = operands[1];
+ DONE;
+}")
+
+(define_expand "cmpsi"
+ [(set (reg:CC 33)
+ (compare:CC (match_operand:SI 0 "register_operand" "")
+ (match_operand:SI 1 "general_operand" "")))]
+ ""
+ "
+{
+ s390_compare_op0 = operands[0];
+ s390_compare_op1 = operands[1];
+ DONE;
+}")
+
+;(define_expand "cmphi"
+; [(set (reg:CC 33)
+; (compare:CC (match_operand:HI 0 "register_operand" "")
+; (match_operand:HI 1 "general_operand" "")))]
+; ""
+; "
+;{
+; s390_compare_op0 = operands[0];
+; s390_compare_op1 = operands[1];
+; DONE;
+;}")
+
+;(define_expand "cmpqi"
+; [(set (reg:CC 33)
+; (compare:CC (match_operand:QI 0 "register_operand" "")
+; (match_operand:QI 1 "general_operand" "")))]
+; ""
+; "
+;{
+; s390_compare_op0 = operands[0];
+; s390_compare_op1 = operands[1];
+; DONE;
+;}")
+
+(define_expand "cmpdf"
+ [(set (reg:CC 33)
+ (compare:CC (match_operand:DF 0 "register_operand" "")
+ (match_operand:DF 1 "general_operand" "")))]
+ "TARGET_HARD_FLOAT"
+ "
+{
+ s390_compare_op0 = operands[0];
+ s390_compare_op1 = operands[1];
+ DONE;
+}")
+
+(define_expand "cmpsf"
+ [(set (reg:CC 33)
+ (compare:CC (match_operand:SF 0 "register_operand" "")
+ (match_operand:SF 1 "general_operand" "")))]
+ "TARGET_HARD_FLOAT"
+ "
+{
+ s390_compare_op0 = operands[0];
+ s390_compare_op1 = operands[1];
+ DONE;
+}")
+
+
+; DI instructions
+
+(define_insn "*cmpdi_tm2"
+ [(set (reg 33)
+ (compare (zero_extract:DI (match_operand:DI 0 "register_operand" "d")
+ (match_operand:DI 1 "const1_operand" "")
+ (match_operand:DI 2 "immediate_operand" "I"))
+ (const_int 0)))]
+ "s390_match_ccmode(insn, CCTmode) &&
+ INTVAL(operands[2]) >= 0 && INTVAL(operands[2]) < 64"
+ "*
+{
+ if (INTVAL (operands[2]) > 47)
+ {
+ operands[1] = GEN_INT (1 << (63 - INTVAL(operands[2])));
+ return \"tmll\\t%0,%x1\";
+ }
+ else if (INTVAL (operands[2]) > 31)
+ {
+ operands[1] = GEN_INT (1 << (47 - INTVAL(operands[2])));
+ return \"tmlh\\t%0,%x1\";
+ }
+ else if (INTVAL (operands[2]) > 15)
+ {
+ operands[1] = GEN_INT (1 << (31 - INTVAL(operands[2])));
+ return \"tmhl\\t%0,%x1\";
+ }
+ operands[1] = GEN_INT (1 << (15 - INTVAL(operands[2])));
+ return \"tmhh\\t%0,%x1\";
+}"
+ [(set_attr "op_type" "RX")
+ (set_attr "type" "xset")])
+
+
+(define_insn "*cmpdi_tm"
+ [(set (reg 33)
+ (compare (and:DI (match_operand:DI 0 "register_operand" "%d")
+ (match_operand:DI 1 "tmxx_operand" "Lm"))
+ (const_int 0)))]
+ "s390_match_ccmode(insn, CCTmode)"
+ "*
+{
+ unsigned HOST_WIDEST_INT i;
+ if (GET_CODE (operands[1]) == MEM &&
+ GET_CODE (XEXP (operands[1],0)) == SYMBOL_REF &&
+ CONSTANT_POOL_ADDRESS_P (XEXP (operands[1],0)))
+ {
+ operands[1] = get_pool_constant (XEXP (operands[1],0));
+ }
+
+ i = (unsigned HOST_WIDEST_INT) INTVAL (operands[1]);
+
+ if (i >= 0x1000000000000ULL)
+ {
+ operands[1] = GEN_INT (i >> 48);
+ return \"tmhh\\t%0,%x1\";
+ }
+ else if (i > 0x100000000ULL)
+ {
+ operands[1] = GEN_INT (i >> 32);
+ return \"tmhl\\t%0,%x1\";
+ }
+ else if (i >= 0x10000ULL)
+ {
+ operands[1] = GEN_INT (i >> 16);
+ return \"tmlh\\t%0,%x1\";
+ }
+ else
+ return \"tmll\\t%0,%x1\";
+}"
+ [(set_attr "op_type" "RX")
+ (set_attr "type" "xset")])
+
+
+(define_insn "*ltgr"
+ [(set (reg 33)
+ (compare (match_operand:DI 0 "register_operand" "d")
+ (match_operand:DI 1 "const0_operand" "")))
+ (set (match_operand:DI 2 "register_operand" "=d")
+ (match_dup 0))]
+ "s390_match_ccmode(insn, CCSmode) && TARGET_64BIT"
+ "ltgr\\t%2,%0"
+ [(set_attr "op_type" "RRE")
+ (set_attr "type" "set")])
+
+(define_insn "*cmpdi_ccs_0_64"
+ [(set (reg 33)
+ (compare (match_operand:DI 0 "register_operand" "d")
+ (match_operand:DI 1 "const0_operand" "")))]
+ "s390_match_ccmode(insn, CCSmode) && TARGET_64BIT"
+ "ltgr\\t%0,%0"
+ [(set_attr "op_type" "RRE")
+ (set_attr "type" "set")])
+
+(define_insn "*cmpdi_ccs_0_31"
+ [(set (reg 33)
+ (compare (match_operand:DI 0 "register_operand" "d")
+ (match_operand:DI 1 "const0_operand" "")))]
+ "s390_match_ccmode(insn, CCSmode)"
+ "srda\\t%0,0"
+ [(set_attr "op_type" "RS")
+ (set_attr "type" "set")])
+
+(define_insn "*cmpdi_ccs"
+ [(set (reg 33)
+ (compare (match_operand:DI 0 "register_operand" "d,d,d")
+ (match_operand:DI 1 "general_operand" "d,K,m")))]
+ "s390_match_ccmode(insn, CCSmode) && TARGET_64BIT"
+ "@
+ cgr\\t%0,%1
+ cghi\\t%0,%c1
+ cg\\t%0,%1"
+ [(set_attr "op_type" "RRE,RI,RXE")
+ (set_attr "atype" "reg,reg,mem")])
+
+(define_insn "*cmpdi_ccu"
+ [(set (reg 33)
+ (compare (match_operand:DI 0 "register_operand" "d,d")
+ (match_operand:DI 1 "general_operand" "d,m")))]
+ "s390_match_ccmode(insn, CCUmode) && TARGET_64BIT"
+ "@
+ clgr\\t%0,%1
+ clg\\t%0,%1"
+ [(set_attr "op_type" "RRE,RXE")
+ (set_attr "atype" "reg,mem")])
+
+(define_insn "*cmpdi_ccu_mem"
+ [(set (reg 33)
+ (compare (match_operand:DI 0 "s_operand" "oQ")
+ (match_operand:DI 1 "s_operand" "oQ")))]
+ "s390_match_ccmode(insn, CCUmode)"
+ "clc\\t%O0(8,%R0),%1"
+ [(set_attr "op_type" "SS")
+ (set_attr "atype" "mem")])
+
+; SI instructions
+
+(define_insn "*cmpsi_cct"
+ [(set (reg 33)
+ (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "%d")
+ (match_operand:SI 1 "const1_operand" "")
+ (match_operand:SI 2 "immediate_operand" "I"))
+ (const_int 0)))]
+ "s390_match_ccmode(insn, CCTmode) &&
+ INTVAL(operands[2]) >= 0 && INTVAL(operands[2]) < 32"
+ "*
+{
+ if (INTVAL (operands[2]) > 15)
+ {
+ operands[1] = GEN_INT (1 << (31 - INTVAL(operands[2])));
+ return \"tml\\t%0,%x1\";
+ }
+ operands[1] = GEN_INT (1 << (15 - INTVAL(operands[2])));
+ return \"tmh\\t%0,%x1\";
+}"
+ [(set_attr "op_type" "RI")
+ (set_attr "type" "xset")])
+
+(define_insn "*cmpsi_tm"
+ [(set (reg 33)
+ (compare (and:SI (match_operand:SI 0 "register_operand" "%d")
+ (match_operand:SI 1 "tmxx_operand" "Lm"))
+ (const_int 0)))]
+ "s390_match_ccmode(insn, CCTmode)"
+ "*
+{
+ unsigned long i;
+ if (GET_CODE (operands[1]) == MEM &&
+ GET_CODE (XEXP (operands[1],0)) == SYMBOL_REF &&
+ CONSTANT_POOL_ADDRESS_P (XEXP (operands[1],0)))
+ {
+ operands[1] = get_pool_constant (XEXP (operands[1],0));
+ }
+
+ i = (unsigned long) INTVAL (operands[1]);
+ if (i > 0xffff)
+ {
+ operands[1] = GEN_INT (i / 0x10000);
+ return \"tmh\\t%0,%x1\";
+ }
+ return \"tml\\t%0,%x1\";
+}"
+ [(set_attr "op_type" "RX")
+ (set_attr "type" "xset")])
+
+
+(define_insn "*ltr"
+ [(set (reg 33)
+ (compare (match_operand:SI 0 "register_operand" "d")
+ (match_operand:SI 1 "const0_operand" "")))
+ (set (match_operand:SI 2 "register_operand" "=d")
+ (match_dup 0))]
+ "s390_match_ccmode(insn, CCSmode)"
+ "ltr\\t%2,%0"
+ [(set_attr "op_type" "RR")
+ (set_attr "type" "set")])
+
+(define_insn "*icm15"
+ [(set (reg 33)
+ (compare (match_operand:SI 0 "s_operand" "Qo")
+ (match_operand:SI 1 "const0_operand" "")))
+ (set (match_operand:SI 2 "register_operand" "=d")
+ (match_dup 0))]
+ "s390_match_ccmode(insn, CCSmode)"
+ "icm\\t%2,15,%0"
+ [(set_attr "op_type" "RS")
+ (set_attr "atype" "mem")
+ (set_attr "type" "set")])
+
+(define_insn "*icm15_cconly"
+ [(set (reg 33)
+ (compare (match_operand:SI 0 "s_operand" "Qo")
+ (match_operand:SI 1 "const0_operand" "")))
+ (clobber (match_scratch:SI 2 "=d"))]
+ "s390_match_ccmode(insn, CCSmode)"
+ "icm\\t%2,15,%0"
+ [(set_attr "op_type" "RS")
+ (set_attr "atype" "mem")
+ (set_attr "type" "set")])
+
+(define_insn "*cmpsi_ccs_0"
+ [(set (reg 33)
+ (compare (match_operand:SI 0 "register_operand" "d")
+ (match_operand:SI 1 "const0_operand" "")))]
+ "s390_match_ccmode(insn, CCSmode)"
+ "ltr\\t%0,%0"
+ [(set_attr "op_type" "RR")
+ (set_attr "type" "set")])
+
+(define_insn "*cmpsidi_ccs"
+ [(set (reg 33)
+ (compare (match_operand:SI 0 "register_operand" "d")
+ (sign_extend:SI (match_operand:HI 1 "memory_operand" "m"))))]
+ "s390_match_ccmode(insn, CCSmode)"
+ "ch\\t%0,%1"
+ [(set_attr "op_type" "RR")
+ (set_attr "atype" "mem")
+ (set_attr "type" "xset")])
+
+(define_insn "*cmpsi_ccs"
+ [(set (reg 33)
+ (compare (match_operand:SI 0 "register_operand" "d,d,d")
+ (match_operand:SI 1 "general_operand" "d,K,m")))]
+ "s390_match_ccmode(insn, CCSmode)"
+ "@
+ cr\\t%0,%1
+ chi\\t%0,%c1
+ c\\t%0,%1"
+ [(set_attr "op_type" "RR,RI,RX")
+ (set_attr "atype" "reg,reg,mem")
+ (set_attr "type" "xset,xset,xset")])
+
+(define_insn "*cmpsi_ccu"
+ [(set (reg 33)
+ (compare (match_operand:SI 0 "register_operand" "d,d")
+ (match_operand:SI 1 "general_operand" "d,m")))]
+ "s390_match_ccmode(insn, CCUmode)"
+ "@
+ clr\\t%0,%1
+ cl\\t%0,%1"
+ [(set_attr "op_type" "RR,RX")
+ (set_attr "atype" "reg,mem")])
+
+(define_insn "*cmpsi_ccu_mem"
+ [(set (reg 33)
+ (compare (match_operand:SI 0 "s_operand" "oQ")
+ (match_operand:SI 1 "s_operand" "oQ")))]
+ "s390_match_ccmode(insn, CCUmode)"
+ "clc\\t%O0(4,%R0),%1"
+ [(set_attr "op_type" "SS")
+ (set_attr "atype" "mem")
+ (set_attr "type" "xset")])
+
+
+; HI instructions
+
+(define_insn "*icm3"
+ [(set (reg 33)
+ (compare (match_operand:HI 0 "s_operand" "Qo")
+ (match_operand:HI 1 "const0_operand" "")))
+ (set (match_operand:HI 2 "register_operand" "=d")
+ (match_dup 0))]
+ "s390_match_ccmode(insn, CCSmode)"
+ "icm\\t%2,3,%0"
+ [(set_attr "op_type" "RS")
+ (set_attr "atype" "mem")
+ (set_attr "type" "set")])
+
+(define_insn "*cmphi_cct_0"
+ [(set (reg 33)
+ (compare (match_operand:HI 0 "register_operand" "d")
+ (match_operand:HI 1 "const0_operand" "")))]
+ "s390_match_ccmode(insn, CCTmode)"
+ "tml\\t%0,65535"
+ [(set_attr "op_type" "RX")
+ (set_attr "type" "xset")])
+
+(define_insn "*cmphi_ccs_0"
+ [(set (reg 33)
+ (compare (match_operand:HI 0 "s_operand" "Qo")
+ (match_operand:HI 1 "const0_operand" "")))
+ (clobber (match_scratch:HI 2 "=d"))]
+ "s390_match_ccmode(insn, CCSmode)"
+ "icm\\t%2,3,%0"
+ [(set_attr "op_type" "RS")
+ (set_attr "atype" "mem")
+ (set_attr "type" "set")])
+
+(define_insn "*cmphi_ccu"
+ [(set (reg 33)
+ (compare (match_operand:HI 0 "register_operand" "d")
+ (match_operand:HI 1 "s_operand" "Qo")))]
+ "s390_match_ccmode(insn, CCUmode)"
+ "clm\\t%0,3,%1"
+ [(set_attr "op_type" "RS")
+ (set_attr "atype" "mem")
+ (set_attr "type" "xset")])
+
+(define_insn "*cmphi_ccu_mem"
+ [(set (reg 33)
+ (compare (match_operand:HI 0 "s_operand" "oQ")
+ (match_operand:HI 1 "s_operand" "oQ")))]
+ "s390_match_ccmode(insn, CCUmode)"
+ "clc\\t%O0(2,%R0),%1"
+ [(set_attr "op_type" "SS")
+ (set_attr "atype" "mem")
+ (set_attr "type" "xset")])
+
+
+; QI instructions
+
+(define_insn "*icm1"
+ [(set (reg 33)
+ (compare (match_operand:QI 0 "s_operand" "Qo")
+ (match_operand:QI 1 "const0_operand" "")))
+ (set (match_operand:QI 2 "register_operand" "=d")
+ (match_dup 0))]
+ "s390_match_ccmode(insn, CCSmode)"
+ "icm\\t%2,1,%0"
+ [(set_attr "op_type" "RS")
+ (set_attr "atype" "mem")
+ (set_attr "type" "set")])
+
+(define_insn "*tm_0"
+ [(set (reg 33)
+ (compare (zero_extend:SI (and:QI (match_operand:QI 0 "s_operand" "Qo")
+ (match_operand:QI 1 "immediate_operand" "")))
+ (const_int 0)))]
+ "s390_match_ccmode(insn, CCTmode) &&
+ INTVAL(operands[1]) >= 0 && INTVAL(operands[1]) < 256"
+ "tm\\t%0,%1"
+ [(set_attr "op_type" "RI")
+ (set_attr "atype" "mem")
+ (set_attr "type" "xset")])
+
+(define_insn "*cmpqi_cct_0"
+ [(set (reg 33)
+ (compare (match_operand:QI 0 "register_operand" "d")
+ (match_operand:QI 1 "const0_operand" "")))]
+ "s390_match_ccmode(insn, CCTmode)"
+ "tml\\t%0,255"
+ [(set_attr "op_type" "RI")
+ (set_attr "type" "xset")])
+
+(define_insn "*cmpqi_ccs_0"
+ [(set (reg 33)
+ (compare (match_operand:QI 0 "s_operand" "Qo")
+ (match_operand:QI 1 "const0_operand" "")))
+ (clobber (match_scratch:QI 2 "=d"))]
+ "s390_match_ccmode(insn, CCSmode)"
+ "icm\\t%2,1,%0"
+ [(set_attr "op_type" "RS")
+ (set_attr "type" "xset")])
+
+(define_insn "*cmpqi_ccu_0"
+ [(set (reg 33)
+ (compare (match_operand:QI 0 "s_operand" "Qo")
+ (match_operand:QI 1 "const0_operand" "")))]
+ "s390_match_ccmode(insn, CCUmode)"
+ "cli\\t%0,0"
+ [(set_attr "op_type" "SI")
+ (set_attr "atype" "mem")
+ (set_attr "type" "xset")])
+
+(define_insn "*cmpqi_ccu"
+ [(set (reg 33)
+ (compare (match_operand:QI 0 "register_operand" "d")
+ (match_operand:QI 1 "s_operand" "Qo")))]
+ "s390_match_ccmode(insn, CCUmode)"
+ "clm\\t%0,1,%1"
+ [(set_attr "op_type" "RS")
+ (set_attr "atype" "mem")
+ (set_attr "type" "xset")])
+
+(define_insn "*cmpqi_ccu_immed"
+ [(set (reg 33)
+ (compare (match_operand:QI 0 "s_operand" "Qo")
+ (match_operand:QI 1 "immediate_operand" "")))]
+ "s390_match_ccmode(insn, CCUmode) &&
+ INTVAL(operands[1]) >= 0 && INTVAL(operands[1]) < 256"
+ "cli\\t%0,%1"
+ [(set_attr "op_type" "SI")
+ (set_attr "atype" "mem")
+ (set_attr "type" "xset")])
+
+(define_insn "*cmpqi_ccu_mem"
+ [(set (reg 33)
+ (compare (match_operand:QI 0 "s_operand" "oQ")
+ (match_operand:QI 1 "s_operand" "oQ")))]
+ "s390_match_ccmode(insn, CCUmode)"
+ "clc\\t%O0(1,%R0),%1"
+ [(set_attr "op_type" "SS")
+ (set_attr "atype" "mem")
+ (set_attr "type" "xset")])
+
+
+; DF instructions
+
+(define_insn "*cmpdf_ccs_0"
+ [(set (reg 33)
+ (compare (match_operand:DF 0 "register_operand" "f")
+ (match_operand:DF 1 "const0_operand" "")))]
+ "s390_match_ccmode(insn, CCSmode) && TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+ "ltdbr\\t%0,%0"
+ [(set_attr "op_type" "RR")
+ (set_attr "type" "set")])
+
+(define_insn "*cmpdf_ccs_0_ibm"
+ [(set (reg 33)
+ (compare (match_operand:DF 0 "register_operand" "f")
+ (match_operand:DF 1 "const0_operand" "")))]
+ "s390_match_ccmode(insn, CCSmode) && TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
+ "ltdr\\t%0,%0"
+ [(set_attr "op_type" "RR")
+ (set_attr "type" "set")])
+
+(define_insn "*cmpdf_ccs"
+ [(set (reg 33)
+ (compare (match_operand:DF 0 "register_operand" "f,f")
+ (match_operand:DF 1 "nonimmediate_operand" "f,m")))]
+ "s390_match_ccmode(insn, CCSmode) && TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+ "@
+ cdbr\\t%0,%1
+ cdb\\t%0,%1"
+ [(set_attr "op_type" "RR,RX")
+ (set_attr "atype" "reg,mem")
+ (set_attr "type" "xset,xset")])
+
+(define_insn "*cmpdf_ccs_ibm"
+ [(set (reg 33)
+ (compare (match_operand:DF 0 "register_operand" "f,f")
+ (match_operand:DF 1 "nonimmediate_operand" "f,m")))]
+ "s390_match_ccmode(insn, CCSmode) && TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
+ "@
+ cdr\\t%0,%1
+ cd\\t%0,%1"
+ [(set_attr "op_type" "RR,RX")
+ (set_attr "atype" "reg,mem")
+ (set_attr "type" "xset,xset")])
+
+
+; SF instructions
+
+(define_insn "*cmpsf_ccs_0"
+ [(set (reg 33)
+ (compare (match_operand:SF 0 "register_operand" "f")
+ (match_operand:SF 1 "const0_operand" "")))]
+ "s390_match_ccmode(insn, CCSmode) && TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+ "ltebr\\t%0,%0"
+ [(set_attr "op_type" "RR")
+ (set_attr "type" "set")])
+
+(define_insn "*cmpsf_ccs_0_ibm"
+ [(set (reg 33)
+ (compare (match_operand:SF 0 "register_operand" "f")
+ (match_operand:SF 1 "const0_operand" "")))]
+ "s390_match_ccmode(insn, CCSmode) && TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
+ "lter\\t%0,%0"
+ [(set_attr "op_type" "RR")
+ (set_attr "type" "set")])
+
+(define_insn "*cmpsf_ccs"
+ [(set (reg 33)
+ (compare (match_operand:SF 0 "register_operand" "f,f")
+ (match_operand:SF 1 "nonimmediate_operand" "f,m")))]
+ "s390_match_ccmode(insn, CCSmode) && TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+ "@
+ cebr\\t%0,%1
+ ceb\\t%0,%1"
+ [(set_attr "op_type" "RR,RX")
+ (set_attr "atype" "reg,mem")
+ (set_attr "type" "xset,xset")])
+
+(define_insn "*cmpsf_ccs"
+ [(set (reg 33)
+ (compare (match_operand:SF 0 "register_operand" "f,f")
+ (match_operand:SF 1 "nonimmediate_operand" "f,m")))]
+ "s390_match_ccmode(insn, CCSmode) && TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
+ "@
+ cer\\t%0,%1
+ ce\\t%0,%1"
+ [(set_attr "op_type" "RR,RX")
+ (set_attr "atype" "reg,mem")
+ (set_attr "type" "xset,xset")])
+
+
+;;
+;;- Move instructions.
+;;
+
+;
+; movti instruction pattern(s).
+;
+
+(define_insn "movti"
+ [(set (match_operand:TI 0 "nonimmediate_operand" "=d,d,d,m,Q")
+ (match_operand:TI 1 "general_operand" "d,K,m,d,Q"))]
+ "TARGET_64BIT"
+ "*
+{
+ switch (which_alternative)
+ {
+ case 0: /* d <- d */
+ if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
+ return \"lgr\\t%M0,%M1\;lgr\\t%0,%1\";
+ else
+ return \"lgr\\t%0,%1\;lgr\\t%M0,%M1\";
+
+ case 1: /* d <- K */
+ if (INTVAL(operands[1]) < 0)
+ return \"lghi\\t%0,-1\;lghi\\t%M0,%h1\";
+ else
+ return \"lghi\\t%0,0\;lghi\\t%M0,%h1\";
+
+ case 2: /* d <- m */
+ if (s_operand (operands[1], GET_MODE (operands[1])))
+ return \"lmg\\t%0,%M0,%1\";
+ else
+ return \"la\\t%M0,%1\;lmg\\t%0,%M0,0(%M0)\";
+
+ case 3: /* m <- d */
+ if (!s_operand (operands[0], GET_MODE (operands[0])))
+ return \"stg\\t%1,%0\;stg\\t%M1,%M0\";
+ else
+ return \"stmg\\t%1,%M1,%0\";
+
+ case 4: /* m <- m */
+ return \"mvc\\t%O0(16,%R0),%1\";
+ }
+}"
+ [(set_attr "op_type" "NN,NN,RS,RS,SS")
+ (set_attr "atype" "reg,reg,mem,mem,mem")
+ (set_attr "type" "set")
+ (set_attr "length" "12,8,10,10,*")])
+
+;
+; movdi instruction pattern(s).
+;
+
+;; If generating PIC code and operands[1] is a symbolic CONST, emit a
+;; move to get the address of the symbolic object from the GOT.
+
+(define_expand "movdi"
+ [(set (match_operand:DI 0 "general_operand" "")
+ (match_operand:DI 1 "general_operand" ""))]
+ ""
+ "
+{
+ if (CONSTANT_P (operands[1])
+ && !LEGITIMATE_CONSTANT_P (operands[1]))
+ operands[1] = force_const_mem (DImode, operands[1]);
+
+ if (TARGET_64BIT && flag_pic && SYMBOLIC_CONST (operands[1]))
+ emit_pic_move (operands, DImode);
+}")
+
+(define_insn "*movdi_64"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,d,m,Q")
+ (match_operand:DI 1 "general_operand" "d,K,S,m,d,Q"))]
+ "TARGET_64BIT"
+ "@
+ lgr\\t%0,%1
+ lghi\\t%0,%h1
+ larl\\t%0,%1
+ lg\\t%0,%1
+ stg\\t%1,%0
+ mvc\\t%O0(8,%R0),%1"
+ [(set_attr "op_type" "RRE,RI,RIL,RXE,RXE,SS")
+ (set_attr "atype" "reg,reg,reg,mem,mem,mem")
+ (set_attr "type" "set,set,la,set,set,set")])
+
+(define_insn "*movdi_31"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,m,Q")
+ (match_operand:DI 1 "general_operand" "d,K,m,d,Q"))]
+ "!TARGET_64BIT"
+ "*
+{
+ switch (which_alternative)
+ {
+ case 0: /* d <- d */
+ if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
+ return \"lr\\t%N0,%N1\;lr\\t%0,%1\";
+ else
+ return \"lr\\t%0,%1\;lr\\t%N0,%N1\";
+
+ case 1: /* d <- K */
+ if (INTVAL (operands[1]) < 0)
+ return \"lhi\\t%0,-1\;lhi\\t%N0,%h1\";
+ else
+ return \"lhi\\t%0,0\;lhi\\t%N0,%h1\";
+
+ case 2: /* d <- m */
+ if (s_operand (operands[1], GET_MODE (operands[1])))
+ return \"lm\\t%0,%N0,%1\";
+ else
+ return \"la\\t%N0,%1\;lm\\t%0,%N0,0(%N0)\";
+
+ case 3: /* m <- d */
+ if (s_operand (operands[0], GET_MODE (operands[0])))
+ return \"stm\\t%1,%N1,%0\";
+ else
+ return \"st\\t%1,%0\;st\\t%N1,%N0\";
+
+ case 4: /* m <- m */
+ return \"mvc\\t%O0(8,%R0),%1\";
+ }
+}"
+ [(set_attr "op_type" "NN,NN,RS,RS,SS")
+ (set_attr "atype" "reg,reg,mem,mem,mem")
+ (set_attr "type" "set")
+ (set_attr "length" "4,8,8,8,*")])
+
+
+;
+; movsi instruction pattern(s).
+;
+
+;; If generating PIC code and operands[1] is a symbolic CONST, emit a
+;; move to get the address of the symbolic object from the GOT.
+
+(define_expand "movsi"
+ [(set (match_operand:SI 0 "general_operand" "")
+ (match_operand:SI 1 "general_operand" ""))]
+ ""
+ "
+{
+ if (CONSTANT_P (operands[1])
+ && !LEGITIMATE_CONSTANT_P (operands[1]))
+ operands[1] = force_const_mem (SImode, operands[1]);
+
+ if (flag_pic && SYMBOLIC_CONST (operands[1]))
+ emit_pic_move (operands, SImode);
+}")
+
+(define_insn "*movsi"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,m,Q")
+ (match_operand:SI 1 "general_operand" "d,K,m,d,Q"))]
+ ""
+ "@
+ lr\\t%0,%1
+ lhi\\t%0,%h1
+ l\\t%0,%1
+ st\\t%1,%0
+ mvc\\t%O0(4,%R0),%1"
+ [(set_attr "op_type" "RR,RI,RX,RX,SS")
+ (set_attr "atype" "reg,reg,mem,mem,mem")
+ (set_attr "type" "set")])
+
+
+;
+; movhi instruction pattern(s).
+;
+
+(define_insn "movhi"
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,m")
+ (match_operand:HI 1 "r_or_x_or_im16_operand" "d,K,m,d"))]
+ ""
+ "@
+ lr\\t%0,%1
+ lhi\\t%0,%h1
+ lh\\t%0,%1
+ sth\\t%1,%0"
+ [(set_attr "op_type" "RR,RI,RX,RX")
+ (set_attr "atype" "reg,reg,mem,mem")
+ (set_attr "type" "xset")])
+
+
+;
+; movqi instruction pattern(s).
+;
+
+(define_insn "movqi_64"
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,m,Q")
+ (match_operand:QI 1 "general_operand" "d,K,m,d,n"))]
+ "TARGET_64BIT"
+ "@
+ lr\\t%0,%1
+ llill\\t%0,%x1
+ llgc\\t%0,%1
+ stc\\t%1,%0
+ mvi\\t%0,%b1"
+ [(set_attr "op_type" "RR,RI,RXE,RX,SI")
+ (set_attr "atype" "reg,reg,mem,mem,mem")
+ (set_attr "type" "xset")])
+
+
+(define_insn "movqi"
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,m,Q")
+ (match_operand:QI 1 "r_or_x_or_im16_operand" "d,n,m,d,n"))]
+ ""
+ "@
+ lr\\t%0,%1
+ lhi\\t%0,%c1
+ ic\\t%0,%1
+ stc\\t%1,%0
+ mvi\\t%0,%b1"
+ [(set_attr "op_type" "RR,RX,RX,RX,SI")
+ (set_attr "atype" "reg,reg,mem,mem,mem")
+ (set_attr "type" "xset")])
+
+
+;
+; moveqstrictqi instruction pattern(s).
+;
+
+(define_insn "*movstrictqi"
+ [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+d,m"))
+ (match_operand:QI 1 "nonimmediate_operand" "m,d"))]
+ ""
+ "@
+ ic\\t%0,%1
+ stc\\t%1,%0"
+ [(set_attr "op_type" "RX,RX")
+ (set_attr "atype" "mem,mem")])
+
+
+;
+; movstricthi instruction pattern(s).
+;
+
+(define_insn "*movstricthi"
+ [(set (strict_low_part (match_operand:HI 0 "r_or_s_operand" "+d,Q"))
+ (match_operand:HI 1 "r_or_s_operand" "Q,d"))
+ (clobber (reg:CC 33))]
+ ""
+ "@
+ icm\\t%0,3,%1
+ stcm\\t%1,3,%0"
+ [(set_attr "op_type" "RS,RS")
+ (set_attr "atype" "mem")
+ (set_attr "type" "xset")])
+
+
+;
+; movstrictsi instruction pattern(s).
+;
+
+(define_insn "movestrictsi"
+ [(set (strict_low_part (match_operand:SI 0 "nonimmediate_operand" "+d,d,m"))
+ (match_operand:SI 1 "nonimmediate_operand" "d,m,d"))]
+ "TARGET_64BIT"
+ "@
+ lr\\t%0,%1
+ l\\t%0,%1
+ st\\t%1,%0"
+ [(set_attr "op_type" "RR,RS,RS")
+ (set_attr "atype" "reg,mem,mem")
+ (set_attr "type" "xset")])
+
+
+;
+; movdf instruction pattern(s).
+;
+
+(define_expand "movdf"
+ [(set (match_operand:DF 0 "nonimmediate_operand" "")
+ (match_operand:DF 1 "general_operand" ""))]
+ ""
+ "
+{
+ if (GET_CODE (operands[1]) == CONST_DOUBLE)
+ operands[1] = force_const_mem (DFmode, operands[1]);
+}")
+
+(define_insn "*movdf_64"
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,m,d,m,d,Q")
+ (match_operand:DF 1 "general_operand" "f,m,f,m,d,d,Q"))]
+ "TARGET_64BIT && TARGET_HARD_FLOAT"
+ "@
+ ldr\\t%0,%1
+ ld\\t%0,%1
+ std\\t%1,%0
+ lg\\t%0,%1
+ stg\\t%1,%0
+ lgr\\t%0,%1
+ mvc\\t%O0(8,%R0),%1"
+ [(set_attr "op_type" "RR,RX,RX,RXE,RXE,RR,SS")
+ (set_attr "atype" "reg,mem,mem,mem,mem,mem,mem")
+ (set_attr "type" "xset")])
+
+(define_insn "*movdf_31"
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,m,d,m,d,Q")
+ (match_operand:DF 1 "general_operand" "f,m,f,m,d,d,Q"))]
+ "TARGET_HARD_FLOAT"
+ "*
+{
+ switch (which_alternative)
+ {
+ case 0: /* f <- f */
+ return \"ldr\\t%0,%1\";
+
+ case 1: /* f <- m */
+ return \"ld\\t%0,%1\";
+
+ case 2: /* m <- f */
+ return \"std\\t%1,%0\";
+
+ case 3: /* d <- m */
+ if (s_operand (operands[1], GET_MODE (operands[1])))
+ return \"lm\\t%0,%N0,%1\";
+ else
+ return \"la\\t%N0,%1\;lm\\t%0,%N0,0(%N0)\";
+
+ case 4: /* m <- d */
+ if (s_operand (operands[0], GET_MODE (operands[0])))
+ return \"stm\\t%1,%N1,%0\";
+ else
+ return \"st\\t%1,%0\;st\\t%N1,%N0\";
+
+ case 5: /* d <- d */
+ if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
+ return \"lr\\t%N0,%N1\;lr\\t%0,%1\";
+ else
+ return \"lr\\t%0,%1\;lr\\t%N0,%N1\";
+
+ case 6: /* m <- m */
+ return \"mvc\\t%O0(8,%R0),%1\";
+ }
+}"
+ [(set_attr "op_type" "RR,RX,RX,RS,RS,NN,SS")
+ (set_attr "atype" "reg,mem,mem,mem,mem,reg,mem")
+ (set_attr "length" "*,*,*,*,*,4,*")])
+
+(define_insn "*movdf_soft_64"
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=d,m,d,Q")
+ (match_operand:DF 1 "general_operand" "m,d,d,Q"))]
+ "TARGET_64BIT && TARGET_SOFT_FLOAT"
+ "@
+ lg\\t%0,%1
+ stg\\t%1,%0
+ lgr\\t%0,%1
+ mvc\\t%O0(8,%R0),%1"
+ [(set_attr "op_type" "RXE,RXE,RR,SS")
+ (set_attr "atype" "mem,mem,mem,mem")
+ (set_attr "type" "xset")])
+
+(define_insn "*movdf_soft_31"
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=!d,d,m,Q")
+ (match_operand:DF 1 "general_operand" "!d,m,d,Q"))]
+ "TARGET_SOFT_FLOAT"
+ "*
+{
+ switch (which_alternative)
+ {
+ case 0: /* d <- d */
+ if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
+ return \"lr\\t%N0,%N1\;lr\\t%0,%1\";
+ else
+ return \"lr\\t%0,%1\;lr\\t%N0,%N1\";
+
+ case 1: /* d <- m */
+ if (s_operand (operands[1], GET_MODE (operands[1])))
+ return \"lm\\t%0,%N0,%1\";
+ else
+ return \"la\\t%N0,%1\;lm\\t%0,%N0,0(%N0)\";
+
+ case 2: /* m <- d */
+ if (s_operand (operands[0], GET_MODE (operands[0])))
+ return \"stm\\t%1,%N1,%0\";
+ else
+ return \"st\\t%1,%0\;st\\t%N1,%N0\";
+
+ case 3: /* m <- m */
+ return \"mvc\\t%O0(8,%R0),%1\";
+ }
+}"
+ [(set_attr "op_type" "NN,RS,RS,SS")
+ (set_attr "atype" "reg,mem,mem,mem")
+ (set_attr "length" "8,*,*,*")])
+
+
+;
+; movsf instruction pattern(s).
+;
+
+(define_expand "movsf"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "")
+ (match_operand:SF 1 "general_operand" ""))]
+ ""
+ "
+{
+ if (GET_CODE (operands[1]) == CONST_DOUBLE)
+ operands[1] = force_const_mem (SFmode, operands[1]);
+}")
+
+(define_insn "*movsf_64"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,m,d,m,d,Q")
+ (match_operand:SF 1 "general_operand" "f,m,f,m,d,d,Q"))]
+ "TARGET_64BIT && TARGET_HARD_FLOAT"
+ "@
+ ler\\t%0,%1
+ le\\t%0,%1
+ ste\\t%1,%0
+ llgf\\t%0,%1
+ st\\t%1,%0
+ lgr\\t%0,%1
+ mvc\\t%O0(4,%R0),%1"
+ [(set_attr "op_type" "RR,RX,RX,RXE,RX,RR,SS")
+ (set_attr "atype" "reg,mem,mem,mem,mem,reg,mem")])
+
+(define_insn "*movsf_31"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,m,d,m,d,Q")
+ (match_operand:SF 1 "general_operand" "f,m,f,m,d,d,Q"))]
+ "TARGET_HARD_FLOAT"
+ "@
+ ler\\t%0,%1
+ le\\t%0,%1
+ ste\\t%1,%0
+ l\\t%0,%1
+ st\\t%1,%0
+ lr\\t%0,%1
+ mvc\\t%O0(4,%R0),%1"
+ [(set_attr "op_type" "RR,RX,RX,RX,RX,RR,SS")
+ (set_attr "atype" "reg,mem,mem,mem,mem,reg,mem")])
+
+(define_insn "*movsf_soft"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=d,d,m,Q")
+ (match_operand:SF 1 "general_operand" "d,m,d,Q"))]
+ "TARGET_SOFT_FLOAT"
+ "@
+ lr\\t%0,%1
+ l\\t%0,%1
+ st\\t%1,%0
+ mvc\\t%O0(4,%R0),%1"
+ [(set_attr "op_type" "RR,RX,RX,SS")
+ (set_attr "atype" "reg,mem,mem,mem")])
+;
+; load_multiple pattern(s).
+;
+
+(define_expand "load_multiple"
+ [(match_par_dup 3 [(set (match_operand 0 "" "")
+ (match_operand 1 "" ""))
+ (use (match_operand 2 "" ""))])]
+ ""
+ "
+{
+ int regno;
+ int count;
+ rtx from;
+ int i;
+
+ /* Support only loading a constant number of fixed-point registers from
+ memory and only bother with this if more than two */
+ if (GET_CODE (operands[2]) != CONST_INT
+ || INTVAL (operands[2]) <= 2
+ || INTVAL (operands[2]) > 16
+ || GET_CODE (operands[1]) != MEM
+ || GET_CODE (operands[0]) != REG
+ || REGNO (operands[0]) >= 16)
+ FAIL;
+
+ count = INTVAL (operands[2]);
+ regno = REGNO (operands[0]);
+
+ operands[3] = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
+ from = force_reg (Pmode, XEXP (operands[1], 0));
+
+ for (i = 0; i < count; i++)
+ XVECEXP (operands[3], 0, i)
+ = gen_rtx_SET (VOIDmode, gen_rtx_REG (Pmode, regno + i),
+ change_address (operands[1], Pmode,
+ plus_constant (from, i * 4)));
+}")
+
+(define_insn "*load_multiple_di"
+ [(match_parallel 0 "load_multiple_operation"
+ [(set (match_operand:DI 1 "register_operand" "=r")
+ (match_operand:DI 2 "s_operand" "oQ"))])]
+ ""
+ "*
+{
+ int words = XVECLEN (operands[0], 0);
+
+ if (XVECLEN (operands[0], 0) == 1)
+ return \"lg\\t%1,0(%2)\";
+
+ operands[0] = gen_rtx_REG (DImode, REGNO (operands[1]) + words - 1);
+ return \"lmg\\t%1,%0,%2\";
+}"
+ [(set_attr "op_type" "RXE")
+ (set_attr "atype" "mem")
+ (set_attr "type" "set")])
+
+(define_insn "*load_multiple_si"
+ [(match_parallel 0 "load_multiple_operation"
+ [(set (match_operand:SI 1 "register_operand" "=r")
+ (match_operand:SI 2 "s_operand" "oQ"))])]
+ ""
+ "*
+{
+ int words = XVECLEN (operands[0], 0);
+
+ if (XVECLEN (operands[0], 0) == 1)
+ return \"l\\t%1,0(%2)\";
+
+ operands[0] = gen_rtx_REG (SImode, REGNO (operands[1]) + words - 1);
+ return \"lm\\t%1,%0,%2\";
+}"
+ [(set_attr "op_type" "RXE")
+ (set_attr "atype" "mem")
+ (set_attr "type" "set")])
+
+;
+; store multiple pattern(s).
+;
+
+(define_expand "store_multiple"
+ [(match_par_dup 3 [(set (match_operand 0 "" "")
+ (match_operand 1 "" ""))
+ (use (match_operand 2 "" ""))])]
+ ""
+ "
+{
+ int regno;
+ int count;
+ rtx to;
+ int i;
+
+ /* Support only storing a constant number of fixed-point registers to
+ memory and only bother with this if more than two. */
+ if (GET_CODE (operands[2]) != CONST_INT
+ || INTVAL (operands[2]) <= 2
+ || INTVAL (operands[2]) > 16
+ || GET_CODE (operands[0]) != MEM
+ || GET_CODE (operands[1]) != REG
+ || REGNO (operands[1]) >= 16)
+ FAIL;
+
+ count = INTVAL (operands[2]);
+ regno = REGNO (operands[1]);
+
+ operands[3] = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
+ to = force_reg (Pmode, XEXP (operands[0], 0));
+
+ for (i = 0; i < count; i++)
+ XVECEXP (operands[3], 0, i)
+ = gen_rtx_SET (VOIDmode,
+ change_address (operands[0], Pmode,
+ plus_constant (to, i * 4)),
+ gen_rtx_REG (Pmode, regno + i));
+}")
+
+(define_insn "*store_multiple_di"
+ [(match_parallel 0 "store_multiple_operation"
+ [(set (match_operand:DI 1 "s_operand" "=oQ")
+ (match_operand:DI 2 "register_operand" "r"))])]
+ ""
+ "*
+{
+ int words = XVECLEN (operands[0], 0);
+
+ if (XVECLEN (operands[0], 0) == 1)
+ return \"stg\\t%1,0(%2)\";
+
+ operands[0] = gen_rtx_REG (DImode, REGNO (operands[2]) + words - 1);
+ return \"stmg\\t%2,%0,%1\";
+}"
+ [(set_attr "op_type" "RXE")
+ (set_attr "atype" "mem")
+ (set_attr "type" "xset")])
+
+
+(define_insn "*store_multiple_si"
+ [(match_parallel 0 "store_multiple_operation"
+ [(set (match_operand:SI 1 "s_operand" "=oQ")
+ (match_operand:SI 2 "register_operand" "r"))])]
+ ""
+ "*
+{
+ int words = XVECLEN (operands[0], 0);
+
+ if (XVECLEN (operands[0], 0) == 1)
+ return \"st\\t%1,0(%2)\";
+
+ operands[0] = gen_rtx_REG (SImode, REGNO (operands[2]) + words - 1);
+ return \"stm\\t%2,%0,%1\";
+}"
+ [(set_attr "op_type" "RXE")
+ (set_attr "atype" "mem")
+ (set_attr "type" "xset")])
+
+;;
+;; String instructions.
+;;
+
+;
+; movstrdi instruction pattern(s).
+;
+
+(define_expand "movstrdi"
+ [(set (match_operand:BLK 0 "general_operand" "")
+ (match_operand:BLK 1 "general_operand" ""))
+ (use (match_operand:DI 2 "general_operand" ""))
+ (match_operand 3 "" "")]
+ "TARGET_64BIT"
+ "
+{
+ rtx addr0, addr1;
+
+ addr0 = force_operand (XEXP (operands[0], 0), NULL_RTX);
+ addr1 = force_operand (XEXP (operands[1], 0), NULL_RTX);
+
+ if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) <= 256)
+ {
+ operands[0] = change_address (operands[0], VOIDmode, addr0);
+ operands[1] = change_address (operands[1], VOIDmode, addr1);
+ operands[2] = GEN_INT (INTVAL (operands[2]) - 1);
+
+ emit_insn (gen_movstrsico (operands[0], operands[1], operands[2]));
+ DONE;
+ }
+ else
+ {
+ if (TARGET_MVCLE)
+ {
+ /* implementation suggested by Richard Henderson <rth@cygnus.com> */
+ rtx reg0 = gen_reg_rtx (TImode);
+ rtx reg1 = gen_reg_rtx (TImode);
+ rtx len = operands[2];
+
+ if (! CONSTANT_P (len))
+ len = force_reg (DImode, len);
+
+ /* Load up the address+length pairs. */
+
+ emit_move_insn (gen_rtx_SUBREG (DImode, reg0, 0), addr0);
+ emit_move_insn (gen_rtx_SUBREG (DImode, reg0, 1), len);
+
+ emit_move_insn (gen_rtx_SUBREG (DImode, reg1, 0), addr1);
+ emit_move_insn (gen_rtx_SUBREG (DImode, reg1, 1), len);
+
+ /* MOVE */
+ emit_insn (gen_movstrdi_64 (reg0, reg1));
+ DONE;
+ }
+ else
+ {
+ rtx label = gen_label_rtx ();
+ rtx reg0, reg1, len;
+
+ reg0 = gen_reg_rtx (DImode);
+ reg1 = gen_reg_rtx (DImode);
+ len = gen_reg_rtx (DImode);
+
+ emit_move_insn (len, operands[2]);
+ emit_insn (gen_cmpdi (len, const0_rtx));
+ emit_jump_insn (gen_beq (label));
+ emit_move_insn (reg0, addr0);
+ emit_move_insn (reg1, addr1);
+ emit_insn (gen_adddi3 (len, len, constm1_rtx));
+ emit_insn (gen_movstrdix_64 (reg0, reg1, len));
+ emit_label (label);
+ DONE;
+ }
+ }
+}")
+
+;
+; movstrsi instruction pattern(s).
+;
+
+(define_expand "movstrsi"
+ [(set (match_operand:BLK 0 "general_operand" "")
+ (match_operand:BLK 1 "general_operand" ""))
+ (use (match_operand:SI 2 "general_operand" ""))
+ (match_operand 3 "" "")]
+ ""
+ "
+{
+ rtx addr0 = force_operand (XEXP (operands[0], 0), NULL_RTX);
+ rtx addr1 = force_operand (XEXP (operands[1], 0), NULL_RTX);
+
+ if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) <= 256)
+ {
+ operands[0] = change_address (operands[0], VOIDmode, addr0);
+ operands[1] = change_address (operands[1], VOIDmode, addr1);
+ operands[2] = GEN_INT (INTVAL (operands[2]) - 1);
+
+ emit_insn (gen_movstrsico (operands[0], operands[1], operands[2]));
+ DONE;
+ }
+ else
+ {
+ if (TARGET_64BIT)
+ FAIL;
+
+ if (TARGET_MVCLE)
+ {
+ /* implementation suggested by Richard Henderson <rth@cygnus.com> */
+ rtx reg0 = gen_reg_rtx (DImode);
+ rtx reg1 = gen_reg_rtx (DImode);
+ rtx len = operands[2];
+
+
+ if (! CONSTANT_P (len))
+ len = force_reg (SImode, len);
+
+ /* Load up the address+length pairs. */
+
+ emit_move_insn (gen_rtx_SUBREG (SImode, reg0, 0), addr0);
+ emit_move_insn (gen_rtx_SUBREG (SImode, reg0, 1), len);
+
+ emit_move_insn (gen_rtx_SUBREG (SImode, reg1, 0), addr1);
+ emit_move_insn (gen_rtx_SUBREG (SImode, reg1, 1), len);
+
+ /* MOVE */
+ emit_insn (gen_movstrsi_31 (reg0, reg1));
+ DONE;
+ }
+ else
+ {
+ rtx label = gen_label_rtx ();
+ rtx reg0, reg1, len;
+
+ reg0 = gen_reg_rtx (SImode);
+ reg1 = gen_reg_rtx (SImode);
+ len = gen_reg_rtx (SImode);
+
+ emit_move_insn (len, operands[2]);
+ emit_insn (gen_cmpsi (len, const0_rtx));
+ emit_jump_insn (gen_beq (label));
+ emit_move_insn (reg0, addr0);
+ emit_move_insn (reg1, addr1);
+ emit_insn (gen_addsi3 (len, len, constm1_rtx));
+ emit_insn (gen_movstrsix_31 (reg0, reg1, len));
+ emit_label (label);
+ DONE;
+ }
+ }
+}")
+
+; Move a block that is less than 256 bytes in length.
+
+(define_insn "movstrsico"
+ [(set (match_operand:BLK 0 "s_operand" "=oQ")
+ (match_operand:BLK 1 "s_operand" "oQ"))
+ (use (match_operand 2 "const_int_operand" "I"))]
+ "((unsigned) INTVAL (operands[2]) < 256)"
+ "mvc\\t%O0(%c2+1,%R0),%1"
+ [(set_attr "op_type" "SS")
+ (set_attr "atype" "mem")])
+
+; Move a block that is more than 256 bytes in lenght or length in register
+
+(define_insn "movstrdix_64"
+ [(set (mem:BLK (match_operand:DI 0 "register_operand" "a"))
+ (mem:BLK (match_operand:DI 1 "register_operand" "a")))
+ (use (match_operand:DI 2 "register_operand" "a"))
+ (clobber (match_dup 0))
+ (clobber (match_dup 1))
+ (clobber (match_scratch:DI 3 "=&a"))
+ (clobber (reg:CC 33))]
+ ""
+ "*
+{
+ rtx xop[4];
+ xop[0] = gen_label_rtx ();
+ xop[1] = gen_label_rtx ();
+ xop[2] = gen_label_rtx ();
+ xop[3] = operands[3];
+ output_asm_insn (\"srag\\t%3,%2,8\",operands);
+ output_asm_insn (\"jz\\t%l1\",xop);
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
+ CODE_LABEL_NUMBER (xop[0]));
+ output_asm_insn (\"mvc\\t0(256,%0),0(%1)\",operands);
+ output_asm_insn (\"la\\t%0,256(%0)\",operands);
+ output_asm_insn (\"la\\t%1,256(%1)\",operands);
+ xop[3] = operands[3];
+ output_asm_insn (\"brct\\t%3,%l0\",xop);
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
+ CODE_LABEL_NUMBER (xop[1]));
+ xop[3] = operands[3];
+ output_asm_insn (\"bras\\t%3,%l2\",xop);
+ output_asm_insn (\"mvc\\t0(1,%0),0(%1)\",operands);
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
+ CODE_LABEL_NUMBER (xop[2]));
+ return \"ex\\t%2,0(%3)\";
+}"
+ [(set_attr "op_type" "NN")
+ (set_attr "atype" "mem")
+ (set_attr "length" "44")])
+
+(define_insn "movstrsix_31"
+ [(set (mem:BLK (match_operand:SI 0 "register_operand" "a"))
+ (mem:BLK (match_operand:SI 1 "register_operand" "a")))
+ (use (match_operand:SI 2 "register_operand" "a"))
+ (clobber (match_dup 0))
+ (clobber (match_dup 1))
+ (clobber (match_scratch:SI 3 "=&a"))
+ (clobber (reg:CC 33))]
+ ""
+ "*
+{
+ rtx xop[4];
+ xop[0] = gen_label_rtx ();
+ xop[1] = gen_label_rtx ();
+ xop[2] = gen_label_rtx ();
+ xop[3] = operands[3];
+ output_asm_insn (\"lr\\t%3,%2\",operands);
+ output_asm_insn (\"sra\\t%3,8\",operands);
+ output_asm_insn (\"jz\\t%l1\",xop);
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
+ CODE_LABEL_NUMBER (xop[0]));
+ output_asm_insn (\"mvc\\t0(256,%0),0(%1)\",operands);
+ output_asm_insn (\"la\\t%0,256(%0)\",operands);
+ output_asm_insn (\"la\\t%1,256(%1)\",operands);
+ xop[3] = operands[3];
+ output_asm_insn (\"brct\\t%3,%l0\",xop);
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
+ CODE_LABEL_NUMBER (xop[1]));
+ xop[3] = operands[3];
+ output_asm_insn (\"bras\\t%3,%l2\",xop);
+ output_asm_insn (\"mvc\\t0(1,%0),0(%1)\",operands);
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
+ CODE_LABEL_NUMBER (xop[2]));
+ return \"ex\\t%2,0(%3)\";
+}"
+ [(set_attr "op_type" "NN")
+ (set_attr "length" "42")
+ (set_attr "atype" "mem")])
+
+; Move a block that is larger than 255 bytes in length.
+
+(define_insn "movstrdi_64"
+ [(set (mem:BLK (subreg:DI (match_operand:TI 0 "register_operand" "d") 0))
+ (mem:BLK (subreg:DI (match_operand:TI 1 "register_operand" "d") 0)))
+ (clobber (match_dup 0))
+ (clobber (match_dup 1))
+ (clobber (reg:CC 33))]
+ ""
+ "mvcle\\t%0,%1,0\;jo\\t.-4"
+ [(set_attr "op_type" "NN")
+ (set_attr "atype" "mem")
+ (set_attr "length" "8")])
+
+(define_insn "movstrsi_31"
+ [(set (mem:BLK (subreg:SI (match_operand:DI 0 "register_operand" "d") 0))
+ (mem:BLK (subreg:SI (match_operand:DI 1 "register_operand" "d") 0)))
+ (clobber (match_dup 0))
+ (clobber (match_dup 1))
+ (clobber (reg:CC 33))]
+ ""
+ "mvcle\\t%0,%1,0\;jo\\t.-4"
+ [(set_attr "op_type" "NN")
+ (set_attr "atype" "mem")
+ (set_attr "length" "8")])
+
+;
+; clrstrdi instruction pattern(s).
+;
+
+(define_expand "clrstrdi"
+ [(set (match_operand:BLK 0 "general_operand" "")
+ (const_int 0))
+ (use (match_operand:DI 1 "general_operand" ""))
+ (match_operand 2 "" "")]
+ "TARGET_64BIT"
+ "
+{
+ rtx addr = force_operand (XEXP (operands[0], 0), NULL_RTX);
+
+ operands[0] = change_address (operands[0], VOIDmode, addr);
+
+ if (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) < 256)
+ {
+ emit_insn (gen_clrstrsico (operands[0], operands[1]));
+ DONE;
+ }
+ else
+ {
+ rtx reg0 = gen_reg_rtx (TImode);
+ rtx reg1 = gen_reg_rtx (TImode);
+ rtx len = operands[1];
+
+ if (! CONSTANT_P (len))
+ len = force_reg (DImode, len);
+
+ /* Load up the address+length pairs. */
+
+ emit_move_insn (gen_rtx_SUBREG (DImode, reg0, 0), addr);
+ emit_move_insn (gen_rtx_SUBREG (DImode, reg0, 1), len);
+
+ emit_move_insn (gen_rtx_SUBREG (DImode, reg1, 1), const0_rtx);
+
+ /* Clear! */
+ emit_insn (gen_clrstrsi_64 (reg0, reg1));
+ DONE;
+ }
+}")
+
+;
+; clrstrsi instruction pattern(s).
+;
+
+(define_expand "clrstrsi"
+ [(set (match_operand:BLK 0 "general_operand" "")
+ (const_int 0))
+ (use (match_operand:SI 1 "general_operand" ""))
+ (match_operand 2 "" "")]
+ "!TARGET_64BIT"
+ "
+{
+ rtx addr = force_operand (XEXP (operands[0], 0), NULL_RTX);
+
+ operands[0] = change_address (operands[0], VOIDmode, addr);
+
+ if (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) < 256)
+ {
+ emit_insn (gen_clrstrsico (operands[0], operands[1]));
+ DONE;
+ }
+ else
+ {
+ rtx reg0 = gen_reg_rtx (DImode);
+ rtx reg1 = gen_reg_rtx (DImode);
+ rtx len = operands[1];
+
+ if (! CONSTANT_P (len))
+ len = force_reg (SImode, len);
+
+ /* Load up the address+length pairs. */
+
+ emit_move_insn (gen_rtx_SUBREG (SImode, reg0, 0), addr);
+ emit_move_insn (gen_rtx_SUBREG (SImode, reg0, 1), len);
+
+ emit_move_insn (gen_rtx_SUBREG (SImode, reg1, 1), const0_rtx);
+
+ /* CLear! */
+ emit_insn (gen_clrstrsi_31 (reg0, reg1));
+ DONE;
+ }
+}")
+
+; Clear memory with length less than 256 bytes
+
+(define_insn "clrstrsico"
+ [(set (match_operand:BLK 0 "s_operand" "=Qo")
+ (const_int 0))
+ (use (match_operand 1 "immediate_operand" "I"))
+ (clobber (reg:CC 33))]
+ ""
+ "xc\\t%O0(%1,%R0),%0"
+ [(set_attr "op_type" "RS")
+ (set_attr "atype" "mem")])
+
+; Clear memory with length greater 256 bytes or lenght not constant
+
+(define_insn "clrstrsi_64"
+ [(set (mem:BLK (subreg:DI (match_operand:TI 0 "register_operand" "d") 0))
+ (const_int 0))
+ (use (match_operand:TI 1 "register_operand" "d"))
+ (clobber (match_dup 0))
+ (clobber (match_dup 1))
+ (clobber (reg:CC 33))]
+ "TARGET_64BIT"
+ "mvcle\\t%0,%1,0\;jo\\t.-4"
+ [(set_attr "op_type" "NN")
+ (set_attr "atype" "mem")
+ (set_attr "cycle" "n")
+ (set_attr "length" "8")])
+
+(define_insn "clrstrsi_31"
+ [(set (mem:BLK (subreg:SI (match_operand:DI 0 "register_operand" "d") 0))
+ (const_int 0))
+ (use (match_operand:DI 1 "register_operand" "d"))
+ (clobber (match_dup 0))
+ (clobber (match_dup 1))
+ (clobber (reg:CC 33))]
+ "!TARGET_64BIT"
+ "mvcle\\t%0,%1,0\;jo\\t.-4"
+ [(set_attr "op_type" "NN")
+ (set_attr "atype" "mem")
+ (set_attr "cycle" "n")
+ (set_attr "length" "8")])
+
+;
+; cmpstrdi instruction pattern(s).
+;
+
+(define_expand "cmpstrdi"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (compare:DI (match_operand:BLK 1 "s_operand" "")
+ (match_operand:BLK 2 "s_operand" "") ) )
+ (use (match_operand:DI 3 "general_operand" ""))
+ (use (match_operand:DI 4 "" ""))]
+ "TARGET_64BIT"
+ "
+{
+ rtx addr0, addr1;
+
+ /* for pre/post increment */
+ operands[1] = protect_from_queue (operands[1], 0);
+ operands[2] = protect_from_queue (operands[2], 0);
+ operands[3] = protect_from_queue (operands[3], 0);
+
+ addr0 = force_operand (XEXP (operands[1], 0), NULL_RTX);
+ addr1 = force_operand (XEXP (operands[2], 0), NULL_RTX);
+
+ if (GET_CODE (operands[3]) == CONST_INT && INTVAL (operands[3]) < 256)
+ {
+ if (INTVAL (operands[3]) == 0) {
+ emit_move_insn (operands[0], operands[3]);
+ DONE;
+ }
+
+ operands[1] = change_address (operands[1], VOIDmode, addr0);
+ operands[2] = change_address (operands[2], VOIDmode, addr1);
+
+ emit_insn (gen_cmpstr_const (operands[1], operands[2], operands[3]));
+ emit_insn (gen_cmpint_di (operands[0]));
+ DONE;
+ }
+ else
+ {
+ /* implementation suggested by Richard Henderson <rth@cygnus.com> */
+ rtx reg0 = gen_reg_rtx (TImode);
+ rtx reg1 = gen_reg_rtx (TImode);
+ rtx len = operands[3];
+
+ if (! CONSTANT_P (len))
+ len = force_reg (DImode, len);
+
+ /* Load up the address+length pairs. */
+ emit_move_insn (gen_rtx_SUBREG (DImode, reg0, 0), addr0);
+ emit_move_insn (gen_rtx_SUBREG (DImode, reg0, 1), len);
+
+ emit_move_insn (gen_rtx_SUBREG (DImode, reg1, 0), addr1);
+ emit_move_insn (gen_rtx_SUBREG (DImode, reg1, 1), len);
+
+ /* Compare! */
+ emit_insn (gen_cmpstr_64 (reg0, reg1));
+ emit_insn (gen_cmpint_di (operands[0]));
+ DONE;
+ }
+}")
+
+;
+; cmpstrsi instruction pattern(s).
+;
+
+(define_expand "cmpstrsi"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (compare:SI (match_operand:BLK 1 "s_operand" "")
+ (match_operand:BLK 2 "s_operand" "") ) )
+ (use (match_operand:SI 3 "general_operand" ""))
+ (use (match_operand:SI 4 "" ""))]
+ ""
+ "
+{
+ rtx addr0, addr1;
+
+ /* for pre/post increment */
+ operands[1] = protect_from_queue (operands[1], 0);
+ operands[2] = protect_from_queue (operands[2], 0);
+ operands[3] = protect_from_queue (operands[3], 0);
+
+ addr0 = force_operand (XEXP (operands[1], 0), NULL_RTX);
+ addr1 = force_operand (XEXP (operands[2], 0), NULL_RTX);
+
+ if (GET_CODE (operands[3]) == CONST_INT && INTVAL (operands[3]) < 256)
+ {
+ if (INTVAL (operands[3]) == 0) {
+ emit_move_insn (operands[0], operands[3]);
+ DONE;
+ }
+
+ operands[1] = change_address (operands[1], VOIDmode, addr0);
+ operands[2] = change_address (operands[2], VOIDmode, addr1);
+
+ emit_insn (gen_cmpstr_const (operands[1], operands[2], operands[3]));
+ emit_insn (gen_cmpint_si (operands[0]));
+ DONE;
+ }
+ else
+ {
+ /* implementation suggested by Richard Henderson <rth@cygnus.com> */
+ rtx reg0, reg1;
+ rtx len = operands[3];
+
+ if (TARGET_64BIT)
+ {
+ reg0 = gen_reg_rtx (TImode);
+ reg1 = gen_reg_rtx (TImode);
+ }
+ else
+ {
+ reg0 = gen_reg_rtx (DImode);
+ reg1 = gen_reg_rtx (DImode);
+ }
+
+ if (! CONSTANT_P (len))
+ len = force_reg (Pmode, len);
+
+ /* Load up the address+length pairs. */
+ emit_move_insn (gen_rtx_SUBREG (Pmode, reg0, 0), addr0);
+ emit_move_insn (gen_rtx_SUBREG (Pmode, reg0, 1), len);
+
+ emit_move_insn (gen_rtx_SUBREG (Pmode, reg1, 0), addr1);
+ emit_move_insn (gen_rtx_SUBREG (Pmode, reg1, 1), len);
+
+ /* Compare! */
+ if (TARGET_64BIT)
+ emit_insn (gen_cmpstr_64 (reg0, reg1));
+ else
+ emit_insn (gen_cmpstr_31 (reg0, reg1));
+
+ emit_insn (gen_cmpint_si (operands[0]));
+ DONE;
+ }
+}")
+
+; Compare a block that is less than 256 bytes in length.
+
+(define_insn "cmpstr_const"
+ [(set (reg:CCU 33)
+ (compare:CCU (match_operand:BLK 0 "s_operand" "oQ")
+ (match_operand:BLK 1 "s_operand" "oQ")))
+ (use (match_operand 2 "immediate_operand" "I"))]
+ "(unsigned) INTVAL (operands[2]) < 256"
+ "clc\\t%O0(%c2,%R0),%1"
+ [(set_attr "op_type" "SS")
+ (set_attr "atype" "mem")
+ (set_attr "type" "xset")])
+
+; Compare a block that is larger than 255 bytes in length.
+
+(define_insn "cmpstr_64"
+ [(set (reg:CCU 33)
+ (compare:CCU (mem:BLK (subreg:DI (match_operand:TI 0 "register_operand" "d") 0))
+ (mem:BLK (subreg:DI (match_operand:TI 1 "register_operand" "d") 0))))
+ (clobber (subreg:DI (match_dup 0) 0))
+ (clobber (subreg:DI (match_dup 0) 1))
+ (clobber (subreg:DI (match_dup 1) 0))
+ (clobber (subreg:DI (match_dup 1) 1))]
+ "TARGET_64BIT"
+ "clcl\\t%0,%1"
+ [(set_attr "op_type" "RR")
+ (set_attr "atype" "mem")
+ (set_attr "type" "xset")])
+
+(define_insn "cmpstr_31"
+ [(set (reg:CCU 33)
+ (compare:CCU (mem:BLK (subreg:SI (match_operand:DI 0 "register_operand" "d") 0))
+ (mem:BLK (subreg:SI (match_operand:DI 1 "register_operand" "d") 0))))
+ (clobber (subreg:SI (match_dup 0) 0))
+ (clobber (subreg:SI (match_dup 0) 1))
+ (clobber (subreg:SI (match_dup 1) 0))
+ (clobber (subreg:SI (match_dup 1) 1))]
+ "!TARGET_64BIT"
+ "clcl\\t%0,%1"
+ [(set_attr "op_type" "RR")
+ (set_attr "atype" "mem")
+ (set_attr "type" "xset")])
+
+; Convert condition code to integer in range (-1, 0, 1)
+
+(define_insn "cmpint_si"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (compare:SI (reg:CCU 33) (const_int 0)))]
+ ""
+ "*
+{
+ output_asm_insn (\"lhi\\t%0,1\", operands);
+ output_asm_insn (\"jh\\t.+12\", operands);
+ output_asm_insn (\"jl\\t.+6\", operands);
+ output_asm_insn (\"sr\\t%0,%0\", operands);
+ return \"lcr\\t%0,%0\";
+}"
+ [(set_attr "op_type" "NN")
+ (set_attr "length" "16")
+ (set_attr "atype" "reg")
+ (set_attr "type" "xset")])
+
+(define_insn "cmpint_di"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (compare:DI (reg:CCU 33) (const_int 0)))]
+ "TARGET_64BIT"
+ "*
+{
+ output_asm_insn (\"lghi\\t%0,1\", operands);
+ output_asm_insn (\"jh\\t.+12\", operands);
+ output_asm_insn (\"jl\\t.+6\", operands);
+ output_asm_insn (\"sgr\\t%0,%0\", operands);
+ return \"lcgr\\t%0,%0\";
+}"
+ [(set_attr "op_type" "NN")
+ (set_attr "length" "22")
+ (set_attr "atype" "reg")
+ (set_attr "type" "xset")])
+
+;;
+;;- Conversion instructions.
+;;
+
+;
+; extendsidi2 instruction pattern(s).
+;
+
+(define_insn "extendsidi2"
+ [(set (match_operand:DI 0 "register_operand" "=d,d")
+ (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,m")))]
+ "TARGET_64BIT"
+ "@
+ lgfr\\t%0,%1
+ lgf\\t%0,%1"
+ [(set_attr "op_type" "RRE,RXE")
+ (set_attr "atype" "reg,mem")
+ (set_attr "type" "set")])
+
+
+;
+; extendhidi2 instruction pattern(s).
+;
+
+(define_insn "extendhidi2"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (sign_extend:DI (match_operand:HI 1 "register_operand" "d")))
+ (clobber (reg:CC 33))]
+ "TARGET_64BIT"
+ "sllg\\t%0,%1,48\;srag\\t%0,%0,48"
+ [(set_attr "op_type" "NN")
+ (set_attr "length" "12")
+ (set_attr "cycle" "2")
+ (set_attr "type" "set")])
+
+
+;
+; extendqidi2 instruction pattern(s).
+;
+
+(define_insn "extendqidi2"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (sign_extend:DI (match_operand:QI 1 "register_operand" "d")))
+ (clobber (reg:CC 33))]
+ "TARGET_64BIT"
+ "sllg\\t%0,%1,56\;srag\\t%0,%0,56"
+ [(set_attr "op_type" "NN")
+ (set_attr "length" "12")
+ (set_attr "cycle" "2")
+ (set_attr "type" "set")])
+
+
+;
+; extendhisi2 instruction pattern(s).
+;
+
+(define_insn "extendhisi2"
+ [(set (match_operand:SI 0 "register_operand" "=d,!d,d")
+ (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,d,m")))
+ (clobber (reg:CC 33))]
+ ""
+ "@
+ sll\\t%1,16\;sra\\t%1,16
+ lr\\t%0,%1\;sll\\t%0,16\;sra\\t%0,16
+ lh\\t%0,%1"
+ [(set_attr "op_type" "NN,NN,RX")
+ (set_attr "cycle" "2,3,1")
+ (set_attr "atype" "reg,reg,mem")
+ (set_attr "type" "set")
+ (set_attr "length" "8,10,*")])
+
+
+;
+; extendqisi2 instruction pattern(s).
+;
+
+(define_insn "extendqisi2"
+ [(set (match_operand:SI 0 "register_operand" "=d,d")
+ (sign_extend:SI (match_operand:QI 1 "r_or_s_operand" "0,Q")))
+ (clobber (reg:CC 33))]
+ ""
+ "@
+ sll\\t%0,24\;sra\\t%0,24
+ icm\\t%0,8,%1\;sra\\t%0,24"
+ [(set_attr "op_type" "NN,NN")
+ (set_attr "cycle" "2")
+ (set_attr "atype" "reg,mem")
+ (set_attr "type" "set")
+ (set_attr "length" "8,8")])
+
+
+;
+; extendqihi2 instruction pattern(s).
+;
+
+(define_insn "extendqihi2"
+ [(set (match_operand:HI 0 "register_operand" "=d,d")
+ (sign_extend:HI (match_operand:QI 1 "r_or_s_operand" "0,Q")))
+ (clobber (reg:CC 33))]
+ ""
+ "@
+ sll\\t%0,24\;sra\\t%0,24
+ icm\\t%0,8,%1\;sra\\t%0,24"
+ [(set_attr "op_type" "NN,NN")
+ (set_attr "cycle" "2")
+ (set_attr "atype" "reg,mem")
+ (set_attr "type" "set")
+ (set_attr "length" "8,8")])
+
+
+;
+; zero_extendsidi2 instruction pattern(s).
+;
+
+(define_insn "zero_extendsidi2"
+ [(set (match_operand:DI 0 "register_operand" "=d,d")
+ (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,m")))]
+ "TARGET_64BIT"
+ "@
+ llgfr\\t%0,%1
+ llgf\\t%0,%1"
+ [(set_attr "op_type" "RRE,RXE")
+ (set_attr "atype" "reg,mem")
+ (set_attr "type" "set")])
+
+
+;
+; zero_extendhidi2 instruction pattern(s).
+;
+
+(define_insn "zero_extendhidi2"
+ [(set (match_operand:DI 0 "register_operand" "=!d,d")
+ (zero_extend:DI (match_operand:HI 1 "nonimmediate_operand" "d,m")))]
+ "TARGET_64BIT"
+ "@
+ llgfr\\t%0,%1\;iilh\\t%0,0
+ llgh\\t%0,%1"
+ [(set_attr "op_type" "NN,RXE")
+ (set_attr "cycle" "2,1")
+ (set_attr "atype" "reg,mem")
+ (set_attr "length" "12,*")
+ (set_attr "type" "set")])
+
+
+;
+; zero_extendqidi2 instruction pattern(s)
+;
+
+(define_insn "zero_extendqidi2"
+ [(set (match_operand:DI 0 "register_operand" "=!d,d")
+ (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "d,m")))
+ (clobber (reg:CC 33))]
+ "TARGET_64BIT"
+ "@
+ sllg\\t%0,%1,56\;srlg\\t%0,%0,56
+ llgc\\t%0,%1"
+ [(set_attr "op_type" "NN,RXE")
+ (set_attr "cycle" "2,1")
+ (set_attr "atype" "reg,mem")
+ (set_attr "type" "set")
+ (set_attr "length" "12,*")])
+
+
+;
+; zero_extendhisi2 instruction pattern(s).
+;
+
+(define_expand "zero_extendhisi2"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (zero_extend:SI (match_operand:HI 1 "r_or_s_operand" "")))]
+ ""
+ "
+{
+ if (!TARGET_64BIT)
+ {
+ emit_insn (gen_zero_extendhisi2_31 (operands[0], operands[1],
+ force_const_mem (SImode, const0_rtx)));
+ DONE;
+ }
+}")
+
+(define_insn "*zero_extendhisi2_64"
+ [(set (match_operand:SI 0 "register_operand" "=d,d")
+ (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,m")))]
+ "TARGET_64BIT"
+ "@
+ iilh\\t%0,0
+ llgh\\t%0,%1"
+ [(set_attr "op_type" "RI,RXE")
+ (set_attr "atype" "reg,mem")])
+
+(define_insn "zero_extendhisi2_31"
+ [(set (match_operand:SI 0 "register_operand" "=d,d")
+ (zero_extend:SI (match_operand:HI 1 "r_or_s_operand" "0,Q")))
+ (use (match_operand:SI 2 "memory_operand" "m,m"))
+ (clobber (reg:CC 33))]
+ ""
+ "@
+ icm\\t%0,12,%2
+ icm\\t%0,12,%1\;srl\\t%0,16"
+ [(set_attr "op_type" "RX,NN")
+ (set_attr "cycle" "1,2")
+ (set_attr "atype" "reg,mem")
+ (set_attr "type" "set")
+ (set_attr "length" "*,8")])
+
+
+;
+; zero_extendqisi2 instruction pattern(s).
+;
+
+(define_insn "*zero_extendqisi2_mem_31"
+ [(set (match_operand:SI 0 "register_operand" "=&d")
+ (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))
+ (use (match_operand:SI 2 "memory_operand" "m" ))
+ (clobber (reg:CC 33))]
+ ""
+ "sr\\t%0,%0\;ic\\t%0,%1"
+ [(set_attr "op_type" "NN")
+ (set_attr "cycle" "2")
+ (set_attr "atype" "mem")
+ (set_attr "type" "set")
+ (set_attr "length" "6")])
+
+(define_insn "zero_extendqisi2_reg_31"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (zero_extend:SI (match_operand:QI 1 "register_operand" "0")))
+ (use (match_operand:SI 2 "memory_operand" "m" ))
+ (clobber (reg:CC 33))]
+ ""
+ "icm\\t%0,14,%2"
+ [(set_attr "op_type" "RX")
+ (set_attr "atype" "mem")
+ (set_attr "type" "set")])
+
+(define_insn "*zero_extendqisi2_64"
+ [(set (match_operand:SI 0 "register_operand" "=!d,d")
+ (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "d,m")))]
+ "TARGET_64BIT"
+ "@
+ sllg\\t%0,%1,56\;srlg\\t%0,%0,56
+ llgc\\t%0,%1"
+ [(set_attr "op_type" "NN,RXE")
+ (set_attr "cycle" "2,1")
+ (set_attr "atype" "reg,mem")
+ (set_attr "length" "12,*")])
+
+(define_expand "zero_extendqisi2"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (zero_extend:SI (match_operand:QI 1 "r_or_s_operand" "")))]
+ ""
+ "
+{
+ if (!TARGET_64BIT)
+ {
+ emit_insn (gen_zero_extendqisi2_reg_31 (operands[0], operands[1],
+ force_const_mem (SImode, const0_rtx)));
+ DONE;
+ }
+}")
+
+
+;
+; zero_extendqihi2 instruction pattern(s).
+;
+
+(define_insn "zero_extendqihi2_64"
+ [(set (match_operand:HI 0 "register_operand" "=d,d")
+ (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "0,m")))
+ (clobber (reg:CC 33))]
+ "TARGET_64BIT"
+ "@
+ nill\\t%0,0x00FF
+ llgc\\t%0,%1"
+ [(set_attr "op_type" "RI,RXE")
+ (set_attr "atype" "reg,mem")])
+
+(define_insn "zero_extendqihi2_31"
+ [(set (match_operand:HI 0 "register_operand" "=d,&d")
+ (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "0,m")))
+ (use (match_operand:SI 2 "memory_operand" "m,m"))
+ (clobber (reg:CC 33))]
+ ""
+ "@
+ icm\\t%0,14,%2
+ sr\\t%0,%0\;ic\\t%0,%1"
+ [(set_attr "op_type" "RX,NN")
+ (set_attr "atype" "reg,mem")
+ (set_attr "length" "*,8")])
+
+(define_expand "zero_extendqihi2"
+ [(set (match_operand:HI 0 "register_operand" "")
+ (zero_extend:HI (match_operand:QI 1 "general_operand" "")))]
+ ""
+ "
+{
+ if (!TARGET_64BIT)
+ {
+ emit_insn (gen_zero_extendqihi2_31 (operands[0], operands[1],
+ force_const_mem (SImode, const0_rtx)));
+ DONE;
+ }
+ else
+ {
+ emit_insn (gen_zero_extendqihi2_64 (operands[0], operands[1]));
+ DONE;
+ }
+}")
+
+
+;
+; truncdisi2 instruction pattern(s).
+;
+
+(define_insn "truncdisi2"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (truncate:SI (match_operand:DI 1 "register_operand" "d")))]
+ "TARGET_64BIT"
+ "llgfr\\t%0,%1"
+ [(set_attr "op_type" "RRE")])
+
+
+;
+; truncdihi2 instruction pattern(s).
+;
+
+(define_insn "truncdihi2"
+ [(set (match_operand:HI 0 "register_operand" "=d")
+ (truncate:HI (match_operand:DI 1 "register_operand" "d")))]
+ "TARGET_64BIT"
+ "llgfr\\t%0,%1\;iilh\\t%0,0"
+ [(set_attr "op_type" "NN")
+ (set_attr "length" "10")])
+
+
+;
+; truncdiqi2 instruction pattern(s).
+;
+
+(define_insn "truncdiqi2"
+ [(set (match_operand:QI 0 "register_operand" "=d")
+ (truncate:QI (match_operand:DI 1 "register_operand" "d")))
+ (clobber (reg:CC 33))]
+ "TARGET_64BIT"
+ "sllg\\t%0,%1,56\;srlg\\t%0,%0,56"
+ [(set_attr "op_type" "NN")
+ (set_attr "cycle" "2")
+ (set_attr "length" "12")])
+
+
+;
+; truncsihi2 instruction pattern(s).
+;
+
+(define_expand "truncsihi2"
+ [(set (match_operand:HI 0 "register_operand" "")
+ (truncate:HI (match_operand:SI 1 "register_operand" "")))]
+ ""
+ "
+{
+ if (!TARGET_64BIT)
+ {
+ emit_insn (gen_do_truncsihi2 (operands[0], operands[1],
+ force_const_mem (SImode, const0_rtx)));
+ DONE;
+ }
+}")
+
+
+(define_insn "do_truncsihi2"
+ [(set (match_operand:HI 0 "register_operand" "=d")
+ (truncate:HI (match_operand:SI 1 "register_operand" "0")))
+ (use (match_operand:SI 2 "memory_operand" "m"))
+ (clobber (reg:CC 33))]
+ ""
+ "icm\\t%0,12,%2"
+ [(set_attr "op_type" "RX")])
+
+(define_insn "*truncsihi2_64"
+ [(set (match_operand:HI 0 "register_operand" "=d")
+ (truncate:HI (match_operand:SI 1 "register_operand" "0")))]
+ "TARGET_64BIT"
+ "iilh\\t%0,0"
+ [(set_attr "op_type" "RI")])
+
+
+;
+; truncsiqi2 instruction pattern(s).
+;
+
+(define_insn "truncsiqi2"
+ [(set (match_operand:QI 0 "register_operand" "=d")
+ (truncate:QI (match_operand:SI 1 "register_operand" "0")))
+ (clobber (reg:CC 33))]
+ "TARGET_64BIT"
+ "iilh\\t%0,0\;nill\\t%0,0x00FF"
+ [(set_attr "op_type" "NN")
+ (set_attr "cycle" "2")
+ (set_attr "length" "8")])
+
+
+;
+; trunchiqi2 instruction pattern(s).
+;
+
+(define_insn "trunchiqi2"
+ [(set (match_operand:QI 0 "register_operand" "=d")
+ (truncate:QI (match_operand:HI 1 "register_operand" "0")))
+ (clobber (reg:CC 33))]
+ "TARGET_64BIT"
+ "nill\\t%0,0x00FF"
+ [(set_attr "op_type" "RI")])
+
+
+;
+; fixuns_truncdfdi2 and fix_truncdfsi2 instruction pattern(s).
+;
+
+(define_expand "fixuns_truncdfdi2"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (unsigned_fix:DI (match_operand:DF 1 "register_operand" "")))]
+ "TARGET_64BIT && TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+ "
+{
+ rtx label1 = gen_label_rtx ();
+ rtx label2 = gen_label_rtx ();
+ rtx temp = gen_reg_rtx (DFmode);
+ operands[1] = force_reg (DFmode, operands[1]);
+
+ emit_insn (gen_cmpdf (operands[1], force_const_mem (DFmode,
+ CONST_DOUBLE_FROM_REAL_VALUE (0x8000000000000000ULL, DFmode))));
+ emit_jump_insn (gen_blt (label1));
+
+ emit_insn (gen_subdf3 (temp, operands[1], force_const_mem (DFmode,
+ CONST_DOUBLE_FROM_REAL_VALUE (0x10000000000000000ULL, DFmode))));
+ emit_insn (gen_fix_truncdfdi2_ieee (operands[0], temp, GEN_INT(7)));
+ emit_jump_insn (gen_jump (label2));
+
+ emit_label (label1);
+ emit_insn (gen_fix_truncdfdi2_ieee (operands[0], operands[1], GEN_INT(5)));
+ emit_label (label2);
+ DONE;
+}")
+
+(define_expand "fix_truncdfdi2"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (fix:DI (match_operand:DF 1 "nonimmediate_operand" "")))]
+ "TARGET_64BIT && TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+ "
+{
+ operands[1] = force_reg (DFmode, operands[1]);
+ emit_insn (gen_fix_truncdfdi2_ieee (operands[0], operands[1], GEN_INT(5)));
+ DONE;
+}")
+
+(define_insn "fix_truncdfdi2_ieee"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (fix:DI (match_operand:DF 1 "register_operand" "f")))
+ (unspec:DI [(match_operand:DI 2 "immediate_operand" "K")] 1)
+ (clobber (reg:CC 33))]
+ "TARGET_64BIT && TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+ "cgdbr\\t%0,%h2,%1"
+ [(set_attr "op_type" "RRE")
+ (set_attr "cycle" "n")])
+
+;
+; fixuns_truncdfsi2 and fix_truncdfsi2 instruction pattern(s).
+;
+
+(define_expand "fixuns_truncdfsi2"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (unsigned_fix:SI (match_operand:DF 1 "register_operand" "")))]
+ "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+ "
+{
+ rtx label1 = gen_label_rtx ();
+ rtx label2 = gen_label_rtx ();
+ rtx temp = gen_reg_rtx (DFmode);
+
+ operands[1] = force_reg (DFmode,operands[1]);
+ emit_insn (gen_cmpdf (operands[1], force_const_mem (DFmode,
+ CONST_DOUBLE_FROM_REAL_VALUE (0x80000000, DFmode))));
+ emit_jump_insn (gen_blt (label1));
+ emit_insn (gen_subdf3 (temp, operands[1], force_const_mem (DFmode,
+ CONST_DOUBLE_FROM_REAL_VALUE (0x100000000ULL, DFmode))));
+ emit_insn (gen_fix_truncdfsi2_ieee (operands[0], temp, GEN_INT (7)));
+ emit_jump_insn (gen_jump (label2));
+
+ emit_label (label1);
+ emit_insn (gen_fix_truncdfsi2_ieee (operands[0], operands[1], GEN_INT (5)));
+ emit_label (label2);
+ DONE;
+}")
+
+(define_expand "fix_truncdfsi2"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (fix:SI (match_operand:DF 1 "nonimmediate_operand" "")))]
+ "TARGET_HARD_FLOAT"
+ "
+{
+ if (TARGET_IBM_FLOAT)
+ {
+ /* This is the algorithm from POP chapter A.5.7.2. */
+
+ rtx temp = assign_stack_local (BLKmode, 2 * UNITS_PER_WORD, BITS_PER_WORD);
+ rtx two31r = force_const_mem (DFmode,
+ gen_rtx (CONST_DOUBLE, VOIDmode, cc0_rtx,
+ 0x08000000, 0x4F000000));
+ rtx two32 = force_const_mem (DFmode,
+ gen_rtx (CONST_DOUBLE, VOIDmode, cc0_rtx,
+ 0x0, 0x4E000001));
+
+ operands[1] = force_reg (DFmode, operands[1]);
+ emit_insn (gen_fix_truncdfsi2_ibm (operands[0], operands[1],
+ two31r, two32, temp));
+ }
+ else
+ {
+ operands[1] = force_reg (DFmode, operands[1]);
+ emit_insn (gen_fix_truncdfsi2_ieee (operands[0], operands[1], GEN_INT (5)));
+ }
+
+ DONE;
+}")
+
+(define_insn "fix_truncdfsi2_ieee"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (fix:SI (match_operand:DF 1 "register_operand" "f")))
+ (unspec:SI [(match_operand:SI 2 "immediate_operand" "K")] 1)
+ (clobber (reg:CC 33))]
+ "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+ "cfdbr\\t%0,%h2,%1"
+ [(set_attr "op_type" "RRE")
+ (set_attr "cycle" "n" )])
+
+(define_insn "fix_truncdfsi2_ibm"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (fix:SI (match_operand:DF 1 "nonimmediate_operand" "+f")))
+ (use (match_operand:DF 2 "memory_operand" "m"))
+ (use (match_operand:DF 3 "memory_operand" "m"))
+ (use (match_operand:BLK 4 "memory_operand" "m"))
+ (clobber (reg:CC 33))]
+ "TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
+ "*
+{
+ output_asm_insn (\"sd\\t%1,%2\", operands);
+ output_asm_insn (\"aw\\t%1,%3\", operands);
+ output_asm_insn (\"std\\t%1,%4\", operands);
+ output_asm_insn (\"xi\\t%N4,128\", operands);
+ return \"l\\t%0,%N4\";
+}"
+ [(set_attr "op_type" "NN")
+ (set_attr "cycle" "n")
+ (set_attr "length" "20")])
+
+;
+; fixuns_truncsfdi2 and fix_truncsfdi2 instruction pattern(s).
+;
+
+(define_expand "fixuns_truncsfdi2"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (unsigned_fix:DI (match_operand:SF 1 "register_operand" "")))]
+ "TARGET_64BIT && TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+ "
+{
+ rtx label1 = gen_label_rtx ();
+ rtx label2 = gen_label_rtx ();
+ rtx temp = gen_reg_rtx (SFmode);
+
+ operands[1] = force_reg (SFmode, operands[1]);
+ emit_insn (gen_cmpsf (operands[1], force_const_mem (SFmode,
+ CONST_DOUBLE_FROM_REAL_VALUE (0x8000000000000000ULL, SFmode))));
+ emit_jump_insn (gen_blt (label1));
+
+ emit_insn (gen_subsf3 (temp, operands[1], force_const_mem (SFmode,
+ CONST_DOUBLE_FROM_REAL_VALUE (0x10000000000000000ULL, SFmode))));
+ emit_insn (gen_fix_truncsfdi2_ieee (operands[0], temp, GEN_INT(7)));
+ emit_jump_insn (gen_jump (label2));
+
+ emit_label (label1);
+ emit_insn (gen_fix_truncsfdi2_ieee (operands[0], operands[1], GEN_INT(5)));
+ emit_label (label2);
+ DONE;
+}")
+
+(define_expand "fix_truncsfdi2"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (fix:DI (match_operand:SF 1 "nonimmediate_operand" "")))]
+ "TARGET_64BIT && TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+ "
+{
+ operands[1] = force_reg (SFmode, operands[1]);
+ emit_insn (gen_fix_truncsfdi2_ieee (operands[0], operands[1], GEN_INT(5)));
+ DONE;
+}")
+
+(define_insn "fix_truncsfdi2_ieee"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (fix:DI (match_operand:SF 1 "register_operand" "f")))
+ (unspec:DI [(match_operand:DI 2 "immediate_operand" "K")] 1)
+ (clobber (reg:CC 33))]
+ "TARGET_64BIT && TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+ "cgebr\\t%0,%h2,%1"
+ [(set_attr "op_type" "RRE")
+ (set_attr "cycle" "n")])
+
+;
+; fixuns_truncsfsi2 and fix_truncsfsi2 instruction pattern(s).
+;
+
+(define_expand "fixuns_truncsfsi2"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (unsigned_fix:SI (match_operand:SF 1 "register_operand" "")))]
+ "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+ "
+{
+ rtx label1 = gen_label_rtx ();
+ rtx label2 = gen_label_rtx ();
+ rtx temp = gen_reg_rtx (SFmode);
+
+ operands[1] = force_reg (SFmode, operands[1]);
+ emit_insn (gen_cmpsf (operands[1], force_const_mem (SFmode,
+ CONST_DOUBLE_FROM_REAL_VALUE (0x80000000, SFmode))));
+ emit_jump_insn (gen_blt (label1));
+ emit_insn (gen_subsf3 (temp, operands[1], force_const_mem (SFmode,
+ CONST_DOUBLE_FROM_REAL_VALUE (0x100000000ULL, SFmode))));
+ emit_insn (gen_fix_truncsfsi2_ieee (operands[0], temp, GEN_INT (7)));
+ emit_jump_insn (gen_jump (label2));
+
+ emit_label (label1);
+ emit_insn (gen_fix_truncsfsi2_ieee (operands[0], operands[1], GEN_INT (5)));
+ emit_label (label2);
+ DONE;
+}")
+
+(define_expand "fix_truncsfsi2"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (fix:SI (match_operand:SF 1 "nonimmediate_operand" "")))]
+ "TARGET_HARD_FLOAT"
+ "
+{
+ if (TARGET_IBM_FLOAT)
+ {
+ /* Convert to DFmode and then use the POP algorithm. */
+ rtx temp = gen_reg_rtx (DFmode);
+ emit_insn (gen_extendsfdf2 (temp, operands[1]));
+ emit_insn (gen_fix_truncdfsi2 (operands[0], temp));
+ }
+ else
+ {
+ operands[1] = force_reg (SFmode, operands[1]);
+ emit_insn (gen_fix_truncsfsi2_ieee (operands[0], operands[1], GEN_INT (5)));
+ }
+
+ DONE;
+}")
+
+(define_insn "fix_truncsfsi2_ieee"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (fix:SI (match_operand:SF 1 "register_operand" "f")))
+ (unspec:SI [(match_operand:SI 2 "immediate_operand" "K")] 1)
+ (clobber (reg:CC 33))]
+ "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+ "cfebr\\t%0,%h2,%1"
+ [(set_attr "op_type" "RRE")
+ (set_attr "cycle" "n")])
+
+;
+; floatdidf2 instruction pattern(s).
+;
+
+(define_insn "floatdidf2"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (float:DF (match_operand:DI 1 "register_operand" "d")))]
+ "TARGET_64BIT && TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+ "cdgbr\\t%0,%1"
+ [(set_attr "op_type" "RRE")
+ (set_attr "cycle" "n" )])
+
+;
+; floatdisf2 instruction pattern(s).
+;
+
+(define_insn "floatdisf2"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (float:SF (match_operand:DI 1 "register_operand" "d")))]
+ "TARGET_64BIT && TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+ "cegbr\\t%0,%1"
+ [(set_attr "op_type" "RRE")
+ (set_attr "cycle" "n" )])
+
+;
+; floatsidf2 instruction pattern(s).
+;
+
+(define_expand "floatsidf2"
+ [(set (match_operand:DF 0 "register_operand" "")
+ (float:DF (match_operand:SI 1 "register_operand" "")))]
+ "TARGET_HARD_FLOAT"
+ "
+{
+ if (TARGET_IBM_FLOAT)
+ {
+ /* This is the algorithm from POP chapter A.5.7.1. */
+
+ rtx temp = assign_stack_local (BLKmode, 2 * UNITS_PER_WORD, BITS_PER_WORD);
+ rtx two31 = force_const_mem (DFmode,
+ gen_rtx (CONST_DOUBLE, VOIDmode, cc0_rtx,
+ 0x80000000, 0x4E000000));
+
+ emit_insn (gen_floatsidf2_ibm (operands[0], operands[1], two31, temp));
+ DONE;
+ }
+}")
+
+(define_insn "floatsidf2_ieee"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (float:DF (match_operand:SI 1 "register_operand" "d")))]
+ "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+ "cdfbr\\t%0,%1"
+ [(set_attr "op_type" "RRE")
+ (set_attr "cycle" "n" )])
+
+(define_insn "floatsidf2_ibm"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (float:DF (match_operand:SI 1 "register_operand" "d")))
+ (use (match_operand:DF 2 "memory_operand" "m"))
+ (use (match_operand:BLK 3 "memory_operand" "m"))
+ (clobber (reg:CC 33))]
+ "TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
+ "*
+{
+ output_asm_insn (\"st\\t%0,%N3\", operands);
+ output_asm_insn (\"xi\\t%N3,128\", operands);
+ output_asm_insn (\"mvc\\t%O3(4,%R3),%2\", operands);
+ output_asm_insn (\"ld\\t%0,%3\", operands);
+ return \"sd\\t%0,%2\";
+}"
+ [(set_attr "op_type" "NN")
+ (set_attr "cycle" "n" )
+ (set_attr "length" "20")])
+
+;
+; floatsisf2 instruction pattern(s).
+;
+
+(define_expand "floatsisf2"
+ [(set (match_operand:SF 0 "register_operand" "")
+ (float:SF (match_operand:SI 1 "register_operand" "")))]
+ "TARGET_HARD_FLOAT"
+ "
+{
+ if (TARGET_IBM_FLOAT)
+ {
+ /* Use the POP algorithm to convert to DFmode and then truncate. */
+ rtx temp = gen_reg_rtx (DFmode);
+ emit_insn (gen_floatsidf2 (temp, operands[1]));
+ emit_insn (gen_truncdfsf2 (operands[0], temp));
+ DONE;
+ }
+}")
+
+(define_insn "floatsisf2_ieee"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (float:SF (match_operand:SI 1 "register_operand" "d")))]
+ "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+ "cefbr\\t%0,%1"
+ [(set_attr "op_type" "RRE")
+ (set_attr "cycle" "n" )])
+
+;
+; truncdfsf2 instruction pattern(s).
+;
+
+(define_expand "truncdfsf2"
+ [(set (match_operand:SF 0 "register_operand" "")
+ (float_truncate:SF (match_operand:DF 1 "general_operand" "")))]
+ "TARGET_HARD_FLOAT"
+ "
+{
+ if (CONSTANT_P(operands[1]))
+ operands[1] = force_const_mem (DFmode, operands[1]);
+}")
+
+(define_insn "truncdfsf2_ieee"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (float_truncate:SF (match_operand:DF 1 "nonimmediate_operand" "f")))]
+ "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+ "ledbr\\t%0,%1"
+ [(set_attr "op_type" "RR")])
+
+(define_insn "truncdfsf2_ibm"
+ [(set (match_operand:SF 0 "register_operand" "=f,f")
+ (float_truncate:SF (match_operand:DF 1 "nonimmediate_operand" "f,m")))]
+ "TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
+ "@
+ lrer\\t%0,%1
+ le\\t%0,%1"
+ [(set_attr "op_type" "RR,RX")])
+
+;
+; extendsfdf2 instruction pattern(s).
+;
+
+(define_expand "extendsfdf2"
+ [(set (match_operand:DF 0 "register_operand" "")
+ (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "")))]
+ "TARGET_HARD_FLOAT"
+ "
+{
+ if (TARGET_IBM_FLOAT)
+ {
+ emit_insn (gen_extendsfdf2_ibm (operands[0], operands[1]));
+ DONE;
+ }
+}")
+
+(define_insn "extendsfdf2_ieee"
+ [(set (match_operand:DF 0 "register_operand" "=f,f")
+ (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "f,m")))]
+ "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+ "@
+ ldebr\\t%0,%1
+ ldeb\\t%0,%1"
+ [(set_attr "op_type" "RRE,RXE")])
+
+(define_insn "extendsfdf2_ibm"
+ [(set (match_operand:DF 0 "register_operand" "=f,f")
+ (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "f,m")))
+ (clobber (reg:CC 33))]
+ "TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
+ "@
+ sdr\\t%0,%0\;ler\\t%0,%1
+ sdr\\t%0,%0\;le\\t%0,%1"
+ [(set_attr "op_type" "RRE,RXE")])
+
+
+;;
+;; ARITHMETRIC OPERATIONS
+;;
+; arithmetric operations set the ConditionCode,
+; because of unpredictable Bits in Register for Halfword and Byte
+; the ConditionCode can be set wrong in operations for Halfword and Byte
+
+;;
+;;- Add instructions.
+;;
+
+;
+; adddi3 instruction pattern(s).
+;
+
+(define_insn "addaddr_esame"
+ [(set (match_operand:DI 0 "register_operand" "=a,a")
+ (plus:DI (match_operand:DI 1 "register_operand" "%a,a")
+ (match_operand:DI 2 "nonmemory_operand" "J,a")))]
+ "TARGET_64BIT && (((REGNO (operands[1]) == STACK_POINTER_REGNUM ) ||
+ (REGNO (operands[1]) == BASE_REGISTER)) &&
+ (GET_CODE (operands[2]) == REG ||
+ CONST_OK_FOR_LETTER_P (INTVAL (operands[2]),'J')))"
+ "@
+ la\\t%0,%c2(,%1)
+ la\\t%0,0(%1,%2)"
+ [(set_attr "op_type" "RX")
+ (set_attr "atype" "mem")
+ (set_attr "type" "la")])
+
+(define_insn "adddi3_64"
+ [(set (match_operand:DI 0 "register_operand" "=d,d,d")
+ (plus:DI (match_operand:DI 1 "register_operand" "%0,0,0")
+ (match_operand:DI 2 "general_operand" "d,K,m") ) )
+ (clobber (reg:CC 33))]
+ "TARGET_64BIT"
+ "@
+ agr\\t%0,%2
+ aghi\\t%0,%h2
+ ag\\t%0,%2"
+ [(set_attr "op_type" "RRE,RI,RXE")
+ (set_attr "atype" "reg,reg,mem")
+ (set_attr "type" "set")])
+
+;
+; For weakness of reload, need (set (reg x) (plus (reg y) (reg x)))
+;
+
+(define_insn "adddi3_inv_64"
+ [(set (match_operand:DI 0 "register_operand" "=d,d,d")
+ (plus:DI (match_operand:DI 1 "general_operand" "%d,K,m")
+ (match_operand:DI 2 "register_operand" "0,0,0") ) )
+ (clobber (reg:CC 33))]
+ "TARGET_64BIT"
+ "@
+ agr\\t%0,%1
+ aghi\\t%0,%h1
+ ag\\t%0,%1"
+ [(set_attr "op_type" "RRE,RI,RXE")
+ (set_attr "atype" "reg,reg,mem")
+ (set_attr "type" "set")])
+
+(define_insn "adddi3_31"
+ [(set (match_operand:DI 0 "register_operand" "=d,d")
+ (plus:DI (match_operand:DI 1 "register_operand" "0,0")
+ (match_operand:DI 2 "general_operand" "d,m") ) )
+ (clobber (reg:CC 33))]
+ "!TARGET_64BIT"
+ "*
+{
+ switch(which_alternative)
+ {
+ case 0: /* d <- d */
+ output_asm_insn (\"ar\\t%0,%2\", operands);
+ output_asm_insn (\"alr\\t%N0,%N2\", operands);
+ break;
+
+ case 1: /* d <- m */
+ output_asm_insn (\"a\\t%0,%2\", operands);
+ output_asm_insn (\"al\\t%N0,%N2\", operands);
+ break;
+ }
+
+ output_asm_insn (\"brc\\t12,.+8\", operands);
+ return \"ahi\\t%0,1\";
+}"
+ [(set_attr "op_type" "NN,NN")
+ (set_attr "atype" "reg,mem")
+ (set_attr "length" "12,16")])
+
+(define_expand "adddi3"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (plus:DI (match_operand:DI 1 "register_operand" "")
+ (match_operand:DI 2 "general_operand" "")))]
+ ""
+ "
+{
+ if (TARGET_64BIT)
+ emit_insn(gen_adddi3_64 (operands[0],operands[1],operands[2]));
+ else
+ emit_insn(gen_adddi3_31 (operands[0],operands[1],operands[2]));
+ DONE;
+}")
+
+(define_insn "reload_load_address"
+ [(set (match_operand:DI 0 "register_operand" "=a")
+ (match_operand:QI 1 "address_operand" "p"))]
+ "TARGET_64BIT"
+ "la\\t%0,%a1"
+ [(set_attr "op_type" "RX")
+ (set_attr "atype" "mem")
+ (set_attr "type" "la")])
+
+(define_insn "*reload_load_address_reg_0"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (plus:DI (match_operand:DI 1 "register_operand" "%0")
+ (match_operand:DI 2 "register_operand" "d")))]
+ "TARGET_64BIT"
+ "brxlg\\t%0,%2,.+6"
+ [(set_attr "op_type" "RIE")
+ (set_attr "atype" "reg")
+ (set_attr "type" "set")])
+
+(define_insn "*reload_la_64"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (plus:DI (match_operand:DI 1 "general_operand" "g")
+ (match_operand:DI 2 "general_operand" "g")))]
+ "TARGET_64BIT && reload_in_progress"
+ "#")
+
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (plus:DI (match_operand:DI 1 "general_operand" "")
+ (match_operand:DI 2 "register_operand" "")))]
+ "TARGET_64BIT && reload_completed
+ && !address_operand (gen_rtx_PLUS (DImode, operands[1], operands[2]), QImode)
+ && !rtx_equal_p (operands[0], operands[1])
+ && !rtx_equal_p (operands[0], operands[2])"
+ [(set (match_dup 0) (match_dup 1))
+ (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 2)))]
+ "")
+
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (plus:DI (match_operand:DI 1 "register_operand" "")
+ (match_operand:DI 2 "general_operand" "")))]
+ "TARGET_64BIT && reload_completed
+ && !address_operand (gen_rtx_PLUS (DImode, operands[1], operands[2]), QImode)
+ && !rtx_equal_p (operands[0], operands[1])
+ && !rtx_equal_p (operands[0], operands[2])"
+ [(set (match_dup 0) (match_dup 2))
+ (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 1)))]
+ "")
+
+;
+; addsi3 instruction pattern(s).
+;
+; The following insn is used when it is known that operand one is the stack pointer,
+; and operand two is small enough to fit in the displacement field
+; In this case, the result will be a address
+;
+
+(define_insn "addaddr"
+ [(set (match_operand:SI 0 "register_operand" "=d,d")
+ (plus:SI (match_operand:SI 1 "register_operand" "%a,a")
+ (match_operand:SI 2 "nonmemory_operand" "J,a")))]
+ "(((REGNO (operands[1]) == STACK_POINTER_REGNUM ) ||
+ (REGNO (operands[1]) == BASE_REGISTER)) &&
+ (GET_CODE (operands[2]) == REG ||
+ CONST_OK_FOR_LETTER_P (INTVAL (operands[2]),'J')))"
+ "@
+ la\\t%0,%c2(,%1)
+ la\\t%0,0(%1,%2)"
+ [(set_attr "op_type" "RX")
+ (set_attr "atype" "mem")
+ (set_attr "type" "la")])
+
+(define_insn "*addaddr_picR"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (plus:SI (match_operand:SI 1 "register_operand" "a")
+ (unspec:SI [(match_operand:SI 2 "register_operand" "a")] 101)))]
+ ""
+ "la\\t%0,0(%1,%2)"
+ [(set_attr "op_type" "RX")
+ (set_attr "atype" "mem")
+ (set_attr "type" "la")])
+
+(define_insn "*addaddr_picL"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (plus:SI (unspec:SI [(match_operand:SI 2 "register_operand" "a")] 101)
+ (match_operand:SI 1 "register_operand" "a")))]
+ ""
+ "la\\t%0,0(%1,%2)"
+ [(set_attr "op_type" "RX")
+ (set_attr "atype" "mem")
+ (set_attr "type" "la")])
+
+(define_insn "*addaddr_picN"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (unspec:SI [(match_operand:SI 1 "register_operand" "a")] 101))]
+ ""
+ "la\\t%0,0(%1)"
+ [(set_attr "op_type" "RX")
+ (set_attr "atype" "mem")
+ (set_attr "type" "la")])
+
+(define_insn "*addsi3_cc"
+ [(set (reg 33)
+ (compare (plus:SI (match_operand:SI 1 "register_operand" "%0,0,0")
+ (match_operand:SI 2 "general_operand" "d,K,m"))
+ (const_int 0)))
+ (set (match_operand:SI 0 "register_operand" "=d,d,d")
+ (plus:SI (match_dup 1) (match_dup 2)))]
+ "s390_match_ccmode(insn, CCSmode)"
+ "@
+ ar\\t%0,%2
+ ahi\\t%0,%h2
+ a\\t%0,%2"
+ [(set_attr "op_type" "RR,RI,RX")
+ (set_attr "atype" "reg,reg,mem")
+ (set_attr "type" "set")])
+
+(define_insn "*addsi3_cconly"
+ [(set (reg 33)
+ (compare (plus:SI (match_operand:SI 1 "register_operand" "%0,0,0")
+ (match_operand:SI 2 "general_operand" "d,K,m"))
+ (const_int 0)))
+ (clobber (match_scratch:SI 0 "=d,d,d"))]
+ "s390_match_ccmode(insn, CCSmode)"
+ "@
+ ar\\t%0,%2
+ ahi\\t%0,%h2
+ a\\t%0,%2"
+ [(set_attr "op_type" "RR,RI,RX")
+ (set_attr "atype" "reg,reg,mem")
+ (set_attr "type" "set")])
+
+(define_insn "*addsi3_cconly2"
+ [(set (reg 33)
+ (compare (match_operand:SI 1 "register_operand" "%0,0,0")
+ (neg:SI (match_operand:SI 2 "general_operand" "d,K,m"))))
+ (clobber (match_scratch:SI 0 "=d,d,d"))]
+ "s390_match_ccmode(insn, CCSmode)"
+ "@
+ ar\\t%0,%2
+ ahi\\t%0,%h2
+ a\\t%0,%2"
+ [(set_attr "op_type" "RR,RI,RX")
+ (set_attr "atype" "reg,reg,mem")
+ (set_attr "type" "set")])
+
+(define_insn "addsi3"
+ [(set (match_operand:SI 0 "register_operand" "=d,d,d")
+ (plus:SI (match_operand:SI 1 "register_operand" "%0,0,0")
+ (match_operand:SI 2 "general_operand" "d,K,m")))
+ (clobber (reg:CC 33))]
+ ""
+ "@
+ ar\\t%0,%2
+ ahi\\t%0,%h2
+ a\\t%0,%2"
+ [(set_attr "op_type" "RR,RI,RX")
+ (set_attr "atype" "reg,reg,mem")
+ (set_attr "type" "set")])
+
+(define_insn "do_la"
+ [(set (match_operand:SI 0 "register_operand" "=a")
+ (match_operand:QI 1 "address_operand" "p"))]
+ "volatile_ok"
+ "la\\t%0,%a1"
+ [(set_attr "op_type" "RX")
+ (set_attr "atype" "mem")
+ (set_attr "type" "la")])
+
+(define_insn "*do_la_reg_0"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (plus:SI (match_operand:SI 1 "register_operand" "%0")
+ (match_operand:SI 2 "register_operand" "d")))]
+ ""
+ "brxle\\t%0,%2,.+4"
+ [(set_attr "op_type" "RSI")
+ (set_attr "atype" "reg")
+ (set_attr "type" "set")])
+
+(define_insn "*reload_la_31"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (plus:SI (match_operand:SI 1 "general_operand" "g")
+ (match_operand:SI 2 "general_operand" "g")))]
+ "reload_in_progress"
+ "#")
+
+(define_split
+ [(set (match_operand:SI 0 "register_operand" "")
+ (plus:SI (match_operand:SI 1 "general_operand" "")
+ (match_operand:SI 2 "register_operand" "")))]
+ "reload_completed
+ && !address_operand (gen_rtx_PLUS (SImode, operands[1], operands[2]), QImode)
+ && !rtx_equal_p (operands[0], operands[1])
+ && !rtx_equal_p (operands[0], operands[2])"
+ [(set (match_dup 0) (match_dup 1))
+ (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 2)))]
+ "")
+
+(define_split
+ [(set (match_operand:SI 0 "register_operand" "")
+ (plus:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "general_operand" "")))]
+ "reload_completed
+ && !address_operand (gen_rtx_PLUS (SImode, operands[1], operands[2]), QImode)
+ && !rtx_equal_p (operands[0], operands[1])
+ && !rtx_equal_p (operands[0], operands[2])"
+ [(set (match_dup 0) (match_dup 2))
+ (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
+ "")
+
+(define_insn "addsi_64"
+ [(set (match_operand:SI 0 "register_operand" "=d,d")
+ (plus:SI (match_operand:SI 1 "register_operand" "%a,a")
+ (match_operand:SI 2 "nonmemory_operand" "J,a")))]
+ "TARGET_64BIT"
+ "@
+ la\\t%0,%c2(,%1)
+ la\\t%0,0(%1,%2)"
+ [(set_attr "op_type" "RX")
+ (set_attr "atype" "mem")
+ (set_attr "type" "la")])
+
+;
+; addhi3 instruction pattern(s).
+;
+
+(define_insn "addhi3"
+ [(set (match_operand:HI 0 "register_operand" "=d,d,d")
+ (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0")
+ (match_operand:HI 2 "general_operand" "d,K,m")))
+ (clobber (reg:CC 33))]
+ ""
+ "@
+ ar\\t%0,%2
+ ahi\\t%0,%h2
+ ah\\t%0,%2"
+ [(set_attr "op_type" "RR,RI,RX")
+ (set_attr "atype" "reg,reg,mem")])
+
+
+;
+; addqi3 instruction pattern(s).
+;
+
+(define_insn "addqi3"
+ [(set (match_operand:QI 0 "register_operand" "=d,d")
+ (plus:QI (match_operand:QI 1 "register_operand" "%0,0")
+ (match_operand:QI 2 "general_operand" "a,n")))
+ (clobber (reg:CC 33))]
+ ""
+ "@
+ ar\\t%0,%2
+ ahi\\t%0,%h2"
+ [(set_attr "op_type" "RX,RX")
+ (set_attr "atype" "reg,mem")])
+
+
+;
+; adddf3 instruction pattern(s).
+;
+
+(define_expand "adddf3"
+ [(parallel
+ [(set (match_operand:DF 0 "register_operand" "=f,f")
+ (plus:DF (match_operand:DF 1 "register_operand" "%0,0")
+ (match_operand:DF 2 "nonimmediate_operand" "f,m")))
+ (clobber (reg:CC 33))])]
+ "TARGET_HARD_FLOAT"
+ "")
+
+(define_insn "*adddf3"
+ [(set (match_operand:DF 0 "register_operand" "=f,f")
+ (plus:DF (match_operand:DF 1 "register_operand" "%0,0")
+ (match_operand:DF 2 "nonimmediate_operand" "f,m")))
+ (clobber (reg:CC 33))]
+ "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+ "@
+ adbr\\t%0,%2
+ adb\\t%0,%2"
+ [(set_attr "op_type" "RR,RX")
+ (set_attr "atype" "reg,mem")])
+
+(define_insn "*adddf3_ibm"
+ [(set (match_operand:DF 0 "register_operand" "=f,f")
+ (plus:DF (match_operand:DF 1 "register_operand" "%0,0")
+ (match_operand:DF 2 "nonimmediate_operand" "f,m")))
+ (clobber (reg:CC 33))]
+ "TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
+ "@
+ adr\\t%0,%2
+ ad\\t%0,%2"
+ [(set_attr "op_type" "RR,RX")
+ (set_attr "atype" "reg,mem")])
+
+;
+; addsf3 instruction pattern(s).
+;
+
+(define_expand "addsf3"
+ [(parallel
+ [(set (match_operand:SF 0 "register_operand" "=f,f")
+ (plus:SF (match_operand:SF 1 "register_operand" "%0,0")
+ (match_operand:SF 2 "nonimmediate_operand" "f,m")))
+ (clobber (reg:CC 33))])]
+ "TARGET_HARD_FLOAT"
+ "")
+
+(define_insn "*addsf3"
+ [(set (match_operand:SF 0 "register_operand" "=f,f")
+ (plus:SF (match_operand:SF 1 "register_operand" "%0,0")
+ (match_operand:SF 2 "nonimmediate_operand" "f,m")))
+ (clobber (reg:CC 33))]
+ "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+ "@
+ aebr\\t%0,%2
+ aeb\\t%0,%2"
+ [(set_attr "op_type" "RR,RX")
+ (set_attr "atype" "reg,mem")])
+
+(define_insn "*addsf3"
+ [(set (match_operand:SF 0 "register_operand" "=f,f")
+ (plus:SF (match_operand:SF 1 "register_operand" "%0,0")
+ (match_operand:SF 2 "nonimmediate_operand" "f,m")))
+ (clobber (reg:CC 33))]
+ "TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
+ "@
+ aer\\t%0,%2
+ ae\\t%0,%2"
+ [(set_attr "op_type" "RR,RX")
+ (set_attr "atype" "reg,mem")])
+
+
+;;
+;;- Subtract instructions.
+;;
+
+;
+; subdi3 instruction pattern(s).
+;
+
+(define_insn "*subdi3_64"
+ [(set (match_operand:DI 0 "register_operand" "=d,d")
+ (minus:DI (match_operand:DI 1 "register_operand" "0,0")
+ (match_operand:DI 2 "general_operand" "d,m") ) )
+ (clobber (reg:CC 33))]
+ "TARGET_64BIT"
+ "@
+ sgr\\t%0,%2
+ sg\\t%0,%2"
+ [(set_attr "op_type" "RRE,RRE")
+ (set_attr "atype" "reg,mem")
+ (set_attr "type" "set")])
+
+(define_insn "subdi3"
+ [(set (match_operand:DI 0 "register_operand" "=d,d")
+ (minus:DI (match_operand:DI 1 "register_operand" "0,0")
+ (match_operand:DI 2 "nonimmediate_operand" "d,m")))
+ (clobber (reg:CC 33))]
+ ""
+ "*
+{
+ switch (which_alternative)
+ {
+ case 0: /* d <- d */
+ output_asm_insn (\"sr\\t%0,%2\", operands);
+ output_asm_insn (\"slr\\t%N0,%N2\", operands);
+ break;
+ case 1: /* d <- m */
+ output_asm_insn (\"s\\t%0,%2\", operands);
+ output_asm_insn (\"sl\\t%N0,%N2\", operands);
+ break;
+ }
+
+ output_asm_insn (\"brc\\t11,.+8\", operands);
+ return \"ahi\\t%0,-1\";
+}"
+ [(set_attr "op_type" "NN,NN")
+ (set_attr "atype" "reg,mem")
+ (set_attr "length" "12,16")])
+
+;
+; subsi3 instruction pattern(s).
+;
+
+(define_insn "*subsi3_cc"
+ [(set (reg 33)
+ (compare (minus:SI (match_operand:SI 1 "register_operand" "0,0")
+ (match_operand:SI 2 "general_operand" "d,m"))
+ (const_int 0)))
+ (set (match_operand:SI 0 "register_operand" "=d,d")
+ (minus:SI (match_dup 1) (match_dup 2)))]
+ "s390_match_ccmode(insn, CCSmode)"
+ "@
+ sr\\t%0,%2
+ s\\t%0,%2"
+ [(set_attr "op_type" "RR,RX")
+ (set_attr "atype" "reg,mem")
+ (set_attr "type" "set")])
+
+(define_insn "*subsi3_cconly"
+ [(set (reg 33)
+ (compare (minus:SI (match_operand:SI 1 "register_operand" "0,0")
+ (match_operand:SI 2 "general_operand" "d,m"))
+ (const_int 0)))
+ (clobber (match_scratch:SI 0 "=d,d"))]
+ "s390_match_ccmode(insn, CCSmode)"
+ "@
+ sr\\t%0,%2
+ s\\t%0,%2"
+ [(set_attr "op_type" "RR,RX")
+ (set_attr "atype" "reg,mem")
+ (set_attr "type" "set")])
+
+(define_insn "subsi3"
+ [(set (match_operand:SI 0 "register_operand" "=d,d")
+ (minus:SI (match_operand:SI 1 "register_operand" "0,0")
+ (match_operand:SI 2 "general_operand" "d,m")))
+ (clobber (reg:CC 33))]
+ ""
+ "@
+ sr\\t%0,%2
+ s\\t%0,%2"
+ [(set_attr "op_type" "RR,RX")
+ (set_attr "atype" "reg,mem")
+ (set_attr "type" "set")])
+
+;
+; subhi3 instruction pattern(s).
+;
+
+(define_insn "subhi3"
+ [(set (match_operand:HI 0 "register_operand" "=d,d,d")
+ (minus:HI (match_operand:HI 1 "register_operand" "0,0,0")
+ (match_operand:HI 2 "nonimmediate_operand" "d,K,m")))
+ (clobber (reg:CC 33))]
+ ""
+ "@
+ sr\\t%0,%2
+ ahi\\t%0,-%h2
+ sh\\t%0,%2"
+ [(set_attr "op_type" "RR,RI,RX")
+ (set_attr "atype" "reg,reg,mem")])
+
+;
+; subqi3 instruction pattern(s).
+;
+
+(define_insn "subqi3"
+ [(set (match_operand:QI 0 "register_operand" "=d")
+ (minus:QI (match_operand:QI 1 "register_operand" "0")
+ (match_operand:QI 2 "register_operand" "d")))
+ (clobber (reg:CC 33))]
+ ""
+ "sr\\t%0,%2"
+ [(set_attr "op_type" "RR")])
+
+;
+; subdf3 instruction pattern(s).
+;
+
+(define_expand "subdf3"
+ [(parallel
+ [(set (match_operand:DF 0 "register_operand" "=f,f")
+ (minus:DF (match_operand:DF 1 "register_operand" "0,0")
+ (match_operand:DF 2 "nonimmediate_operand" "f,m")))
+ (clobber (reg:CC 33))])]
+ "TARGET_HARD_FLOAT"
+ "")
+
+(define_insn "*subdf3"
+ [(set (match_operand:DF 0 "register_operand" "=f,f")
+ (minus:DF (match_operand:DF 1 "register_operand" "0,0")
+ (match_operand:DF 2 "nonimmediate_operand" "f,m")))
+ (clobber (reg:CC 33))]
+ "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+ "@
+ sdbr\\t%0,%2
+ sdb\\t%0,%2"
+ [(set_attr "op_type" "RR,RX")
+ (set_attr "atype" "reg,mem")])
+
+(define_insn "*subdf3_ibm"
+ [(set (match_operand:DF 0 "register_operand" "=f,f")
+ (minus:DF (match_operand:DF 1 "register_operand" "0,0")
+ (match_operand:DF 2 "nonimmediate_operand" "f,m")))
+ (clobber (reg:CC 33))]
+ "TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
+ "@
+ sdr\\t%0,%2
+ sd\\t%0,%2"
+ [(set_attr "op_type" "RR,RX")
+ (set_attr "atype" "reg,mem")])
+
+;
+; subsf3 instruction pattern(s).
+;
+
+(define_expand "subsf3"
+ [(parallel
+ [(set (match_operand:SF 0 "register_operand" "=f,f")
+ (minus:SF (match_operand:SF 1 "register_operand" "0,0")
+ (match_operand:SF 2 "nonimmediate_operand" "f,m")))
+ (clobber (reg:CC 33))])]
+ "TARGET_HARD_FLOAT"
+ "")
+
+(define_insn "*subsf3"
+ [(set (match_operand:SF 0 "register_operand" "=f,f")
+ (minus:SF (match_operand:SF 1 "register_operand" "0,0")
+ (match_operand:SF 2 "nonimmediate_operand" "f,m")))
+ (clobber (reg:CC 33))]
+ "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+ "@
+ sebr\\t%0,%2
+ seb\\t%0,%2"
+ [(set_attr "op_type" "RR,RX")
+ (set_attr "atype" "reg,mem")])
+
+(define_insn "*subsf3_ibm"
+ [(set (match_operand:SF 0 "register_operand" "=f,f")
+ (minus:SF (match_operand:SF 1 "register_operand" "0,0")
+ (match_operand:SF 2 "nonimmediate_operand" "f,m")))
+ (clobber (reg:CC 33))]
+ "TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
+ "@
+ ser\\t%0,%2
+ se\\t%0,%2"
+ [(set_attr "op_type" "RR,RX")
+ (set_attr "atype" "reg,mem")])
+
+
+;;
+;;- Multiply instructions.
+;;
+
+(define_expand "muldi3"
+ [(parallel
+ [(set (match_operand:DI 0 "register_operand" "")
+ (mult:DI (match_operand:DI 1 "register_operand" "")
+ (match_operand:DI 2 "register_operand" "")))
+ (clobber (reg:CC 33))])]
+ ""
+ "
+{
+ if (!TARGET_64BIT)
+ {
+ rtx label1 = gen_label_rtx ();
+ rtx label2 = gen_label_rtx ();
+ rtx op0_0 = operand_subword (operands[0], 0 ,1, DImode);
+ rtx op0_1 = operand_subword (operands[0], 1 ,1, DImode);
+ rtx temp1_0 = gen_reg_rtx (SImode);
+ rtx temp1_1 = gen_reg_rtx (SImode);
+ rtx temp2_0 = gen_reg_rtx (SImode);
+ rtx temp2_1 = gen_reg_rtx (SImode);
+
+ emit_move_insn (temp1_0, operand_subword (operands[1], 0 ,1, DImode));
+ emit_move_insn (temp1_1, operand_subword (operands[1], 1 ,1, DImode));
+ emit_move_insn (temp2_0, operand_subword (operands[2], 0 ,1, DImode));
+ emit_move_insn (temp2_1, operand_subword (operands[2], 1 ,1, DImode));
+ emit_move_insn (op0_1, temp1_1);
+ emit_insn (gen_mulsi_6432 (operands[0], operands[0], temp2_1));
+
+ emit_insn (gen_cmpsi (temp1_1, const0_rtx));
+ emit_jump_insn (gen_bge (label1));
+ emit_insn (gen_addsi3 (op0_0, op0_0, temp2_1));
+ emit_label (label1);
+ emit_insn (gen_cmpsi (temp2_1, const0_rtx));
+ emit_jump_insn (gen_bge (label2));
+ emit_insn (gen_addsi3 (op0_0, op0_0, temp1_1));
+ emit_label (label2);
+
+ emit_insn (gen_mulsi3 (temp2_1, temp2_1, temp1_0));
+ emit_insn (gen_addsi3 (op0_0, op0_0, temp2_1));
+
+ emit_insn (gen_mulsi3 (temp1_1, temp1_1, temp2_0));
+ emit_insn (gen_addsi3 (op0_0, op0_0, temp1_1));
+
+ DONE;
+ }
+}")
+
+(define_insn "*muldi3_64"
+ [(set (match_operand:DI 0 "register_operand" "=d,d,d")
+ (mult:DI (match_operand:DI 1 "register_operand" "%0,0,0")
+ (match_operand:DI 2 "general_operand" "d,K,m")))
+ (clobber (reg:CC 33))]
+ "TARGET_64BIT"
+ "@
+ msgr\\t%0,%2
+ mghi\\t%0,%h2
+ msg\\t%0,%2"
+ [(set_attr "op_type" "RRE,RI,RX")
+ (set_attr "cycle" "n")
+ (set_attr "atype" "reg,reg,mem")
+ (set_attr "type" "set")])
+
+;
+; mulsi3 instruction pattern(s).
+;
+
+(define_insn "mulsi3"
+ [(set (match_operand:SI 0 "register_operand" "=d,d,d")
+ (mult:SI (match_operand:SI 1 "register_operand" "%0,0,0")
+ (match_operand:SI 2 "general_operand" "d,K,m")))
+ (clobber (reg:CC 33))]
+ ""
+ "@
+ msr\\t%0,%2
+ mhi\\t%0,%h2
+ ms\\t%0,%2"
+ [(set_attr "op_type" "RRE,RI,RX")
+ (set_attr "cycle" "n")
+ (set_attr "atype" "reg,reg,mem")
+ (set_attr "type" "set")])
+
+(define_insn "mulsi_6432"
+ [(set (match_operand:DI 0 "register_operand" "=d,d")
+ (mult:DI (sign_extend:DI
+ (subreg:SI (match_operand:DI 1 "register_operand" "0,0") 1))
+ (sign_extend:DI
+ (match_operand:SI 2 "general_operand" "d,m"))))
+ (clobber (reg:CC 33))]
+ "!TARGET_64BIT"
+ "@
+ mr\\t%0,%2
+ m\\t%0,%2"
+ [(set_attr "op_type" "RR,RX")
+ (set_attr "cycle" "n")
+ (set_attr "atype" "reg,mem")
+ (set_attr "type" "set")])
+
+
+;
+; muldf3 instruction pattern(s).
+;
+
+(define_expand "muldf3"
+ [(parallel
+ [(set (match_operand:DF 0 "register_operand" "=f,f")
+ (mult:DF (match_operand:DF 1 "register_operand" "%0,0")
+ (match_operand:DF 2 "nonimmediate_operand" "f,m")))
+ (clobber (reg:CC 33))])]
+ "TARGET_HARD_FLOAT"
+ "")
+
+(define_insn "*muldf3"
+ [(set (match_operand:DF 0 "register_operand" "=f,f")
+ (mult:DF (match_operand:DF 1 "register_operand" "%0,0")
+ (match_operand:DF 2 "nonimmediate_operand" "f,m")))
+ (clobber (reg:CC 33))]
+ "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+ "@
+ mdbr\\t%0,%2
+ mdb\\t%0,%2"
+ [(set_attr "op_type" "RR,RX")
+ (set_attr "cycle" "n")
+ (set_attr "atype" "reg,mem")])
+
+(define_insn "*muldf3_ibm"
+ [(set (match_operand:DF 0 "register_operand" "=f,f")
+ (mult:DF (match_operand:DF 1 "register_operand" "%0,0")
+ (match_operand:DF 2 "nonimmediate_operand" "f,m")))
+ (clobber (reg:CC 33))]
+ "TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
+ "@
+ mdr\\t%0,%2
+ md\\t%0,%2"
+ [(set_attr "op_type" "RR,RX")
+ (set_attr "cycle" "n")
+ (set_attr "atype" "reg,mem")])
+
+;
+; mulsf3 instruction pattern(s).
+;
+
+(define_expand "mulsf3"
+ [(parallel
+ [(set (match_operand:SF 0 "register_operand" "=f,f")
+ (mult:SF (match_operand:SF 1 "register_operand" "%0,0")
+ (match_operand:SF 2 "nonimmediate_operand" "f,m")))
+ (clobber (reg:CC 33))])]
+ "TARGET_HARD_FLOAT"
+ "")
+
+(define_insn "*mulsf3"
+ [(set (match_operand:SF 0 "register_operand" "=f,f")
+ (mult:SF (match_operand:SF 1 "register_operand" "%0,0")
+ (match_operand:SF 2 "nonimmediate_operand" "f,m")))
+ (clobber (reg:CC 33))]
+ "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+ "@
+ meebr\\t%0,%2
+ meeb\\t%0,%2"
+ [(set_attr "op_type" "RR,RX")
+ (set_attr "cycle" "n")
+ (set_attr "atype" "reg,mem")])
+
+(define_insn "*mulsf3_ibm"
+ [(set (match_operand:SF 0 "register_operand" "=f,f")
+ (mult:SF (match_operand:SF 1 "register_operand" "%0,0")
+ (match_operand:SF 2 "nonimmediate_operand" "f,m")))
+ (clobber (reg:CC 33))]
+ "TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
+ "@
+ mer\\t%0,%2
+ me\\t%0,%2"
+ [(set_attr "op_type" "RR,RX")
+ (set_attr "cycle" "n")
+ (set_attr "atype" "reg,mem")])
+
+
+;;
+;;- Divide and modulo instructions.
+;;
+
+;
+; divdi3 and moddi3 instruction pattern(s).
+;
+
+(define_expand "divdi3"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (div:DI (match_operand:DI 1 "register_operand" "d")
+ (match_operand:DI 2 "general_operand" "")))]
+ "TARGET_64BIT"
+ "
+{
+ rtx op3 = gen_reg_rtx (TImode);
+
+ if (CONSTANT_P (operands[2]))
+ operands[2] = force_const_mem (DImode, operands[2]);
+
+ emit_move_insn (gen_rtx (SUBREG, DImode, op3, 0), const0_rtx);
+ emit_move_insn (gen_rtx (SUBREG, DImode, op3, 1), operands[1]);
+ emit_insn (gen_divmodtidi3 (op3, op3, operands[2]));
+ emit_move_insn (operands[0], gen_rtx (SUBREG, DImode, op3, 1));
+ DONE;
+}")
+
+(define_expand "moddi3"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (mod:DI (match_operand:DI 1 "register_operand" "d")
+ (match_operand:DI 2 "general_operand" "")))]
+ "TARGET_64BIT"
+ "
+{
+ rtx op3 = gen_reg_rtx (TImode);
+
+ if (CONSTANT_P (operands[2]))
+ operands[2] = force_const_mem (DImode, operands[2]);
+
+ emit_move_insn (gen_rtx (SUBREG, DImode, op3, 0), const0_rtx);
+ emit_move_insn (gen_rtx (SUBREG, DImode, op3, 1), operands[1]);
+ emit_insn (gen_divmodtidi3 (op3, op3, operands[2]));
+ emit_move_insn (operands[0], gen_rtx (SUBREG, DImode, op3, 0));
+ DONE;
+}")
+
+(define_insn "divmodtidi3"
+ [(set (subreg:DI (match_operand:TI 0 "register_operand" "=d,d") 0)
+ (truncate:DI
+ (mod:TI (match_operand:TI 1 "register_operand" "0,0")
+ (sign_extend:TI
+ (match_operand:DI 2 "nonimmediate_operand" "d,m")))))
+ (set (subreg:DI (match_dup 0) 1)
+ (truncate:DI (div:TI (match_dup 1) (sign_extend:TI (match_dup 2)))))
+ (clobber (reg:CC 33))]
+ "TARGET_64BIT"
+ "@
+ dsgr\\t%0,%2
+ dsg\\t%0,%2"
+ [(set_attr "op_type" "RRE,RXE")
+ (set_attr "cycle" "n")
+ (set_attr "atype" "reg,mem")])
+
+;
+; udivdi3 and umoddi3 instruction pattern(s).
+;
+
+(define_expand "udivdi3"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (udiv:DI (match_operand:DI 1 "register_operand" "d")
+ (match_operand:DI 2 "general_operand" "")))]
+ "TARGET_64BIT"
+ "
+{
+ rtx op3 = gen_reg_rtx(TImode);
+
+ if (CONSTANT_P (operands[2]))
+ operands[2] = force_const_mem (DImode, operands[2]);
+
+ emit_move_insn (gen_rtx (SUBREG, DImode, op3, 0), const0_rtx);
+ emit_move_insn (gen_rtx (SUBREG, DImode, op3, 1), operands[1]);
+ emit_insn (gen_udivmodtidi3 (op3, op3, operands[2]));
+ emit_move_insn (operands[0], gen_rtx (SUBREG, DImode, op3, 1));
+ DONE;
+}")
+
+(define_expand "umoddi3"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (umod:DI (match_operand:DI 1 "register_operand" "d")
+ (match_operand:DI 2 "general_operand" "")))]
+ "TARGET_64BIT"
+ "
+{
+ rtx op3 = gen_reg_rtx (TImode);
+
+ if (CONSTANT_P (operands[2]))
+ operands[2] = force_const_mem (DImode, operands[2]);
+
+ emit_move_insn (gen_rtx (SUBREG, DImode, op3, 0), const0_rtx);
+ emit_move_insn (gen_rtx (SUBREG, DImode, op3, 1), operands[1]);
+ emit_insn (gen_udivmodtidi3 (op3, op3, operands[2]));
+ emit_move_insn (operands[0], gen_rtx (SUBREG, DImode, op3, 0));
+ DONE;
+}")
+
+(define_insn "udivmodtidi3"
+ [(set (subreg:DI (match_operand:TI 0 "register_operand" "=d,d") 0)
+ (truncate:DI
+ (umod:TI (match_operand:TI 1 "register_operand" "0,0")
+ (zero_extend:TI
+ (match_operand:DI 2 "nonimmediate_operand" "d,m")))))
+ (set (subreg:DI (match_dup 0) 1)
+ (truncate:DI (udiv:TI (match_dup 1) (zero_extend:TI (match_dup 2)))))
+ (clobber (reg:CC 33))]
+ "TARGET_64BIT"
+ "@
+ dlgr\\t%0,%2
+ dlg\\t%0,%2"
+ [(set_attr "op_type" "RRE,RXE")
+ (set_attr "cycle" "n")
+ (set_attr "atype" "reg,mem")])
+
+;
+; divsi3 and modsi3 instruction pattern(s).
+;
+
+(define_expand "divsi3"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (div:SI (match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "nonimmediate_operand" "")))]
+ "!TARGET_64BIT"
+ "
+{
+ rtx tmp = gen_reg_rtx (DImode);
+
+ if (CONSTANT_P (operands[2]))
+ operands[2] = force_const_mem (SImode, operands[2]);
+ else
+ operands[2] = force_reg (SImode, operands[2]);
+
+ emit_insn (gen_rtx_CLOBBER (SImode, gen_rtx_SUBREG (SImode, tmp, 1)));
+ emit_move_insn (gen_rtx_SUBREG (SImode, tmp, 0), operands[1]);
+ emit_insn (gen_ashrdi3 (tmp, tmp, GEN_INT (32)));
+ emit_insn (gen_divmoddisi3 (tmp, tmp, operands[2]));
+ emit_move_insn (operands[0], gen_rtx (SUBREG, SImode, tmp, 1));
+ DONE;
+}")
+
+(define_expand "modsi3"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (mod:SI (match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "nonimmediate_operand" "")))]
+ "!TARGET_64BIT"
+ "
+{
+ rtx tmp = gen_reg_rtx (DImode);
+
+ if (CONSTANT_P (operands[2]))
+ operands[2] = force_const_mem (SImode, operands[2]);
+ else
+ operands[2] = force_reg (SImode, operands[2]);
+
+ emit_insn (gen_rtx_CLOBBER (SImode, gen_rtx_SUBREG (SImode, tmp, 1)));
+ emit_insn (gen_movsi (gen_rtx_SUBREG (SImode, tmp, 0), operands[1]));
+ emit_insn (gen_ashrdi3 (tmp, tmp, GEN_INT (32)));
+ emit_insn (gen_divmoddisi3 (tmp, tmp, operands[2]));
+ emit_move_insn (operands[0], gen_rtx (SUBREG, SImode, tmp, 0));
+ DONE;
+}")
+
+(define_insn "divmoddisi3"
+ [(set (subreg:SI (match_operand:DI 0 "register_operand" "=d,d") 0)
+ (truncate:SI
+ (mod:DI (match_operand:DI 1 "register_operand" "0,0")
+ (sign_extend:DI
+ (match_operand:SI 2 "nonimmediate_operand" "d,m")))))
+ (set (subreg:SI (match_dup 0) 1)
+ (truncate:SI (div:DI (match_dup 1) (sign_extend:DI (match_dup 2)))))
+ (clobber (reg:CC 33))]
+ "!TARGET_64BIT"
+ "@
+ dr\\t%0,%2
+ d\\t%0,%2"
+ [(set_attr "op_type" "RR,RX")
+ (set_attr "cycle" "n")
+ (set_attr "atype" "reg,mem")])
+
+;
+; udivsi3 and umodsi3 instruction pattern(s).
+;
+
+(define_expand "udivsi3"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (udiv:SI (match_operand:SI 1 "general_operand" "")
+ (match_operand:SI 2 "general_operand" "")))]
+ "!TARGET_64BIT"
+ "
+{
+ rtx dr_0, dr_1, tmp;
+
+ tmp = gen_reg_rtx (DImode);
+ dr_0 = gen_rtx (SUBREG, SImode, tmp, 0);
+ dr_1 = gen_rtx (SUBREG, SImode, tmp, 1);
+
+ if (CONSTANT_P (operands[2]))
+ {
+ if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0)
+ {
+ rtx label1 = gen_label_rtx ();
+
+ emit_move_insn (dr_0, operands[1]);
+ emit_move_insn (dr_1, const0_rtx);
+ emit_insn (gen_cmpsi (dr_0, operands[2]));
+ emit_jump_insn (gen_bltu (label1));
+ emit_move_insn (dr_1, const1_rtx);
+ emit_label (label1);
+ }
+ else
+ {
+ operands[2] = force_const_mem (SImode, operands[2]);
+ emit_move_insn (gen_rtx_SUBREG (SImode, tmp, 0), const0_rtx);
+ emit_move_insn (gen_rtx_SUBREG (SImode, tmp, 1), operands[1]);
+ emit_insn (gen_divmoddisi3 (tmp, tmp, operands[2]));
+ }
+ }
+ else
+ {
+ rtx label1 = gen_label_rtx ();
+ rtx label2 = gen_label_rtx ();
+ rtx label3 = gen_label_rtx ();
+
+ operands[1] = force_reg (SImode, operands[1]);
+ operands[2] = force_reg (SImode, operands[2]);
+
+ emit_move_insn (dr_1, const0_rtx);
+ emit_insn (gen_cmpsi (operands[2], operands[1]));
+ emit_jump_insn (gen_bgtu (label3));
+ emit_insn (gen_cmpsi (operands[2], const1_rtx));
+ emit_jump_insn (gen_blt (label2));
+ emit_insn (gen_cmpsi (operands[2], const1_rtx));
+ emit_jump_insn (gen_beq (label1));
+ emit_move_insn (gen_rtx_SUBREG (SImode, tmp, 0), const0_rtx);
+ emit_move_insn (gen_rtx_SUBREG (SImode, tmp, 1), operands[1]);
+ emit_insn (gen_divmoddisi3 (tmp, tmp, operands[2]));
+ emit_jump_insn (gen_jump (label3));
+ emit_label (label1);
+ emit_move_insn (dr_1, operands[1]);
+ emit_jump_insn (gen_jump (label3));
+ emit_label (label2);
+ emit_move_insn (dr_1, const1_rtx);
+ emit_label (label3);
+ }
+
+ emit_move_insn (operands[0], dr_1);
+ DONE;
+}")
+
+(define_expand "umodsi3"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (umod:SI (match_operand:SI 1 "nonimmediate_operand" "")
+ (match_operand:SI 2 "nonimmediate_operand" "")))]
+ "!TARGET_64BIT"
+ "
+{
+ rtx dr_0, dr_1, tmp;
+
+ tmp = gen_reg_rtx (DImode);
+ dr_0 = gen_rtx (SUBREG, SImode, tmp, 0);
+ dr_1 = gen_rtx (SUBREG, SImode, tmp, 1);
+
+ if (CONSTANT_P (operands[2]))
+ {
+ if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) <= 0)
+ {
+ rtx label1 = gen_label_rtx ();
+
+ emit_move_insn (dr_0, operands[1]);
+ emit_insn (gen_cmpsi (dr_0, operands[2]));
+ emit_jump_insn (gen_bltu (label1));
+ emit_insn (gen_abssi2 (dr_0, operands[2]));
+ emit_insn (gen_addsi3 (dr_0,dr_0, operands[1]));
+ emit_label (label1);
+ }
+ else
+ {
+ operands[2] = force_const_mem (SImode, operands[2]);
+ emit_move_insn (gen_rtx_SUBREG (SImode, tmp, 0), const0_rtx);
+ emit_move_insn (gen_rtx_SUBREG (SImode, tmp, 1), operands[1]);
+ emit_insn (gen_divmoddisi3 (tmp, tmp, operands[2]));
+ }
+ }
+ else
+ {
+ rtx label1 = gen_label_rtx ();
+ rtx label2 = gen_label_rtx ();
+ rtx label3 = gen_label_rtx ();
+
+ operands[1] = force_reg (SImode, operands[1]);
+ operands[2] = force_reg (SImode, operands[2]);
+
+ emit_move_insn(dr_0, operands[1]);
+ emit_insn (gen_cmpsi (operands[2], dr_0));
+ emit_jump_insn (gen_bgtu (label3));
+ emit_insn (gen_cmpsi (operands[2], const1_rtx));
+ emit_jump_insn (gen_blt (label2));
+ emit_insn (gen_cmpsi (operands[2], const1_rtx));
+ emit_jump_insn (gen_beq (label1));
+ emit_move_insn (gen_rtx_SUBREG (SImode, tmp, 0), const0_rtx);
+ emit_move_insn (gen_rtx_SUBREG (SImode, tmp, 1), operands[1]);
+ emit_insn (gen_divmoddisi3 (tmp, tmp, operands[2]));
+ emit_jump_insn (gen_jump (label3));
+ emit_label (label1);
+ emit_move_insn (dr_0, const0_rtx);
+ emit_jump_insn (gen_jump (label3));
+ emit_label (label2);
+ emit_insn (gen_subsi3 (dr_0, dr_0, operands[2]));
+ emit_label (label3);
+ }
+
+ emit_move_insn (operands[0], dr_0);
+ DONE;
+}")
+
+;
+; divdf3 instruction pattern(s).
+;
+
+(define_expand "divdf3"
+ [(parallel
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f")
+ (div:DF (match_operand:DF 1 "general_operand" "0,0")
+ (match_operand:DF 2 "nonimmediate_operand" "f,m")))
+ (clobber (reg:CC 33))])]
+ "TARGET_HARD_FLOAT"
+ "")
+
+(define_insn "*divdf3"
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f")
+ (div:DF (match_operand:DF 1 "general_operand" "0,0")
+ (match_operand:DF 2 "nonimmediate_operand" "f,m")))
+ (clobber (reg:CC 33))]
+ "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+ "@
+ ddbr\\t%0,%2
+ ddb\\t%0,%2"
+ [(set_attr "op_type" "RR,RX")
+ (set_attr "cycle" "n")
+ (set_attr "atype" "reg,mem")])
+
+(define_insn "*divdf3_ibm"
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f")
+ (div:DF (match_operand:DF 1 "general_operand" "0,0")
+ (match_operand:DF 2 "nonimmediate_operand" "f,m")))
+ (clobber (reg:CC 33))]
+ "TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
+ "@
+ ddr\\t%0,%2
+ dd\\t%0,%2"
+ [(set_attr "op_type" "RR,RX")
+ (set_attr "cycle" "n")
+ (set_attr "atype" "reg,mem")])
+
+;
+; divsf3 instruction pattern(s).
+;
+
+(define_expand "divsf3"
+ [(parallel
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f")
+ (div:SF (match_operand:SF 1 "nonimmediate_operand" "0,0")
+ (match_operand:SF 2 "nonimmediate_operand" "f,m")))
+ (clobber (reg:CC 33))])]
+ "TARGET_HARD_FLOAT"
+ "")
+
+(define_insn "*divsf3"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f")
+ (div:SF (match_operand:SF 1 "nonimmediate_operand" "0,0")
+ (match_operand:SF 2 "nonimmediate_operand" "f,m")))
+ (clobber (reg:CC 33))]
+ "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+ "@
+ debr\\t%0,%2
+ deb\\t%0,%2"
+ [(set_attr "op_type" "RR,RX")
+ (set_attr "cycle" "n")
+ (set_attr "atype" "reg,mem")])
+
+(define_insn "*divsf3"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f")
+ (div:SF (match_operand:SF 1 "nonimmediate_operand" "0,0")
+ (match_operand:SF 2 "nonimmediate_operand" "f,m")))
+ (clobber (reg:CC 33))]
+ "TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
+ "@
+ der\\t%0,%2
+ de\\t%0,%2"
+ [(set_attr "op_type" "RR,RX")
+ (set_attr "cycle" "n")
+ (set_attr "atype" "reg,mem")])
+
+
+;;
+;;- And instructions.
+;;
+
+;
+; anddi3 instruction pattern(s).
+;
+
+(define_insn "*anddi3_cc"
+ [(set (reg 33)
+ (compare (and:DI (match_operand:DI 1 "r_or_s_operand" "%0,0,0")
+ (match_operand:DI 2 "r_or_s_operand" "d,m,Q"))
+ (const_int 0)))
+ (set (match_operand:DI 0 "r_or_s_operand" "=d,d,Q")
+ (and:DI (match_dup 1) (match_dup 2)))]
+ "s390_match_ccmode(insn, CCTmode) && TARGET_64BIT"
+ "@
+ ngr\\t%0,%2
+ ng\\t%0,%2
+ nc\\t%O0(8,%R0),%2"
+ [(set_attr "op_type" "RR,RX,SS")
+ (set_attr "atype" "reg,mem,mem")
+ (set_attr "type" "set")])
+
+(define_insn "*anddi3_cconly"
+ [(set (reg 33)
+ (compare (and:DI (match_operand:DI 1 "register_operand" "%0,0")
+ (match_operand:DI 2 "r_or_s_operand" "d,m"))
+ (const_int 0)))
+ (clobber (match_scratch:DI 0 "=d,d"))]
+ "s390_match_ccmode(insn, CCTmode) && TARGET_64BIT"
+ "@
+ ngr\\t%0,%2
+ ng\\t%0,%2"
+ [(set_attr "op_type" "RR,RX")
+ (set_attr "atype" "reg,mem")
+ (set_attr "type" "set")])
+
+(define_insn "anddi3"
+ [(set (match_operand:DI 0 "r_or_s_operand" "=d,d,Q")
+ (and:DI (match_operand:DI 1 "r_or_s_operand" "%0,0,0")
+ (match_operand:DI 2 "r_or_s_operand" "d,m,Q")))
+ (clobber (reg:CC 33))]
+ "TARGET_64BIT"
+ "@
+ ngr\\t%0,%2
+ ng\\t%0,%2
+ nc\\t%O0(8,%R0),%2"
+ [(set_attr "op_type" "RR,RX,SS")
+ (set_attr "atype" "reg,mem,mem")
+ (set_attr "type" "set")])
+
+;
+; andsi3 instruction pattern(s).
+;
+
+(define_insn "*andsi3_cc"
+ [(set (reg 33)
+ (compare (and:SI (match_operand:SI 1 "r_or_s_operand" "%0,0,0")
+ (match_operand:SI 2 "r_or_s_operand" "d,m,Q"))
+ (const_int 0)))
+ (set (match_operand:SI 0 "r_or_s_operand" "=d,d,Q")
+ (and:SI (match_dup 1) (match_dup 2)))]
+ "s390_match_ccmode(insn, CCTmode)"
+ "@
+ nr\\t%0,%2
+ n\\t%0,%2
+ nc\\t%O0(4,%R0),%2"
+ [(set_attr "op_type" "RR,RX,SS")
+ (set_attr "atype" "reg,mem,mem")
+ (set_attr "type" "set")])
+
+(define_insn "*andsi3_cconly"
+ [(set (reg 33)
+ (compare (and:SI (match_operand:SI 1 "register_operand" "%0,0")
+ (match_operand:SI 2 "r_or_s_operand" "d,m"))
+ (const_int 0)))
+ (clobber (match_scratch:SI 0 "=d,d"))]
+ "s390_match_ccmode(insn, CCTmode)"
+ "@
+ nr\\t%0,%2
+ n\\t%0,%2"
+ [(set_attr "op_type" "RR,RX")
+ (set_attr "atype" "reg,mem")
+ (set_attr "type" "set")])
+
+(define_insn "andsi3"
+ [(set (match_operand:SI 0 "r_or_s_operand" "=d,d,Q")
+ (and:SI (match_operand:SI 1 "r_or_s_operand" "%0,0,0")
+ (match_operand:SI 2 "r_or_s_operand" "d,m,Q")))
+ (clobber (reg:CC 33))]
+ ""
+ "@
+ nr\\t%0,%2
+ n\\t%0,%2
+ nc\\t%O0(4,%R0),%2"
+ [(set_attr "op_type" "RR,RX,SS")
+ (set_attr "atype" "reg,mem,mem")
+ (set_attr "type" "set")])
+
+;
+; andhi3 instruction pattern(s).
+;
+
+(define_expand "andhi3"
+ [(parallel
+ [(set (match_operand:HI 0 "r_or_s_operand" "")
+ (and:HI (match_operand:HI 1 "r_or_s_operand" "")
+ (match_operand:HI 2 "r_or_s_operand" "")))
+ (clobber (reg:CC 33))])]
+ ""
+ "
+{
+ if (CONSTANT_P (operands[2]))
+ operands[2] = force_const_mem (HImode, operands[2]);
+}")
+
+(define_insn "*andhi3"
+ [(set (match_operand:HI 0 "r_or_s_operand" "=d,Q")
+ (and:HI (match_operand:HI 1 "r_or_s_operand" "%0,0")
+ (match_operand:HI 2 "r_or_s_operand" "d,Q")))
+ (clobber (reg:CC 33))]
+ ""
+ "@
+ nr\\t%0,%2
+ nc\\t%O0(2,%R0),%2"
+ [(set_attr "op_type" "RR,SS")
+ (set_attr "atype" "reg,mem")])
+
+;
+; andqi3 instruction pattern(s).
+;
+
+(define_insn "andqi3"
+ [(set (match_operand:QI 0 "r_or_s_operand" "=d,Q,Q")
+ (and:QI (match_operand:QI 1 "r_or_s_operand" "%0,0,0")
+ (match_operand:QI 2 "r_or_s_or_im8_operand" "d,n,Q")))
+ (clobber (reg:CC 33))]
+ ""
+ "@
+ nr\\t%0,%2
+ ni\\t%0,%b2
+ nc\\t%O0(1,%R0),%2"
+ [(set_attr "op_type" "RR,SI,SS")
+ (set_attr "atype" "reg,mem,mem")])
+
+
+;;
+;;- Bit set (inclusive or) instructions.
+;;
+
+;
+; iordi3 instruction pattern(s).
+;
+
+(define_insn "iordi3"
+ [(set (match_operand:DI 0 "r_or_s_operand" "=d,d,Q,d")
+ (ior:DI (match_operand:DI 1 "r_or_s_operand" "%0,0,0,0")
+ (match_operand:DI 2 "r_or_s_operand" "d,m,Q,L")))
+ (clobber (reg:CC 33))]
+ "TARGET_64BIT"
+ "@
+ ogr\\t%0,%2
+ og\\t%0,%2
+ oc\\t%O0(8,%R0),%2
+ oill\\t%0,%2"
+ [(set_attr "op_type" "RRE,RXE,SS,RI")
+ (set_attr "atype" "reg,mem,mem,reg")
+ (set_attr "type" "set")])
+
+;
+; iorsi3 instruction pattern(s).
+;
+
+(define_expand "iorsi3"
+ [(parallel
+ [(set (match_operand:SI 0 "r_or_s_operand" "")
+ (ior:SI (match_operand:SI 1 "r_or_s_operand" "")
+ (match_operand:SI 2 "r_or_s_operand" "")))
+ (clobber (reg:CC 33))])]
+ ""
+ "
+{
+ if (CONSTANT_P (operands[2]))
+ operands[2] = force_const_mem (SImode, operands[2]);
+}")
+
+(define_insn "*iorsi3"
+ [(set (match_operand:SI 0 "r_or_s_operand" "=d,d,Q")
+ (ior:SI (match_operand:SI 1 "r_or_s_operand" "%0,0,0")
+ (match_operand:SI 2 "r_or_s_operand" "d,m,Q")))
+ (clobber (reg:CC 33))]
+ ""
+ "@
+ or\\t%0,%2
+ o\\t%0,%2
+ oc\\t%O0(4,%R0),%2"
+ [(set_attr "op_type" "RR,RX,SS")
+ (set_attr "atype" "reg,mem,mem")
+ (set_attr "type" "set")])
+
+;
+; iorhi3 instruction pattern(s).
+;
+
+(define_expand "iorhi3"
+ [(parallel
+ [(set (match_operand:HI 0 "r_or_s_operand" "")
+ (ior:HI (match_operand:HI 1 "r_or_s_operand" "")
+ (match_operand:HI 2 "r_or_s_operand" "")))
+ (clobber (reg:CC 33))])]
+ ""
+ "
+{
+ if (CONSTANT_P (operands[2]))
+ operands[2] = force_const_mem (HImode, operands[2]);
+}")
+
+(define_insn "*iorhi3"
+ [(set (match_operand:HI 0 "r_or_s_operand" "=d,Q")
+ (ior:HI (match_operand:HI 1 "r_or_s_operand" "%0,0")
+ (match_operand:HI 2 "r_or_s_operand" "d,Q")))
+ (clobber (reg:CC 33))]
+ ""
+ "@
+ or\\t%0,%2
+ oc\\t%O0(2,%R0),%2"
+ [(set_attr "op_type" "RR,SS")
+ (set_attr "atype" "reg,mem")])
+
+;
+; iorqi3 instruction pattern(s).
+;
+
+(define_insn "iorqi3"
+ [(set (match_operand:QI 0 "r_or_s_operand" "=d,Q,Q")
+ (ior:QI (match_operand:QI 1 "r_or_s_operand" "%0,0,0")
+ (match_operand:QI 2 "r_or_s_or_im8_operand" "d,n,Q")))
+ (clobber (reg:CC 33))]
+ ""
+ "@
+ or\\t%0,%2
+ oi\\t%0,%b2
+ oc\\t%O0(1,%R0),%2"
+ [(set_attr "op_type" "RR,SI,SS")
+ (set_attr "atype" "reg,mem,mem")])
+
+
+;;
+;;- Xor instructions.
+;;
+
+;
+; xordi3 instruction pattern(s).
+;
+
+(define_insn "xordi3"
+ [(set (match_operand:DI 0 "r_or_s_operand" "=d,d,Q")
+ (xor:DI (match_operand:DI 1 "r_or_s_operand" "%0,0,0")
+ (match_operand:DI 2 "r_or_s_operand" "d,m,Q")))
+ (clobber (reg:CC 33))]
+ "TARGET_64BIT"
+ "@
+ xgr\\t%0,%2
+ xg\\t%0,%2
+ xc\\t%O0(8,%R0),%2"
+ [(set_attr "op_type" "RRE,RXE,SS")
+ (set_attr "atype" "reg,mem,mem")
+ (set_attr "type" "set")])
+
+;
+; xorsi3 instruction pattern(s).
+;
+
+(define_expand "xorsi3"
+ [(parallel
+ [(set (match_operand:SI 0 "r_or_s_operand" "")
+ (xor:SI (match_operand:SI 1 "r_or_s_operand" "")
+ (match_operand:SI 2 "r_or_s_operand" "")))
+ (clobber (reg:CC 33))])]
+ ""
+ "
+{
+ if (CONSTANT_P (operands[2]))
+ operands[2] = force_const_mem (SImode, operands[2]);
+}")
+
+(define_insn "*xorsi3"
+ [(set (match_operand:SI 0 "r_or_s_operand" "=d,d,Q")
+ (xor:SI (match_operand:SI 1 "r_or_s_operand" "%0,0,0")
+ (match_operand:SI 2 "r_or_s_operand" "d,m,Q")))
+ (clobber (reg:CC 33))]
+ ""
+ "@
+ xr\\t%0,%2
+ x\\t%0,%2
+ xc\\t%O0(4,%R0),%2"
+ [(set_attr "op_type" "RR,RX,SS")
+ (set_attr "atype" "reg,mem,mem")
+ (set_attr "type" "set")])
+
+;
+; xorhi3 instruction pattern(s).
+;
+
+(define_expand "xorhi3"
+ [(parallel
+ [(set (match_operand:HI 0 "r_or_s_operand" "")
+ (xor:HI (match_operand:HI 1 "r_or_s_operand" "")
+ (match_operand:HI 2 "r_or_s_operand" "")))
+ (clobber (reg:CC 33))])]
+ ""
+ "
+{
+ if (CONSTANT_P (operands[2]))
+ operands[2] = force_const_mem (HImode, operands[2]);
+}")
+
+(define_insn "*xorhi3"
+ [(set (match_operand:HI 0 "r_or_s_operand" "=d,Q")
+ (xor:HI (match_operand:HI 1 "r_or_s_operand" "%0,0")
+ (match_operand:HI 2 "r_or_s_operand" "d,Q")))
+ (clobber (reg:CC 33))]
+ ""
+ "@
+ xr\\t%0,%2
+ xc\\t%O0(2,%R0),%2"
+ [(set_attr "op_type" "RR,SS")
+ (set_attr "atype" "reg,mem")])
+
+;
+; xorqi3 instruction pattern(s).
+;
+
+(define_insn "xorqi3"
+ [(set (match_operand:QI 0 "r_or_s_operand" "=d,Q,Q")
+ (xor:QI (match_operand:QI 1 "r_or_s_operand" "0,0,0")
+ (match_operand:QI 2 "r_or_s_or_im8_operand" "d,n,Q")))
+ (clobber (reg:CC 33))]
+ ""
+ "@
+ xr\\t%0,%2
+ xi\\t%0,%b2
+ xc\\t%O0(1,%R0),%2"
+ [(set_attr "op_type" "RR,SI,SS")
+ (set_attr "atype" "reg,mem,mem")])
+
+
+;;
+;;- Negate instructions.
+;;
+
+;
+; negdi2 instruction pattern(s).
+;
+
+(define_expand "negdi2"
+ [(parallel
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (neg:DI (match_operand:DI 1 "register_operand" "d")))
+ (clobber (reg:CC 33))])]
+ ""
+ "")
+
+(define_insn "*negdi2_64"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (neg:DI (match_operand:DI 1 "register_operand" "d")))
+ (clobber (reg:CC 33))]
+ "TARGET_64BIT"
+ "lcgr\\t%0,%1"
+ [(set_attr "op_type" "RR")
+ (set_attr "type" "set")])
+
+(define_insn "*negdi2_31"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (neg:DI (match_operand:DI 1 "register_operand" "d")))
+ (clobber (reg:CC 33))]
+ "!TARGET_64BIT"
+ "*
+{
+ rtx xop[1];
+ xop[0] = gen_label_rtx ();
+ output_asm_insn (\"lcr\\t%0,%1\", operands);
+ output_asm_insn (\"lcr\\t%N0,%N1\", operands);
+ output_asm_insn (\"je\\t%l0\", xop);
+ output_asm_insn (\"bctr\\t%0,0\", operands);
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
+ CODE_LABEL_NUMBER (xop[0]));
+ return \"\";
+}"
+ [(set_attr "op_type" "NN")
+ (set_attr "length" "10")])
+
+;
+; negsi2 instruction pattern(s).
+;
+
+(define_insn "negsi2"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (neg:SI (match_operand:SI 1 "register_operand" "d")))
+ (clobber (reg:CC 33))]
+ ""
+ "lcr\\t%0,%1"
+ [(set_attr "op_type" "RR")
+ (set_attr "type" "set")])
+
+;
+; negdf2 instruction pattern(s).
+;
+
+(define_expand "negdf2"
+ [(parallel
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (neg:DF (match_operand:DF 1 "register_operand" "f")))
+ (clobber (reg:CC 33))])]
+ "TARGET_HARD_FLOAT"
+ "")
+
+(define_insn "*negdf2"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (neg:DF (match_operand:DF 1 "register_operand" "f")))
+ (clobber (reg:CC 33))]
+ "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+ "lcdbr\\t%0,%1"
+ [(set_attr "op_type" "RR")])
+
+(define_insn "*negdf2_ibm"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (neg:DF (match_operand:DF 1 "register_operand" "f")))
+ (clobber (reg:CC 33))]
+ "TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
+ "lcdr\\t%0,%1"
+ [(set_attr "op_type" "RR")])
+
+;
+; negsf2 instruction pattern(s).
+;
+
+(define_expand "negsf2"
+ [(parallel
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (neg:SF (match_operand:SF 1 "register_operand" "f")))
+ (clobber (reg:CC 33))])]
+ "TARGET_HARD_FLOAT"
+ "")
+
+(define_insn "*negsf2"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (neg:SF (match_operand:SF 1 "register_operand" "f")))
+ (clobber (reg:CC 33))]
+ "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+ "lcebr\\t%0,%1"
+ [(set_attr "op_type" "RR")])
+
+(define_insn "*negsf2"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (neg:SF (match_operand:SF 1 "register_operand" "f")))
+ (clobber (reg:CC 33))]
+ "TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
+ "lcer\\t%0,%1"
+ [(set_attr "op_type" "RR")])
+
+
+;;
+;;- Absolute value instructions.
+;;
+
+;
+; absdi2 instruction pattern(s).
+;
+
+(define_insn "absdi2"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (abs:DI (match_operand:DI 1 "register_operand" "d")))
+ (clobber (reg:CC 33))]
+ "TARGET_64BIT"
+ "lpgr\\t%0,%1"
+ [(set_attr "op_type" "RRE")
+ (set_attr "type" "set")])
+
+;
+; abssi2 instruction pattern(s).
+;
+
+(define_insn "abssi2"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (abs:SI (match_operand:SI 1 "register_operand" "d")))
+ (clobber (reg:CC 33))]
+ ""
+ "lpr\\t%0,%1"
+ [(set_attr "op_type" "RR")
+ (set_attr "type" "set")])
+
+;
+; abshi2 instruction pattern(s).
+;
+
+(define_insn "abshi2"
+ [(set (match_operand:HI 0 "register_operand" "=d")
+ (abs:HI (match_operand:HI 1 "register_operand" "d")))
+ (clobber (reg:CC 33))]
+ ""
+ "sll\\t%1,16\;sra\\t%1,16\;lpr\\t%0,%1"
+ [(set_attr "op_type" "NN")
+ (set_attr "cycle" "3")
+ (set_attr "length" "10")])
+
+;
+; absdf2 instruction pattern(s).
+;
+
+(define_expand "absdf2"
+ [(parallel
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (abs:DF (match_operand:DF 1 "register_operand" "f")))
+ (clobber (reg:CC 33))])]
+ "TARGET_HARD_FLOAT"
+ "")
+
+(define_insn "*absdf2"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (abs:DF (match_operand:DF 1 "register_operand" "f")))
+ (clobber (reg:CC 33))]
+ "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+ "lpdbr\\t%0,%1"
+ [(set_attr "op_type" "RR")])
+
+(define_insn "*absdf2_ibm"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (abs:DF (match_operand:DF 1 "register_operand" "f")))
+ (clobber (reg:CC 33))]
+ "TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
+ "lpdr\\t%0,%1"
+ [(set_attr "op_type" "RR")])
+
+;
+; abssf2 instruction pattern(s).
+;
+
+(define_expand "abssf2"
+ [(parallel
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (abs:SF (match_operand:SF 1 "register_operand" "f")))
+ (clobber (reg:CC 33))])]
+ "TARGET_HARD_FLOAT"
+ "")
+
+(define_insn "*abssf2"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (abs:SF (match_operand:SF 1 "register_operand" "f")))
+ (clobber (reg:CC 33))]
+ "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+ "lpebr\\t%0,%1"
+ [(set_attr "op_type" "RR")])
+
+(define_insn "*abssf2_ibm"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (abs:SF (match_operand:SF 1 "register_operand" "f")))
+ (clobber (reg:CC 33))]
+ "TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
+ "lper\\t%0,%1"
+ [(set_attr "op_type" "RR")])
+
+
+;;
+;;- One complement instructions.
+;;
+
+;
+; one_cmpldi2 instruction pattern(s).
+;
+
+(define_expand "one_cmpldi2"
+ [(parallel
+ [(set (match_operand:DI 0 "r_or_s_operand" "=d")
+ (not:DI (match_operand:DI 1 "r_or_s_operand" "0")))
+ (use (match_dup 2))
+ (clobber (reg:CC 33))])]
+ "TARGET_64BIT"
+ "{ operands[2] = force_const_mem (DImode, constm1_rtx); }")
+
+(define_insn "*one_cmpldi2"
+ [(set (match_operand:DI 0 "r_or_s_operand" "=d,Q")
+ (not:DI (match_operand:DI 1 "r_or_s_operand" "0,0")))
+ (use (match_operand:DI 2 "memory_operand" "m,m"))
+ (clobber (reg:CC 33))]
+ ""
+ "@
+ xg\\t%0,%2
+ xc\\t%O0(8,%R0),%2"
+ [(set_attr "op_type" "RR,SS")
+ (set_attr "atype" "mem")])
+
+;
+; one_cmplsi2 instruction pattern(s).
+;
+
+(define_expand "one_cmplsi2"
+ [(parallel
+ [(set (match_operand:SI 0 "r_or_s_operand" "=d")
+ (not:SI (match_operand:SI 1 "r_or_s_operand" "0")))
+ (use (match_dup 2))
+ (clobber (reg:CC 33))])]
+ ""
+ "{ operands[2] = force_const_mem (SImode, constm1_rtx); }")
+
+(define_insn "*one_cmplsi2"
+ [(set (match_operand:SI 0 "r_or_s_operand" "=d,Q")
+ (not:SI (match_operand:SI 1 "r_or_s_operand" "0,0")))
+ (use (match_operand:SI 2 "memory_operand" "m,m"))
+ (clobber (reg:CC 33))]
+ ""
+ "@
+ x\\t%0,%2
+ xc\\t%O0(4,%R0),%2"
+ [(set_attr "op_type" "RR,SS")
+ (set_attr "atype" "mem")])
+
+;
+; one_cmplhi2 instruction pattern(s).
+;
+
+(define_expand "one_cmplhi2"
+ [(parallel
+ [(set (match_operand:HI 0 "r_or_s_operand" "=d")
+ (not:HI (match_operand:HI 1 "r_or_s_operand" "0")))
+ (use (match_dup 2))
+ (clobber (reg:CC 33))])]
+ ""
+ "{ operands[2] = force_const_mem (SImode, constm1_rtx); }")
+
+(define_insn "*one_cmplhi2"
+ [(set (match_operand:HI 0 "r_or_s_operand" "=d,Q")
+ (not:HI (match_operand:HI 1 "r_or_s_operand" "0,0")))
+ (use (match_operand:SI 2 "memory_operand" "m,m"))
+ (clobber (reg:CC 33))]
+ ""
+ "@
+ x\\t%0,%2
+ xc\\t%O0(2,%R0),%2"
+ [(set_attr "op_type" "RX,SS")
+ (set_attr "atype" "mem")])
+
+;
+; one_cmplqi2 instruction pattern(s).
+;
+
+(define_insn "one_cmpqi2"
+ [(set (match_operand:QI 0 "memory_operand" "=Q")
+ (not:QI (match_operand:QI 1 "memory_operand" "0")))
+ (clobber (reg:CC 33))]
+ ""
+ "xi\\t%0,255"
+ [(set_attr "op_type" "SI")])
+
+
+;;
+;;- Rotate instructions.
+;;
+
+;
+; rotldi3 instruction pattern(s).
+;
+
+(define_insn "rotldi3"
+ [(set (match_operand:DI 0 "register_operand" "=d,d")
+ (rotate:DI (match_operand:DI 1 "register_operand" "d,d")
+ (match_operand:DI 2 "nonmemory_operand" "J,a")))
+ (clobber (reg:CC 33))]
+ "TARGET_64BIT"
+ "@
+ rllg\\t%0,%1,%c2
+ rllg\\t%0,%1,0(%2)"
+ [(set_attr "op_type" "RSE")
+ (set_attr "type" "set")])
+
+;
+; rotlsi3 instruction pattern(s).
+;
+
+(define_insn "rotlsi3"
+ [(set (match_operand:SI 0 "register_operand" "=d,d")
+ (rotate:SI (match_operand:SI 1 "register_operand" "d,d")
+ (match_operand:SI 2 "nonmemory_operand" "J,a")))
+ (clobber (reg:CC 33))]
+ "TARGET_64BIT"
+ "@
+ rll\\t%0,%1,%c2
+ rll\\t%0,%1,0(%2)"
+ [(set_attr "op_type" "RSE")
+ (set_attr "type" "set")])
+
+
+;;
+;;- Arithmetic shift instructions.
+;;
+;; for left shifts always setal shifts are used (ANSI-C)
+
+;
+; ashldi3 instruction pattern(s).
+;
+
+(define_expand "ashldi3"
+ [(parallel
+ [(set (match_operand:DI 0 "register_operand" "")
+ (ashift:DI (match_operand:DI 1 "register_operand" "")
+ (match_operand:SI 2 "nonmemory_operand" "")))
+ (clobber (reg:CC 33))])]
+ ""
+ "")
+
+(define_insn "*ashldi3_31"
+ [(set (match_operand:DI 0 "register_operand" "=d,d")
+ (ashift:DI (match_operand:DI 1 "register_operand" "0,0")
+ (match_operand:SI 2 "nonmemory_operand" "J,a")))
+ (clobber (reg:CC 33))]
+ "!TARGET_64BIT"
+ "@
+ sldl\\t%0,%c2
+ sldl\\t%0,0(%2)"
+ [(set_attr "op_type" "RS")
+ (set_attr "type" "set")])
+
+(define_insn "*ashldi3_64"
+ [(set (match_operand:DI 0 "register_operand" "=d,d")
+ (ashift:DI (match_operand:DI 1 "register_operand" "d,d")
+ (match_operand:SI 2 "nonmemory_operand" "J,a")))
+ (clobber (reg:CC 33))]
+ "TARGET_64BIT"
+ "@
+ sllg\\t%0,%1,%2
+ sllg\\t%0,%1,0(%2)"
+ [(set_attr "op_type" "RSE")
+ (set_attr "type" "set")])
+
+;
+; ashrdi3 instruction pattern(s).
+;
+
+(define_expand "ashrdi3"
+ [(parallel
+ [(set (match_operand:DI 0 "register_operand" "")
+ (ashiftrt:DI (match_operand:DI 1 "register_operand" "")
+ (match_operand:SI 2 "nonmemory_operand" "")))
+ (clobber (reg:CC 33))])]
+ ""
+ "")
+
+(define_insn "*ashrdi3_31"
+ [(set (match_operand:DI 0 "register_operand" "=d,d")
+ (ashiftrt:DI (match_operand:DI 1 "register_operand" "0,0")
+ (match_operand:SI 2 "nonmemory_operand" "J,a")))
+ (clobber (reg:CC 33))]
+ "!TARGET_64BIT"
+ "@
+ srda\\t%0,%c2
+ srda\\t%0,0(%2)"
+ [(set_attr "op_type" "RS")])
+
+(define_insn "*ashrdi3_64"
+ [(set (match_operand:DI 0 "register_operand" "=d,d")
+ (ashiftrt:DI (match_operand:DI 1 "register_operand" "d,d")
+ (match_operand:SI 2 "nonmemory_operand" "J,a")))
+ (clobber (reg:CC 33))]
+ "TARGET_64BIT"
+ "@
+ srag\\t%0,%1,%c2
+ srag\\t%0,%1,0(%2)"
+ [(set_attr "op_type" "RSE")
+ (set_attr "type" "set")])
+
+;
+; ashlsi3 instruction pattern(s).
+;
+; all 32 bits has to be shifted (testcase co750c)
+
+(define_insn "ashlsi3"
+ [(set (match_operand:SI 0 "register_operand" "=d,d")
+ (ashift:SI (match_operand:SI 1 "register_operand" "0,0")
+ (match_operand:SI 2 "r_or_im8_operand" "J,a")))
+ (clobber (reg:CC 33))]
+ ""
+ "@
+ sll\\t%0,%c2
+ sll\\t%0,0(%2)"
+ [(set_attr "op_type" "RS")
+ (set_attr "type" "set")])
+
+;
+; ashrsi3 instruction pattern(s).
+;
+
+(define_insn "ashrsi3"
+ [(set (match_operand:SI 0 "register_operand" "=d,d")
+ (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0")
+ (match_operand:SI 2 "r_or_im8_operand" "J,a")))
+ (clobber (reg:CC 33))]
+ ""
+ "@
+ sra\\t%0,%c2
+ sra\\t%0,0(%2)"
+ [(set_attr "op_type" "RS")
+ (set_attr "type" "set")])
+
+;
+; ashlhi3 instruction pattern(s).
+;
+
+(define_insn "ashlhi3"
+ [(set (match_operand:HI 0 "register_operand" "=d,d")
+ (ashift:HI (match_operand:HI 1 "register_operand" "0,0")
+ (match_operand:SI 2 "r_or_im8_operand" "J,a")))
+ (clobber (reg:CC 33))]
+ ""
+ "@
+ sll\\t%0,%c2
+ sll\\t%0,0(%2)"
+ [(set_attr "op_type" "RS,RS")])
+
+;
+; ashrhi3 instruction pattern(s).
+;
+
+(define_insn "ashrhi3"
+ [(set (match_operand:HI 0 "register_operand" "=d,d")
+ (ashiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
+ (match_operand:SI 2 "r_or_im8_operand" "J,a")))
+ (clobber (reg:CC 33))]
+ ""
+ "@
+ sll\\t%0,16\;sra\\t%0,16+%c2
+ sll\\t%0,16\;sra\\t%0,16(%2)"
+ [(set_attr "op_type" "NN,NN")
+ (set_attr "length" "8,8")])
+
+
+;;
+;;- logical shift instructions.
+;;
+
+;
+; lshrdi3 instruction pattern(s).
+;
+
+(define_expand "lshrdi3"
+ [(parallel
+ [(set (match_operand:DI 0 "register_operand" "")
+ (lshiftrt:DI (match_operand:DI 1 "register_operand" "")
+ (match_operand:SI 2 "nonmemory_operand" "")))
+ (clobber (reg:CC 33))])]
+ ""
+ "")
+
+(define_insn "*lshrdi3_31"
+ [(set (match_operand:DI 0 "register_operand" "=d,d")
+ (lshiftrt:DI (match_operand:DI 1 "register_operand" "0,0")
+ (match_operand:SI 2 "nonmemory_operand" "J,a")))
+ (clobber (reg:CC 33))]
+ "!TARGET_64BIT"
+ "@
+ srdl\\t%0,%c2
+ srdl\\t%0,0(%2)"
+ [(set_attr "op_type" "RS,RS")])
+
+(define_insn "*lshrdi3_64"
+ [(set (match_operand:DI 0 "register_operand" "=d,d")
+ (lshiftrt:DI (match_operand:DI 1 "register_operand" "d,d")
+ (match_operand:SI 2 "nonmemory_operand" "J,a")))
+ (clobber (reg:CC 33))]
+ "TARGET_64BIT"
+ "@
+ srlg\\t%0,%1,%c2
+ srlg\\t%0,%1,0(%2)"
+ [(set_attr "op_type" "RS,RS")
+ (set_attr "type" "set")])
+
+;
+; lshrsi3 instruction pattern(s).
+;
+
+(define_insn "lshrsi3"
+ [(set (match_operand:SI 0 "register_operand" "=d,d")
+ (lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0")
+ (match_operand:SI 2 "r_or_im8_operand" "J,a")))
+ (clobber (reg:CC 33))]
+ ""
+ "@
+ srl\\t%0,%c2
+ srl\\t%0,0(%2)"
+ [(set_attr "op_type" "RS")
+ (set_attr "type" "set")])
+
+;
+; lshrhi3 instruction pattern(s).
+;
+
+(define_insn "lshrhi3"
+ [(set (match_operand:HI 0 "register_operand" "=d,d")
+ (lshiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
+ (match_operand:SI 2 "r_or_im8_operand" "J,a")))
+ (clobber (reg:CC 33))]
+ ""
+ "@
+ sll\\t%0,16\;srl\\t%0,16+%c2
+ sll\\t%0,16\;srl\\t%0,16(%2)"
+ [(set_attr "op_type" "NN,NN")
+ (set_attr "length" "8,8")])
+
+
+;;
+;; Branch instruction patterns.
+;;
+
+(define_expand "beq"
+ [(set (reg:CCZ 33) (compare:CCZ (match_dup 1) (match_dup 2)))
+ (set (pc)
+ (if_then_else (eq (reg:CCZ 33) (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "{ operands[1] = s390_compare_op0; operands[2] = s390_compare_op1; }")
+
+(define_expand "bne"
+ [(set (reg:CCZ 33) (compare:CCZ (match_dup 1) (match_dup 2)))
+ (set (pc)
+ (if_then_else (ne (reg:CCZ 33) (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "{ operands[1] = s390_compare_op0; operands[2] = s390_compare_op1; }")
+
+(define_expand "bgt"
+ [(set (reg:CCS 33) (compare:CCS (match_dup 1) (match_dup 2)))
+ (set (pc)
+ (if_then_else (gt (reg:CCS 33) (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "{ operands[1] = s390_compare_op0; operands[2] = s390_compare_op1; }")
+
+(define_expand "bgtu"
+ [(set (reg:CCU 33) (compare:CCU (match_dup 1) (match_dup 2)))
+ (set (pc)
+ (if_then_else (gtu (reg:CCU 33) (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "{ operands[1] = s390_compare_op0; operands[2] = s390_compare_op1; }")
+
+(define_expand "blt"
+ [(set (reg:CCS 33) (compare:CCS (match_dup 1) (match_dup 2)))
+ (set (pc)
+ (if_then_else (lt (reg:CCS 33) (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "{ operands[1] = s390_compare_op0; operands[2] = s390_compare_op1; }")
+
+(define_expand "bltu"
+ [(set (reg:CCU 33) (compare:CCU (match_dup 1) (match_dup 2)))
+ (set (pc)
+ (if_then_else (ltu (reg:CCU 33) (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "{ operands[1] = s390_compare_op0; operands[2] = s390_compare_op1; }")
+
+(define_expand "bge"
+ [(set (reg:CCS 33) (compare:CCS (match_dup 1) (match_dup 2)))
+ (set (pc)
+ (if_then_else (ge (reg:CCS 33) (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "{ operands[1] = s390_compare_op0; operands[2] = s390_compare_op1; }")
+
+(define_expand "bgeu"
+ [(set (reg:CCU 33) (compare:CCU (match_dup 1) (match_dup 2)))
+ (set (pc)
+ (if_then_else (geu (reg:CCU 33) (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "{ operands[1] = s390_compare_op0; operands[2] = s390_compare_op1; }")
+
+(define_expand "ble"
+ [(set (reg:CCS 33) (compare:CCS (match_dup 1) (match_dup 2)))
+ (set (pc)
+ (if_then_else (le (reg:CCS 33) (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "{ operands[1] = s390_compare_op0; operands[2] = s390_compare_op1; }")
+
+(define_expand "bleu"
+ [(set (reg:CCU 33) (compare:CCU (match_dup 1) (match_dup 2)))
+ (set (pc)
+ (if_then_else (leu (reg:CCU 33) (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "{ operands[1] = s390_compare_op0; operands[2] = s390_compare_op1; }")
+
+
+;;
+;;- Conditional jump instructions.
+;;
+
+(define_insn "cjump"
+ [(set (pc)
+ (if_then_else
+ (match_operator 1 "comparison_operator" [(reg 33) (const_int 0)])
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+{
+ if (get_attr_length (insn) == 4 || !TARGET_64BIT)
+ return \"j%C1\\t%l0\";
+ else
+ return \"jg%C1\\t%l0\";
+}"
+ [(set_attr "op_type" "RI")
+ (set (attr "length") (if_then_else
+ (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
+ (const_int 4) (const_int 6)))])
+
+(define_insn "*cjump_long"
+ [(set (pc)
+ (if_then_else
+ (match_operator 1 "comparison_operator" [(reg 33) (const_int 0)])
+ (match_operand 0 "address_operand" "p")
+ (pc)))]
+ ""
+ "*
+{
+ if (get_attr_op_type (insn) == OP_TYPE_RR)
+ return \"b%C1r\\t%0\";
+ else
+ return \"b%C1\\t%a0\";
+}"
+ [(set (attr "op_type")
+ (if_then_else (match_operand 0 "register_operand" "")
+ (const_string "RR") (const_string "RX")))
+ (set_attr "atype" "mem")])
+
+
+;;
+;;- Negated conditional jump instructions.
+;;
+
+(define_insn "icjump"
+ [(set (pc)
+ (if_then_else
+ (match_operator 1 "comparison_operator" [(reg 33) (const_int 0)])
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+{
+ if (get_attr_length (insn) == 4 || !TARGET_64BIT)
+ return \"j%D1\\t%l0\";
+ else
+ return \"jg%D1\\t%l0\";
+}"
+ [(set_attr "op_type" "RI")
+ (set (attr "length") (if_then_else
+ (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
+ (const_int 4) (const_int 6)))])
+
+(define_insn "*icjump_long"
+ [(set (pc)
+ (if_then_else
+ (match_operator 1 "comparison_operator" [(reg 33) (const_int 0)])
+ (pc)
+ (match_operand 0 "address_operand" "p")))]
+ ""
+ "*
+{
+ if (get_attr_op_type (insn) == OP_TYPE_RR)
+ return \"b%D1r\\t%0\";
+ else
+ return \"b%D1\\t%a0\";
+}"
+ [(set (attr "op_type")
+ (if_then_else (match_operand 0 "register_operand" "")
+ (const_string "RR") (const_string "RX")))
+ (set_attr "atype" "mem")])
+
+
+;;
+;;- Subtract one and jump if not zero.
+;;
+
+;(define_expand "decrement_and_branch_on_count"
+; [(use (match_operand 0 "register_operand" ""))
+; (use (label_ref (match_operand 1 "" "")))]
+; ""
+; "
+;{
+;/* if (TARGET_64BIT)
+; emit_jump_insn (gen_brctdi (operands[0], operands[1]));
+; else */
+; emit_jump_insn (gen_brctsi (operands[0], operands[1]));
+; DONE;
+;}")
+;
+;(define_insn "brctsi"
+; [(set (pc)
+; (if_then_else
+; (ne (match_operand:SI 0 "register_operand" "+a")
+; (const_int 1))
+; (label_ref (match_operand 1 "" ""))
+; (pc)))
+; (set (match_dup 0)
+; (plus:SI (match_dup 0) (const_int -1)))]
+; ""
+; "brct\\t%0,%l1"
+; [(set_attr "op_type" "RI")
+; (set_attr "type" "branch")]
+;)
+;
+;(define_insn "ibrctsi"
+; [(set (pc)
+; (if_then_else
+; (eq (match_operand:SI 0 "register_operand" "+a")
+; (const_int 1))
+; (pc)
+; (label_ref (match_operand 1 "" ""))))
+; (set (match_dup 0)
+; (plus:SI (match_dup 0) (const_int -1)))]
+; ""
+; "brct\\t%0,%l1"
+; [(set_attr "op_type" "RI")
+; (set_attr "type" "branch")]
+;)
+
+
+;;
+;;- Unconditional jump instructions.
+;;
+
+;
+; jump instruction pattern(s).
+;
+
+(define_insn "jump"
+ [(set (pc) (label_ref (match_operand 0 "" "")))]
+ ""
+ "*
+{
+ if (get_attr_length (insn) == 4 || !TARGET_64BIT)
+ return \"j\\t%l0\";
+ else
+ return \"jg\\t%l0\";
+}"
+ [(set_attr "op_type" "RI")
+ (set (attr "length") (if_then_else
+ (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
+ (const_int 4) (const_int 6)))])
+
+;
+; indirect-jump instruction pattern(s).
+;
+
+(define_insn "indirect_jump"
+ [(set (pc) (match_operand 0 "address_operand" "p"))]
+ ""
+ "*
+{
+ if (get_attr_op_type (insn) == OP_TYPE_RR)
+ return \"br\\t%0\";
+ else
+ return \"b\\t%a0\";
+}"
+ [(set (attr "op_type")
+ (if_then_else (match_operand 0 "register_operand" "")
+ (const_string "RR") (const_string "RX")))
+ (set_attr "atype" "mem")])
+
+;
+; casesi instruction pattern(s).
+;
+
+(define_insn "casesi_jump"
+ [(set (pc) (match_operand 0 "address_operand" "p"))
+ (use (label_ref (match_operand 1 "" "")))]
+ ""
+ "*
+{
+ if (get_attr_op_type (insn) == OP_TYPE_RR)
+ return \"br\\t%0\";
+ else
+ return \"b\\t%a0\";
+}"
+ [(set (attr "op_type")
+ (if_then_else (match_operand 0 "register_operand" "")
+ (const_string "RR") (const_string "RX")))
+ (set_attr "atype" "mem")])
+
+(define_expand "casesi"
+ [(match_operand:SI 0 "general_operand" "")
+ (match_operand:SI 1 "general_operand" "")
+ (match_operand:SI 2 "general_operand" "")
+ (label_ref (match_operand 3 "" ""))
+ (label_ref (match_operand 4 "" ""))]
+ ""
+ "
+{
+ rtx index = gen_reg_rtx (SImode);
+ rtx base = gen_reg_rtx (Pmode);
+ rtx target = gen_reg_rtx (Pmode);
+
+ emit_move_insn (index, operands[0]);
+ emit_insn (gen_subsi3 (index, index, operands[1]));
+ emit_cmp_and_jump_insns (index, operands[2], GTU, NULL_RTX, SImode, 1,
+ 0, operands[4]);
+
+ if (Pmode != SImode)
+ index = convert_to_mode (Pmode, index, 1);
+ if (GET_CODE (index) != REG)
+ index = copy_to_mode_reg (Pmode, index);
+
+ if (TARGET_64BIT)
+ emit_insn (gen_ashldi3 (index, index, GEN_INT (3)));
+ else
+ emit_insn (gen_ashlsi3 (index, index, GEN_INT (2)));
+
+ emit_move_insn (base, gen_rtx_LABEL_REF (Pmode, operands[3]));
+
+ index = gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, base, index));
+ emit_move_insn (target, index);
+
+ if (flag_pic)
+ target = gen_rtx_PLUS (Pmode, base, target);
+ emit_jump_insn (gen_casesi_jump (target, operands[3]));
+
+ DONE;
+}")
+
+
+;;
+;;- Jump to subroutine.
+;;
+;;
+
+;
+; untyped call instruction pattern(s).
+;
+
+;; 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, 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)]
+ ""
+ "")
+
+
+;
+; call instruction pattern(s).
+;
+
+(define_expand "call"
+ [(parallel [(call (match_operand 0 "" "")
+ (match_operand 1 "" ""))
+ (clobber (match_operand 2 "" ""))])]
+ ""
+ "
+{
+ /* Abuse operand 2 to hold the return register. */
+ operands[2] = gen_rtx_REG (Pmode, RETURN_REGNUM);
+
+ /* In 31-bit, we must load the GOT register even if the
+ compiler doesn't know about it, because the PLT glue
+ code uses it. In 64-bit, this is not necessary. */
+ if (flag_pic && !TARGET_64BIT)
+ current_function_uses_pic_offset_table = 1;
+
+ /* Direct function calls need special treatment. */
+ if (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
+ {
+ rtx sym = XEXP (operands[0], 0);
+
+ /* When calling a global routine in PIC mode, we must
+ replace the symbol itself with the PLT stub. */
+ if (flag_pic && !SYMBOL_REF_FLAG(sym))
+ {
+ sym = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, sym), 113);
+ sym = gen_rtx_CONST (Pmode, sym);
+ }
+
+ /* Unless we can use the bras(l) insn, force the
+ routine address into a register. */
+ if (!TARGET_SMALL_EXEC && !TARGET_64BIT)
+ {
+ rtx target = gen_reg_rtx (Pmode);
+ emit_move_insn (target, sym);
+ sym = target;
+ }
+
+ operands[0] = gen_rtx_MEM (QImode, sym);
+ }
+}")
+
+(define_insn "brasl"
+ [(call (mem:QI (match_operand:DI 0 "bras_sym_operand" "X"))
+ (match_operand:SI 1 "const_int_operand" "n"))
+ (clobber (match_operand:DI 2 "register_operand" "=r"))]
+ "TARGET_64BIT"
+ "brasl\\t%2,%0"
+ [(set_attr "op_type" "RIL")
+ (set_attr "cycle" "n")])
+
+(define_insn "bras"
+ [(call (mem:QI (match_operand:SI 0 "bras_sym_operand" "X"))
+ (match_operand:SI 1 "const_int_operand" "n"))
+ (clobber (match_operand:SI 2 "register_operand" "=r"))]
+ "TARGET_SMALL_EXEC"
+ "bras\\t%2,%0"
+ [(set_attr "op_type" "RI")
+ (set_attr "cycle" "n")])
+
+(define_insn "basr_64"
+ [(call (mem:QI (match_operand:DI 0 "register_operand" "a"))
+ (match_operand:SI 1 "const_int_operand" "n"))
+ (clobber (match_operand:DI 2 "register_operand" "=r"))]
+ "TARGET_64BIT"
+ "basr\\t%2,%0"
+ [(set_attr "op_type" "RR")
+ (set_attr "cycle" "n")
+ (set_attr "atype" "mem")])
+
+(define_insn "basr_31"
+ [(call (mem:QI (match_operand:SI 0 "register_operand" "a"))
+ (match_operand:SI 1 "const_int_operand" "n"))
+ (clobber (match_operand:SI 2 "register_operand" "=r"))]
+ "!TARGET_64BIT"
+ "basr\\t%2,%0"
+ [(set_attr "op_type" "RR")
+ (set_attr "cycle" "n")
+ (set_attr "atype" "mem")])
+
+(define_insn "bas_64"
+ [(call (mem:QI (match_operand:QI 0 "address_operand" "p"))
+ (match_operand:SI 1 "const_int_operand" "n"))
+ (clobber (match_operand:DI 2 "register_operand" "=r"))]
+ "TARGET_64BIT"
+ "bas\\t%2,%a0"
+ [(set_attr "op_type" "RX")
+ (set_attr "cycle" "n")
+ (set_attr "atype" "mem")])
+
+(define_insn "bas_31"
+ [(call (mem:QI (match_operand:QI 0 "address_operand" "p"))
+ (match_operand:SI 1 "const_int_operand" "n"))
+ (clobber (match_operand:SI 2 "register_operand" "=r"))]
+ "!TARGET_64BIT"
+ "bas\\t%2,%a0"
+ [(set_attr "op_type" "RX")
+ (set_attr "cycle" "n")
+ (set_attr "atype" "mem")])
+
+
+;
+; call_value instruction pattern(s).
+;
+
+(define_expand "call_value"
+ [(parallel [(set (match_operand 0 "" "")
+ (call (match_operand 1 "" "")
+ (match_operand 2 "" "")))
+ (clobber (match_operand 3 "" ""))])]
+ ""
+ "
+{
+ /* Abuse operand 3 to hold the return register. */
+ operands[3] = gen_rtx_REG (Pmode, RETURN_REGNUM);
+
+ /* In 31-bit, we must load the GOT register even if the
+ compiler doesn't know about it, because the PLT glue
+ code uses it. In 64-bit, this is not necessary. */
+ if (flag_pic && !TARGET_64BIT)
+ current_function_uses_pic_offset_table = 1;
+
+ /* Direct function calls need special treatment. */
+ if (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
+ {
+ rtx sym = XEXP (operands[1], 0);
+
+ /* When calling a global routine in PIC mode, we must
+ replace the symbol itself with the PLT stub. */
+ if (flag_pic && !SYMBOL_REF_FLAG(sym))
+ {
+ sym = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, sym), 113);
+ sym = gen_rtx_CONST (Pmode, sym);
+ }
+
+ /* Unless we can use the bras(l) insn, force the
+ routine address into a register. */
+ if (!TARGET_SMALL_EXEC && !TARGET_64BIT)
+ {
+ rtx target = gen_reg_rtx (Pmode);
+ emit_move_insn (target, sym);
+ sym = target;
+ }
+
+ operands[1] = gen_rtx_MEM (QImode, sym);
+ }
+}")
+
+(define_insn "brasl_r"
+ [(set (match_operand 0 "register_operand" "=df")
+ (call (mem:QI (match_operand:DI 1 "bras_sym_operand" "X"))
+ (match_operand:SI 2 "const_int_operand" "n")))
+ (clobber (match_operand:DI 3 "register_operand" "=r"))]
+ "TARGET_64BIT"
+ "brasl\\t%3,%1"
+ [(set_attr "op_type" "RIL")
+ (set_attr "cycle" "n")])
+
+(define_insn "bras_r"
+ [(set (match_operand 0 "register_operand" "=df")
+ (call (mem:QI (match_operand:SI 1 "bras_sym_operand" "X"))
+ (match_operand:SI 2 "const_int_operand" "n")))
+ (clobber (match_operand:SI 3 "register_operand" "=r"))]
+ "TARGET_SMALL_EXEC"
+ "bras\\t%3,%1"
+ [(set_attr "op_type" "RI")
+ (set_attr "cycle" "n")])
+
+(define_insn "basr_r_64"
+ [(set (match_operand 0 "register_operand" "=df")
+ (call (mem:QI (match_operand:DI 1 "register_operand" "a"))
+ (match_operand:SI 2 "const_int_operand" "n")))
+ (clobber (match_operand:DI 3 "register_operand" "=r"))]
+ "TARGET_64BIT"
+ "basr\\t%3,%1"
+ [(set_attr "op_type" "RR")
+ (set_attr "cycle" "n")])
+
+(define_insn "basr_r_31"
+ [(set (match_operand 0 "register_operand" "=df")
+ (call (mem:QI (match_operand:SI 1 "register_operand" "a"))
+ (match_operand:SI 2 "const_int_operand" "n")))
+ (clobber (match_operand:SI 3 "register_operand" "=r"))]
+ "!TARGET_64BIT"
+ "basr\\t%3,%1"
+ [(set_attr "op_type" "RR")
+ (set_attr "cycle" "n")
+ (set_attr "atype" "mem")])
+
+(define_insn "bas_r_64"
+ [(set (match_operand 0 "register_operand" "=df")
+ (call (mem:QI (match_operand:QI 1 "address_operand" "p"))
+ (match_operand:SI 2 "const_int_operand" "n")))
+ (clobber (match_operand:DI 3 "register_operand" "=r"))]
+ "TARGET_64BIT"
+ "bas\\t%3,%a1"
+ [(set_attr "op_type" "RX")
+ (set_attr "cycle" "n")
+ (set_attr "atype" "mem")])
+
+(define_insn "bas_r_31"
+ [(set (match_operand 0 "register_operand" "=df")
+ (call (mem:QI (match_operand:QI 1 "address_operand" "p"))
+ (match_operand:SI 2 "const_int_operand" "n")))
+ (clobber (match_operand:SI 3 "register_operand" "=r"))]
+ "!TARGET_64BIT"
+ "bas\\t%3,%a1"
+ [(set_attr "op_type" "RX")
+ (set_attr "cycle" "n")
+ (set_attr "atype" "mem")])
+
+
+;;
+;;- Miscellaneous instructions.
+;;
+
+;
+; allocate stack instruction pattern(s).
+;
+
+(define_expand "allocate_stack"
+ [(set (reg 15)
+ (plus (reg 15) (match_operand 1 "general_operand" "")))
+ (set (match_operand 0 "general_operand" "")
+ (reg 15))]
+ ""
+ "
+{
+ rtx stack = gen_rtx (REG, Pmode, STACK_POINTER_REGNUM);
+ rtx chain = gen_rtx (MEM, Pmode, stack);
+ rtx temp = gen_reg_rtx (Pmode);
+
+ emit_move_insn (temp, chain);
+
+ if (TARGET_64BIT)
+ emit_insn (gen_adddi3 (stack, stack, negate_rtx (Pmode, operands[1])));
+ else
+ emit_insn (gen_addsi3 (stack, stack, negate_rtx (Pmode, operands[1])));
+
+ emit_move_insn (chain, temp);
+
+ emit_move_insn (operands[0], virtual_stack_dynamic_rtx);
+ DONE;
+}")
+
+
+;
+; setjmp/longjmp instruction pattern(s).
+;
+
+(define_expand "builtin_setjmp_setup"
+ [(unspec [(match_operand 0 "register_operand" "a")] 1)]
+ ""
+ "
+{
+ rtx base = gen_rtx_MEM (Pmode, plus_constant (operands[0], 4 * GET_MODE_SIZE (Pmode)));
+ rtx basereg = gen_rtx_REG (Pmode, BASE_REGISTER);
+
+ emit_move_insn (base, basereg);
+ DONE;
+}")
+
+(define_expand "builtin_setjmp_receiver"
+ [(unspec_volatile [(label_ref (match_operand 0 "" ""))] 2)]
+ "flag_pic"
+ "
+{
+ rtx gotreg = gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM);
+ rtx got = gen_rtx_SYMBOL_REF (Pmode, \"_GLOBAL_OFFSET_TABLE_\");
+ SYMBOL_REF_FLAG (got) = 1;
+
+ emit_move_insn (gotreg, got);
+ emit_insn (gen_rtx_USE (VOIDmode, gotreg));
+ DONE;
+}")
+
+(define_expand "builtin_longjmp"
+ [(unspec_volatile [(match_operand 0 "register_operand" "r")] 3)]
+ ""
+ "
+{
+ /* The elements of the buffer are, in order: */
+ rtx fp = gen_rtx_MEM (Pmode, operands[0]);
+ rtx lab = gen_rtx_MEM (Pmode, plus_constant (operands[0], GET_MODE_SIZE (Pmode)));
+ rtx stack = gen_rtx_MEM (Pmode, plus_constant (operands[0], 2 * GET_MODE_SIZE (Pmode)));
+ rtx base = gen_rtx_MEM (Pmode, plus_constant (operands[0], 4 * GET_MODE_SIZE (Pmode)));
+ rtx basereg = gen_rtx_REG (Pmode, BASE_REGISTER);
+ rtx jmp = gen_rtx_REG (Pmode, 14);
+
+ emit_move_insn (jmp, lab);
+ emit_move_insn (basereg, base);
+ emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX);
+ emit_move_insn (hard_frame_pointer_rtx, fp);
+
+ emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
+ emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
+ emit_insn (gen_rtx_USE (VOIDmode, basereg));
+ emit_indirect_jump (jmp);
+ DONE;
+}")
+
+
+;; These patterns say how to save and restore the stack pointer. We need not
+;; save the stack pointer at function level since we are careful to
+;; preserve the backchain. At block level, we have to restore the backchain
+;; when we restore the stack pointer.
+;;
+;; For nonlocal gotos, we must save both the stack pointer and its
+;; backchain and restore both. Note that in the nonlocal case, the
+;; save area is a memory location.
+
+(define_expand "save_stack_function"
+ [(match_operand 0 "general_operand" "")
+ (match_operand 1 "general_operand" "")]
+ ""
+ "DONE;")
+
+(define_expand "restore_stack_function"
+ [(match_operand 0 "general_operand" "")
+ (match_operand 1 "general_operand" "")]
+ ""
+ "DONE;")
+
+(define_expand "restore_stack_block"
+ [(use (match_operand 0 "register_operand" ""))
+ (set (match_dup 2) (match_dup 3))
+ (set (match_dup 0) (match_operand 1 "register_operand" ""))
+ (set (match_dup 3) (match_dup 2))]
+ ""
+ "
+{
+ operands[2] = gen_reg_rtx (Pmode);
+ operands[3] = gen_rtx_MEM (Pmode, operands[0]);
+}")
+
+(define_expand "save_stack_nonlocal"
+ [(match_operand 0 "memory_operand" "")
+ (match_operand 1 "register_operand" "")]
+ ""
+ "
+{
+ rtx temp = gen_reg_rtx (Pmode);
+
+ /* Copy the backchain to the first word, sp to the second. */
+ emit_move_insn (temp, gen_rtx_MEM (Pmode, operands[1]));
+ emit_move_insn (operand_subword (operands[0], 0, 0,
+ TARGET_64BIT ? TImode : DImode),
+ temp);
+ emit_move_insn (operand_subword (operands[0], 1, 0,
+ TARGET_64BIT ? TImode : DImode),
+ operands[1]);
+ DONE;
+}")
+
+(define_expand "restore_stack_nonlocal"
+ [(match_operand 0 "register_operand" "")
+ (match_operand 1 "memory_operand" "")]
+ ""
+ "
+{
+ rtx temp = gen_reg_rtx (Pmode);
+
+ /* Restore the backchain from the first word, sp from the second. */
+ emit_move_insn (temp,
+ operand_subword (operands[1], 0, 0,
+ TARGET_64BIT ? TImode : DImode));
+ emit_move_insn (operands[0],
+ operand_subword (operands[1], 1, 0,
+ TARGET_64BIT ? TImode : DImode));
+ emit_move_insn (gen_rtx_MEM (Pmode, operands[0]), temp);
+ DONE;
+}")
+
+
+(define_expand "eh_epilogue"
+ [(use (match_operand 0 "register_operand" ""))
+ (use (match_operand 1 "register_operand" ""))
+ (use (match_operand 2 "register_operand" ""))]
+ ""
+ "
+{
+ s390_expand_eh_epilogue (operands[0], operands[1], operands[2]);
+ DONE;
+}")
+
+
+;
+; nop instruction pattern(s).
+;
+
+(define_insn "nop"
+ [(const_int 0)]
+ ""
+ "lr\\t0,0"
+ [(set_attr "op_type" "RR")])
+
+
+;
+; Special literal pool access instruction pattern(s).
+;
+
+(define_insn "reload_base"
+ [(parallel [(set (reg 13) (pc))
+ (use (label_ref (match_operand 0 "" "")))])]
+ ""
+ "*
+{
+ if (TARGET_64BIT)
+ return \"larl\\t13,%y0\";
+ else
+ return \"basr\\t13,0\;ahi\\t13,%Y0\";
+}"
+ [(set_attr "op_type" "NN")
+ (set_attr "cycle" "2")
+ (set_attr "length" "8")])
+
+(define_insn "ltorg"
+ [(parallel [(set (reg 13) (pc))
+ (use (match_operand:SI 0 "const_int_operand" ""))])]
+ ""
+ "*
+{
+ s390_dump_literal_pool (insn, operands[0]);
+ return \"0:\";
+}"
+ [(set_attr "op_type" "NN")
+ (set_attr "cycle" "n")
+ (set_attr "length" "4096")])
+
+
+;;
+;; Peephole optimization patterns.
+;;
+
+(define_peephole
+ [(set (match_operand:SI 0 "memory_operand" "m")
+ (match_operand:SI 1 "register_operand" "d"))
+ (set (match_dup 1)
+ (match_dup 0))]
+ ""
+ "st\\t%1,%0")
+
+(define_peephole
+ [(set (match_operand:SI 0 "memory_operand" "m")
+ (match_operand:SI 1 "register_operand" "d"))
+ (set (match_dup 0)
+ (match_dup 1))]
+ ""
+ "st\\t%1,%0")
+
+(define_peephole
+ [(set (match_operand:SI 0 "register_operand" "")
+ (match_operand:SI 1 "register_operand" ""))
+ (parallel
+ [(set (match_dup 0)
+ (plus:SI (match_dup 0)
+ (match_operand:SI 2 "immediate_operand" "")))
+ (clobber (reg:CC 33))])]
+ "(REGNO (operands[0]) == STACK_POINTER_REGNUM ||
+ REGNO (operands[1]) == STACK_POINTER_REGNUM ||
+ REGNO (operands[0]) == BASE_REGISTER ||
+ REGNO (operands[1]) == BASE_REGISTER) &&
+ INTVAL (operands[2]) > 0 && INTVAL (operands[2]) < 4096"
+ "la\\t%0,%c2(%1)")
+
+;
+; peepholes for fast char instructions
+;
+
+;(define_peephole
+; [(set (match_operand:QI 0 "register_operand" "d")
+; (match_operand:QI 1 "s_operand" "Q"))
+; (set (match_operand:SI 2 "register_operand" "0")
+; (zero_extend:SI (match_dup 0)))]
+; "REGNO(operands[0]) == REGNO(operands[2])"
+; "icm\\t%0,8,%1\;srl\\t%0,24")
+
+;(define_peephole
+; [(set (match_operand:QI 0 "register_operand" "d")
+; (match_operand:QI 1 "s_operand" "Q"))
+; (set (match_operand:SI 2 "register_operand" "0")
+; (sign_extend:SI (match_dup 0)))]
+; "REGNO(operands[0]) == REGNO(operands[2])"
+; "icm\\t%0,8,%1\;sra\\t%0,24")
+
+(define_peephole
+ [(set (match_operand:QI 0 "register_operand" "d")
+ (match_operand:QI 1 "immediate_operand" "J"))
+ (set (match_operand:SI 2 "register_operand" "0" )
+ (sign_extend:SI (match_dup 0) ) )]
+ "REGNO(operands[0]) == REGNO(operands[2])"
+ "lhi\\t%0,%h1")
+
+;
+; peepholes for fast short instructions
+;
+
+;(define_peephole
+; [(set (match_operand:HI 0 "register_operand" "d")
+; (match_operand:HI 1 "s_operand" "Q"))
+; (set (match_operand:SI 2 "register_operand" "0" )
+; (zero_extend:SI (match_dup 0)))]
+; "REGNO(operands[0]) == REGNO(operands[2])"
+; "icm\\t%0,12,%1\;srl\\t%0,16")
+
+(define_peephole
+ [(set (match_operand:HI 0 "register_operand" "d")
+ (match_operand:HI 1 "memory_operand" "m"))
+ (set (match_operand:SI 2 "register_operand" "0" )
+ (sign_extend:SI (match_dup 0)))]
+ "REGNO(operands[0]) == REGNO(operands[2])"
+ "lh\\t%0,%1")
+
+(define_peephole
+ [(set (match_operand:HI 0 "register_operand" "d")
+ (match_operand:HI 1 "immediate_operand" "K"))
+ (set (match_operand:SI 2 "register_operand" "0" )
+ (sign_extend:SI (match_dup 0) ) )]
+ "REGNO(operands[0]) == REGNO(operands[2])"
+ "lhi\\t%0,%h1")
+
+;
+; peepholes for divide instructions
+;
+
+(define_peephole
+ [(set (match_operand:DI 0 "register_operand" "d")
+ (match_operand:DI 1 "memory_operand" "m"))
+ (set (match_dup 0)
+ (lshiftrt:DI (match_dup 0)
+ (match_operand:SI 2 "immediate_operand" "J")))
+ (set (match_dup 0)
+ (div:SI (match_dup 0)
+ (match_operand:SI 3 "nonimmediate_operand" "g")))
+ (set (match_dup 1)
+ (match_dup 0))]
+ ""
+ "*
+{
+ output_asm_insn (\"l\\t%0,%1\", operands);
+ output_asm_insn (\"srdl\\t%0,%b2\", operands);
+
+ if (REG_P (operands[3]))
+ output_asm_insn (\"dr\\t%0,%3\", operands);
+ else
+ output_asm_insn (\"d\\t%0,%3\", operands);
+
+ return \"st\\t%N0,%N1\";
+}")
+
+(define_peephole
+ [(set (match_operand:DI 0 "register_operand" "d")
+ (match_operand:DI 1 "memory_operand" "m"))
+ (set (match_dup 0)
+ (lshiftrt:DI (match_dup 0)
+ (match_operand:SI 2 "immediate_operand" "J")))
+ (set (match_dup 0)
+ (mod:SI (match_dup 0)
+ (match_operand:SI 3 "nonimmediate_operand" "g")))
+ (set (match_dup 1)
+ (match_dup 0))]
+ ""
+ "*
+{
+ output_asm_insn (\"l\\t%0,%1\", operands);
+ output_asm_insn (\"srdl\\t%0,%b2\", operands);
+
+ if (REG_P (operands[3]))
+ output_asm_insn (\"dr\\t%0,%3\", operands);
+ else
+ output_asm_insn (\"d\\t%0,%3\", operands);
+
+ return \"st\\t%0,%1\";
+}")
+
diff --git a/gcc/config/s390/t-linux b/gcc/config/s390/t-linux
new file mode 100644
index 00000000000..91585b77b3f
--- /dev/null
+++ b/gcc/config/s390/t-linux
@@ -0,0 +1,6 @@
+# The crtbegin and crtend must not depend on a small GOT
+CRTSTUFF_T_CFLAGS = -O2 -fPIC
+
+# Compile libgcc2.a with pic.
+TARGET_LIBGCC2_CFLAGS = -fPIC -include $(srcdir)/config/s390/fixdfdi.h
+
diff --git a/gcc/config/s390/xm-s390.h b/gcc/config/s390/xm-s390.h
new file mode 100644
index 00000000000..a98f23acf10
--- /dev/null
+++ b/gcc/config/s390/xm-s390.h
@@ -0,0 +1,41 @@
+/* Configuration for GNU C-compiler for S/390
+ Copyright (C) 1999 Free Software Foundation, Inc.
+ Contributed by Hartmut Penner (hpenner@de.ibm.com).
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* This describes the machine the compiler is hosted on. */
+
+#define HOST_BITS_PER_CHAR 8
+#define HOST_BITS_PER_SHORT 16
+#define HOST_BITS_PER_INT 32
+#define HOST_BITS_PER_LONG 32
+#define HOST_BITS_PER_LONGLONG 64
+
+#define HOST_WORDS_BIG_ENDIAN 1
+
+/* Target machine dependencies. tm.h is a symbolic link to the actual
+ target specific file. */
+
+#include "tm.h"
+
+/* Arguments to use with `exit'. */
+
+#define SUCCESS_EXIT_CODE 0
+#define FATAL_EXIT_CODE 33
+
diff --git a/gcc/config/s390/xm-s390x.h b/gcc/config/s390/xm-s390x.h
new file mode 100644
index 00000000000..dd96b909b03
--- /dev/null
+++ b/gcc/config/s390/xm-s390x.h
@@ -0,0 +1,41 @@
+/* Configuration for GNU C-compiler for S/390
+ Copyright (C) 1999 Free Software Foundation, Inc.
+ Contributed by Hartmut Penner (hpenner@de.ibm.com).
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* This describes the machine the compiler is hosted on. */
+
+#define HOST_BITS_PER_CHAR 8
+#define HOST_BITS_PER_SHORT 16
+#define HOST_BITS_PER_INT 32
+#define HOST_BITS_PER_LONG 64
+#define HOST_BITS_PER_LONGLONG 64
+
+#define HOST_WORDS_BIG_ENDIAN 1
+
+/* Target machine dependencies. tm.h is a symbolic link to the actual
+ target specific file. */
+
+#include "tm.h"
+
+/* Arguments to use with `exit'. */
+
+#define SUCCESS_EXIT_CODE 0
+#define FATAL_EXIT_CODE 33
+
diff --git a/gcc/config/sh/crti.asm b/gcc/config/sh/crti.asm
index ece86667e74..cfed71d2a86 100644
--- a/gcc/config/sh/crti.asm
+++ b/gcc/config/sh/crti.asm
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 Free Software Foundation, Inc.
+/* Copyright (C) 2000, 2001 Free Software Foundation, Inc.
This file was adapted from glibc sources.
This file is part of GNU CC.
@@ -39,7 +39,7 @@ Boston, MA 02111-1307, USA. */
such object files. */
.section .init
-/* The alignment below can't be smaller, otherwide the mova below
+/* The alignment below can't be smaller, otherwise the mova below
breaks. Yes, we might align just the label, but then we'd be
exchanging an alignment here for one there, since the code fragment
below ensures 4-byte alignment on __ELF__. */
@@ -70,7 +70,7 @@ _init:
#endif
.section .fini
-/* The alignment below can't be smaller, otherwide the mova below
+/* The alignment below can't be smaller, otherwise the mova below
breaks. Yes, we might align just the label, but then we'd be
exchanging an alignment here for one there, since the code fragment
below ensures 4-byte alignment on __ELF__. */
diff --git a/gcc/config/sh/crtn.asm b/gcc/config/sh/crtn.asm
index 86a4ee3f976..6aa9a52d2d6 100644
--- a/gcc/config/sh/crtn.asm
+++ b/gcc/config/sh/crtn.asm
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 Free Software Foundation, Inc.
+/* Copyright (C) 2000, 2001 Free Software Foundation, Inc.
This file was adapted from glibc sources.
This file is part of GNU CC.
@@ -30,7 +30,7 @@ Boston, MA 02111-1307, USA. */
/* See an explanation about .init and .fini in crti.asm. */
.section .init
- mov r15,r14
+ mov r14,r15
lds.l @r15+,pr
mov.l @r15+,r14
rts
@@ -41,7 +41,7 @@ Boston, MA 02111-1307, USA. */
#endif
.section .fini
- mov r15,r14
+ mov r14,r15
lds.l @r15+,pr
mov.l @r15+,r14
rts
diff --git a/gcc/config/sh/lib1funcs.asm b/gcc/config/sh/lib1funcs.asm
index 5ebea99c4d1..7d75cd8f90a 100644
--- a/gcc/config/sh/lib1funcs.asm
+++ b/gcc/config/sh/lib1funcs.asm
@@ -845,7 +845,7 @@ GLOBAL(movstrSI12_i4):
!
GLOBAL(mulsi3):
- mulu r4,r5 ! multiply the lsws macl=bb*dd
+ mulu.w r4,r5 ! multiply the lsws macl=bb*dd
mov r5,r3 ! r3 = ccdd
swap.w r4,r2 ! r2 = bbaa
xtrct r2,r3 ! r3 = aacc
@@ -855,9 +855,9 @@ GLOBAL(mulsi3):
sts macl,r0
hiset: sts macl,r0 ! r0 = bb*dd
- mulu r2,r5 ! brewing macl = aa*dd
+ mulu.w r2,r5 ! brewing macl = aa*dd
sts macl,r1
- mulu r3,r4 ! brewing macl = cc*bb
+ mulu.w r3,r4 ! brewing macl = cc*bb
sts macl,r2
add r1,r2
shll16 r2
@@ -1217,18 +1217,23 @@ GLOBAL(ic_invalidate):
ocbwb @r4
mova 0f,r0
mov.w 1f,r1
+/* Compute how many cache lines 0f is away from r4. */
sub r0,r4
and r1,r4
- add #4,r4
+/* Prepare to branch to 0f plus the cache-line offset. */
+ add # 0f - 1f,r4
braf r4
nop
1:
.short 0x1fe0
- nop
+ .p2align 5
+/* This must be aligned to the beginning of a cache line. */
0:
- .rept 2048
+ .rept 256 /* There are 256 cache lines of 32 bytes. */
rts
+ .rept 15
nop
.endr
+ .endr
#endif /* SH4 */
#endif /* L_ic_invalidate */
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
index 4385a0fa6e0..94e3a6b9e2f 100644
--- a/gcc/config/sh/sh.c
+++ b/gcc/config/sh/sh.c
@@ -27,7 +27,6 @@ Boston, MA 02111-1307, USA. */
#include "rtl.h"
#include "tree.h"
#include "flags.h"
-#include "insn-flags.h"
#include "expr.h"
#include "function.h"
#include "regs.h"
@@ -44,6 +43,9 @@ int code_for_indirect_jump_scratch = CODE_FOR_indirect_jump_scratch;
#define MSW (TARGET_LITTLE_ENDIAN ? 1 : 0)
#define LSW (TARGET_LITTLE_ENDIAN ? 0 : 1)
+/* Set to 1 by expand_prologue() when the function is an interrupt handler. */
+int current_function_interrupt;
+
/* ??? The pragma interrupt support will not work for SH3. */
/* This is set by #pragma interrupt and #pragma trapa, and causes gcc to
output code for the next function appropriate for an interrupt handler. */
@@ -148,6 +150,7 @@ static void push_regs PARAMS ((int, int));
static int calc_live_regs PARAMS ((int *, int *));
static void mark_use PARAMS ((rtx, rtx *));
static HOST_WIDE_INT rounded_frame_size PARAMS ((int));
+static rtx mark_constant_pool_use PARAMS ((rtx));
/* Print the operand address in x to the stream. */
@@ -171,7 +174,7 @@ print_operand_address (stream, x)
switch (GET_CODE (index))
{
case CONST_INT:
- fprintf (stream, "@(%d,%s)", INTVAL (index),
+ fprintf (stream, "@(%d,%s)", (int) INTVAL (index),
reg_names[true_regnum (base)]);
break;
@@ -202,6 +205,7 @@ print_operand_address (stream, x)
break;
default:
+ x = mark_constant_pool_use (x);
output_addr_const (stream, x);
break;
}
@@ -262,6 +266,7 @@ print_operand (stream, x, code)
fprintf (stream, "\n\tnop");
break;
case 'O':
+ x = mark_constant_pool_use (x);
output_addr_const (stream, x);
break;
case 'R':
@@ -800,8 +805,12 @@ output_branch (logic, insn, operands)
rtx insn;
rtx *operands;
{
- switch (get_attr_length (insn))
+ int len = get_attr_length (insn);
+
+ switch (len)
{
+ case 16:
+ case 12:
case 6:
/* This can happen if filling the delay slot has caused a forward
branch to exceed its range (we could reverse it, but only
@@ -824,16 +833,24 @@ output_branch (logic, insn, operands)
if (final_sequence
&& ! INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0)))
{
- asm_fprintf (asm_out_file, "\tb%s%ss\t%LLF%d\n", logic ? "f" : "t",
+ asm_fprintf (asm_out_file, "\tb%s%ss\t%LLF%d\n",
+ logic ? "f" : "t",
ASSEMBLER_DIALECT ? "/" : ".", label);
print_slot (final_sequence);
}
else
- asm_fprintf (asm_out_file, "\tb%s\t%LLF%d\n", logic ? "f" : "t", label);
+ asm_fprintf (asm_out_file, "\tb%s\t%LLF%d\n", logic ? "f" : "t",
+ label);
- output_asm_insn ("bra\t%l0", &op0);
- fprintf (asm_out_file, "\tnop\n");
- ASM_OUTPUT_INTERNAL_LABEL(asm_out_file, "LF", label);
+ if (len == 6)
+ {
+ output_asm_insn ("bra\t%l0", &op0);
+ fprintf (asm_out_file, "\tnop\n");
+ }
+ else
+ output_far_jump (insn, op0);
+
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LF", label);
return "";
}
@@ -905,8 +922,8 @@ output_file_start (file)
{
output_file_directive (file, main_input_filename);
- /* Switch to the data section so that the coffsem symbol and the
- gcc2_compiled. symbol aren't in the text section. */
+ /* Switch to the data section so that the coffsem symbol
+ isn't in the text section. */
data_section ();
if (TARGET_LITTLE_ENDIAN)
@@ -1439,7 +1456,7 @@ shl_and_kind (left_rtx, mask_rtx, attrp)
}
}
/* Try to use a scratch register to hold the AND operand. */
- can_ext = ((mask << left) & 0xe0000000) == 0;
+ can_ext = ((mask << left) & ((unsigned HOST_WIDE_INT)3 << 30)) == 0;
for (i = 0; i <= 2; i++)
{
if (i > right)
@@ -1921,6 +1938,7 @@ typedef struct
{
rtx value; /* Value in table. */
rtx label; /* Label of value. */
+ rtx wend; /* End of window. */
enum machine_mode mode; /* Mode of value. */
} pool_node;
@@ -1931,6 +1949,8 @@ typedef struct
#define MAX_POOL_SIZE (1020/4)
static pool_node pool_vector[MAX_POOL_SIZE];
static int pool_size;
+static rtx pool_window_label;
+static int pool_window_last;
/* ??? If we need a constant in HImode which is the truncated value of a
constant we need in SImode, we could combine the two entries thus saving
@@ -1951,7 +1971,7 @@ add_constant (x, mode, last_value)
rtx last_value;
{
int i;
- rtx lab;
+ rtx lab, new, ref, newref;
/* First see if we've already got it. */
for (i = 0; i < pool_size; i++)
@@ -1966,15 +1986,25 @@ add_constant (x, mode, last_value)
}
if (rtx_equal_p (x, pool_vector[i].value))
{
- lab = 0;
+ lab = new = 0;
if (! last_value
|| ! i
|| ! rtx_equal_p (last_value, pool_vector[i-1].value))
{
- lab = pool_vector[i].label;
- if (! lab)
- pool_vector[i].label = lab = gen_label_rtx ();
+ new = gen_label_rtx ();
+ LABEL_REFS (new) = pool_vector[i].label;
+ pool_vector[i].label = lab = new;
+ }
+ if (lab && pool_window_label)
+ {
+ newref = gen_rtx_LABEL_REF (VOIDmode, pool_window_label);
+ ref = pool_vector[pool_window_last].wend;
+ LABEL_NEXTREF (newref) = ref;
+ pool_vector[pool_window_last].wend = newref;
}
+ if (new)
+ pool_window_label = new;
+ pool_window_last = i;
return lab;
}
}
@@ -1988,6 +2018,17 @@ add_constant (x, mode, last_value)
lab = gen_label_rtx ();
pool_vector[pool_size].mode = mode;
pool_vector[pool_size].label = lab;
+ pool_vector[pool_size].wend = NULL_RTX;
+ if (lab && pool_window_label)
+ {
+ newref = gen_rtx_LABEL_REF (VOIDmode, pool_window_label);
+ ref = pool_vector[pool_window_last].wend;
+ LABEL_NEXTREF (newref) = ref;
+ pool_vector[pool_window_last].wend = newref;
+ }
+ if (lab)
+ pool_window_label = lab;
+ pool_window_last = pool_size;
pool_size++;
return lab;
}
@@ -2000,6 +2041,7 @@ dump_table (scan)
{
int i;
int need_align = 1;
+ rtx lab, ref;
/* Do two passes, first time dump out the HI sized constants. */
@@ -2014,8 +2056,15 @@ dump_table (scan)
scan = emit_insn_after (gen_align_2 (), scan);
need_align = 0;
}
- scan = emit_label_after (p->label, scan);
- scan = emit_insn_after (gen_consttable_2 (p->value), scan);
+ for (lab = p->label; lab; lab = LABEL_REFS (lab))
+ scan = emit_label_after (lab, scan);
+ scan = emit_insn_after (gen_consttable_2 (p->value, const0_rtx),
+ scan);
+ for (ref = p->wend; ref; ref = LABEL_NEXTREF (ref))
+ {
+ lab = XEXP (ref, 0);
+ scan = emit_insn_after (gen_consttable_window_end (lab), scan);
+ }
}
}
@@ -2037,9 +2086,10 @@ dump_table (scan)
scan = emit_label_after (gen_label_rtx (), scan);
scan = emit_insn_after (gen_align_4 (), scan);
}
- if (p->label)
- scan = emit_label_after (p->label, scan);
- scan = emit_insn_after (gen_consttable_4 (p->value), scan);
+ for (lab = p->label; lab; lab = LABEL_REFS (lab))
+ scan = emit_label_after (lab, scan);
+ scan = emit_insn_after (gen_consttable_4 (p->value, const0_rtx),
+ scan);
break;
case DFmode:
case DImode:
@@ -2049,19 +2099,31 @@ dump_table (scan)
scan = emit_label_after (gen_label_rtx (), scan);
scan = emit_insn_after (gen_align_4 (), scan);
}
- if (p->label)
- scan = emit_label_after (p->label, scan);
- scan = emit_insn_after (gen_consttable_8 (p->value), scan);
+ for (lab = p->label; lab; lab = LABEL_REFS (lab))
+ scan = emit_label_after (lab, scan);
+ scan = emit_insn_after (gen_consttable_8 (p->value, const0_rtx),
+ scan);
break;
default:
abort ();
break;
}
+
+ if (p->mode != HImode)
+ {
+ for (ref = p->wend; ref; ref = LABEL_NEXTREF (ref))
+ {
+ lab = XEXP (ref, 0);
+ scan = emit_insn_after (gen_consttable_window_end (lab), scan);
+ }
+ }
}
scan = emit_insn_after (gen_consttable_end (), scan);
scan = emit_barrier_after (scan);
pool_size = 0;
+ pool_window_label = NULL_RTX;
+ pool_window_last = 0;
}
/* Return non-zero if constant would be an ok source for a
@@ -2720,7 +2782,7 @@ struct far_branch
static void gen_far_branch PARAMS ((struct far_branch *));
enum mdep_reorg_phase_e mdep_reorg_phase;
-void
+static void
gen_far_branch (bp)
struct far_branch *bp;
{
@@ -2824,7 +2886,7 @@ barrier_align (barrier_or_label)
the table to the minimum for proper code alignment. */
return ((TARGET_SMALLCODE
|| (XVECLEN (pat, 1) * GET_MODE_SIZE (GET_MODE (pat))
- <= 1 << (CACHE_LOG - 2)))
+ <= (unsigned)1 << (CACHE_LOG - 2)))
? 1 : CACHE_LOG);
}
@@ -2856,7 +2918,7 @@ barrier_align (barrier_or_label)
investigation. Skip to the insn before it. */
prev = prev_real_insn (prev);
- for (slot = 2, credit = 1 << (CACHE_LOG - 2) + 2;
+ for (slot = 2, credit = (1 << (CACHE_LOG - 2)) + 2;
credit >= 0 && prev && GET_CODE (prev) == INSN;
prev = prev_real_insn (prev))
{
@@ -3933,7 +3995,7 @@ rounded_frame_size (pushed)
HOST_WIDE_INT size = get_frame_size ();
HOST_WIDE_INT align = STACK_BOUNDARY / BITS_PER_UNIT;
- return (size + pushed + align - 1 & -align) - pushed;
+ return ((size + pushed + align - 1) & -align) - pushed;
}
void
@@ -3944,6 +4006,11 @@ sh_expand_prologue ()
int live_regs_mask2;
int save_flags = target_flags;
+ current_function_interrupt
+ = lookup_attribute ("interrupt_handler",
+ DECL_MACHINE_ATTRIBUTES (current_function_decl))
+ != NULL_TREE;
+
/* We have pretend args if we had an object sent partially in registers
and partially on the stack, e.g. a large structure. */
output_stack_adjust (-current_function_pretend_args_size,
@@ -3987,7 +4054,23 @@ sh_expand_prologue ()
push_regs (live_regs_mask, live_regs_mask2);
if (flag_pic && regs_ever_live[PIC_OFFSET_TABLE_REGNUM])
- emit_insn (gen_GOTaddr2picreg ());
+ {
+ rtx insn = get_last_insn ();
+ rtx last = emit_insn (gen_GOTaddr2picreg ());
+
+ /* Mark these insns as possibly dead. Sometimes, flow2 may
+ delete all uses of the PIC register. In this case, let it
+ delete the initialization too. */
+ do
+ {
+ insn = NEXT_INSN (insn);
+
+ REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD,
+ const0_rtx,
+ REG_NOTES (insn));
+ }
+ while (insn != last);
+ }
if (target_flags != save_flags)
{
@@ -5013,7 +5096,7 @@ reg_unused_after (reg, insn)
return 1;
}
-extern struct obstack permanent_obstack;
+#include "ggc.h"
rtx
get_fpscr_rtx ()
@@ -5181,8 +5264,6 @@ static rtx
get_free_reg (regs_live)
HARD_REG_SET regs_live;
{
- rtx reg;
-
if (! TEST_HARD_REG_BIT (regs_live, 1))
return gen_rtx_REG (Pmode, 1);
@@ -5204,8 +5285,10 @@ fpscr_set_from_mem (mode, regs_live)
enum attr_fp_mode fp_mode = mode;
rtx addr_reg = get_free_reg (regs_live);
- emit_insn ((fp_mode == (TARGET_FPU_SINGLE ? FP_MODE_SINGLE : FP_MODE_DOUBLE)
- ? gen_fpu_switch1 : gen_fpu_switch0) (addr_reg));
+ if (fp_mode == (enum attr_fp_mode) NORMAL_MODE (FP_MODE))
+ emit_insn (gen_fpu_switch1 (addr_reg));
+ else
+ emit_insn (gen_fpu_switch0 (addr_reg));
}
/* Is the given character a logical line separator for the assembler? */
@@ -5327,7 +5410,7 @@ nonpic_symbol_mentioned_p (x)
rtx
legitimize_pic_address (orig, mode, reg)
rtx orig;
- enum machine_mode mode;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
rtx reg;
{
if (GET_CODE (orig) == LABEL_REF
@@ -5352,3 +5435,68 @@ legitimize_pic_address (orig, mode, reg)
}
return orig;
}
+
+/* Mark the use of a constant in the literal table. If the constant
+ has multiple labels, make it unique. */
+static rtx mark_constant_pool_use (x)
+ rtx x;
+{
+ rtx insn, lab, pattern;
+
+ if (x == NULL)
+ return x;
+
+ switch (GET_CODE (x))
+ {
+ case LABEL_REF:
+ x = XEXP (x, 0);
+ case CODE_LABEL:
+ break;
+ default:
+ return x;
+ }
+
+ /* Get the first label in the list of labels for the same constant
+ and delete another labels in the list. */
+ lab = x;
+ for (insn = PREV_INSN (x); insn; insn = PREV_INSN (insn))
+ {
+ if (GET_CODE (insn) != CODE_LABEL
+ || LABEL_REFS (insn) != NEXT_INSN (insn))
+ break;
+ lab = insn;
+ }
+
+ for (insn = LABEL_REFS (lab); insn; insn = LABEL_REFS (insn))
+ INSN_DELETED_P (insn) = 1;
+
+ /* Mark constants in a window. */
+ for (insn = NEXT_INSN (x); insn; insn = NEXT_INSN (insn))
+ {
+ if (GET_CODE (insn) != INSN)
+ continue;
+
+ pattern = PATTERN (insn);
+ if (GET_CODE (pattern) != UNSPEC_VOLATILE)
+ continue;
+
+ switch (XINT (pattern, 1))
+ {
+ case UNSPECV_CONST2:
+ case UNSPECV_CONST4:
+ case UNSPECV_CONST8:
+ XVECEXP (pattern, 0, 1) = const1_rtx;
+ break;
+ case UNSPECV_WINDOW_END:
+ if (XVECEXP (pattern, 0, 0) == x)
+ return lab;
+ break;
+ case UNSPECV_CONST_END:
+ return lab;
+ default:
+ break;
+ }
+ }
+
+ return lab;
+}
diff --git a/gcc/config/sh/sh.h b/gcc/config/sh/sh.h
index 01473bd3a52..7e39af85f82 100644
--- a/gcc/config/sh/sh.h
+++ b/gcc/config/sh/sh.h
@@ -1670,13 +1670,6 @@ extern int current_function_anonymous_args;
/* Nonzero if access to memory by bytes is no faster than for words. */
#define SLOW_BYTE_ACCESS 1
-/* Force sizeof(bool) == 1 to maintain binary compatibility; otherwise, the
- change in SLOW_BYTE_ACCESS would have changed it to 4. */
-
-/* This used to use INT_TYPE_SIZE / CHAR_TYPE_SIZE, but these are
- not guaranteed to be defined when BOOL_TYPE_SIZE is used. */
-#define BOOL_TYPE_SIZE (flag_new_abi ? BITS_PER_WORD : BITS_PER_UNIT)
-
/* We assume that the store-condition-codes instructions store 0 for false
and some other value for true. This is the value stored for true. */
@@ -1799,6 +1792,13 @@ do \
} \
while (0)
+/* We can't directly access anything that contains a symbol,
+ nor can we indirect via the constant pool. */
+#define LEGITIMATE_PIC_OPERAND_P(X) \
+ (! nonpic_symbol_mentioned_p (X) \
+ && (! CONSTANT_POOL_ADDRESS_P (X) \
+ || ! nonpic_symbol_mentioned_p (get_pool_constant (X))))
+
#define SYMBOLIC_CONST_P(X) \
((GET_CODE (X) == SYMBOL_REF || GET_CODE (X) == LABEL_REF) \
&& nonpic_symbol_mentioned_p (X))
@@ -1865,7 +1865,7 @@ while (0)
#define ASM_APP_ON ""
#define ASM_APP_OFF ""
#define FILE_ASM_OP "\t.file\n"
-#define IDENT_ASM_OP "\t.ident\n"
+#define IDENT_ASM_OP "\t.ident\t"
#define SET_ASM_OP "\t.set\t"
/* How to change between sections. */
@@ -2298,6 +2298,10 @@ extern enum mdep_reorg_phase_e mdep_reorg_phase;
extern int pragma_interrupt;
+/* Set when processing a function with interrupt attribute. */
+
+extern int current_function_interrupt;
+
/* Set to an RTX containing the address of the stack to switch to
for interrupt functions. */
extern struct rtx_def *sp_switch;
diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md
index b471a4a9773..0c0911841bb 100644
--- a/gcc/config/sh/sh.md
+++ b/gcc/config/sh/sh.md
@@ -117,6 +117,7 @@
(UNSPECV_CONST2 2)
(UNSPECV_CONST4 4)
(UNSPECV_CONST8 6)
+ (UNSPECV_WINDOW_END 10)
(UNSPECV_CONST_END 11)
])
@@ -546,7 +547,7 @@
(const_string "yes")))
(define_attr "interrupt_function" "no,yes"
- (const (symbol_ref "pragma_interrupt")))
+ (const (symbol_ref "current_function_interrupt")))
(define_attr "in_delay_slot" "yes,no"
(cond [(eq_attr "type" "cbranch") (const_string "no")
@@ -576,7 +577,9 @@
(ior (and (eq_attr "interrupt_function" "no")
(eq_attr "type" "!pload,prset"))
(and (eq_attr "interrupt_function" "yes")
- (eq_attr "hit_stack" "no")))) (nil) (nil)])
+ (ior
+ (ne (symbol_ref "TARGET_SH3") (const_int 0))
+ (eq_attr "hit_stack" "no"))))) (nil) (nil)])
;; Since a call implicitly uses the PR register, we can't allow
;; a PR register store in a jsr delay slot.
@@ -1160,7 +1163,7 @@
(zero_extend:SI
(match_operand:HI 1 "arith_reg_operand" "r"))))]
""
- "mulu %1,%0"
+ "mulu.w %1,%0"
[(set_attr "type" "smpy")])
(define_insn "mulhisi3_i"
@@ -1170,7 +1173,7 @@
(sign_extend:SI
(match_operand:HI 1 "arith_reg_operand" "r"))))]
""
- "muls %1,%0"
+ "muls.w %1,%0"
[(set_attr "type" "smpy")])
(define_expand "mulhisi3"
@@ -2438,8 +2441,8 @@
;; ??? This allows moves from macl to fpul to be recognized, but these moves
;; will require a reload.
(define_insn "movsi_ie"
- [(set (match_operand:SI 0 "general_movdst_operand" "=r,r,t,r,r,r,r,m,<,<,x,l,x,l,y,r,y,r,y")
- (match_operand:SI 1 "general_movsrc_operand" "Q,rI,r,mr,x,l,t,r,x,l,r,r,>,>,>,i,r,y,y"))]
+ [(set (match_operand:SI 0 "general_movdst_operand" "=r,r,t,r,r,r,r,m,<,<,x,l,x,l,y,<,r,y,r,y")
+ (match_operand:SI 1 "general_movsrc_operand" "Q,rI,r,mr,x,l,t,r,x,l,r,r,>,>,>,y,i,r,y,y"))]
"TARGET_SH3E
&& (register_operand (operands[0], SImode)
|| register_operand (operands[1], SImode))"
@@ -2459,12 +2462,13 @@
lds.l %1,%0
lds.l %1,%0
lds.l %1,%0
+ sts.l %1,%0
fake %1,%0
lds %1,%0
sts %1,%0
! move optimized away"
- [(set_attr "type" "pcload_si,move,*,load_si,move,prget,move,store,store,pstore,move,prset,load,pload,load,pcload_si,gp_fpul,gp_fpul,nil")
- (set_attr "length" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,0")])
+ [(set_attr "type" "pcload_si,move,*,load_si,move,prget,move,store,store,pstore,move,prset,load,pload,load,store,pcload_si,gp_fpul,gp_fpul,nil")
+ (set_attr "length" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,0")])
(define_insn "movsi_i_lowpart"
[(set (strict_low_part (match_operand:SI 0 "general_movdst_operand" "+r,r,r,r,r,r,m,r"))
@@ -3084,11 +3088,11 @@
;; when the destination changes mode.
(define_insn "movsf_ie"
[(set (match_operand:SF 0 "general_movdst_operand"
- "=f,r,f,f,fy,f,m,r,r,m,f,y,y,rf,r<,y,y")
+ "=f,r,f,f,fy,f,m,r,r,m,f,y,y,rf,r,y,<,y,y")
(match_operand:SF 1 "general_movsrc_operand"
- "f,r,G,H,FQ,mf,f,FQ,mr,r,y,f,>,fr,y,r>,y"))
- (use (match_operand:PSI 2 "fpscr_operand" "c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c"))
- (clobber (match_scratch:SI 3 "=X,X,X,X,&z,X,X,X,X,X,X,X,X,y,X,X,X"))]
+ "f,r,G,H,FQ,mf,f,FQ,mr,r,y,f,>,fr,y,r,y,>,y"))
+ (use (match_operand:PSI 2 "fpscr_operand" "c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c"))
+ (clobber (match_scratch:SI 3 "=X,X,X,X,&z,X,X,X,X,X,X,X,X,y,X,X,X,X,X"))]
"TARGET_SH3E
&& (arith_reg_operand (operands[0], SFmode)
@@ -3117,9 +3121,11 @@
#
sts %1,%0
lds %1,%0
+ sts.l %1,%0
+ lds.l %1,%0
! move optimized away"
- [(set_attr "type" "fmove,move,fmove,fmove,pcload,load,store,pcload,load,store,fmove,fmove,load,*,gp_fpul,gp_fpul,nil")
- (set_attr "length" "*,*,*,*,4,*,*,*,*,*,2,2,2,4,2,2,0")
+ [(set_attr "type" "fmove,move,fmove,fmove,pcload,load,store,pcload,load,store,fmove,fmove,load,*,gp_fpul,gp_fpul,store,load,nil")
+ (set_attr "length" "*,*,*,*,4,*,*,*,*,*,2,2,2,4,2,2,2,2,0")
(set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
(const_string "single")
(const_string "none")))])
@@ -3749,6 +3755,15 @@
}
")
+(define_expand "builtin_setjmp_receiver"
+ [(match_operand 0 "" "")]
+ "flag_pic"
+ "
+{
+ emit_insn (gen_GOTaddr2picreg ());
+ DONE;
+}")
+
(define_expand "call_site"
[(unspec [(match_dup 0)] UNSPEC_CALLER)]
""
@@ -4107,12 +4122,14 @@
; 2 byte integer in line
(define_insn "consttable_2"
- [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")]
+ [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
+ (match_operand 1 "" "")]
UNSPECV_CONST2)]
""
"*
{
- assemble_integer (operands[0], 2, 1);
+ if (operands[1] != const0_rtx)
+ assemble_integer (operands[0], 2, 1);
return \"\";
}"
[(set_attr "length" "2")
@@ -4121,12 +4138,14 @@
; 4 byte integer in line
(define_insn "consttable_4"
- [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")]
+ [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
+ (match_operand 1 "" "")]
UNSPECV_CONST4)]
""
"*
{
- assemble_integer (operands[0], 4, 1);
+ if (operands[1] != const0_rtx)
+ assemble_integer (operands[0], 4, 1);
return \"\";
}"
[(set_attr "length" "4")
@@ -4135,12 +4154,14 @@
; 8 byte integer in line
(define_insn "consttable_8"
- [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")]
+ [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
+ (match_operand 1 "" "")]
UNSPECV_CONST8)]
""
"*
{
- assemble_integer (operands[0], 8, 1);
+ if (operands[1] != const0_rtx)
+ assemble_integer (operands[0], 8, 1);
return \"\";
}"
[(set_attr "length" "8")
@@ -4149,14 +4170,18 @@
; 4 byte floating point
(define_insn "consttable_sf"
- [(unspec_volatile [(match_operand:SF 0 "general_operand" "=g")]
+ [(unspec_volatile [(match_operand:SF 0 "general_operand" "=g")
+ (match_operand 1 "" "")]
UNSPECV_CONST4)]
""
"*
{
- union real_extract u;
- memcpy (&u, &CONST_DOUBLE_LOW (operands[0]), sizeof u);
- assemble_real (u.d, SFmode);
+ if (operands[1] != const0_rtx)
+ {
+ union real_extract u;
+ memcpy (&u, &CONST_DOUBLE_LOW (operands[0]), sizeof u);
+ assemble_real (u.d, SFmode);
+ }
return \"\";
}"
[(set_attr "length" "4")
@@ -4165,14 +4190,18 @@
; 8 byte floating point
(define_insn "consttable_df"
- [(unspec_volatile [(match_operand:DF 0 "general_operand" "=g")]
+ [(unspec_volatile [(match_operand:DF 0 "general_operand" "=g")
+ (match_operand 1 "" "")]
UNSPECV_CONST8)]
""
"*
{
- union real_extract u;
- memcpy (&u, &CONST_DOUBLE_LOW (operands[0]), sizeof u);
- assemble_real (u.d, DFmode);
+ if (operands[1] != const0_rtx)
+ {
+ union real_extract u;
+ memcpy (&u, &CONST_DOUBLE_LOW (operands[0]), sizeof u);
+ assemble_real (u.d, DFmode);
+ }
return \"\";
}"
[(set_attr "length" "8")
@@ -4218,6 +4247,15 @@
"* return output_jump_label_table ();"
[(set_attr "in_delay_slot" "no")])
+; emitted at the end of the window in the literal table.
+
+(define_insn "consttable_window_end"
+ [(unspec_volatile [(match_operand 0 "" "")] UNSPECV_WINDOW_END)]
+ ""
+ ""
+ [(set_attr "length" "0")
+ (set_attr "in_delay_slot" "no")])
+
;; -------------------------------------------------------------------------
;; Misc
;; -------------------------------------------------------------------------
diff --git a/gcc/config/sh/xm-sh.h b/gcc/config/sh/xm-sh.h
index f51b787f6df..d28538c7b61 100644
--- a/gcc/config/sh/xm-sh.h
+++ b/gcc/config/sh/xm-sh.h
@@ -18,10 +18,6 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* #defines that need visibility everywhere. */
-#define FALSE 0
-#define TRUE 1
-
/* This describes the machine the compiler is hosted on. */
#define HOST_BITS_PER_CHAR 8
#define HOST_BITS_PER_SHORT 16
diff --git a/gcc/config/sparc/linux-aout.h b/gcc/config/sparc/linux-aout.h
index 91561b0e264..c40c79c124e 100644
--- a/gcc/config/sparc/linux-aout.h
+++ b/gcc/config/sparc/linux-aout.h
@@ -42,11 +42,7 @@ Boston, MA 02111-1307, USA. */
/* Output at beginning of assembler file. */
/* The .file command should always begin the output. */
#undef ASM_FILE_START
-#define ASM_FILE_START(FILE) \
- do { \
- output_file_directive (FILE, main_input_filename); \
- fprintf (FILE, "\t.version\t\"01.01\"\n"); \
- } while (0)
+#define ASM_FILE_START(FILE) output_file_directive (FILE, main_input_filename)
#undef STARTFILE_SPEC
#define STARTFILE_SPEC "%{pg:gcrt0.o%s} %{!pg:%{p:gcrt0.o%s} %{!p:crt0.o%s}} %{static:-static}"
diff --git a/gcc/config/sparc/linux.h b/gcc/config/sparc/linux.h
index ee3b7fde9d1..236d0e95679 100644
--- a/gcc/config/sparc/linux.h
+++ b/gcc/config/sparc/linux.h
@@ -45,15 +45,6 @@ Boston, MA 02111-1307, USA. */
#undef MD_EXEC_PREFIX
#undef MD_STARTFILE_PREFIX
-/* Output at beginning of assembler file. */
-/* The .file command should always begin the output. */
-#undef ASM_FILE_START
-#define ASM_FILE_START(FILE) \
- do { \
- output_file_directive (FILE, main_input_filename); \
- fprintf (FILE, "\t.version\t\"01.01\"\n"); \
- } while (0)
-
/* Provide a STARTFILE_SPEC appropriate for GNU/Linux. Here we add
the GNU/Linux magical crtbegin.o file (see crtstuff.c) which
provides part of the support for getting C++ file-scope static
diff --git a/gcc/config/sparc/linux64.h b/gcc/config/sparc/linux64.h
index da2f4fe825a..94b59ee1a0f 100644
--- a/gcc/config/sparc/linux64.h
+++ b/gcc/config/sparc/linux64.h
@@ -44,15 +44,6 @@ Boston, MA 02111-1307, USA. */
+ MASK_STACK_BIAS + MASK_APP_REGS + MASK_EPILOGUE + MASK_FPU + MASK_LONG_DOUBLE_128)
#endif
-/* Output at beginning of assembler file. */
-/* The .file command should always begin the output. */
-#undef ASM_FILE_START
-#define ASM_FILE_START(FILE) \
- do { \
- output_file_directive (FILE, main_input_filename); \
- fprintf (FILE, "\t.version\t\"01.01\"\n"); \
- } while (0)
-
#undef ASM_CPU_DEFAULT_SPEC
#define ASM_CPU_DEFAULT_SPEC "-Av9a"
diff --git a/gcc/config/sparc/openbsd.h b/gcc/config/sparc/openbsd.h
index c5dc4431726..ba97ac7b9de 100644
--- a/gcc/config/sparc/openbsd.h
+++ b/gcc/config/sparc/openbsd.h
@@ -64,5 +64,6 @@ Boston, MA 02111-1307, USA. */
configuration files... */
#define DWARF2_UNWIND_INFO 0
-/* Default sparc.h does already define ASM_OUTPUT_MI_THUNK */
+#undef ASM_PREFERRED_EH_DATA_FORMAT
+/* Default sparc.h does already define ASM_OUTPUT_MI_THUNK */
diff --git a/gcc/config/sparc/rtems.h b/gcc/config/sparc/rtems.h
index 36fcf33f578..eeb773042bb 100644
--- a/gcc/config/sparc/rtems.h
+++ b/gcc/config/sparc/rtems.h
@@ -25,7 +25,7 @@ Boston, MA 02111-1307, USA. */
#undef CPP_PREDEFINES
#define CPP_PREDEFINES "-Dsparc -D__GCC_NEW_VARARGS__ -Drtems -D__rtems__ \
- -Asystem=rtems -Acpu=sparc -Amachine=sparc"
+ -Asystem=rtems"
/* Generate calls to memcpy, memcmp and memset. */
#ifndef TARGET_MEM_FUNCTIONS
diff --git a/gcc/config/sparc/rtemself.h b/gcc/config/sparc/rtemself.h
index 62277abe79d..cfc95f28b8c 100644
--- a/gcc/config/sparc/rtemself.h
+++ b/gcc/config/sparc/rtemself.h
@@ -1,4 +1,4 @@
-/* Definitions for rtems targeting a SPARC using a.out.
+/* Definitions for rtems targeting a SPARC using ELF.
Copyright (C) 1996, 1997, 2000 Free Software Foundation, Inc.
Contributed by Joel Sherrill (joel@OARcorp.com).
@@ -23,7 +23,7 @@ Boston, MA 02111-1307, USA. */
#undef CPP_PREDEFINES
#define CPP_PREDEFINES "-Dsparc -D__GCC_NEW_VARARGS__ -Drtems -D__rtems__ \
- -Asystem=rtems -Acpu=sparc -Amachine=sparc"
+ -Asystem=rtems"
/* Generate calls to memcpy, memcmp and memset. */
#ifndef TARGET_MEM_FUNCTIONS
diff --git a/gcc/config/sparc/sol2-sld-64.h b/gcc/config/sparc/sol2-sld-64.h
index a00f010f899..9179635c636 100644
--- a/gcc/config/sparc/sol2-sld-64.h
+++ b/gcc/config/sparc/sol2-sld-64.h
@@ -136,7 +136,7 @@
%{!p: \
%{pg:gcrt1.o%s gmon.o%s} \
%{!pg:crt1.o%s}}}} \
- crti.o%s" STARTFILE_ARCH_SPEC " \
+ crti.o%s " STARTFILE_ARCH_SPEC " \
crtbegin.o%s"
#ifdef SPARC_BI_ARCH
@@ -161,11 +161,35 @@
%{!m32:" ASM_CPU64_DEFAULT_SPEC "} \
")
+/* wchar_t is called differently in <wchar.h> for 32 and 64-bit
+ compilations. This is called for by SCD 2.4.1, p. 6-83, Figure 6-65
+ (32-bit) and p. 6P-10, Figure 6.38 (64-bit). */
+#define NO_BUILTIN_WCHAR_TYPE
+
+#undef WCHAR_TYPE
+#define WCHAR_TYPE (TARGET_ARCH64 ? "int" : "long int")
+
+#undef WCHAR_TYPE_SIZE
+#define WCHAR_TYPE_SIZE 32
+
+/* Same for wint_t. See SCD 2.4.1, p. 6-83, Figure 6-66 (32-bit). There's
+ no corresponding 64-bit definition, but this is what Solaris 8
+ <iso/wchar_iso.h> uses. */
+#define NO_BUILTIN_WINT_TYPE
+
+#undef WINT_TYPE
+#define WINT_TYPE (TARGET_ARCH64 ? "int" : "long int")
+
+#undef WINT_TYPE_SIZE
+#define WINT_TYPE_SIZE 32
+
#undef CPP_ARCH32_SPEC
#define CPP_ARCH32_SPEC "-D__SIZE_TYPE__=unsigned\\ int -D__PTRDIFF_TYPE__=int \
+-D__WCHAR_TYPE__=long\\ int -D__WINT_TYPE__=long\\ int \
-D__GCC_NEW_VARARGS__ -Acpu=sparc -Amachine=sparc"
#undef CPP_ARCH64_SPEC
#define CPP_ARCH64_SPEC "-D__SIZE_TYPE__=long\\ unsigned\\ int -D__PTRDIFF_TYPE__=long\\ int \
+-D__WCHAR_TYPE__=int -D__WINT_TYPE__=int \
-D__arch64__ -Acpu=sparc64 -Amachine=sparcv9 -D__sparcv9"
#undef CPP_ARCH_SPEC
diff --git a/gcc/config/sparc/sol2.h b/gcc/config/sparc/sol2.h
index 5075f9a1013..ee7fa063b17 100644
--- a/gcc/config/sparc/sol2.h
+++ b/gcc/config/sparc/sol2.h
@@ -1,5 +1,6 @@
/* Definitions of target machine for GNU compiler, for SPARC running Solaris 2
- Copyright 1992, 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+ Copyright 1992, 1995, 1996, 1997, 1998, 1999, 2000,
+ 2001 Free Software Foundation, Inc.
Contributed by Ron Guilmette (rfg@netcom.com).
Additional changes by David V. Henkel-Wallace (gumby@cygnus.com).
@@ -23,6 +24,14 @@ Boston, MA 02111-1307, USA. */
/* Supposedly the same as vanilla sparc svr4, except for the stuff below: */
#include "sparc/sysv4.h"
+/* Solaris 2 uses a wint_t different from the default. This is required
+ by the SCD 2.4.1, p. 6-83, Figure 6-66. */
+#undef WINT_TYPE
+#define WINT_TYPE "long int"
+
+#undef WINT_TYPE_SIZE
+#define WINT_TYPE_SIZE BITS_PER_WORD
+
#undef CPP_PREDEFINES
#define CPP_PREDEFINES \
"-Dsparc -Dsun -Dunix -D__svr4__ -D__SVR4 \
@@ -35,6 +44,14 @@ Boston, MA 02111-1307, USA. */
%{compat-bsd:-iwithprefixbefore ucbinclude -I/usr/ucbinclude} \
"
+/* For C++ we need to add some additional macro definitions required
+ by the C++ standard library. */
+#define CPLUSPLUS_CPP_SPEC "\
+-D_XOPEN_SOURCE=500 -D_LARGEFILE_SOURCE=1 -D_LARGEFILE64_SOURCE=1 \
+-D__EXTENSIONS__ \
+%(cpp) \
+"
+
/* The sun bundled assembler doesn't accept -Yd, (and neither does gas).
It's safe to pass -s always, even if -g is not used. */
#undef ASM_SPEC
diff --git a/gcc/config/sparc/sp64-elf.h b/gcc/config/sparc/sp64-elf.h
index b3148999c5d..cdd8f4c2361 100644
--- a/gcc/config/sparc/sp64-elf.h
+++ b/gcc/config/sparc/sp64-elf.h
@@ -119,38 +119,6 @@ crtbegin.o%s \
#undef PREFERRED_DEBUGGING_TYPE
#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
-/* Stabs doesn't use this, and it confuses a simulator. */
-/* ??? Need to see what DWARF needs, if anything. */
-#undef ASM_IDENTIFY_GCC
-#define ASM_IDENTIFY_GCC(FILE)
-
-/* Define the names of various pseudo-ops used by the Sparc/svr4 assembler.
- ??? If ints are 64 bits then UNALIGNED_INT_ASM_OP (defined elsewhere) is
- misnamed. These should all refer to explicit sizes (half/word/xword?),
- anything other than short/int/long/etc. */
-
-#define UNALIGNED_LONGLONG_ASM_OP "\t.uaxword\t"
-
-/* DWARF stuff. */
-
-#define ASM_OUTPUT_DWARF_ADDR(FILE, LABEL) \
-do { \
- fprintf ((FILE), "%s", UNALIGNED_LONGLONG_ASM_OP); \
- assemble_name ((FILE), (LABEL)); \
- fprintf ((FILE), "\n"); \
-} while (0)
-
-#define ASM_OUTPUT_DWARF_ADDR_CONST(FILE, RTX) \
-do { \
- fprintf ((FILE), "%s", UNALIGNED_LONGLONG_ASM_OP); \
- output_addr_const ((FILE), (RTX)); \
- fputc ('\n', (FILE)); \
-} while (0)
-
-/* ??? Not sure if this should be 4 or 8 bytes. 4 works for now. */
-#define ASM_OUTPUT_DWARF_REF(FILE, LABEL) \
-do { \
- fprintf ((FILE), "%s", UNALIGNED_INT_ASM_OP); \
- assemble_name ((FILE), (LABEL)); \
- fprintf ((FILE), "\n"); \
-} while (0)
+/* Define the names of various pseudo-ops used by the Sparc/svr4 assembler. */
+
+#define UNALIGNED_DOUBLE_INT_ASM_OP "\t.uaxword\t"
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index 0d194f1b28a..8ebe05fef90 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -31,7 +31,6 @@ Boston, MA 02111-1307, USA. */
#include "real.h"
#include "insn-config.h"
#include "conditions.h"
-#include "insn-flags.h"
#include "output.h"
#include "insn-attr.h"
#include "flags.h"
@@ -2378,6 +2377,11 @@ eligible_for_epilogue_delay (trial, slot)
if (num_gfregs)
return 0;
+ /* If the function uses __builtin_eh_return, the eh_return machinery
+ occupies the delay slot. */
+ if (current_function_calls_eh_return)
+ return 0;
+
/* In the case of a true leaf function, anything can go into the delay slot.
A delay slot only exists however if the frame size is zero, otherwise
we will put an insn to adjust the stack after the return. */
@@ -2414,7 +2418,8 @@ eligible_for_epilogue_delay (trial, slot)
src = SET_SRC (pat);
/* This matches "*return_[qhs]i" or even "*return_di" on TARGET_ARCH64. */
- if (arith_operand (src, GET_MODE (src)))
+ if (GET_MODE_CLASS (GET_MODE (src)) != MODE_FLOAT
+ && arith_operand (src, GET_MODE (src)))
{
if (TARGET_ARCH64)
return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (DImode);
@@ -2423,7 +2428,8 @@ eligible_for_epilogue_delay (trial, slot)
}
/* This matches "*return_di". */
- else if (arith_double_operand (src, GET_MODE (src)))
+ else if (GET_MODE_CLASS (GET_MODE (src)) != MODE_FLOAT
+ && arith_double_operand (src, GET_MODE (src)))
return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (DImode);
/* This matches "*return_sf_no_fpu". */
@@ -2520,7 +2526,8 @@ eligible_for_sibcall_delay (trial)
src = SET_SRC (pat);
- if (arith_operand (src, GET_MODE (src)))
+ if (GET_MODE_CLASS (GET_MODE (src)) != MODE_FLOAT
+ && arith_operand (src, GET_MODE (src)))
{
if (TARGET_ARCH64)
return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (DImode);
@@ -2528,7 +2535,8 @@ eligible_for_sibcall_delay (trial)
return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (SImode);
}
- else if (arith_double_operand (src, GET_MODE (src)))
+ else if (GET_MODE_CLASS (GET_MODE (src)) != MODE_FLOAT
+ && arith_double_operand (src, GET_MODE (src)))
return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (DImode);
else if (! TARGET_FPU && restore_operand (SET_DEST (pat), SFmode)
@@ -3591,8 +3599,17 @@ output_function_epilogue (file, size, leaf_function)
if (! leaf_function)
{
+ if (current_function_calls_eh_return)
+ {
+ if (current_function_epilogue_delay_list)
+ abort ();
+ if (SKIP_CALLERS_UNIMP_P)
+ abort ();
+
+ fputs ("\trestore\n\tretl\n\tadd\t%sp, %g1, %sp\n", file);
+ }
/* If we wound up with things in our delay slot, flush them here. */
- if (current_function_epilogue_delay_list)
+ else if (current_function_epilogue_delay_list)
{
rtx delay = PATTERN (XEXP (current_function_epilogue_delay_list, 0));
@@ -3632,6 +3649,8 @@ output_function_epilogue (file, size, leaf_function)
else
fprintf (file, "\t%s\n\trestore\n", ret);
}
+ else if (current_function_calls_eh_return)
+ abort ();
/* All of the following cases are for leaf functions. */
else if (current_function_epilogue_delay_list)
{
@@ -4683,9 +4702,11 @@ function_value (type, mode, incoming_p)
return function_arg_record_value (type, mode, 0, 1, regbase);
}
- else if (TREE_CODE (type) == UNION_TYPE)
+ else if (AGGREGATE_TYPE_P (type))
{
- int bytes = int_size_in_bytes (type);
+ /* All other aggregate types are passed in an integer register
+ in a mode corresponding to the size of the type. */
+ HOST_WIDE_INT bytes = int_size_in_bytes (type);
if (bytes > 32)
abort ();
@@ -4697,7 +4718,7 @@ function_value (type, mode, incoming_p)
if (TARGET_ARCH64
&& GET_MODE_CLASS (mode) == MODE_INT
&& GET_MODE_SIZE (mode) < UNITS_PER_WORD
- && type && TREE_CODE (type) != UNION_TYPE)
+ && type && ! AGGREGATE_TYPE_P (type))
mode = DImode;
if (incoming_p)
@@ -6886,7 +6907,7 @@ sparc_flat_epilogue_delay_slots ()
return 0;
}
-/* Return true is TRIAL is a valid insn for the epilogue delay slot.
+/* 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 is OK. */
diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h
index cc6b014900f..4d6feac7997 100644
--- a/gcc/config/sparc/sparc.h
+++ b/gcc/config/sparc/sparc.h
@@ -223,6 +223,7 @@ Unrecognized value in TARGET_CPU_DEFAULT.
/* Common CPP definitions used by CPP_SPEC amongst the various targets
for handling -mcpu=xxx switches. */
#define CPP_CPU_SPEC "\
+%{msoft-float:-D_SOFT_FLOAT} \
%{mcypress:} \
%{msparclite:-D__sparclite__} \
%{mf930:-D__sparclite__} %{mf934:-D__sparclite__} \
@@ -2235,7 +2236,10 @@ LFLGRET"ID":\n\
bias if present. */
#define INCOMING_FRAME_SP_OFFSET SPARC_STACK_BIAS
-#define DOESNT_NEED_UNWINDER (! TARGET_FLAT)
+/* Describe how we implement __builtin_eh_return. */
+#define EH_RETURN_DATA_REGNO(N) ((N) < 4 ? (N) + 24 : INVALID_REGNUM)
+#define EH_RETURN_STACKADJ_RTX gen_rtx_REG (Pmode, 1) /* %g1 */
+#define EH_RETURN_HANDLER_RTX gen_rtx_REG (Pmode, 31) /* %i7 */
/* Addressing modes, and classification of registers for them. */
diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md
index 861aee2c866..f552082e9ef 100644
--- a/gcc/config/sparc/sparc.md
+++ b/gcc/config/sparc/sparc.md
@@ -3095,11 +3095,58 @@
[(set_attr "type" "fpmove,fpmove,move,move,move,*,load,fpload,fpstore,store")
(set_attr "length" "1")])
+;; Exactly the same as above, except that all `f' cases are deleted.
+;; This is necessary to prevent reload from ever trying to use a `f' reg
+;; when -mno-fpu.
+
+(define_insn "*movsf_no_f_insn"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,r,r,r,m")
+ (match_operand:SF 1 "input_operand" "G,Q,rR,S,m,rG"))]
+ "! TARGET_FPU
+ && (register_operand (operands[0], SFmode)
+ || register_operand (operands[1], SFmode)
+ || fp_zero_operand (operands[1], SFmode))"
+ "*
+{
+ if (GET_CODE (operands[1]) == CONST_DOUBLE
+ && (which_alternative == 1
+ || which_alternative == 2
+ || which_alternative == 3))
+ {
+ REAL_VALUE_TYPE r;
+ long i;
+
+ REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
+ REAL_VALUE_TO_TARGET_SINGLE (r, i);
+ operands[1] = GEN_INT (i);
+ }
+
+ switch (which_alternative)
+ {
+ case 0:
+ return \"clr\\t%0\";
+ case 1:
+ return \"sethi\\t%%hi(%a1), %0\";
+ case 2:
+ return \"mov\\t%1, %0\";
+ case 3:
+ return \"#\";
+ case 4:
+ return \"ld\\t%1, %0\";
+ case 5:
+ return \"st\\t%r1, %0\";
+ default:
+ abort();
+ }
+}"
+ [(set_attr "type" "move,move,move,*,load,store")
+ (set_attr "length" "1")])
+
(define_insn "*movsf_lo_sum"
- [(set (match_operand:SF 0 "register_operand" "")
- (lo_sum:SF (match_operand:SF 1 "register_operand" "")
- (match_operand:SF 2 "const_double_operand" "")))]
- "TARGET_FPU && fp_high_losum_p (operands[2])"
+ [(set (match_operand:SF 0 "register_operand" "=r")
+ (lo_sum:SF (match_operand:SF 1 "register_operand" "r")
+ (match_operand:SF 2 "const_double_operand" "S")))]
+ "fp_high_losum_p (operands[2])"
"*
{
REAL_VALUE_TYPE r;
@@ -3114,9 +3161,9 @@
(set_attr "length" "1")])
(define_insn "*movsf_high"
- [(set (match_operand:SF 0 "register_operand" "")
- (high:SF (match_operand:SF 1 "const_double_operand" "")))]
- "TARGET_FPU && fp_high_losum_p (operands[1])"
+ [(set (match_operand:SF 0 "register_operand" "=r")
+ (high:SF (match_operand:SF 1 "const_double_operand" "S")))]
+ "fp_high_losum_p (operands[1])"
"*
{
REAL_VALUE_TYPE r;
@@ -3133,30 +3180,12 @@
(define_split
[(set (match_operand:SF 0 "register_operand" "")
(match_operand:SF 1 "const_double_operand" ""))]
- "TARGET_FPU
- && fp_high_losum_p (operands[1])
+ "fp_high_losum_p (operands[1])
&& (GET_CODE (operands[0]) == REG
&& REGNO (operands[0]) < 32)"
[(set (match_dup 0) (high:SF (match_dup 1)))
(set (match_dup 0) (lo_sum:SF (match_dup 0) (match_dup 1)))])
-;; Exactly the same as above, except that all `f' cases are deleted.
-;; This is necessary to prevent reload from ever trying to use a `f' reg
-;; when -mno-fpu.
-
-(define_insn "*movsf_no_f_insn"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
- (match_operand:SF 1 "input_operand" "r,m,r"))]
- "! TARGET_FPU
- && (register_operand (operands[0], SFmode)
- || register_operand (operands[1], SFmode))"
- "@
- mov\\t%1, %0
- ld\\t%1, %0
- st\\t%1, %0"
- [(set_attr "type" "move,load,store")
- (set_attr "length" "1")])
-
(define_expand "movsf"
[(set (match_operand:SF 0 "general_operand" "")
(match_operand:SF 1 "general_operand" ""))]
@@ -7108,8 +7137,8 @@
(match_operand:SI 2 "arith_operand" "rI")])
(const_int 0)))
(set (match_operand:SI 0 "register_operand" "=r")
- (match_dup 3))]
- ""
+ (match_operator:SI 4 "cc_arithop" [(match_dup 1) (match_dup 2)]))]
+ "GET_CODE (operands[3]) == GET_CODE (operands[4])"
"%A3cc\\t%1, %2, %0"
[(set_attr "type" "compare")
(set_attr "length" "1")])
@@ -7122,8 +7151,8 @@
(match_operand:DI 2 "arith_double_operand" "rHI")])
(const_int 0)))
(set (match_operand:DI 0 "register_operand" "=r")
- (match_dup 3))]
- "TARGET_ARCH64"
+ (match_operator:DI 4 "cc_arithop" [(match_dup 1) (match_dup 2)]))]
+ "TARGET_ARCH64 && GET_CODE (operands[3]) == GET_CODE (operands[4])"
"%A3cc\\t%1, %2, %0"
[(set_attr "type" "compare")
(set_attr "length" "1")])
@@ -7208,8 +7237,9 @@
(match_operand:SI 2 "reg_or_0_operand" "rJ")])
(const_int 0)))
(set (match_operand:SI 0 "register_operand" "=r")
- (match_dup 3))]
- ""
+ (match_operator:SI 4 "cc_arithopn"
+ [(not:SI (match_dup 1)) (match_dup 2)]))]
+ "GET_CODE (operands[3]) == GET_CODE (operands[4])"
"%B3cc\\t%r2, %1, %0"
[(set_attr "type" "compare")
(set_attr "length" "1")])
@@ -7222,8 +7252,9 @@
(match_operand:DI 2 "reg_or_0_operand" "rJ")])
(const_int 0)))
(set (match_operand:DI 0 "register_operand" "=r")
- (match_dup 3))]
- "TARGET_ARCH64"
+ (match_operator:DI 4 "cc_arithopn"
+ [(not:DI (match_dup 1)) (match_dup 2)]))]
+ "TARGET_ARCH64 && GET_CODE (operands[3]) == GET_CODE (operands[4])"
"%B3cc\\t%r2, %1, %0"
[(set_attr "type" "compare")
(set_attr "length" "1")])
@@ -8935,9 +8966,9 @@
#if 0
rtx chain = operands[0];
#endif
- rtx fp = operands[1];
+ rtx lab = operands[1];
rtx stack = operands[2];
- rtx lab = operands[3];
+ rtx fp = operands[3];
rtx labreg;
/* Trap instruction to flush all the register windows. */
@@ -9451,8 +9482,7 @@
(clobber (reg:SI 15))])
(set (pc) (label_ref (match_operand 3 "" "")))]
"short_branch (INSN_UID (insn), INSN_UID (operands[3]))
- && in_same_eh_region (insn, operands[3])
- && in_same_eh_region (insn, ins1)"
+ && (USING_SJLJ_EXCEPTIONS || ! can_throw_internal (insn))"
"call\\t%a1, %2\\n\\tadd\\t%%o7, (%l3-.-4), %%o7")
(define_peephole
@@ -9461,8 +9491,7 @@
(clobber (reg:SI 15))])
(set (pc) (label_ref (match_operand 2 "" "")))]
"short_branch (INSN_UID (insn), INSN_UID (operands[2]))
- && in_same_eh_region (insn, operands[2])
- && in_same_eh_region (insn, ins1)"
+ && (USING_SJLJ_EXCEPTIONS || ! can_throw_internal (insn))"
"call\\t%a0, %1\\n\\tadd\\t%%o7, (%l2-.-4), %%o7")
(define_peephole
@@ -9473,8 +9502,7 @@
(set (pc) (label_ref (match_operand 3 "" "")))]
"TARGET_ARCH64
&& short_branch (INSN_UID (insn), INSN_UID (operands[3]))
- && in_same_eh_region (insn, operands[3])
- && in_same_eh_region (insn, ins1)"
+ && (USING_SJLJ_EXCEPTIONS || ! can_throw_internal (insn))"
"call\\t%a1, %2\\n\\tadd\\t%%o7, (%l3-.-4), %%o7")
(define_peephole
@@ -9484,8 +9512,7 @@
(set (pc) (label_ref (match_operand 2 "" "")))]
"TARGET_ARCH64
&& short_branch (INSN_UID (insn), INSN_UID (operands[2]))
- && in_same_eh_region (insn, operands[2])
- && in_same_eh_region (insn, ins1)"
+ && (USING_SJLJ_EXCEPTIONS || ! can_throw_internal (insn))"
"call\\t%a0, %1\\n\\tadd\\t%%o7, (%l2-.-4), %%o7")
(define_expand "prologue"
diff --git a/gcc/config/sparc/t-openbsd b/gcc/config/sparc/t-openbsd
new file mode 100644
index 00000000000..898a24e079d
--- /dev/null
+++ b/gcc/config/sparc/t-openbsd
@@ -0,0 +1,5 @@
+# The native linker doesn't handle linking -fpic code with -fPIC code. Ugh.
+# We cope by building both variants of libgcc.
+MULTILIB_OPTIONS = fpic/fPIC
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
diff --git a/gcc/config/sparc/xm-sparc.h b/gcc/config/sparc/xm-sparc.h
index e553a0df0b2..037fc4548c6 100644
--- a/gcc/config/sparc/xm-sparc.h
+++ b/gcc/config/sparc/xm-sparc.h
@@ -19,11 +19,6 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-
-/* #defines that need visibility everywhere. */
-#define FALSE 0
-#define TRUE 1
-
/* This describes the machine the compiler is hosted on. */
#define HOST_BITS_PER_CHAR 8
#define HOST_BITS_PER_SHORT 16
diff --git a/gcc/config/sparc/xm-sysv4.h b/gcc/config/sparc/xm-sysv4.h
index 6e663d12cfa..43cacdb35a8 100644
--- a/gcc/config/sparc/xm-sysv4.h
+++ b/gcc/config/sparc/xm-sysv4.h
@@ -19,11 +19,6 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-
-/* #defines that need visibility everywhere. */
-#define FALSE 0
-#define TRUE 1
-
/* This describes the machine the compiler is hosted on. */
#define HOST_BITS_PER_CHAR 8
#define HOST_BITS_PER_SHORT 16
diff --git a/gcc/config/t-freebsd b/gcc/config/t-freebsd
index d284b3e7e41..da9c6429acd 100644
--- a/gcc/config/t-freebsd
+++ b/gcc/config/t-freebsd
@@ -1,2 +1,8 @@
# Don't run fixproto
STMP_FIXPROTO =
+
+# Compile crtbeginS.o and crtendS.o with pic.
+CRTSTUFF_T_CFLAGS_S = -fPIC
+
+# Compile libgcc.a with pic.
+TARGET_LIBGCC2_CFLAGS += -fPIC
diff --git a/gcc/config/t-freebsd-thread b/gcc/config/t-freebsd-thread
index 06315c803b0..bcaa51dde87 100644
--- a/gcc/config/t-freebsd-thread
+++ b/gcc/config/t-freebsd-thread
@@ -1,4 +1,4 @@
# This is currently needed to compile libgcc2 for threads support
-TARGET_LIBGCC2_CFLAGS=-pthread
+TARGET_LIBGCC2_CFLAGS += -pthread
#T_CFLAGS=-pthread
#T_CPPFLAGS=-pthread
diff --git a/gcc/config/t-libgcc-pic b/gcc/config/t-libgcc-pic
new file mode 100644
index 00000000000..ff935fe1e05
--- /dev/null
+++ b/gcc/config/t-libgcc-pic
@@ -0,0 +1,2 @@
+# Compile libgcc2.a with pic.
+TARGET_LIBGCC2_CFLAGS = -fPIC
diff --git a/gcc/config/t-linux b/gcc/config/t-linux
index cac5d2e936a..f1b9340ff54 100644
--- a/gcc/config/t-linux
+++ b/gcc/config/t-linux
@@ -1,28 +1,14 @@
# Don't run fixproto
STMP_FIXPROTO =
-# Don't install "assert.h" in gcc. We use the one in glibc.
-INSTALL_ASSERT_H =
-
# Compile crtbeginS.o and crtendS.o with pic.
CRTSTUFF_T_CFLAGS_S = -fPIC
# Compile libgcc2.a with pic.
TARGET_LIBGCC2_CFLAGS = -fPIC
-# Build a shared libgcc library.
-SHLIB_EXT = .so
-SHLIB_LINK = $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) -shared -nodefaultlibs \
- -Wl,--soname=@shlib_base_name@.so.0 \
- -Wl,--version-script=@shlib_map_file@ \
- -o @shlib_base_name@.so @multilib_flags@ @shlib_objs@ -lc && \
- rm -f @shlib_base_name@.so.0 && \
- $(LN_S) @shlib_base_name@.so @shlib_base_name@.so.0
-# $(slibdir) double quoted to protect it from expansion while building
-# libgcc.mk. We want this delayed until actual install time.
-SHLIB_INSTALL = $(INSTALL_DATA) @shlib_base_name@.so $$(slibdir)/@shlib_base_name@.so.0; \
- rm -f $$(slibdir)/@shlib_base_name@.so; \
- $(LN_S) @shlib_base_name@.so.0 $$(slibdir)/@shlib_base_name@.so
-SHLIB_MKMAP = $(srcdir)/mkmap-symver.awk
-SHLIB_MAPFILES = $(srcdir)/libgcc-std.ver $(srcdir)/config/libgcc-glibc.ver
+
+# Override t-slibgcc-elf-ver to export some libgcc symbols with
+# the symbol versions that glibc used.
+SHLIB_MAPFILES += $(srcdir)/config/libgcc-glibc.ver
# Do not build libgcc1. Let gcc generate those functions. The GNU/Linux
# C library can handle them.
diff --git a/gcc/config/t-linux-aout b/gcc/config/t-linux-aout
index 8826cddcab6..d08bcff9867 100644
--- a/gcc/config/t-linux-aout
+++ b/gcc/config/t-linux-aout
@@ -1,9 +1,6 @@
# Don't run fixproto
STMP_FIXPROTO =
-# Don't install "assert.h" in gcc. We use the one in glibc.
-INSTALL_ASSERT_H =
-
# Do not build libgcc1. Let gcc generate those functions. The GNU/Linux
# C library can handle them.
LIBGCC1 =
diff --git a/gcc/config/t-netbsd b/gcc/config/t-netbsd
index 85d6057feb0..f64fe29b6d1 100644
--- a/gcc/config/t-netbsd
+++ b/gcc/config/t-netbsd
@@ -4,6 +4,3 @@ LIBGCC1_TEST=
# Don't run fixproto
STMP_FIXPROTO =
-
-# Don't install "assert.h" in gcc. We use the one in glibc.
-INSTALL_ASSERT_H =
diff --git a/gcc/config/t-openbsd b/gcc/config/t-openbsd
index 14bebc13e6b..0489e872038 100644
--- a/gcc/config/t-openbsd
+++ b/gcc/config/t-openbsd
@@ -3,5 +3,3 @@ STMP_FIXPROTO =
# We don't need GCC's own include files but we do need lang specific ones.
USER_H = ${LANG_EXTRA_HEADERS}
-INSTALL_ASSERT_H =
-
diff --git a/gcc/config/t-rtems b/gcc/config/t-rtems
index 5d7d5696c3d..c403ff85dda 100644
--- a/gcc/config/t-rtems
+++ b/gcc/config/t-rtems
@@ -1,9 +1,6 @@
# RTEMS uses newlib which does not require prototype fixing
STMP_FIXPROTO =
-# Don't install "assert.h" in gcc. RTEMS uses the one in newlib.
-INSTALL_ASSERT_H =
-
# RTEMS always has limits.h.
LIMITS_H_TEST = true
diff --git a/gcc/config/sparc/t-slibgcc b/gcc/config/t-slibgcc-elf-ver
index 1c52bcb1323..9b17c565170 100644
--- a/gcc/config/sparc/t-slibgcc
+++ b/gcc/config/t-slibgcc-elf-ver
@@ -1,16 +1,17 @@
-# Build a shared libgcc library with the GNU linker.
+# Build a shared libgcc library for ELF with symbol versioning
+# with the GNU linker.
SHLIB_EXT = .so
SHLIB_LINK = $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) -shared -nodefaultlibs \
- -Wl,--soname=@shlib_base_name@.so.0 \
+ -Wl,--soname=@shlib_base_name@.so.1 \
-Wl,--version-script=@shlib_map_file@ \
-o @shlib_base_name@.so @multilib_flags@ @shlib_objs@ -lc && \
- rm -f @shlib_base_name@.so.0 && \
- $(LN_S) @shlib_base_name@.so @shlib_base_name@.so.0
+ rm -f @shlib_base_name@.so.1 && \
+ $(LN_S) @shlib_base_name@.so @shlib_base_name@.so.1
# $(slibdir) double quoted to protect it from expansion while building
# libgcc.mk. We want this delayed until actual install time.
-SHLIB_INSTALL = $(INSTALL_DATA) @shlib_base_name@.so $$(slibdir)/@shlib_base_name@.so.0; \
+SHLIB_INSTALL = $(INSTALL_DATA) @shlib_base_name@.so $$(slibdir)/@shlib_base_name@.so.1; \
rm -f $$(slibdir)/@shlib_base_name@.so; \
- $(LN_S) @shlib_base_name@.so.0 $$(slibdir)/@shlib_base_name@.so
+ $(LN_S) @shlib_base_name@.so.1 $$(slibdir)/@shlib_base_name@.so
SHLIB_MKMAP = $(srcdir)/mkmap-symver.awk
SHLIB_MAPFILES = $(srcdir)/libgcc-std.ver
diff --git a/gcc/config/sparc/t-slibgcc-sld b/gcc/config/t-slibgcc-sld
index 50107229e50..83db1a95042 100644
--- a/gcc/config/sparc/t-slibgcc-sld
+++ b/gcc/config/t-slibgcc-sld
@@ -2,15 +2,15 @@
SHLIB_EXT = .so
SHLIB_LINK = $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) -shared -nodefaultlibs \
- -Wl,-h,@shlib_base_name@.so.0 -Wl,-z,text -Wl,-z,defs \
+ -Wl,-h,@shlib_base_name@.so.1 -Wl,-z,text -Wl,-z,defs \
-Wl,-M,@shlib_map_file@ -o @shlib_base_name@.so \
@multilib_flags@ @shlib_objs@ -lc && \
- rm -f @shlib_base_name@.so.0 && \
- $(LN_S) @shlib_base_name@.so @shlib_base_name@.so.0
+ rm -f @shlib_base_name@.so.1 && \
+ $(LN_S) @shlib_base_name@.so @shlib_base_name@.so.1
# $(slibdir) double quoted to protect it from expansion while building
# libgcc.mk. We want this delayed until actual install time.
-SHLIB_INSTALL = $(INSTALL_DATA) @shlib_base_name@.so $$(slibdir)/@shlib_base_name@.so.0; \
+SHLIB_INSTALL = $(INSTALL_DATA) @shlib_base_name@.so $$(slibdir)/@shlib_base_name@.so.1; \
rm -f $$(slibdir)/@shlib_base_name@.so; \
- $(LN_S) @shlib_base_name@.so.0 $$(slibdir)/@shlib_base_name@.so
+ $(LN_S) @shlib_base_name@.so.1 $$(slibdir)/@shlib_base_name@.so
SHLIB_MKMAP = $(srcdir)/mkmap-symver.awk
SHLIB_MAPFILES = $(srcdir)/libgcc-std.ver
diff --git a/gcc/config/v850/v850.c b/gcc/config/v850/v850.c
index ffc2a2474de..78f6f588bce 100644
--- a/gcc/config/v850/v850.c
+++ b/gcc/config/v850/v850.c
@@ -29,7 +29,6 @@ Boston, MA 02111-1307, USA. */
#include "real.h"
#include "insn-config.h"
#include "conditions.h"
-#include "insn-flags.h"
#include "output.h"
#include "insn-attr.h"
#include "flags.h"
@@ -2806,7 +2805,8 @@ static void
v850_mark_machine_status (p)
struct function * p;
{
- ggc_mark_rtx (p->machine->ra_rtx);
+ if (p->machine)
+ ggc_mark_rtx (p->machine->ra_rtx);
}
static void
diff --git a/gcc/config/v850/xm-v850.h b/gcc/config/v850/xm-v850.h
index 7e2da6749a3..aa6f75bd804 100644
--- a/gcc/config/v850/xm-v850.h
+++ b/gcc/config/v850/xm-v850.h
@@ -19,10 +19,6 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* #defines that need visibility everywhere. */
-#define FALSE 0
-#define TRUE 1
-
/* This describes the machine the compiler is hosted on. */
#define HOST_BITS_PER_CHAR 8
#define HOST_BITS_PER_SHORT 16
diff --git a/gcc/config/vax/vax.c b/gcc/config/vax/vax.c
index 38c86f05351..e642ed965cb 100644
--- a/gcc/config/vax/vax.c
+++ b/gcc/config/vax/vax.c
@@ -27,7 +27,6 @@ Boston, MA 02111-1307, USA. */
#include "real.h"
#include "insn-config.h"
#include "conditions.h"
-#include "insn-flags.h"
#include "function.h"
#include "output.h"
#include "insn-attr.h"
diff --git a/gcc/config/vax/vax.h b/gcc/config/vax/vax.h
index 06b6d219d77..a3a9dde538d 100644
--- a/gcc/config/vax/vax.h
+++ b/gcc/config/vax/vax.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler. Vax version.
Copyright (C) 1987, 1988, 1991, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000 Free Software Foundation, Inc.
+ 1999, 2000, 2001 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -865,6 +865,10 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
is done just by pretending it is already truncated. */
#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
+/* When a prototype says `char' or `short', really pass an `int'.
+ (On the vax, this is required for system-library compatibility.) */
+#define PROMOTE_PROTOTYPES 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. */
@@ -982,7 +986,30 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
CC_STATUS_INIT; \
else if (GET_CODE (SET_DEST (EXP)) != ZERO_EXTRACT \
&& GET_CODE (SET_DEST (EXP)) != PC) \
- { cc_status.flags = 0; \
+ { \
+ cc_status.flags = 0; \
+ /* The integer operations below don't set carry or \
+ set it in an incompatible way. That's ok though \
+ as the Z bit is all we need when doing unsigned \
+ comparisons on the result of these insns (since \
+ they're always with 0). Set CC_NO_OVERFLOW to \
+ generate the correct unsigned branches. */ \
+ switch (GET_CODE (SET_SRC (EXP))) \
+ { \
+ case NEG: \
+ if (GET_MODE_CLASS (GET_MODE (EXP)) == MODE_FLOAT)\
+ break; \
+ case AND: \
+ case IOR: \
+ case XOR: \
+ case NOT: \
+ case MEM: \
+ case REG: \
+ cc_status.flags = CC_NO_OVERFLOW; \
+ break; \
+ default: \
+ break; \
+ } \
cc_status.value1 = SET_DEST (EXP); \
cc_status.value2 = SET_SRC (EXP); } } \
else if (GET_CODE (EXP) == PARALLEL \
@@ -1018,8 +1045,17 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
/* Control the assembler format that we output. */
/* Output at beginning of assembler file. */
+/* When debugging, we want to output an extra dummy label so that gas
+ can distinguish between D_float and G_float prior to processing the
+ .stabs directive identifying type double. */
+
+#define ASM_FILE_START(FILE) \
+ do { \
+ fputs (ASM_APP_OFF, FILE); \
+ if (write_symbols == DBX_DEBUG) \
+ fprintf (FILE, "___vax_%c_doubles:\n", ASM_DOUBLE_CHAR); \
+ } while (0)
-#define ASM_FILE_START(FILE) fprintf (FILE, "#NO_APP\n");
/* Output to assembler file text saying following lines
may contain character constants, extra white space, comments, etc. */
@@ -1208,17 +1244,6 @@ do { char dstr[30]; \
( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \
sprintf ((OUTPUT), "%s.%d", (NAME), (LABELNO)))
-/* When debugging, we want to output an extra dummy label so that gas
- can distinguish between D_float and G_float prior to processing the
- .stabs directive identifying type double. */
-
-#define ASM_IDENTIFY_LANGUAGE(FILE) \
- do { \
- output_lang_identify (FILE); \
- if (write_symbols == DBX_DEBUG) \
- fprintf (FILE, "___vax_%c_doubles:\n", ASM_DOUBLE_CHAR); \
- } while (0)
-
/* Output code to add DELTA to the first argument, and then jump to FUNCTION.
Used for C++ multiple inheritance.
.mask ^m<r2,r3,r4,r5,r6,r7,r8,r9,r10,r11> #conservative entry mask
diff --git a/gcc/config/vax/xm-vax.h b/gcc/config/vax/xm-vax.h
index d7ef168f3cd..0f2cffc64cd 100644
--- a/gcc/config/vax/xm-vax.h
+++ b/gcc/config/vax/xm-vax.h
@@ -18,10 +18,6 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* #defines that need visibility everywhere. */
-#define FALSE 0
-#define TRUE 1
-
/* target machine dependencies.
tm.h is a symbolic link to the actual target specific file. */
#include "tm.h"
@@ -42,4 +38,3 @@ Boston, MA 02111-1307, USA. */
/* isinf isn't there, but finite is. */
#define isinf(x) (!finite(x))
-
diff --git a/gcc/config/vax/xm-vms.h b/gcc/config/vax/xm-vms.h
index e2980f29fd6..5ff290eebcf 100644
--- a/gcc/config/vax/xm-vms.h
+++ b/gcc/config/vax/xm-vms.h
@@ -18,10 +18,6 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* #defines that need visibility everywhere. */
-#define FALSE 0
-#define TRUE 1
-
/* Other configurations get these via autoconfig. */
#define STDC_HEADERS 1
#define HAVE_STDLIB_H 1
diff --git a/gcc/config/we32k/xm-we32k.h b/gcc/config/we32k/xm-we32k.h
index be617d37317..c437c25f406 100644
--- a/gcc/config/we32k/xm-we32k.h
+++ b/gcc/config/we32k/xm-we32k.h
@@ -19,11 +19,6 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-
-/* #defines that need visibility everywhere. */
-#define FALSE 0
-#define TRUE 1
-
/* This describes the machine the compiler is hosted on. */
#define HOST_BITS_PER_CHAR 8
#define HOST_BITS_PER_SHORT 16
diff --git a/gcc/config/x-linux b/gcc/config/x-linux
index a7c091799e8..d284b3e7e41 100644
--- a/gcc/config/x-linux
+++ b/gcc/config/x-linux
@@ -1,5 +1,2 @@
# Don't run fixproto
STMP_FIXPROTO =
-
-# Don't install "assert.h" in gcc. We use the one in glibc.
-INSTALL_ASSERT_H =
diff --git a/gcc/config/xm-lynx.h b/gcc/config/xm-lynx.h
index 009f8445eab..aa75f01021b 100644
--- a/gcc/config/xm-lynx.h
+++ b/gcc/config/xm-lynx.h
@@ -22,10 +22,6 @@ Boston, MA 02111-1307, USA. */
running Lynx. This file should not be specified as $xm_file itself;
instead $xm_file should be CPU/xm-lynx.h, which should include this one. */
-/* #defines that need visibility everywhere. */
-#define FALSE 0
-#define TRUE 1
-
/* Arguments to use with `exit'. */
#define SUCCESS_EXIT_CODE 0
#define FATAL_EXIT_CODE 33
diff --git a/gcc/config/xm-std32.h b/gcc/config/xm-std32.h
index c52782e9741..e38f8247355 100644
--- a/gcc/config/xm-std32.h
+++ b/gcc/config/xm-std32.h
@@ -18,10 +18,6 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* #defines that need visibility everywhere. */
-#define FALSE 0
-#define TRUE 1
-
/* This describes the machine the compiler is hosted on. */
#define HOST_BITS_PER_CHAR 8
#define HOST_BITS_PER_SHORT 16